개요
현재, 사용자용 API 서버에 어드민에서 사용되는 API가 포함되어 있다.
다시 말해 한 프로젝트 안에 사용자용 API와 어드민용 API가 함께 제공되고 있다.
따라서 어드민용 API가 새로 배포될 때마다 사용자용 서버 또한 함께 재배포가 이루어진다.
또한, dev와 prod 환경이 각각 dev, main 브랜치로 분리되어 있는데, 어드민 API 배포를 하려면 main 브랜치로 바로 커밋하거나 dev에서 main을 거쳐야 하기 때문에 커밋 히스토리 관리가 불편하다는 점이 있다.
따라서 어드민용 API 서버를 분리하여 배포가 독립적으로 이루어질 수 있도록 한다.
그러면 어떻게 분리하면 될까?
실행 계획
작업 기간
10월까지 케어링 기능을 배포해야 한다.
10월 배포까지는 약 7주가 남았다.
7주 동안 부지런히 해야 하는 정도이기에 늦어도 이번 주까지만 진행해야 한다.
이번 주는 수, 목, 금, 토로 약 4일정도 소요 가능한 상황이다.
작업 방법
작업 방법은 두 가지가 있을 것 같다.
1. 새로 프로젝트를 만들고, 기존 프로젝트에 있는 코드를 모두 그대로 옮긴다.
- 모듈화와 패키지 분리 작업을 하지 않아도 되기에 공수가 그나마 적게 든다. 대신, 한번에 패키지만 똑 떼서 분리하기엔 불가능하다. 따라서 도메인 단위 혹은 API 단위로 점진적 마이그레이션을 해야 한다.
- 부단히 하면 이번 주까지는 가능할 것으로 보인다.
- 모듈화가 되지 않은 탓에 중복된 코드가 존재하게 된다. 공통으로 사용되는 엔티티의 필드가 변경되면 같이 변경해줘야 한다. 각 엔티티의 변경 가능성이 낮은 편은 아니다.
- Admin 서버가 분리가 완료되어야, 안전하게 기존 API 서버에서 어드민 관련 로직을 제거하는 작업이 필요하다.
2. 각 도메인 단위로 모듈화하여 분리한다.
- 패키지 의존성 분리가 선행되어야 한다. 하지만 현재 신경쓰지 않고 개발하여 많이 꼬여있는 상태일 것이다. 이를 풀어내려면 많은 시간이 필요할 것이다.
- 작업을 마무리한다는 가정하에 확실히 시스템의 독립성, 유지보수성이 증가할 것이다. 다만 해야 하는 작업이 많고 익숙한 작업이 아니라 많은 시간이 소요될 것이다.
결론
작업 기간과 엔티티 동기화가 되지 않았을 때 장애의 심각도를 따져봤을 때 패키지 의존성을 분리하고 모듈화까지는 오버 엔지니어링이라고 판단된다.
이에 인증부터 시작해서 도메인 단위 하나씩 혹은 API 단위로 하나씩 옮기는 방향으로 점진적 마이그레이션을 진행한다.
마이그레이션이 끝나면, 기존 프로젝트에서 어드민 관련 코드를 제거한다.
의문
- 점진적 마이그레이션이 최선의 방법일까?
- 점진적 마이그레이션 하는 방법에서 생기는 코드 중복은 어쩔 수 없는 것일까?
- 어드민을 분리하는 작업과 MSA에는 어떤 차이가 있는가?
3-1. 어드민만 떼고 보면 MSA를 적용했다고 볼 수 있는 것인가?
의문에 대한 Gemini 답변
1. 점진적 마이그레이션이 최선의 방법일까?
네, 현재 상황에서는 점진적 마이그레이션이 최선의 방법이라고 판단됩니다.
두 가지 방법(전체 이전 vs. 모듈화 후 이전)을 비교했을 때, '전체 이전'은 기존 코드를 그대로 옮기는 방식이므로 공수가 적게 들고, 정해진 시간 안에 작업을 완료할 가능성이 높습니다. 특히 7주라는 촉박한 기간 내에 핵심 기능인 케어링 배포를 병행해야 하는 상황이므로, 안정적인 방식인 점진적 마이그레이션을 선택하는 것이 합리적입니다.
반면에, '모듈화 후 이전'은 장기적으로 시스템의 유지보수성과 독립성을 높일 수 있지만, 현재 의존성이 복잡하게 꼬여있는 상태에서 모듈화 작업을 진행하려면 예상보다 훨씬 많은 시간이 소요될 수 있습니다. 이는 10월까지 케어링 기능을 배포해야 하는 일정에 차질을 줄 위험이 큽니다.
따라서, 우선은 점진적 마이그레이션을 통해 어드민 서버를 분리하여 배포 독립성을 확보하고, 추후에 서비스 안정화 및 여유가 생겼을 때 리팩터링을 통해 코드 중복을 해소하고 모듈화하는 방향을 고려하는 것이 좋습니다.
2. 점진적 마이그레이션 하는 방법에서 생기는 코드 중복은 어쩔 수 없는 것일까?
점진적 마이그레이션 과정에서 일시적으로 발생하는 코드 중복은 피하기 어렵습니다.
이는 도메인 로직이나 공통으로 사용되는 엔티티와 같은 부분을 두 서버에서 모두 관리하게 되기 때문입니다.
하지만 이는 다음과 같은 방법으로 최소화하고 관리할 수 있습니다.
공통 모듈 분리: 당장 전체 모듈화를 하기 어렵더라도, 양쪽 서버에서 공통으로 사용되는 핵심 코드(예: 엔티티, DTO 등)를 별도의 라이브러리 또는 모듈로 분리하여 관리하는 방법을 고려해볼 수 있습니다. 이를 통해 공통 코드가 변경되었을 때 두 서버의 코드를 모두 수정해야 하는 번거로움을 줄일 수 있습니다. 예를 들어, Maven이나 Gradle과 같은 빌드 도구를 사용해 공통 모듈을 패키징하고, 이를 두 프로젝트에서 의존성으로 추가하여 사용할 수 있습니다.
API Gateway 패턴 활용: 어드민 API와 사용자용 API를 분리하면서 API Gateway 패턴을 도입하는 것도 좋은 해결책이 될 수 있습니다. API Gateway를 통해 각 서버의 API를 통합 관리하고, 중복되는 인증 로직이나 로깅 등을 한 곳에서 처리할 수 있습니다.
점진적인 리팩터링: 마이그레이션 완료 후, 기존 서버에서 어드민 관련 코드를 제거하는 과정에서 중복된 코드나 로직을 정리하는 리팩터링 작업을 병행하면 좋습니다. 이를 통해 최종적으로 코드 중복을 해소할 수 있습니다.
요약하자면, 점진적 마이그레이션 초기에는 코드 중복이 불가피하지만, 공통 모듈 분리, API Gateway 패턴 도입, 그리고 마이그레이션 후의 리팩터링을 통해 이러한 문제를 효과적으로 관리하고 최종적으로는 해결할 수 있습니다.
3. 어드민을 분리하는 작업과 MSA에는 어떤 차이가 있는가?
어드민 서버를 분리하는 것은 MSA(Microservices Architecture)로 가는 첫 단계로 볼 수 있습니다.
둘의 가장 큰 차이점은 분리하는 대상의 규모와 목적에 있습니다.
어드민 서버 분리
어드민 서버 분리는 말 그대로 어드민 기능만을 별도의 서버로 분리하는 것입니다. 기존에 하나의 애플리케이션에 사용자용 API와 어드민용 API가 함께 있었는데, 이 중 어드민 기능을 담당하는 부분을 독립적인 프로젝트로 만드는 것입니다.
목적: 배포의 독립성을 확보하고, 개발 및 운영의 복잡성을 줄이는 데 초점을 맞춥니다.
규모: 전체 서비스 중 **하나의 기능(어드민)**을 분리하는 비교적 작은 규모의 작업입니다.
아키텍처: 여전히 하나의 거대한 모놀리식(Monolithic) 아키텍처 안에 어드민 기능만 떨어져 나온 형태에 가깝습니다.
MSA(마이크로 서비스 아키텍처)
MSA는 애플리케이션 전체를 여러 개의 작은 독립적인 서비스로 분리하는 아키텍처 방식입니다. 각 서비스는 특정 비즈니스 기능(예: 사용자 관리, 결제, 상품 관리 등)을 담당하며, 자체 데이터베이스를 가질 수 있습니다.
목적: 대규모 시스템의 복잡성을 관리하고, 개발 팀의 독립성을 보장하며, 특정 서비스의 장애가 전체 시스템에 미치는 영향을 최소화하는 데 있습니다.
규모: 애플리케이션의 모든 핵심 기능을 서비스 단위로 분리하는 대규모 작업입니다.
아키텍처: 여러 서비스가 서로 통신하며 전체 애플리케이션을 구성하는 분산 시스템 형태입니다.
3-1. 어드민만 떼고 보면 MSA를 적용했다고 볼 수 있는 것인가?
아닙니다, 기존 모놀리식 프로젝트에서 어드민 기능만 분리했다고 해서 MSA를 적용했다고 보기는 어렵습니다.
어드민 분리는 MSA의 첫걸음 또는 부분적인 적용 사례로 볼 수 있지만, MSA의 핵심 원칙을 모두 충족하는 것은 아닙니다.
MSA는 다음과 같은 특징을 갖습니다.
독립적인 배포: 각 마이크로 서비스는 독립적으로 개발되고 배포됩니다.
비즈니스 도메인 중심: 서비스가 특정 비즈니스 기능(예: 주문, 결제, 사용자 관리)을 중심으로 설계됩니다.
느슨한 결합: 각 서비스가 서로 독립적으로 동작하며, API를 통해 통신합니다.
자체 데이터베이스: 각 서비스가 자신만의 데이터베이스를 가질 수 있습니다.
어드민 분리의 경우, 독립적인 배포라는 한 가지 특징을 만족하지만, 나머지 서비스들은 여전히 하나의 모놀리식 프로젝트에 묶여 있습니다. 따라서 전체 아키텍처가 MSA로 전환된 것이 아니라, 모놀리식 아키텍처의 일부를 분리한 것으로 이해하는 것이 더 정확합니다.
진짜 결론
정말 운좋게 무료 멘토링을 통해 알게 되어 몇 번 술자리까지 함께 한 JSCODE 형님에게 조언을 구해보았다.
아래는 그에 대한 질답이다.
우선, 내가 분리해야겠다고 느낀 이유가 무엇이었을까?
문제의 근원을 파고 들어가보니 꼭 프로젝트 분리만이 정답이 아니었다.
무중단 배포를 적용하여 브랜치를 적절히 이용해 문제를 해결할 수 있었고, API 버저닝 같은 방법으로 해결할 수 있는 문제였다.
직접 해주신 말씀 중에 '닭 잡는 데 소잡는 칼'쓰는 격이라는 표현이 딱이었다.
실제로 프로젝트를 분리하는 작업은 정말 오래 걸리는 작업이라고 해주었다.
게다가 보통 프로젝트를 분리할 때에는 사용자용과 어드민용 프로젝트를 구분하기보단, 도메인 단위로 나눈다고 해주셨다.
그렇다. MSA로 가는 여정 중 하나가 된다.
추가적인 조언으로 시간 날 때 MSA 분리를 위한 작업도 하라고 조언해주셨다.
오늘 질답하는 시간을 통해, '사수가 있었더라면 더 많이 그리고 더 빨리 배울 수 있었을텐데'라는 아쉬움이 크게 다가왔다.
앞으로 틈틈히 인프런 같은 곳에서 유료 멘토링을 통해 페이스 메이커를 두는 것이 좋겠다.