[MSA] 기본 서버 구축하기

Hinolog·2025년 5월 14일

MSA

목록 보기
3/5

📚 목차

  1. Eureka Server 구축
  2. Config Server 구축 (Local Native 모드)
  3. API Gateway 구축
  4. 구축 흐름 요약 및 주요 설정 체크리스트
  5. 추가 고민거리: 고가용성(HA), Failover 설계
  6. 최신 기술 대안 검토
  7. 마무리 및 실습 느낀 점

1. Eureka Server 구축


1.1 Eureka Server란?

Eureka Server는 Netflix OSS에서 제공하는 서비스 디스커버리 서버이다.
MSA에서는 각각의 서비스가 독립적으로 배포되기 때문에,
고정된 IP와 포트로 통신하는 것이 불가능하다.

Eureka Server의 역할

  • 모든 서비스가 자신의 정보를 Eureka에 등록한다.
  • 각 서비스는 다른 서비스의 위치를 Eureka를 통해 조회한다.

요약

Eureka는 MSA 환경에서 서비스 간 동적 통신을 가능하게 만드는 핵심 인프라다.


1.2 Eureka Server 구축 방법

1) 의존성 추가

build.gradle

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
}

spring-boot-starter-web + spring-cloud-starter-netflix-eureka-server를 추가한다.


2) 메인 클래스 수정

EurekaServerApplication.java

@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

@EnableEurekaServer 어노테이션이 반드시 필요하다. (이게 있어야 서버로 동작함)


3) application.yml 설정

application.yml

server:
  port: 8761

spring:
  application:
    name: eureka-server

eureka:
  client:
    register-with-eureka: false  # 자기 자신은 등록할 필요 없음
    fetch-registry: false        # 다른 레지스트리에서 목록 가져올 필요 없음

설명

  • register-with-eureka: false
    • 자기 자신(Eureka 서버)을 또 Eureka에 등록할 필요 없다.
  • fetch-registry: false
    • 다른 Eureka 서버에서 등록된 목록을 가져올 필요 없다.

1.3 실행 및 확인

  1. 서버를 실행한다.
  2. 브라우저에서 http://localhost:8761로 접속한다.
  3. 정상적으로 Eureka Dashboard 화면이 뜨면 성공!

초기 화면 특징

  • 등록된 인스턴스가 없기 때문에
    "NO INSTANCES AVAILABLE" 메시지가 보인다.
  • 다른 서비스들이 등록되기 시작하면 목록에 나타난다.

1.4 Eureka Server 구축 시 주의할 점

포인트이유
@EnableEurekaServer 반드시 추가안 넣으면 그냥 웹 서버만 띄워짐
포트 중복 주의 (8761)기존 서비스랑 충돌 가능성
Spring Cloud 버전 호환성 주의Spring Boot 3.4.4 기준, 최신 Spring Cloud 2023.x 사용
등록/탐색 설정 명확히 구분(register/fetch 둘 다 false 설정 필요)

Eureka Server 구축 정리

Eureka Server는 MSA 환경에서 서비스들의 "주소록" 같은 역할을 한다.
이를 통해 서비스들은 동적으로 서로를 찾고 통신할 수 있다.


2. Config Server 구축 (Local Native 모드)


2.1 Config Server란?

Config Server는 여러 마이크로서비스의 설정 파일을 중앙 집중식으로 관리하는 서버다.
MSA 환경에서는 수십 개, 수백 개의 서비스가 각각 다른 설정을 필요로 하므로,
각 서비스가 따로 설정 파일을 관리하면 유지보수가 거의 불가능해진다.

Config Server를 사용하면

  • 하나의 중앙 서버가 모든 서비스 설정을 관리
  • 변경 시 즉시 반영 가능
  • 일관된 설정 버전 관리 가능

2.2 Config Server 구축 방법

1) 의존성 추가

build.gradle

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.cloud:spring-cloud-config-server'
}

spring-cloud-config-server 의존성만 추가하면 된다.


2) 메인 클래스 수정

ConfigServerApplication.java

@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}

@EnableConfigServer 어노테이션이 있어야 Config Server로 동작한다.


3) application.yml 설정

application.yml

spring:
  profiles:
    active: native  # native 모드: 로컬 디렉토리에서 설정 읽음

  application:
    name: config-service

  cloud:
    config:
      server:
        native:
          search-locations: classpath:/configurations  # classpath 안의 configurations 폴더 참조
      override-system-properties: false  # 시스템 프로퍼티 덮어쓰기 방지

server:
  port: 8888

