티스토리 뷰
Spring Boot 기반 MSA 설계 가이드
대표적인 마이크로서비스 구성 예시
일반적으로 전자상거래 시스템을 예로 들면 마이크로서비스로 사용자 서비스(User Service), 주문 서비스(Order Service), 재고 서비스(Inventory Service), 결제 서비스(Payment Service), 배송 서비스(Shipping Service) 등을 구성할 수 있습니다. 예를 들어 Asish Panda의 사례에서는 “User Service: 사용자 프로필 및 인증 처리, Order Service: 주문 및 추적 관리, Inventory Service: 상품 재고 관리” 등을 언급하여 각 서비스가 분리된 도메인별 역할을 담당함을 보여주고 있습니다. 이 외에 상품 서비스(Product Service), 결제 서비스, 알림 서비스(Notification Service) 등 업무 범위에 따라 서비스 단위를 정의하여 구성할 수 있습니다.
서비스별 Spring Boot 프로젝트 구성 방식
각 마이크로서비스는 독립적인 Spring Boot 프로젝트로 구현하며, 빌드 도구로는 Maven 또는 Gradle을 사용합니다. Spring 공식 가이드에 따르면 “빌드를 위한 어떤 시스템(Gradle, Maven)이든 사용할 수 있다”는 점을 명시하고 있습니다. 일반적으로 각 서비스는 실행 가능한 JAR 형태로 패키징하며, 패키지 구조는 도메인(예: com.example.userservice)이나 기능(컨트롤러, 서비스, 리포지토리) 단위로 분리합니다. 예를 들어 회원 관련 기능은 com.example.user.controller, com.example.user.service 등으로 구성할 수 있습니다. 여러 서비스에서 공통으로 사용하는 코드(인증 로직, DTO, 유틸리티 등)는 별도의 **공통 모듈(라이브러리)**로 분리하여 관리할 수 있습니다. 예를 들어 하나의 프로젝트에서 인증/예외 처리와 같은 전역 코드는 shboard-common 모듈로, 회원 도메인 코드는 member-service 모듈로 분리한 사례가 있습니다.
- 빌드 도구: Maven 또는 Gradle 사용 (Spring 가이드에 따르면 “어떤 빌드 시스템을 사용해도 된다”).
- 패키징: 각 서비스는 독립적인 JAR로 패키징(단일 애플리케이션).
- 패키지 구조: 기능/도메인별로 패키지 분리 (예: controller, service, repository 계층별 또는 도메인별 패키지).
- 공통 모듈: 다수 서비스가 사용하는 공통 코드는 별도 라이브러리/모듈로 분리하여 의존성 관리.
서비스 간 통신 방식 설계 (REST, gRPC, 메시지 브로커)
마이크로서비스 간 통신은 크게 동기식 HTTP(REST)와 비동기식 메시지 방식으로 구분할 수 있습니다.
- REST API (동기): 스프링의 @RestController로 RESTful 엔드포인트를 구현하고, RestTemplate 또는 WebClient로 다른 서비스에 HTTP 요청을 보냅니다. 예를 들어 주문 처리 시 주문 서비스에서 재고 서비스를 REST 호출로 재고를 확인하는 방식입니다. REST 통신은 이해가 쉽고 도구(예: Swagger/OpenAPI)로 문서화가 용이하며 동기적 상호작용에 적합합니다.
- gRPC (동기): HTTP/2와 Protocol Buffers를 사용하는 고성능 RPC 통신입니다. gRPC는 이진 직렬화로 대역폭과 처리 속도가 뛰어나고, 서비스 간 명확한 인터페이스 계약을 제공합니다. 예를 들어 결제 서비스와 주문 서비스 간 내부 호출에 gRPC를 적용할 수 있습니다. Sayed Khaled는 “gRPC는 HTTP/2를 사용하여 멀티플렉싱과 낮은 레이턴시를 제공하며, Protocol Buffers는 JSON보다 훨씬 빠르고 콤팩트하다”고 설명합니다.
- 메시지 브로커 (비동기 이벤트): Apache Kafka, RabbitMQ 등의 메시지 큐를 통해 이벤트를 발행/구독합니다. Spring Cloud Stream을 사용하여 주문 생성 이벤트를 발행하고, 재고/결제 서비스가 이를 구독하도록 구현할 수 있습니다. 예를 들어 주문 서비스가 OrderPlaced 이벤트를 발행하면 재고 서비스와 결제 서비스가 이를 받아 재고 차감이나 결제 처리를 수행합니다. 비동기 이벤트 아키텍처는 서비스 간 의존성을 낮추고 확장성을 높이며, 장애 격리에 유리합니다.
API Gateway 구성 예
API Gateway는 클라이언트 요청의 단일 진입점 역할을 하며, 내부 서비스로의 라우팅과 인증/인가, 로깅, 부하 분산 등을 처리합니다. 예를 들어 Spring Cloud Gateway를 사용하면 application.yml에서 경로별 라우팅과 필터(인증·권한 검사)를 설정할 수 있습니다. 또한 쿠버네티스 환경에서는 NGINX Ingress나 Kong Gateway 등을 API 게이트웨이로 활용할 수 있습니다.
- Spring Cloud Gateway: Spring 기반 Gateway로, 라우트 설정과 필터(로그인 검사, 인증 토큰 해석 등)를 지원합니다. 스프링 생태계에서 쉽게 통합할 수 있으며, 자바로 플러그인을 작성할 수 있습니다.
- NGINX/Ingress: NGINX(또는 NGINX Plus)를 리버스 프록시로 사용하여 API Gateway 기능을 수행할 수 있습니다. Kubernetes에서는 NGINX Ingress Controller로 구현하여 트래픽 라우팅, TLS 종료, JWT 검증 등을 처리합니다. NGINX는 고성능으로 알려져 있습니다.
- Kong Gateway: NGINX 기반의 오픈소스 API 게이트웨이로, 다양한 플러그인(예: JWT 인증 플러그인)과 관리 UI를 제공합니다. 쿠버네티스에서도 Helm 차트로 쉽게 배포 가능합니다.
JWT 기반 인증·인가 설계
JWT(Json Web Token)를 이용한 인증 아키텍처를 구성할 때는 별도의 **인증 서비스(Auth Service)**를 두어야 합니다. 클라이언트가 로그인하면 인증 서비스가 사용자 자격증명을 확인한 뒤 JWT를 발급합니다. Xoriant 사례에 따르면 “클라이언트가 /token/generate-token으로 자격증명을 전송하면, 인증 서비스는 이를 검증하고 사용자 정보와 권한을 담은 JWT를 생성하여 응답”한다고 합니다. JWT에는 사용자 ID, 권한(role) 등의 클레임과 함께 만료시간(exp)이 포함됩니다. 발급된 토큰은 클라이언트가 이후 요청 시 Authorization 헤더에 담아 전송하며, API Gateway 또는 각 서비스에서 서명을 검증하고 인가를 수행합니다. 만약 액세스 토큰(access token)이 만료되면, **리프레시 토큰(refresh token)**을 통해 새로운 액세스 토큰을 발급받을 수 있습니다. 예를 들어 Refresh Token을 같이 발급하여 Access Token은 510분 정도 짧게, Refresh Token은 1224시간 정도로 길게 설정하는 방식이 일반적입니다. 이를 통해 JWT 탈취 시 피해를 제한하고, 만료된 토큰에 대해서는 재발급 절차로 보완할 수 있습니다.
Service Discovery 도구 및 설정 예 (Eureka, Consul 등)
마이크로서비스 간 통신을 위해서는 서비스 디스커버리가 필요합니다. Spring Cloud에서는 Netflix Eureka나 HashiCorp Consul을 많이 사용합니다. 예를 들어 Eureka를 사용할 경우, 별도 Spring Boot 프로젝트에 @EnableEurekaServer를 붙여 Eureka 서버를 띄우고 서비스들은 @EnableDiscoveryClient와 함께 spring-cloud-starter-netflix-eureka-client를 추가하여 본인 정보를 Eureka 서버에 등록합니다. Xoriant 사례에서 보여주듯이, Eureka 서버를 실행하면 기본 포트 8761에서 대시보드가 나타나고, 각 서비스가 등록되는 것을 확인할 수 있습니다. Consul을 사용할 경우 spring-cloud-starter-consul-discovery 의존성을 추가하고, spring.cloud.consul.host 등 설정을 통해 Consul 에이전트에 서비스 정보를 등록합니다. (참고로 쿠버네티스 자체적으로는 서비스 DNS를 통한 기본 디스커버리를 제공하므로, 별도의 Eureka/Consul 없이도 클러스터 내 통신이 가능합니다.)
Kubernetes 배포 전략 및 구성 (Helm, ConfigMap, Secret 등)
MSA 서비스를 쿠버네티스에 배포할 때는 각 마이크로서비스를 컨테이너화하여 Deployment, Service 등의 리소스로 관리합니다. 일반적으로 Deployment의 롤링 업데이트 전략(기본값)으로 무중단 배포를 수행하며, 필요하면 Canary 배포나 Blue-Green 전략으로 확장할 수 있습니다. 헬름(Helm) 차트를 사용하면 이러한 k8s 리소스 정의를 템플릿화하여 버전 관리할 수 있습니다. 예를 들어 helm create로 차트 스캐폴딩을 생성하고, values.yaml에서 환경별 설정을 관리하며, templates/에 Deployment, Service, Ingress 등을 정의합니다.
설정 관리 측면에서는 ConfigMap과 Secret을 활용합니다. ConfigMap에는 비민감 환경변수(예: 로그 레벨, 일반 설정값)를 저장하고, Secret에는 데이터베이스 암호, JWT 서명키 등 민감 정보를 저장합니다. Pod 템플릿에서 환경변수나 파일로 ConfigMap/Secret을 참조하도록 하면, 애플리케이션 코드를 재빌드하지 않고도 설정을 주입할 수 있습니다. 예를 들어 Secret을 kubectl create secret generic로 생성한 후, Deployment 매니페스트에 env.valueFrom.secretKeyRef로 참조하여 주입할 수 있습니다. 이렇게 하면 보안성을 유지하면서 운영환경 설정을 관리할 수 있습니다.
공통 모듈 및 설정 공유 방안
분산 시스템에서는 여러 서비스가 공유하는 코드나 설정을 중앙에서 관리하면 효율적입니다. 공통 코드(인증 유틸, 예외 처리기, DTO 등)는 별도의 라이브러리 모듈로 분리하여 Git/Maven에서 의존성으로 가져오도록 합니다. 예를 들어 앞서 언급한 사례에서는 shboard-common 모듈을 두어 인증 및 전역 예외 처리 코드를 공유하였습니다.
공통 설정을 위해서는 Spring Cloud Config Server를 도입할 수 있습니다. Config Server는 Git, 로컬 파일시스템, Vault 등의 저장소를 백엔드로 사용하여 모든 서비스의 application.yml 설정을 중앙 저장소에서 관리하도록 지원합니다. 이를 통해 여러 서비스가 동일한 속성을 공유할 수 있으며, 중앙 저장소의 설정만 변경하면 모든 서비스에 자동으로 반영됩니다. Spring Cloud Config를 사용하면 설정 변경 시 서비스 재배포 없이도 설정을 업데이트할 수 있고, 민감 정보도 Vault 연동으로 안전하게 관리할 수 있습니다.
- Total
- Today
- Yesterday
- Stack Area
- First-class citizen
- generated_body()
- MCP
- 언리얼엔진
- 타입 안전성
- method Area
- 도커
- 자바
- springai
- JAVA 프로그래밍
- cqrs
- 카프카 개념
- RESTfull
- react.js
- redis
- JVM
- 코틀린
- 코프링
- 스브링부트
- 언리얼엔진5
- unreal engjin
- 스프링부트
- ai통합
- model context protocol
- 일급 객체
- 디자인패턴
- Java
- vite
- Heap Area
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |