1차 목표인 기능 구현을 마치고 이번엔 MSA의 핵심인 서비스 디스커버리와 API Gateway를 구성했다. Eureka Server로 서비스를 등록하고 Spring Cloud Gateway로 단일 진입점을 만드는 것이 목표였다.
Eureka Server 구성
Eureka Server는 각 마이크로서비스의 위치를 관리하는 서비스 레지스트리다. 서비스가 실행되면 자동으로 Eureka에 등록되고, Gateway는 Eureka를 통해 서비스의 위치를 찾아 라우팅한다.
eureka-server 모듈을 새로 만들고 의존성을 추가했다.
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
}
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
server:
port: 8761
spring:
application:
name: eureka-server
eureka:
client:
register-with-eureka: false
fetch-registry: false
register-with-eureka: false 와 fetch-registry: false 는 Eureka Server 자체는 레지스트리에 등록하지 않겠다는 설정이다.
각 서비스 Eureka Client 등록
기존 4개 서비스에 Eureka Client 의존성을 추가하고 application.yml 에 Eureka 서버 주소를 등록했다.
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
서비스를 실행하면 localhost:8761 Eureka 대시보드에서 등록된 서비스를 확인할 수 있다.
Spring Cloud Gateway 구성
Gateway는 모든 요청의 단일 진입점 역할을 한다. 클라이언트는 각 서비스의 포트를 알 필요 없이 8080 포트 하나로만 통신하면 된다.
gateway-service 모듈을 새로 만들고 의존성을 추가했다.
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-gateway-server-webflux'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
}
라우팅 설정은 application.yml 에서 관리한다. lb:// 는 Eureka를 통해 서비스를 로드밸런싱한다는 의미다.
spring:
application:
name: gateway-service
cloud:
gateway:
server:
webflux:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/users/**
- id: product-service
uri: lb://product-service
predicates:
- Path=/products/**
- id: order-service
uri: lb://order-service
predicates:
- Path=/orders/**
Feign Client — 서비스 간 통신
주문 생성 시 product-service에 재고 차감 요청을 보내야 한다. Feign Client를 사용하면 마치 로컬 메서드를 호출하듯 다른 서비스의 API를 호출할 수 있다.
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
@FeignClient(name = "product-service")
public interface ProductClient {
@PostMapping("/products/{id}/stock/decrease")
void decreaseStock(@PathVariable UUID id, @RequestBody StockRequest request);
}
@EnableFeignClients 를 Application 클래스에 추가하고, OrderService에서 ProductClient를 주입받아 사용했다.
주문 생성 시 흐름:
POST /orders → order-service → Feign Client → product-service 재고 차감
실제로 재고가 10에서 8로 줄어드는 것을 확인했다.
서비스 실행 순서
MSA에서는 서비스 실행 순서가 중요하다.
1. Eureka Server
2. 각 마이크로서비스 (user, product, order)
3. Gateway (마지막)
Gateway가 먼저 실행되면 Eureka에 등록된 서비스가 없어서 라우팅에 실패한다.
'Spring 개발일지' 카테고리의 다른 글
| [개인 프로젝트] Notification Service + Slack 알림 연동 (0) | 2026.04.14 |
|---|---|
| [개인 프로젝트] JWT 기반 인증 구현 — Gateway에서 토큰 검증하기 (0) | 2026.04.13 |
| [개인 프로젝트] Spring Boot MSA 프로젝트 구조 설계 및 기능 구현 (0) | 2026.04.11 |
| [대규모 AI 시스템 프로젝트] 트러블슈팅(2) + 발표자료 준비 (0) | 2026.04.10 |
| [대규모 AI 시스템 프로젝트] 추가 리팩토링 상황 (0) | 2026.04.09 |