1. 글을 작성하게 된 계기
입사 한 달 차에, 회사에서 인프라 아키텍처를 전면 개편해야 할 일이 있었습니다. 적응도 하기 전, 인프라 세팅을 혼자 맡아 진행하게 됐는데, 이 과정에서 어떤 문제가 있었고, 이를 어떻게 해결하려고 했는지에 대해 생각을 정리하기 위해 글을 작성하게 되었습니다.
- 개편 계기
- 문제 상황
- 해결책 역 제안
- 결과 및 느낀 점
2. 개편 계기
인프라를 개편하게 된 계기는 서버 측 IP 주소가 노출되는 것이었습니다. 당시 클라이언트에서 API 서버를 바로 호출하고 있었기 때문에 서버 IP 주소가 바로 노출되고 있었습니다.
당연히 서버의 IP가 노출되면 안 되지만, 아쉽게도 현재 서버 아키텍처는 이를 노출하고 있는 상태였습니다.
이를 해결하기 위해 리버스 프록시(Reverse-Proxy)를 세팅을 하며, 인프라 아키텍처 전체를 다시 구축/세팅해달라는 요구사항이 들어왔습니다. 기존 아키텍처와는 비교도 할 수 없을 정도로 많은 자원이 추가됐고, 복잡도도 증가했습니다. 아래와 같이요.
기존 아키텍처는 정말 심플했습니다.
3. 문제 상황, 고려할 점
여기서 몇 가지 문제 사항과 고려할 점 있었는데, 개발 일정, 기존 자원 활용 불가, 과도하게 복잡한 아키텍처 크게 세 가지였습니다.
- 개발 일정
- 기존 자원의 활용
- 과도하게 복잡한 아키텍처
3-1. 개발 일정
첫 번째는 개발 일정입니다. 당시 회사의 계획을 듣고 실제 세팅할 수 있는 기간이 1주일 조금 넘게 주어졌습니다. 클라이언트 서버를 새로 띄우기 위해서는 아래와 같은 몇 가지 고려 사항/추가 작업이 필요했습니다. 또한, 기존 API가 오류 없이 잘 동작하는 테스트도 해야 했고요. 따라서 일정이 촉박해 보였습니다.
- Nginx 서버 설정 및 기존 자원 이전
- 배포 스크립트 작성
- 정적 자원 캐싱
- 기존 API 점검 및 테스트
3-2. 기존 자원의 활용
두 번째는 기존 자원을 잘 활용하지 못하는 점 이었습니다. CloudFront와 같은 현재 사용 중인 자원들을 폐기하고, 완전히 새로운 서버를 구축하고 자원을 이전해야 했기 때문입니다. 트래픽이 많은 서비스도 아닌데, 그렇다고 비용적 문제가 있지도 않은데, 기존 자원들을 활용하지 않고 새로운 서버를 구축하는 것은 비효율적이란 생각이 들었습니다.
- 기존 자원은 문제 없이 잘 동작하는데, CloudFront/S3 폐기
- 트래픽이 적어 비용적 문제도 존재하지 않는 상황
3-3. 과도하게 복잡한 아키텍처
세 번째는 과도하게 복잡한 아키텍처입니다. 당시 사용자는 기껏해야 6,000 ~ 7,000명이었습니다. 그것도 자주 사용하는 것도 아니고요. 서버 한두 대로도 충분히 버틸 수 있으며, API 서버 앞단에 리버스 프록시 서버 한 대만 두면 되는데, 이렇게 복잡할 필요가 있을까? 하는 생각이 들었습니다. 서버 비용은 소중하니까요. 😠
설사 구축은 한다고 해도 아키텍처가 복잡하면 유지보수에도 많은 자원이 들어갑니다.
4. 해결책 역 제시
그래서 해결책을 역 제시했습니다. 우리가 해결하고 싶은 문제는 클라이언트 측에서 서버의 IP 주소를 알기 때문에, 이를 숨기고 싶은 것이었습니다. 따라서 클라이언트 서버의 자원을 이전하지 않고 그대로 두면서, API Gateway만 띄워 뒷단 서버를 호출하면 되지 않을까? 하는 생각이 들었습니다.
이렇게 되면 클라이언트 서버를 별도로 띄울 필요가 없으므로 배포 스크립트도 작성할 필요가 없으며, API Gateway 서버 하나만 올리면 되는 심플한 상황이 됩니다. 결과는 똑같고요.
양쪽 모두 사용한 경험이 있었기에, 각각의 장/단점을 떠올려 봤습니다. 가장 고민했던 부분은 SOA(Single Point of Access)인데요, API Gateway의 장애가 서비스 전체의 장애가 될 수 있기 때문입니다. 하지만 현재 서비스는 트래픽이 많지도 않으며, Rate Limiter와 같은 장치를 둘 필요도 없었기 때문에, 장애 포인트가 많지 않아 보였습니다.
차라리 사고가 난다면 API Gateway보다는, API 서버가 더 걱정되었습니다. 레거시 코드가 정말 많았거든요. 👀
또한, 둘 다 L7 계층에서 동작하기 때문에, 로드 밸런싱과 같은 몇몇 기능도 거의 동일하게 사용할 수 있습니다. 여튼, 기타 이슈가 조금 남아 있지만, API Gateway를 통로로만 사용한다면 자바 코드 몇 줄로 이를 깔끔하게 해결할 수 있을 것 같았습니다.
결과가 받아들여지는 것은 별개지만요. 😂
5. 결과 및 느낀점
안타깝지만 제시한 사항은 받아들여지지 않았고, 혼자 날밤을 까며 모든 걸 구축/세팅했습니다. 당시 잠을 못 자서 고생했는데, 그래도 이를 통해 꽤 많은 것들을 생각해 보고 배울 수 있었습니다. 그리고 이런 거대한 아키텍처를 직접 구축/운영해보는 것은 평소에 하지 못할 경험이기에 재밌기도 했습니다. 😃
- 문제의 본질 파악
- 현재 자원의 활용
- 평소 학습의 중요성
5-1. 문제의 본질 파악
문제의 본질이 무엇인지 잘 파악하는 게 중요하다라는 것을 느꼈습니다. 문제의 본질을 해결할 수 있다면 꼭 한 가지 방법으로 해결하지 않아도 되니까요. 평소 리버스 프록시는 Nginx 외에는 생각해 본 적이 없는데, 이번 프로젝트를 통해 API Gateway도 생각해 볼 수 있었습니다.
다만, 최근 생각이 조금 바뀐 부분이 있는데,
코드/설계에 정답은 없지만, 좋지 못한 문제 해결 방법은 존재한다.입니다. 최근 좋지 못한 방식으로 문제를 해결해 뒷사람들이 힘들어하는 것을 너무 많이 보기 때문입니다.
5-2. 현재 자원의 활용
문제를 해결하기 위해 모든 것을 새로 만들 필요는 없다라는 것을 느꼈습니다. 현재 우리가 가진 자원이 올바르게 동작하고 있다면, 성능상 큰 문제가 없다면 이를 최대한 활용하는 것도 하나의 방법이기 때문입니다. 시간은 한정돼 있는데, 빈대 잡자고 집을 태울 순 없잖아요?
평소
학습과좋은 설계를 빙자한 오버엔지니어링도 했기 때문에 더 와닿았는지도 모르겠네요.
5-3. 평소 학습의 중요성
평소 학습의 중요성을 느낄 수 있었습니다. 사실 Nginx, 스프링 API Gateway 두 방법 모두 사용해 봤던 방법이고, 개인적으로 운영 중인 서버에서는 Nginx를 사용하고 있습니다. 따라서 이를 세팅하고, 어떤 사항을 고려해야 하는지 이미 알고 있었기 때문에 빠르게 판단해 대안을 역 제시해 볼 수 있었습니다.
평소 이를 시도해 해보지 않았다면,
이런 방법이 있다는 것을 알지 못했을 것이고,운 좋게 방법은 찾았더라도, 어떤 문제점과 장/단점이 있는지 파악하는 데 오랜 시간이 걸려쉽게 말을 꺼내지 못했을 것입니다.
이번 일을 통해 왜 평소에 개발자가 학습을 게을리하면 안 되는지, 다양한 시도와 그 과정에서의 실패를 철저하게 기록해야 하는지에 대해 몸소 느낄 수 있었습니다. 저는 동작 과정이나 중요하다고 생각하는 일 외에는 포스팅 하지 않는 편인데요, 이번 계기를 통해 사소한 문제 해결일 지라도, 꼭 기술적이지 않더라도 기록하는 습관을 들여야겠다는 것을 깨닫게 되었습니다.
- 평소에도 기술적 시도/학습을 꾸준하게 한다.
- 실패한 것도 기록한다.
- 꼭 기술적이지 않더라도, 사소한 아이디어/문제 해결도 글로 남긴다.
6. 정리
입사 후 이렇게 빨리 큰 업무를 맡게 될 줄 몰랐는데, 이를 통해 정말 빠르게 성장한 것 같습니다. 너무 재밌었고요. 이런 큰 규모의 아키텍처는 개인적으로는 만들 일이 없을 것 같은데, 두고두고 생각날 것 같습니다.
- 코드/설계에 정답은 없다. 문제의 본질을 파악하자.
- 현재 자원을 최대한 활용하자.
- 개발자의 평소 학습은 중요하다.