management:
  endpoints:
    web:
      exposure:
        include: health,info,env  # Actuator로 health, info, env 엔드포인트 노출
  endpoint:
    health:
      show-details: always  # health 상태 세부정보 항상 보여주기

logging:
  level:
    org.springframework.cloud.config.server: INFO

요약

  • native 모드로 Git이 아닌 로컬 디렉토리를 사용.
  • /resources/configurations/ 폴더 안에 서비스별 설정 파일(application-service.yml)을 관리.
  • Actuator를 통해 서버 상태를 모니터링할 수 있도록 설정.

2.3 Config Server 경로 설정 옵션

Config Server의 search-locations 속성은 설정 파일을 어디서 찾을지 지정합니다. 여기서는 classpath:/configurations를 사용했지만, 프로젝트 구성에 따라 다양한 경로 옵션이 가능합니다:

spring:
  cloud:
    config:
      server:
        native:
          search-locations:
            - classpath:/configurations  # JAR 내부 경로
            - file:./config              # 현재 실행 디렉토리의 config 폴더
            - file:/opt/config           # 절대 경로
            - file:${user.home}/config   # 사용자 홈 디렉토리

각 옵션별 특징:

  • classpath:/path: JAR 내부 경로 (개발 환경에 적합)
  • file:./path: 상대 경로 (개발/테스트 환경에 유연함)
  • file:/absolute/path: 절대 경로 (운영 환경에 적합)

실무 팁: 개발 환경에서는 classpath:/configurations를, 운영 환경에서는 외부 파일 시스템 경로를 사용하는 것이 일반적입니다. 컨테이너 환경(Docker)에서는 볼륨 마운트와 함께 파일 경로를 사용하면 설정 변경이 용이합니다.


2.4 디렉토리 구조

src/
└── main/
    └── resources/
        └── configurations/
            ├── application.yml
            ├── user-service.yml
            ├── auth-service.yml
            └── ...

각 서비스별로 설정 파일을 따로 관리한다.


2.5 실행 및 확인

  1. 서버를 실행한다.
  2. 브라우저에서 다음 URL로 설정 확인 가능:
    • http://localhost:8888/application/default
    • http://localhost:8888/user-service/default
    • http://localhost:8888/auth-service/default
  3. JSON 형식으로 설정 내용이 정상 반환되면 성공!

Tip:
로컬 설정을 잘못 읽으면 404 오류가 발생한다. 디렉토리 경로와 파일명을 꼭 확인하자.


2.6 Config Server 구축 시 주의할 점

포인트이유
native 모드 설정 (active: native)Git 설정과 혼동하지 말 것
search-locations 경로 정확히 작성classpath:/configurations ← 정확하게 써야 함
Actuator 엔드포인트 노출 확인상태 모니터링에 필요 (health, env 등)
로컬 환경과 운영 환경 구분 필요이후 Git 연동으로 전환 고려

Config Server 구축 정리

Config Server는 MSA에서 서비스 설정을 통합 관리하고,
native 모드를 통해 빠른 개발 환경 세팅이 가능하다.
(운영 전환 시 Git 연동 권장)


3. API Gateway 구축


3.1 API Gateway란?

API Gateway는 클라이언트 요청을 받아, 적절한 서비스로 전달하고 응답을 반환하는 유일한 진입점(Entry Point) 역할을 한다.
MSA에서는 수많은 마이크로서비스가 존재하므로,
클라이언트가 직접 각각의 서비스를 호출하게 하면 관리가 불가능하다.

API Gateway가 필요한 이유:

  • 요청 경로를 통합 관리할 수 있다.
  • 인증, 인가, 로깅, 트래픽 제어 등 공통 기능을 처리할 수 있다.
  • 외부에 노출되는 API 경로를 단순화할 수 있다.

3.2 API Gateway 구축 방법

1) 의존성 추가

build.gradle

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-webflux'
    implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
    implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
}

설명

  • spring-cloud-starter-gateway: API Gateway 핵심 기능 제공
  • spring-boot-starter-webflux: 비동기 서버 기반 (WebFlux) 필요
  • spring-cloud-starter-netflix-eureka-client: Eureka를 통한 서비스 검색 기능 사용

3.3 Spring Cloud Gateway와 WebFlux

Spring Cloud Gateway는 비동기, 논블로킹 방식으로 동작하는 API Gateway 서비스입니다. 이런 특성은 Spring WebFlux 기반으로 구현되었기 때문에 가능합니다.

