상세 컨텐츠

본문 제목

[프로젝트 노트]MA에서 MSA로 마이그레이션하기

카테고리 없음

by aeongiii 2025. 1. 27. 00:23

본문

E-Commerce 프로젝트를 진행하면서, 기존 Monolithic Architecture(MA)에서 MicroService Architecture(MSA)로 변경하게 되었다. 어떤 의사결정이 있었는지 정리해보려고 한다.

출처 : https://ozip.me/J7VeXTf

1. 배경


프로젝트 초 반에는 모놀리식(MA) 구조로 개발을 진행했다.

모놀리식 구조로 개발한 이유는, 빠르게 개발하고 실행해볼 수 있기 때문이었다.특히, 회원가입, 상품 조회, 주문, 결제와 같이 E-Commerce 서비스의 핵심 기능들을 빨리 개발하고 검증해볼 수 있기 때문에 모놀리식 구조를 채택했다.

 

그러나, 프로젝트를 진행하다보니 몇 가지 문제가 생겼다.- 문제 1. 트래픽이 몰리는 '한정판 구매' 시나리오를 만들어야 하는데, 기존 구조로는 트래픽이 몰릴 때 주문 및 결제 기능이 병목 현상을 일으켜 성능 저하가 발생했다.- 문제 2. 단일 애플리케이션에서 모든 기능을 처리하다보니 유지보수가 어려워졌고, 장애 발생 시 전체 코드를 들여다봐야 했다.- 문제 3. 특정 기능(ex. 주문, 결제)에 트래픽이 몰릴 경우 전체 시스템을 확장해야 하는 비효율적인 구조였다.

 

이러한 문제를 해결하고 서비스 확장성을 확보하기 위해 모놀리식에서 MSA로 마이그레이션했다.내 프로젝트에서 MSA가 더 적절하다고 생각한 이유는 아래와 같다.

- 이유 1. 특정 기능에 트래픽이 몰릴 경우 해당 서비스만 별도로 스케일-아웃 할 수 있어 성능을 최적화할 수 있다.

- 이유 2.  각 서비스가 독립적으로 관리되므로 유지보수가 쉽고, 특정 서비스에 장애가 발생해도 나머지 시스템은 정상적으로 운영될 수 있다.

- 이유 3. 서비스 간 결합도가 감소하여 확장성이 높아진다. 

 

그래서 나는 각 도메인(회원, 상품, 주문, 결제)을 개별 서비스로 분리하는 MSA를 채택했다.

 

 

2. MSA 설계 및 적용


1) Eureka 도입 - 서비스 디스커버리 & 로드밸런싱 구현

MSA 구조에서는 각 서비스가 독립적으로 실행되기 때문에, 서비스의 위치(IP, 포트)가 고정되어있지 않다. 각 서비스를 동적으로 관리하기 위해 Spring Cloud Netflix Eureka를 사용하여 서비스 디스커버리 기능을 구현했다.

 

- Eureka Server : 각 서비스가 실행될 때 자동으로 등록되도록 설정

- Eureka Client : 다른 서비스의 위치를 동적으로 검색할 수 있도록 구현

- 로드밸런싱을 통해 여러 서비스 인스턴스를 균등하게 배분

 

이를 통해 새로운 서비스가 추가되거나 기존 서비스가 장애로 종료되더라도 자동으로 감지하여 트래픽을 정상적인 인스턴스로 라우팅할 수 있는 구조가 가능하게 되었다.

 

 

2) API Gateway 활용 - 단일 엔드포인트 설정

모놀리식 구조에서는 클라이언트가 단일 서버에 요청을 보내면 된다. 그러나 MSA에서는 여러 서비스가 존재하므로 클라이언트가 각각의 서비스에 직접 접근하면 복잡해질 수 있고, 보안이 취약해질 수 있다. 이러한 문제를 해결하기 위해 Spring Cloud Gateway를 활용하여 단일 엔드포인트만 공개했다.

 

- 클라이언트는 API Gateway를 통해서만 요청을 보낼 수 있도록 설정하여 보안 강화

- 인증/인가 로직을 게이트웨이에서 처리한 뒤, 각 요청을 내부 서비스로 적절히 라우팅하도록 구현

 

특히 API Gateway를 통해 JWT 기반 인증을 통합적으로 처리할 수 있었다.

 

 

3) FeignClient 활용 - 내부 서비스 간 통신 최적화

MSA 환경에서는 각 서비스가 독립적으로 운영되지만, 일부 기능에서는 다른 서비스의 데이터를 직접 활용해야 하는 경우도 있다. 이때 서비스 간 직접 HTTP 요청을 사용할 경우 유지보수가 어렵고 복잡해진다. 이를 해결하기 위해 Spring Cloud FeignClient를 사용하여 내부 서비스 간 통신을 선언적으로 관리했다.

 

이를 통해, 서비스 간 호출의 유지보수성이 향상되었다. FeignClient로 내부 서비스 호출을 단순화하고, 재사용 가능하도록 구성했다. 또한, API Gateway를 거치지 않으므로 응답 속도를 최적화 할 수 있었다.

 

 

 

3. 적용 후 개선된 점


 

1) 트래픽 증가에 대한 유연한 대응

한정판 상품 구매 시나리오에서는 특정 시간대에 동시 접속자가 폭증하게 될 것이다. MSA 구조를 적용하면서 트래픽이 급증하는 특정 서비스만 개별적으로 확장할 수 있게 되었다. 

 

2) 서비스 결합도 감소 ➡️ 유지보수성 및 장애 대응 가능

기존 모놀리식 구조에서는 한 부분에서 장애가 발생하면 전체 서비스가 중단되는 리스크가 있었다. 그러나 MSA 구조에서는 각 서비스가 독립적으로 실행되므로, 한 서비스의 장애가 전체 시스템에 영향을 주지 않도록 설계할 수 있었다. 이로 인해 시스템 안정성이 향상되었다.

 

예를 들어,

- 한정판 구매 상황으로 인해 주문 서비스가 일시적으로 다운되더라도, 회원가입을 진행하거나 일반 상품의 상세정보를 확인하는 기능은 정상적으로 동작한다.

- Eureka와 API Gateway를 활용하여, 문제가 발생한 서비스로의 트래픽을 우회할 수 있다.

 

3) 보안성 강화 및 인증 로직 최적화

API Gateway를 도입한 덕분에 각 개별 서비스가 직접 외부에 노출되지 않도록 보호할 수 있게 되었고, 클라이언트는 모든 엔드포인트를 알아야 할 필요가 없다. 또한, JWT 기반 인증을 API Gateway에서 통합적으로 처리하여 유지보수성과 확장성이 향상되었다. 

 

 

4. 결론


프로젝트 초기에는 MSA를 도입하면 관리해야 할 서비스가 많아지고 복잡성이 증가할 것이라는 부담감이 있었다. 그러나, Eureka, API Gateway, FeignClient를 효과적으로 활용하여, 관리 가능한 수준의 마이크로서비스 구조를 설계하고 결합도를 낮출 수 있었다.

 

한정판 구매 시나리오가 포함된 이 프로젝트에서 MSA 구조는 단순한 선택이 아니라, 확장성과 유지보수성을 고려한 필수적인 의사결정이었다.

 

앞으로 서비스가 증가할수록 MSA의 장점은 극대화될 것이라고 생각한다.