WebFlux의 핵심 특징

  1. 비동기(Asynchronous) 처리

    • 요청 처리 시 블로킹 되지 않고 다른 요청을 계속 처리
    • Mono<T>, Flux<T> 타입을 반환하여 리액티브 스트림 지원
  2. 논블로킹(Non-blocking) I/O

    • 전통적인 서블릿 기반 방식과 달리 I/O 작업에서 스레드 블로킹이 없음
    • 적은 수의 스레드로 많은 요청 처리 가능
  3. 높은 확장성

    • 동시 접속자가 많은 경우 전통적인 MVC보다 효율적
    • 메모리 사용량이 적고 CPU 효율이 높음

Gateway에서의 활용

@Component
public class CustomGlobalFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 비동기 처리
        return chain.filter(exchange)
                .doOnSuccess(v -> {
                    // 응답 성공 후 처리
                })
                .doOnError(e -> {
                    // 오류 처리
                });
    }
}

2) application.yml 설정

application.yml

server:
  port: 8080

spring:
  application:
    name: api-gateway

  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service  # Eureka에 등록된 서비스 이름
          predicates:
            - Path=/user/**

        - id: auth-service
          uri: lb://auth-service
          predicates:
            - Path=/auth/**

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

요약

  • /user/** 요청은 user-service
  • /auth/** 요청은 auth-service
  • lb://Load Balancer를 의미하며, Eureka에 등록된 서비스 이름 기준으로 라우팅한다.

3) 기본 라우팅 동작 흐름

[Client] 
    ↓
[API Gateway] 
    ↓
[등록된 서비스 (User, Auth 등)]
  • 클라이언트는 Gateway 하나만 호출한다.
  • Gateway는 경로를 기준으로 각 서비스로 요청을 전달한다.
  • 모든 서비스는 Eureka에 등록되어 있어야 Gateway가 인식할 수 있다.

3.4 실행 및 확인

  1. Gateway 서버를 실행한다.
  2. 브라우저 또는 Postman으로 요청을 보낸다:
    • http://localhost:8080/user/hello
    • http://localhost:8080/auth/login
  3. 각각 user-service, auth-service로 연결되는지 확인한다.

Tip:
Eureka Server 대시보드에서도 Gateway가 api-gateway로 정상 등록되는지 확인할 수 있다.


3.5 Gateway 구축 시 주의할 점

포인트이유
경로(Path) 패턴 정확히 설정잘못 설정하면 요청이 안 넘어간다
Eureka 등록 필수Gateway는 서비스 이름 기반으로 라우팅한다
lb:// 프로토콜 사용LoadBalancerClient를 통해 Eureka와 통신
webflux 기반 서버Gateway는 기본적으로 WebFlux 위에서 동작한다

API Gateway 구축 정리

API Gateway는 클라이언트와 각 서비스를 중계하며,
요청 경로를 제어하고 시스템 진입을 일원화하는 핵심 컴포넌트다.


4. 구축 흐름 요약 및 주요 설정 체크리스트


4.1 전체 구축 흐름 요약

MSA 기본 인프라 구축은 다음 순서로 진행된다.


1) Config Server 구축

  • 역할: 모든 서비스의 설정 파일을 중앙 집중화해서 관리한다.
  • 주요 포인트:
    • native 모드(spring.profiles.active=native) 사용
    • classpath:/configurations 디렉토리에서 설정 파일 제공
    • 서비스별 application-서비스이름.yml 파일 작성

2) Eureka Server 구축

  • 역할: 서비스 디스커버리를 담당한다.
    (서비스 등록, 서비스 탐색)
  • 주요 포인트:
    • @EnableEurekaServer 추가
    • 포트는 기본 8761 사용
    • register-with-eureka: false, fetch-registry: false 설정

3) API Gateway 구축

  • 역할: 클라이언트 요청을 받아 적절한 서비스로 라우팅한다.
  • 주요 포인트:
    • spring-cloud-starter-gateway 사용
    • spring-cloud-starter-netflix-eureka-client 연동
    • 경로(Path) 패턴에 따라 서비스 분기 처리
    • lb://서비스이름 사용해 Eureka 기반 라우팅

4) 마이크로서비스 (예: User-Service, Auth-Service) 구축

  • 역할: 실제 비즈니스 로직 담당
  • 주요 포인트:
    • Config Server를 통해 설정 수신
    • Eureka에 서비스 등록
    • Gateway를 통해 외부 요청을 수신

전체 흐름

[Client]
    ↓
[API Gateway] --(Service Discovery)--> [Eureka Server]
    ↓
[Routed to...]
    ↓
[User-Service] ← Config from Config Server
[Auth-Service] ← Config from Config Server
...
  • 클라이언트는 Gateway만 알고 요청한다.
  • Gateway는 Eureka를 통해 대상 서비스를 찾는다.
  • 서비스는 Config Server에서 설정을 가져와 부팅된다.

4.2 주요 설정 체크리스트

체크 항목설명
Config Server native 설정 적용Git이 아닌 로컬 디렉토리 사용 (classpath:/configurations)
Config Server actuator 노출 설정health, info, env 확인 가능해야 함
Eureka Server에 @EnableEurekaServer 적용메인 클래스에 붙였는지 확인
Eureka Server 포트 충돌 없음기본 8761 사용, 충돌 여부 확인
Gateway lb://서비스이름으로 라우팅 설정경로와 서비스 이름 정확히 매칭
모든 서비스가 Eureka에 정상 등록Eureka 대시보드에서 확인
모든 서비스가 Config Server에서 설정 로딩서버 부팅 시 Config Server 호출 성공 여부 확인

요약

Config Server → Eureka Server → API Gateway → 각 마이크로서비스
이 순서로 인프라를 깔끔하게 연결해야
MSA 기본 뼈대가 제대로 구축된다.


5. 추가 고민거리: 고가용성(HA), Failover 설계


5.1 왜 운영 환경에서는 추가 고민이 필요한가?

지금까지 구축한 MSA 기본 인프라는 개발/테스트 환경에서는 충분히 잘 동작한다.
하지만 실제 운영(Production) 환경에서는 단순 구축만으로는 부족하다.

운영 환경에서는 이런 상황이 생긴다:

  • Eureka Server 다운 → 모든 서비스 디스커버리 불가
  • Config Server 장애 → 서비스 설정 로드 실패
  • Gateway 다운 → 모든 클라이언트 요청 실패

즉, 하나라도 서버가 죽으면 전체 시스템이 흔들린다.

그래서 HA (High Availability)Failover 설계를 추가로 고려해야 한다.


5.2 Eureka Server HA 구성

Eureka 단일 구성의 문제점

  • 단일 서버에 장애가 나면 모든 서비스 디스커버리가 중단된다.

Eureka 다중 인스턴스(Replication) 구성

방법 요약

  • Eureka Server를 최소 2대 이상 띄운다.
  • 서로를 service-url에 등록해서 복제(replication)하게 만든다.

application.yml 예시 (Eureka Server 1)

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:8762/eureka/

application.yml 예시 (Eureka Server 2)

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:8761/eureka/

즉, 서로를 등록하고, 서비스 목록을 공유(sync)한다.


5.3 Config Server Failover 고려

Config 단일 서버의 문제점

  • Config Server가 죽으면 서비스 설정을 못 불러오고 부팅 실패.

Failover 방법

  • Config Server도 다중 인스턴스로 구성하거나
  • Config Server를 두고 Load Balancer로 묶는다.
  • Spring Cloud Config Client 쪽에서도 다중 URI를 설정할 수 있다.

예시: 서비스에서 설정

spring:
  config:
    import: configserver:http://config1:8888,http://config2:8888

Config Server가 죽어도 다른 서버로 fallback 가능하게 만든다.


5.4 API Gateway 확장

Gateway 단일 서버 문제점

  • Gateway 서버가 죽으면 전체 외부 요청이 막힌다.

확장 방법

  • Gateway 서버를 여러 대 띄운다.
  • Load Balancer로 트래픽을 분산시킨다.
  • 무중단 배포(Blue-Green Deployment) 같은 전략도 함께 고려한다.

API Gateway도 반드시 다중화하고 부하 분산해야 한다.


5.5 추가 고려 사항 요약

항목고가용성(HA) 전략비고
Eureka Server다중 인스턴스 구성 + 상호 복제 설정최소 2대 이상 권장
Config Server다중 인스턴스 + Client Failover URI 설정안정성 향상
API Gateway다중 인스턴스 + LoadBalancer 앞단 구성필수 구성

MSA는 기본 구축 후에도 운영 환경에 맞춘 견고한 아키텍처 설계가 필요하다.


6. 최신 기술 대안 검토


6.1 서비스 디스커버리 대안

Netflix Eureka는 널리 사용되는 서비스 디스커버리 솔루션이지만, 대안 기술들도 검토해볼 가치가 있습니다.

HashiCorp Consul

Consul은 서비스 디스커버리와 함께 분산 구성 관리 기능을 제공합니다.

장점:

  • 경량 DNS 인터페이스 지원
  • 강력한 건강 체크 기능
  • Key-Value 저장소 내장
  • 다중 데이터 센터 지원

Kubernetes Service Discovery

컨테이너 오케스트레이션 플랫폼인 Kubernetes를 사용하는 경우, 내장된 서비스 디스커버리 기능을 활용할 수 있습니다.

장점:

  • 네이티브 DNS 기반 서비스 검색
  • 자동 로드 밸런싱
  • 자동 헬스 체크 및 복구
  • 확장성이 뛰어남

6.2 설정 관리 대안

Spring Cloud Config Server 외에도 다양한 설정 관리 솔루션이 있습니다.

HashiCorp Vault

Vault는 민감한 정보(비밀번호, API 키 등)의 안전한 저장 및 접근 관리에 특화되어 있습니다.

장점:

  • 강력한 보안 기능
  • 동적 시크릿 생성
  • 암호화 서비스 제공
  • 세분화된 접근 제어

Apollo (Ctrip)

Apollo는 중국의 Ctrip에서 개발한 분산 설정 관리 시스템으로, 실시간 설정 변경 전파와 강력한 관리 기능을 제공합니다.

장점:

  • 멀티 환경/클러스터 지원
  • 설정 변경 시 실시간 푸시
  • 완전한 변경 이력 관리
  • 웹 기반 관리 콘솔

6.3 API Gateway 대안

Spring Cloud Gateway 외에도 다양한 API Gateway 솔루션이 있습니다.

Netflix Zuul

Netflix의 Zuul은 Spring 생태계에서 오랫동안 사용되어 온 API Gateway입니다.

특징:

  • 서블릿 기반 (동기식)
  • 필터 체인 아키텍처
  • 안정성 검증됨
  • Spring Cloud Gateway보다 오래됨

참고: Zuul 1.x는 Netflix에서 더 이상 적극적으로 개발하지 않고 있으며, Spring Cloud Gateway로의 마이그레이션이 권장됩니다.


Kong Gateway

Kong은 Lua 기반의 확장 가능한 API Gateway입니다.

장점:

  • 높은 성능 (Nginx 기반)
  • 풍부한 플러그인 생태계
  • Kubernetes 네이티브 지원
  • 상업/오픈소스 버전 모두 제공

6.4 대안 기술 선택 기준

MSA 인프라 구축 시 대안 기술을 선택할 때는 다음 기준을 고려하세요:

기준설명
운영 환경Kubernetes 환경이라면 K8s 네이티브 솔루션 고려
팀 역량팀이 이미 익숙한 기술 스택 우선
확장성 요구대규모 서비스는 더 확장성 높은 솔루션 필요
보안 요구사항금융/의료 등 보안이 중요한 도메인은 Vault 같은 솔루션 고려
생태계 연동기존 모니터링/로깅 시스템과의 통합 용이성

7. 마무리 및 실습 느낀 점


7.1 실습을 통해 얻은 것

이번 실습에서는 단순히 서비스를 쪼개는 것만으로는 MSA가 완성되지 않는다는 것을 체감했다.
Config Server, Eureka Server, API Gateway라는 인프라 서버들이 있어야
진짜로 서비스들이 "제대로 연결되고 관리"될 수 있다는 것을 명확히 이해했다.

핵심 배운 점 3가지

  • 단순 분산이 아니라, 서비스 간 연결과 설정 체계가 핵심이다.
  • MSA는 독립성 + 연결성을 모두 고려해야 한다.
  • 인프라 서버 자체도 장애를 대비해 고가용성을 설계해야 한다.

7.2 실습하면서 느낀 어려움

  • Config Server 설정 경로 실수(native 모드 설정 경로 classpath:/configurations) → 애초에 서버가 안 떠버림
  • Eureka Server 포트 중복 실수 → 서버 띄울 때 충돌
  • Gateway 경로(Path) 오타 → 라우팅 실패 및 404 에러

7.3 개인적으로 가장 크게 느낀 것

MSA를 구축하는 것은 생각보다 단순한 작업이 아니다.
기본 인프라 서버를 준비하는 것부터
서비스 간 통신, 장애 대비 구조까지 전부 설계해야
비로소 "운영 가능한" 시스템이 된다는 것을 배웠다.

또한,
이번 실습을 통해 Spring Cloud의 편리함을 느끼면서도,
"편리함" 이면에 숨어 있는 "구조적 복잡성"도 분명히 존재한다는 것을 경험했다.


요약

MSA는 단순히 기술을 배우는 게 아니라,
서비스를 어떻게 관리하고 연결할지에 대한 깊은 고민이 필요한 아키텍처다.


0개의 댓글