본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 21. · 4 Views
Netflix Eureka 서비스 디스커버리 완벽 가이드
MSA 환경에서 수많은 마이크로서비스들이 서로를 어떻게 찾고 통신할까요? Netflix Eureka는 이 문제를 해결하는 강력한 서비스 디스커버리 도구입니다. 초급 개발자도 쉽게 이해할 수 있도록 실무 중심으로 설명합니다.
목차
1. 서비스 디스커버리란?
입사 6개월 차 주니어 개발자 김개발 씨는 오늘도 열심히 코드를 작성하고 있었습니다. 회사가 최근 모놀리식 아키텍처에서 마이크로서비스로 전환하면서 갑자기 관리해야 할 서비스가 10개가 넘어갔습니다.
"주문 서비스가 회원 서비스를 호출하려면 IP 주소를 어떻게 알아야 하지?" 김개발 씨는 고민에 빠졌습니다.
서비스 디스커버리는 마이크로서비스 아키텍처에서 각 서비스의 위치 정보를 자동으로 관리하고 찾아주는 메커니즘입니다. 마치 전화번호부처럼 "주문 서비스야, 회원 서비스 어디 있어?"라고 물으면 정확한 주소를 알려주는 것과 같습니다.
Netflix Eureka는 이런 서비스 디스커버리 기능을 제공하는 대표적인 오픈소스 도구입니다.
다음 코드를 살펴봅시다.
// 전통적인 방식: 하드코딩된 IP 주소 (문제가 많음)
public class OrderService {
private static final String MEMBER_SERVICE_URL = "http://192.168.0.10:8080";
public Member getMember(Long memberId) {
// IP가 바뀌면? 서버가 여러 대면? 장애 발생하면?
RestTemplate restTemplate = new RestTemplate();
return restTemplate.getForObject(
MEMBER_SERVICE_URL + "/members/" + memberId,
Member.class
);
}
}
김개발 씨는 선배 개발자 박시니어 씨에게 조심스럽게 질문했습니다. "선배님, 주문 서비스에서 회원 서비스를 호출하려면 IP 주소를 코드에 직접 써야 하나요?" 박시니어 씨는 미소를 지으며 대답했습니다.
"좋은 질문이네요. 그렇게 하면 큰 문제가 생길 수 있어요." 하드코딩의 문제점 옛날 모놀리식 시스템에서는 모든 기능이 하나의 애플리케이션 안에 있었습니다.
회원 관리도, 주문 처리도, 결제도 모두 한 곳에서 처리했죠. 하지만 마이크로서비스로 전환하면서 상황이 완전히 달라졌습니다.
주문 서비스가 회원 정보를 조회하려면 네트워크를 통해 회원 서비스를 호출해야 합니다. 가장 단순한 방법은 IP 주소를 코드에 직접 작성하는 것입니다.
"192.168.0.10:8080으로 요청을 보내면 되겠지?" 하지만 이 방식에는 치명적인 문제가 있습니다. 서버를 재배포하면서 IP가 바뀌면 어떻게 될까요?
부하 분산을 위해 회원 서비스를 3대로 늘리면? 한 서버에서 장애가 발생하면?
전화번호부의 비유 서비스 디스커버리를 이해하는 가장 쉬운 방법은 전화번호부를 떠올리는 것입니다. 옛날에는 친구의 전화번호를 외우거나 수첩에 적어뒀습니다.
친구가 번호를 바꾸면? 일일이 수정해야 했죠.
하지만 요즘은 스마트폰 주소록이 있습니다. "김철수"라는 이름만 알면 번호가 바뀌어도 자동으로 연결됩니다.
서비스 디스커버리도 똑같습니다. "회원 서비스"라는 이름만 알면, IP가 바뀌든 서버가 늘어나든 자동으로 올바른 주소를 찾아줍니다.
마이크로서비스의 도전 과제 김개발 씨가 일하는 회사의 시스템은 현재 15개의 마이크로서비스로 구성되어 있습니다. 회원, 주문, 결제, 상품, 재고, 배송, 알림, 리뷰, 쿠폰, 포인트...
목록은 계속 늘어갑니다. 각 서비스는 서로를 호출합니다.
주문 서비스는 회원, 상품, 재고, 결제 서비스를 호출합니다. 만약 모든 IP 주소를 하드코딩한다면?
악몽이 시작됩니다. 게다가 클라우드 환경에서는 서버가 자동으로 생성되고 삭제됩니다.
오토스케일링으로 트래픽이 많을 때 서버가 10대로 늘어났다가, 새벽에는 2대로 줄어듭니다. IP 주소는 계속 바뀝니다.
Netflix Eureka의 등장 바로 이런 문제를 해결하기 위해 Netflix Eureka가 등장했습니다. Netflix는 수천 개의 마이크로서비스를 운영하면서 이 문제를 가장 먼저 경험한 회사입니다.
그들이 만든 해결책이 바로 Eureka입니다. 이후 오픈소스로 공개되어 전 세계 개발자들이 사용하고 있습니다.
Eureka의 동작 원리는 간단합니다. 중앙에 Eureka Server라는 레지스트리가 있습니다.
각 마이크로서비스는 시작할 때 자신의 정보를 Eureka Server에 등록합니다. "나는 회원 서비스이고, 192.168.0.10:8080에서 실행 중이야." 다른 서비스가 회원 서비스를 호출하려면 Eureka Server에 물어봅니다.
"회원 서비스 어디 있어?" Eureka는 등록된 정보를 조회해서 알려줍니다. "192.168.0.10:8080로 가세요." 동적인 환경 대응 더 놀라운 점은 동적으로 변화하는 환경에 자동으로 대응한다는 것입니다.
회원 서비스가 재배포되어 IP가 192.168.0.20으로 바뀌었습니다. 문제없습니다.
서비스가 시작하면서 새로운 IP를 Eureka에 재등록합니다. 다른 서비스들은 코드 수정 없이 새로운 주소로 호출합니다.
트래픽이 급증해서 회원 서비스를 3대로 늘렸습니다. 역시 문제없습니다.
3대 모두 Eureka에 등록되고, Eureka는 로드밸런싱까지 자동으로 처리합니다. 한 서버에서 장애가 발생했습니다.
Eureka는 헬스 체크를 통해 죽은 서버를 감지하고, 목록에서 제거합니다. 트래픽은 정상 서버로만 전달됩니다.
개발자의 삶이 편해진다 박시니어 씨가 설명을 마무리했습니다. "Eureka를 사용하면 IP 주소는 신경 쓸 필요가 없어요.
서비스 이름만 알면 됩니다. 나머지는 Eureka가 알아서 처리해줍니다." 김개발 씨는 눈이 반짝였습니다.
"와, 정말 편리하네요!" 서비스 디스커버리는 마이크로서비스 아키텍처의 핵심 패턴 중 하나입니다. Netflix, Amazon, Uber 같은 글로벌 기업들이 모두 사용하는 검증된 방법입니다.
여러분도 Eureka를 마스터하면 진정한 MSA 개발자로 성장할 수 있습니다.
실전 팁
💡 - 서비스 디스커버리는 MSA 환경에서 필수입니다. IP 주소를 하드코딩하는 것은 절대 피하세요.
- Eureka 외에도 Consul, Zookeeper 등 다른 서비스 디스커버리 도구들도 있습니다만, Spring Cloud와는 Eureka가 가장 잘 통합됩니다.
2. Eureka Server 설정
김개발 씨는 이제 Eureka의 개념을 이해했습니다. "좋아, 그럼 실제로 어떻게 만드는 거지?" 박시니어 씨는 노트북을 열며 말했습니다.
"생각보다 훨씬 간단해요. Spring Boot와 함께 사용하면 설정 몇 줄이면 끝납니다."
Eureka Server는 모든 마이크로서비스의 정보를 저장하고 관리하는 중앙 레지스트리입니다. Spring Cloud Netflix는 Eureka Server를 매우 간단하게 구성할 수 있도록 @EnableEurekaServer 어노테이션을 제공합니다.
의존성을 추가하고 어노테이션 하나만 붙이면 Eureka Server가 완성됩니다.
다음 코드를 살펴봅시다.
// pom.xml에 의존성 추가
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
// EurekaServerApplication.java - 메인 클래스
package com.example.eurekaserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer // 이 한 줄로 Eureka Server 활성화!
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
김개발 씨는 박시니어 씨의 화면을 보며 놀랐습니다. "이게 전부예요?
이렇게 간단하다고요?" "맞아요. Spring Cloud의 장점이 바로 이거예요.
복잡한 설정 없이도 엔터프라이즈급 기능을 사용할 수 있죠." Maven 의존성 추가 가장 먼저 할 일은 Eureka Server 라이브러리를 프로젝트에 추가하는 것입니다. Maven을 사용한다면 pom.xml에 의존성을 추가합니다.
Gradle을 사용한다면 build.gradle에 추가하면 됩니다. spring-cloud-starter-netflix-eureka-server라는 이름이 조금 깁니다.
하지만 이름만 봐도 의미를 알 수 있습니다. Spring Cloud에서 Netflix Eureka Server를 사용하기 위한 스타터입니다.
스타터(Starter)는 Spring Boot의 핵심 개념 중 하나입니다. 필요한 모든 라이브러리를 하나로 묶어서 제공합니다.
개발자는 버전 충돌이나 의존성 관리를 걱정할 필요가 없습니다. 마법의 어노테이션 의존성을 추가했다면 이제 메인 클래스를 만듭니다.
일반적인 Spring Boot 애플리케이션과 똑같습니다. @SpringBootApplication 어노테이션을 붙이고, main 메서드를 작성합니다.
여기서 중요한 것은 @EnableEurekaServer 어노테이션입니다. 이 한 줄이 모든 것을 바꿉니다.
@EnableEurekaServer를 붙이는 순간, Spring Boot는 이 애플리케이션을 Eureka Server로 인식합니다. 자동으로 필요한 빈(Bean)들을 생성하고, REST API 엔드포인트를 만들고, 웹 대시보드를 준비합니다.
Spring의 자동 설정 마법 김개발 씨는 의아했습니다. "그런데 서버 포트는요?
데이터베이스는요? 보안 설정은요?" 박시니어 씨가 설명했습니다.
"Spring Boot의 자동 설정(Auto Configuration) 덕분이에요. 기본값으로 모든 것이 설정됩니다.
물론 나중에 커스터마이징할 수 있지만, 일단 시작하는 데는 이것만으로 충분해요." Spring Boot는 Convention over Configuration 철학을 따릅니다. 설정보다는 관례를 우선한다는 뜻입니다.
개발자가 특별히 설정하지 않으면 합리적인 기본값을 사용합니다. Eureka Server의 기본 포트는 8761입니다.
왜 8761일까요? 전화기 키패드에서 "EUREKA"를 누르면 나오는 숫자입니다.
Netflix 개발자들의 재치가 느껴지는 부분입니다. 어노테이션의 동작 원리 @EnableEurekaServer는 단순한 마커(marker)가 아닙니다.
내부적으로 @Import 어노테이션을 통해 EurekaServerConfiguration이라는 설정 클래스를 불러옵니다. 이 설정 클래스는 Eureka Server에 필요한 모든 빈을 등록합니다.
PeerAwareInstanceRegistry, PeerEurekaNodes, EurekaServerContext 등 수십 개의 컴포넌트가 자동으로 생성됩니다. 개발자는 이런 내부 동작을 몰라도 됩니다.
그저 어노테이션 하나만 붙이면 모든 것이 작동합니다. 이것이 바로 Spring의 강력함입니다.
IDE에서 실행하기 코드를 작성했다면 이제 실행해봅시다. IntelliJ나 Eclipse에서 main 메서드를 실행하면 됩니다.
또는 터미널에서 mvn spring-boot:run 명령어를 입력해도 됩니다. 애플리케이션이 시작되면서 콘솔에 로그가 쏟아집니다.
조금 기다리면 "Started EurekaServerApplication"이라는 메시지가 보입니다. 성공입니다!
웹 브라우저를 열고 http://localhost:8761에 접속해보세요. Eureka Server의 웹 대시보드가 나타납니다.
아직 등록된 서비스가 없어서 목록은 비어있지만, 서버가 정상 작동하고 있다는 증거입니다. 이렇게 간단한 이유 김개발 씨는 감탄했습니다.
"Netflix 같은 대기업이 사용하는 기술이 이렇게 쉽다니!" 박시니어 씨가 대답했습니다. "Netflix가 내부적으로 사용하던 도구들을 오픈소스로 공개했고, Spring 팀이 이를 Spring Boot와 완벽하게 통합했어요.
그 덕분에 우리는 복잡한 설정 없이도 엔터프라이즈급 서비스를 만들 수 있는 거죠." 실제로 Netflix는 Eureka뿐만 아니라 Ribbon(로드밸런서), Hystrix(서킷 브레이커), Zuul(API 게이트웨이) 등 많은 도구를 오픈소스로 공개했습니다. 이들을 통틀어 **Netflix OSS(Open Source Software)**라고 부릅니다.
Spring Cloud Netflix는 이런 Netflix OSS 도구들을 Spring Boot에서 쉽게 사용할 수 있도록 래핑한 프로젝트입니다. @Enable 어노테이션 하나로 복잡한 인프라를 구축할 수 있는 것은 모두 이런 노력 덕분입니다.
다음 단계 Eureka Server를 만드는 것은 시작에 불과합니다. 이제 실제로 마이크로서비스를 등록하고, 설정을 커스터마이징하고, 고가용성을 구성해야 합니다.
하지만 가장 어려운 첫 걸음을 내딛었습니다. 나머지는 이 기초 위에 하나씩 쌓아가면 됩니다.
여러분도 지금 당장 새 Spring Boot 프로젝트를 만들고 따라해보세요. 직접 해보는 것이 가장 빠른 학습 방법입니다.
실전 팁
💡 - Spring Initializr(start.spring.io)를 사용하면 Eureka Server 프로젝트를 더 쉽게 생성할 수 있습니다. 의존성 선택 화면에서 "Eureka Server"를 검색해보세요.
- @EnableEurekaServer는 반드시 @SpringBootApplication이 붙은 메인 클래스에 함께 사용하세요.
3. 서버 프로젝트 생성
김개발 씨는 어노테이션만으로 서버를 만들 수 있다는 사실에 놀랐습니다. "그런데 선배님, 실제 프로젝트를 만들려면 어떤 순서로 해야 하나요?" 박시니어 씨는 Spring Initializr 사이트를 열며 말했습니다.
"처음부터 차근차근 만들어봅시다."
Eureka Server 프로젝트를 생성하는 가장 쉬운 방법은 Spring Initializr를 사용하는 것입니다. 이 웹 도구는 Spring Boot 프로젝트의 기본 구조를 자동으로 생성해줍니다.
필요한 의존성을 선택하고 다운로드하면 바로 개발을 시작할 수 있습니다.
다음 코드를 살펴봅시다.
// Spring Initializr 설정 예시
Project: Maven
Language: Java
Spring Boot: 3.2.0
Group: com.example
Artifact: eureka-server
Name: eureka-server
Package name: com.example.eurekaserver
Packaging: Jar
Java: 17
// Dependencies 선택
- Eureka Server
// 생성된 프로젝트 구조
eureka-server/
├── src/
│ ├── main/
│ │ ├── java/com/example/eurekaserver/
│ │ │ └── EurekaServerApplication.java
│ │ └── resources/
│ │ └── application.properties
│ └── test/
├── pom.xml
└── mvnw
박시니어 씨는 브라우저에서 https://start.spring.io를 열었습니다. 깔끔한 인터페이스가 나타났습니다.
"이게 바로 Spring Initializr예요. Spring 공식 사이트에서 제공하는 프로젝트 생성 도구입니다.
모든 Spring Boot 프로젝트는 여기서 시작한다고 보면 됩니다." 프로젝트 메타데이터 설정 화면 왼쪽에는 여러 옵션들이 보입니다. 하나씩 설정해봅시다.
먼저 Project 타입을 선택합니다. Maven과 Gradle 중 하나를 고르면 됩니다.
Maven이 좀 더 전통적이고 안정적입니다. Gradle은 더 현대적이고 빠릅니다.
어느 것을 선택해도 괜찮지만, 이 예제에서는 Maven을 사용하겠습니다. Language는 당연히 Java입니다.
Kotlin이나 Groovy도 선택할 수 있지만, 대부분의 Spring 프로젝트는 Java를 사용합니다. Spring Boot 버전은 최신 안정 버전을 선택하면 됩니다.
SNAPSHOT이나 M1, RC1 같은 것들은 아직 정식 릴리스가 아니므로 피하는 것이 좋습니다. 3.2.0이나 3.1.5 같은 숫자만 있는 버전을 선택하세요.
Group과 Artifact 김개발 씨가 물었습니다. "Group이랑 Artifact는 뭔가요?" "좋은 질문이에요.
이것들은 프로젝트를 식별하는 이름입니다." Group은 보통 회사나 조직의 도메인을 거꾸로 쓴 형태입니다. 예를 들어 회사 도메인이 example.com이라면 Group은 com.example이 됩니다.
이렇게 하면 전 세계 수많은 프로젝트 중에서 우리 프로젝트를 고유하게 식별할 수 있습니다. Artifact는 프로젝트의 이름입니다.
eureka-server, member-service, order-service 같은 식으로 의미 있는 이름을 붙입니다. 이 이름은 나중에 JAR 파일 이름으로도 사용됩니다.
Package name은 Group과 Artifact를 합친 형태로 자동 생성됩니다. Java 패키지 명명 규칙을 따르면 됩니다.
Packaging과 Java 버전 Packaging은 Jar를 선택합니다. War는 전통적인 서블릿 컨테이너에 배포할 때 사용하지만, Spring Boot는 내장 톰캣을 사용하므로 Jar가 적합합니다.
Java 버전은 17 이상을 권장합니다. Java 8도 아직 지원하지만, 새 프로젝트라면 최신 LTS 버전을 사용하는 것이 좋습니다.
Java 17은 현재 가장 많이 사용되는 LTS 버전입니다. 의존성 추가하기 이제 가장 중요한 단계입니다.
오른쪽의 ADD DEPENDENCIES 버튼을 클릭합니다. 검색창이 나타나면 "eureka"를 입력합니다.
여러 옵션이 나타납니다. Eureka Server와 Eureka Discovery Client가 보입니다.
우리가 원하는 것은 Eureka Server입니다. 클릭해서 추가합니다.
이것만으로 충분합니다. 물론 나중에 다른 의존성을 추가할 수도 있지만, Eureka Server를 만드는 데는 이것 하나면 됩니다.
프로젝트 생성과 다운로드 모든 설정이 끝났다면 아래의 GENERATE 버튼을 클릭합니다. ZIP 파일이 다운로드됩니다.
ZIP 파일을 압축 해제하면 완전한 Spring Boot 프로젝트 구조가 나타납니다. src/main/java에는 메인 클래스가 있고, src/main/resources에는 설정 파일이 있습니다.
pom.xml에는 우리가 선택한 의존성들이 모두 들어있습니다. IDE로 프로젝트 열기 IntelliJ IDEA를 사용한다면 Open을 선택하고 압축 해제한 폴더를 선택합니다.
IntelliJ는 자동으로 Maven 프로젝트를 인식하고 필요한 라이브러리를 다운로드합니다. Eclipse를 사용한다면 Import > Existing Maven Projects를 선택합니다.
역시 자동으로 의존성을 다운로드합니다. 처음 열면 잠시 시간이 걸립니다.
Maven이 인터넷에서 라이브러리들을 다운로드하기 때문입니다. 인터넷 속도에 따라 수십 초에서 몇 분 정도 소요됩니다.
기본 구조 확인 다운로드가 완료되면 프로젝트 구조를 살펴봅시다. EurekaServerApplication.java라는 메인 클래스가 보입니다.
이미 @SpringBootApplication 어노테이션이 붙어있습니다. 여기에 @EnableEurekaServer만 추가하면 됩니다.
application.properties 파일은 아직 비어있습니다. 여기에 나중에 설정을 추가할 것입니다.
pom.xml을 열어보면 spring-cloud-starter-netflix-eureka-server 의존성이 들어있습니다. 버전 정보는 Spring Boot가 자동으로 관리하므로 우리가 신경 쓸 필요가 없습니다.
왜 Initializr를 사용하는가 김개발 씨가 물었습니다. "직접 만들어도 되지 않나요?" "물론 가능해요.
하지만 Initializr를 사용하면 실수를 줄일 수 있어요. 버전 충돌, 잘못된 패키지 구조, 누락된 설정 파일 같은 문제를 피할 수 있죠." 실제로 Spring Boot 프로젝트를 처음부터 손으로 만들려면 신경 써야 할 것이 많습니다.
pom.xml의 parent 설정, plugin 설정, 의존성 버전 관리 등등... Initializr는 이 모든 것을 자동으로 처리해줍니다.
게다가 Spring 팀에서 공식적으로 제공하는 도구이므로 항상 최신 베스트 프랙티스가 반영됩니다. 새로운 Spring Boot 버전이 나오면 Initializr도 즉시 업데이트됩니다.
실무 팁 박시니어 씨가 마지막으로 조언했습니다. "프로젝트를 만들 때마다 Initializr를 사용하세요.
5분이면 완벽한 프로젝트 구조를 얻을 수 있어요. 시간을 아끼고 버그를 줄이는 가장 확실한 방법입니다." 이제 여러분도 직접 start.spring.io에 접속해서 Eureka Server 프로젝트를 만들어보세요.
설정하고, 다운로드하고, IDE로 열어보세요. 손으로 직접 해보는 것이 백 번 읽는 것보다 낫습니다.
실전 팁
💡 - IntelliJ Ultimate 버전을 사용한다면 IDE 내부의 Spring Initializr 통합 기능을 사용할 수 있습니다. New Project > Spring Initializr를 선택하세요.
- Initializr에서 생성한 프로젝트에는
.gitignore파일도 자동으로 포함됩니다. Git 저장소로 바로 사용할 수 있습니다.
4. application.yml 구성
프로젝트는 만들어졌고, 어노테이션도 추가했습니다. 김개발 씨는 설정 파일을 열었습니다.
"선배님, 이 파일이 비어있는데요?" 박시니어 씨가 설명했습니다. "기본값으로도 작동하지만, 실무에서는 몇 가지 설정을 추가해야 해요."
application.yml 파일은 Spring Boot 애플리케이션의 모든 설정을 담는 곳입니다. Eureka Server는 기본값으로도 작동하지만, 포트 번호, 서비스 이름, 자체 등록 방지 같은 중요한 설정들을 명시적으로 지정하는 것이 좋습니다.
YAML 형식을 사용하면 계층 구조를 명확하게 표현할 수 있습니다.
다음 코드를 살펴봅시다.
# application.yml
server:
port: 8761 # Eureka Server 기본 포트
spring:
application:
name: eureka-server # 애플리케이션 이름
eureka:
client:
register-with-eureka: false # 자기 자신을 등록하지 않음
fetch-registry: false # 레지스트리 정보를 가져오지 않음
service-url:
defaultZone: http://localhost:8761/eureka/ # Eureka Server URL
server:
enable-self-preservation: true # 자기 보존 모드 활성화
김개발 씨는 application.properties 파일을 application.yml로 이름을 바꿨습니다. 박시니어 씨가 말했습니다.
"좋아요. YAML 형식이 더 읽기 쉬워요." Properties vs YAML Spring Boot는 두 가지 설정 파일 형식을 지원합니다.
.properties와 .yml입니다. Properties 형식은 전통적인 방식입니다.
server.port=8761 같은 식으로 작성합니다. 간단하지만 계층이 깊어지면 가독성이 떨어집니다.
YAML 형식은 들여쓰기로 계층을 표현합니다. 시각적으로 구조가 명확하고, 중복을 줄일 수 있습니다.
최근에는 YAML을 선호하는 추세입니다. 주의할 점은 YAML은 들여쓰기를 탭이 아닌 스페이스로 해야 한다는 것입니다.
보통 2칸 스페이스를 사용합니다. 서버 포트 설정 첫 번째 설정은 서버 포트입니다.
Eureka Server의 관례적인 포트는 8761입니다. yaml server: port: 8761 물론 다른 포트를 사용해도 됩니다.
8080이나 9090 같은 포트를 써도 상관없습니다. 하지만 8761을 사용하면 다른 개발자들이 "아, 이건 Eureka Server구나"라고 바로 알 수 있습니다.
포트를 명시하지 않으면 기본값인 8080이 사용됩니다. 하지만 8080은 다른 Spring Boot 애플리케이션들도 많이 사용하므로 충돌할 수 있습니다.
애플리케이션 이름 다음은 애플리케이션 이름입니다. yaml spring: application: name: eureka-server 이 이름은 여러 곳에서 사용됩니다.
로그에 표시되고, 모니터링 도구에서 식별자로 쓰이고, Eureka 대시보드에도 나타납니다. 명확하고 의미 있는 이름을 붙이세요.
eureka-server, discovery-service, registry-server 같은 이름이 좋습니다. Eureka Client 설정 여기서 조금 헷갈리는 부분이 나옵니다.
Eureka Server인데 왜 Eureka Client 설정을 하는 걸까요? 박시니어 씨가 설명했습니다.
"Eureka Server도 내부적으로는 Eureka Client 기능을 가지고 있어요. 고가용성을 위해 다른 Eureka Server에 자기 자신을 등록할 수 있거든요." 하지만 지금은 단일 Eureka Server만 만들고 있습니다.
따라서 자기 자신을 등록할 필요가 없습니다. yaml eureka: client: register-with-eureka: false fetch-registry: false register-with-eureka를 false로 설정하면 Eureka Server가 자기 자신을 레지스트리에 등록하지 않습니다.
fetch-registry를 false로 설정하면 다른 서버에서 레지스트리 정보를 가져오지 않습니다. 이 두 설정이 없으면 어떻게 될까요?
Eureka Server가 시작하면서 자기 자신에게 등록하려고 시도합니다. 당연히 아직 준비가 안 됐으므로 실패합니다.
계속 재시도하면서 로그에 에러가 쌓입니다. 기능상 문제는 없지만 불필요한 에러 로그가 발생합니다.
Service URL 설정 defaultZone은 Eureka Server의 위치를 지정합니다. yaml eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ "잠깐, 이것도 Eureka Server인데 왜 자기 자신의 URL을 설정하나요?" 김개발 씨가 물었습니다.
"좋은 질문이에요. 나중에 고가용성 구성을 할 때 필요해요.
여러 Eureka Server를 띄우고 서로를 바라보게 할 때 사용합니다. 지금은 그냥 자기 자신을 가리키도록 하면 됩니다." URL 끝에 /eureka/가 붙는 것을 주의하세요.
이것은 Eureka의 REST API 엔드포인트 경로입니다. 빼먹으면 연결이 안 됩니다.
자기 보존 모드 마지막으로 중요한 설정이 **자기 보존 모드(Self Preservation Mode)**입니다. yaml eureka: server: enable-self-preservation: true 자기 보존 모드는 네트워크 장애 상황에서 등록된 서비스를 함부로 제거하지 않는 기능입니다.
예를 들어 네트워크가 일시적으로 끊겼다고 생각해봅시다. 정상적으로 작동 중인 서비스들이 Eureka에 하트비트를 보내지 못합니다.
자기 보존 모드가 꺼져 있으면 Eureka는 이 서비스들을 모두 제거해버립니다. 하지만 자기 보존 모드가 켜져 있으면 Eureka는 "이건 서비스 문제가 아니라 네트워크 문제일 수 있어"라고 판단합니다.
서비스를 제거하지 않고 기다립니다. 운영 환경과 개발 환경 박시니어 씨가 조언했습니다.
"운영 환경에서는 자기 보존 모드를 켜두는 게 좋아요. 하지만 로컬 개발 환경에서는 끄는 게 편할 수 있어요." 개발하면서 서비스를 자주 재시작하다 보면, 죽은 서비스가 Eureka 목록에 계속 남아있을 수 있습니다.
자기 보존 모드를 끄면 즉시 제거됩니다. 개발 환경용 설정은 application-dev.yml에 따로 만들 수 있습니다.
프로필을 분리하면 환경별로 다른 설정을 사용할 수 있습니다. 설정 파일의 힘 김개발 씨는 이해했습니다.
"코드는 하나도 안 바꿨는데 설정만으로 동작을 제어할 수 있네요." "맞아요. 이게 바로 **외부 설정(Externalized Configuration)**의 힘입니다.
코드는 그대로 두고 환경에 따라 다른 설정을 주입할 수 있어요." Spring Boot는 설정 파일뿐만 아니라 환경 변수, 커맨드 라인 인자, 프로퍼티 파일 등 다양한 방식으로 설정을 받을 수 있습니다. 이를 통해 같은 JAR 파일을 개발, 테스트, 운영 환경에서 다르게 실행할 수 있습니다.
이제 실행해보자 설정 파일까지 완성했습니다. 이제 애플리케이션을 실행하면 완전히 작동하는 Eureka Server를 얻을 수 있습니다.
main 메서드를 실행하고 브라우저에서 http://localhost:8761을 열어보세요. 깔끔한 Eureka 대시보드가 나타날 것입니다.
축하합니다. 여러분은 이제 Eureka Server를 만들 수 있습니다!
실전 팁
💡 - YAML 파일은 들여쓰기가 매우 중요합니다. 탭 대신 스페이스 2칸을 사용하세요.
application-{profile}.yml형식으로 환경별 설정 파일을 만들 수 있습니다. 예:application-dev.yml,application-prod.yml
5. Eureka 대시보드
애플리케이션을 실행한 김개발 씨는 브라우저를 열었습니다. http://localhost:8761을 입력하자 낯선 화면이 나타났습니다.
"선배님, 이게 Eureka 대시보드인가요?" 박시니어 씨가 고개를 끄덕였습니다. "맞아요.
모든 서비스를 한눈에 볼 수 있는 관리 화면입니다."
Eureka 대시보드는 웹 기반의 관리 콘솔입니다. 등록된 모든 마이크로서비스의 상태, 인스턴스 개수, 헬스 체크 정보 등을 시각적으로 보여줍니다.
별도 설정 없이 Eureka Server를 실행하면 자동으로 제공되며, 개발과 운영 모두에서 유용하게 사용됩니다.
다음 코드를 살펴봅시다.
// Eureka Client 서비스 예시 (대시보드에 등록될 서비스)
@SpringBootApplication
@EnableEurekaClient // Eureka Client 활성화
public class MemberServiceApplication {
public static void main(String[] args) {
SpringApplication.run(MemberServiceApplication.class, args);
}
}
// application.yml (클라이언트 설정)
spring:
application:
name: member-service # 대시보드에 표시될 이름
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/ # Eureka Server 위치
김개발 씨는 대시보드 화면을 자세히 살펴봤습니다. 화면 상단에는 Eureka 로고와 함께 시스템 상태가 표시되어 있었습니다.
대시보드의 구조 Eureka 대시보드는 크게 세 영역으로 나뉩니다. 맨 위에는 System Status 영역이 있습니다.
Eureka Server 자체의 상태를 보여줍니다. 환경 정보, 데이터센터 정보, 현재 시간 등이 표시됩니다.
중간에는 DS Replicas 영역입니다. DS는 Discovery Service의 약자입니다.
고가용성 구성에서 다른 Eureka Server들의 목록을 보여줍니다. 지금은 단일 서버라서 비어있습니다.
가장 중요한 것은 하단의 Instances currently registered with Eureka 영역입니다. 여기에 등록된 모든 마이크로서비스가 표시됩니다.
빈 대시보드 "선배님, 아무것도 안 보이는데요?" 김개발 씨가 물었습니다. "당연해요.
아직 어떤 서비스도 등록하지 않았으니까요. Eureka Server만 띄운 상태예요." 대시보드 아래쪽에 빨간 글씨로 경고 메시지가 보입니다.
"No instances available". 등록된 인스턴스가 없다는 뜻입니다.
첫 번째 서비스 등록하기 박시니어 씨는 새로운 Spring Boot 프로젝트를 만들었습니다. 이번에는 member-service라는 이름의 일반 마이크로서비스입니다.
pom.xml에 spring-cloud-starter-netflix-eureka-client 의존성을 추가했습니다. Server가 아니라 Client입니다.
메인 클래스에 @EnableEurekaClient 어노테이션을 붙였습니다. 그리고 application.yml에 설정을 추가했습니다.
yaml spring: application: name: member-service eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ 서비스 이름을 member-service로 지정했습니다. 그리고 Eureka Server의 위치를 알려줬습니다.
마법의 순간 member-service를 실행하자 콘솔에 로그가 흘렀습니다. "DiscoveryClient_MEMBER-SERVICE...
- registration status: 204". 등록 성공입니다!
김개발 씨는 재빨리 Eureka 대시보드를 새로고침했습니다. 놀랍게도 화면이 바뀌었습니다.
Instances currently registered with Eureka 영역에 새로운 항목이 나타났습니다. "MEMBER-SERVICE"라는 큰 글씨와 함께 상태 정보가 표시됩니다.
대시보드 정보 읽기 각 서비스 항목에는 여러 정보가 표시됩니다. - Application: 서비스 이름입니다.
대문자로 변환되어 표시됩니다. - AMIs: Amazon Machine Image 정보입니다.
AWS 환경에서 유용합니다. - Availability Zones: 가용 영역 정보입니다.
역시 클라우드 환경용입니다. - Status: 현재 상태입니다.
UP이면 정상, DOWN이면 장애, STARTING이면 시작 중입니다. 서비스 이름을 클릭하면 상세 정보가 나타납니다.
호스트 이름, IP 주소, 포트 번호, 메타데이터 등을 볼 수 있습니다. 여러 인스턴스 실행하기 박시니어 씨가 말했습니다.
"이번에는 같은 서비스를 여러 개 띄워봅시다." IntelliJ에서 실행 설정을 복사하고, VM 옵션에 -Dserver.port=8081을 추가했습니다. 같은 member-service를 다른 포트에서 실행하는 것입니다.
두 번째 인스턴스를 실행하고 대시보드를 새로고침했습니다. 이번에는 MEMBER-SERVICE 아래에 두 개의 인스턴스가 표시됩니다.
MEMBER-SERVICE (2) DESKTOP-ABC:member-service:8080 - UP DESKTOP-ABC:member-service:8081 - UP 김개발 씨는 감탄했습니다. "와, 자동으로 여러 인스턴스를 인식하네요!" 헬스 체크와 자기 보존 모드 박시니어 씨는 하나의 member-service를 강제로 종료했습니다.
잠시 후 대시보드를 새로고침하자 해당 인스턴스가 사라졌습니다. "Eureka는 주기적으로 **하트비트(heartbeat)**를 받아요.
각 서비스가 30초마다 '나 살아있어!'라고 신호를 보냅니다. 90초 동안 신호가 없으면 죽은 것으로 간주하고 목록에서 제거합니다." 만약 갑자기 많은 서비스가 하트비트를 보내지 않으면?
자기 보존 모드가 작동합니다. 대시보드 상단에 빨간 경고 메시지가 나타납니다.
"EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT." 이것은 네트워크 장애일 가능성이 높으니 함부로 서비스를 제거하지 않겠다는 Eureka의 방어 메커니즘입니다.
실무에서의 활용 "개발할 때는 대시보드를 항상 켜두세요." 박시니어 씨가 조언했습니다. "서비스가 제대로 등록됐는지, 모든 인스턴스가 정상인지 한눈에 볼 수 있어요." 운영 환경에서도 마찬가지입니다.
장애가 발생했을 때 대시보드를 보면 어떤 서비스가 문제인지 즉시 파악할 수 있습니다. 물론 대시보드는 읽기 전용입니다.
여기서 서비스를 시작하거나 중지할 수는 없습니다. 단지 현재 상태를 보여줄 뿐입니다.
REST API도 제공 대시보드는 웹 UI일 뿐입니다. 내부적으로는 REST API를 사용합니다.
http://localhost:8761/eureka/apps에 접속하면 XML 형식으로 모든 서비스 정보를 받을 수 있습니다. JSON을 선호한다면 헤더에 Accept: application/json을 추가하면 됩니다.
이를 통해 모니터링 도구나 스크립트에서 Eureka 정보를 읽을 수 있습니다. 보안 고려사항 김개발 씨가 물었습니다.
"누구나 대시보드를 볼 수 있는 건가요?" "기본 설정에서는 그래요. 그래서 운영 환경에서는 반드시 보안을 추가해야 합니다." Spring Security를 의존성에 추가하고 기본 인증을 설정할 수 있습니다.
또는 방화벽으로 특정 IP에서만 접근을 허용할 수도 있습니다. 내부 관리 도구이므로 외부에 노출되어서는 안 됩니다.
VPN 내부나 프라이빗 네트워크에서만 접근 가능하도록 구성하는 것이 일반적입니다. 직접 확인해보세요 대시보드는 직접 눈으로 봐야 이해가 됩니다.
지금 당장 Eureka Server를 실행하고 브라우저를 열어보세요. 그리고 간단한 클라이언트 서비스를 만들어 등록해보세요.
서비스가 대시보드에 나타나는 순간, Eureka의 매력을 느낄 수 있을 것입니다.
실전 팁
💡 - 대시보드는 기본적으로 / 경로에서 제공됩니다. REST API는 /eureka/apps에서 제공됩니다.
- 프로덕션 환경에서는 Spring Security를 추가하여 대시보드를 보호하세요.
6. 고가용성 구성
김개발 씨는 Eureka Server를 성공적으로 만들었습니다. 하지만 문득 걱정이 들었습니다.
"선배님, Eureka Server가 죽으면 어떻게 되나요?" 박시니어 씨는 심각한 표정으로 대답했습니다. "좋은 질문이에요.
그래서 운영 환경에서는 항상 고가용성 구성을 해야 합니다."
고가용성(High Availability) 구성은 단일 장애점을 제거하는 것입니다. Eureka Server를 여러 대 띄우고 서로를 복제하면, 한 서버가 죽어도 나머지가 계속 작동합니다.
각 Eureka Server는 다른 서버를 peer로 등록하고, 서비스 정보를 동기화합니다.
다음 코드를 살펴봅시다.
// application-peer1.yml (첫 번째 Eureka Server)
server:
port: 8761
spring:
application:
name: eureka-server
eureka:
instance:
hostname: peer1
client:
register-with-eureka: true # peer 서버에 등록
fetch-registry: true # peer에서 정보 가져오기
service-url:
defaultZone: http://peer2:8762/eureka/ # 두 번째 서버 위치
// application-peer2.yml (두 번째 Eureka Server)
server:
port: 8762
eureka:
instance:
hostname: peer2
client:
service-url:
defaultZone: http://peer1:8761/eureka/ # 첫 번째 서버 위치
박시니어 씨는 화이트보드에 그림을 그렸습니다. Eureka Server 하나와 그 주변의 여러 마이크로서비스들이 보였습니다.
그리고 Eureka Server에 큰 X표시를 했습니다. "Eureka Server가 죽으면 어떻게 될까요?" 단일 장애점의 문제 Single Point of Failure, 약자로 SPOF라고 부릅니다.
시스템의 한 부분이 죽으면 전체가 마비되는 상황입니다. 만약 Eureka Server가 하나뿐인데 그것이 죽으면?
다행히 기존 서비스들은 계속 작동합니다. 각 클라이언트가 로컬 캐시를 가지고 있기 때문입니다.
하지만 새로운 서비스를 등록할 수 없습니다. 오토스케일링으로 새 인스턴스가 생성되어도 등록할 곳이 없습니다.
기존 서비스의 주소가 바뀌어도 업데이트할 수 없습니다. 시간이 지나면서 캐시 정보는 점점 부정확해집니다.
결국 서비스 간 통신에 문제가 생기기 시작합니다. 복제를 통한 해결 해결책은 간단합니다.
Eureka Server를 여러 개 띄우는 것입니다. 보통 3개를 권장합니다.
2개는 최소 구성이고, 3개면 한 개가 죽어도 quorum을 유지할 수 있습니다. 여러 Eureka Server는 서로를 peer로 인식합니다.
한 서버에 서비스가 등록되면 자동으로 다른 서버들에게 복제됩니다. 마치 거울처럼 모든 서버가 동일한 정보를 가집니다.
설정 파일 분리 고가용성 구성의 핵심은 각 Eureka Server가 다른 서버들을 바라보도록 만드는 것입니다. Spring Profile을 사용하면 환경별로 다른 설정을 적용할 수 있습니다.
application-peer1.yml과 application-peer2.yml을 만듭니다. peer1은 8761 포트에서 실행되고, peer2를 바라봅니다.
peer2는 8762 포트에서 실행되고, peer1을 바라봅니다. 서로가 서로를 peer로 등록하는 것입니다.
중요한 설정 변경 단일 서버 구성에서는 register-with-eureka와 fetch-registry를 false로 설정했습니다. 하지만 고가용성 구성에서는 true로 바꿔야 합니다.
각 Eureka Server가 다른 서버에 자기 자신을 등록하고, 다른 서버의 정보를 가져와야 복제가 이루어지기 때문입니다. hostname도 명시적으로 지정합니다.
peer1, peer2 같은 이름을 사용하면 나중에 로그를 볼 때 어떤 서버인지 구분하기 쉽습니다. hosts 파일 설정 로컬 개발 환경에서 테스트하려면 /etc/hosts (Windows는 C:\Windows\System32\drivers\etc\hosts) 파일을 수정해야 합니다.
127.0.0.1 peer1 127.0.0.1 peer2 이렇게 하면 peer1과 peer2라는 호스트명을 localhost로 해석합니다. 실제 운영 환경에서는 서로 다른 서버의 실제 호스트명이나 IP를 사용합니다.
서버 실행하기 이제 두 개의 Eureka Server를 실행합니다. 첫 번째 터미널에서: bash java -jar eureka-server.jar --spring.profiles.active=peer1 두 번째 터미널에서: bash java -jar eureka-server.jar --spring.profiles.active=peer2 각 서버는 시작하면서 다른 peer에 자기 자신을 등록하려고 시도합니다.
처음에는 실패할 수 있습니다. 하지만 재시도를 통해 결국 연결됩니다.
대시보드 확인 브라우저에서 http://localhost:8761과 http://localhost:8762를 각각 열어봅니다. 두 대시보드 모두 DS Replicas 영역에 서로의 정보가 표시됩니다.
peer1 대시보드에는 peer2가, peer2 대시보드에는 peer1이 보입니다. 이제 member-service를 실행해봅시다.
application.yml의 defaultZone에 두 서버를 모두 지정합니다. yaml eureka: client: service-url: defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/ 서비스가 시작되면 두 Eureka Server 모두에 등록됩니다.
한 서버의 대시보드를 보든, 다른 서버의 대시보드를 보든 동일한 서비스 목록이 나타납니다. 장애 테스트 진짜 고가용성인지 확인해봅시다.
peer1 서버를 강제로 종료합니다. member-service는 여전히 정상 작동합니다.
peer2에서 정보를 가져오기 때문입니다. 새로운 서비스를 띄워도 peer2에 등록되고, 다른 서비스들은 peer2에서 조회합니다.
peer1을 다시 시작하면? 자동으로 peer2와 동기화됩니다.
동기화가 완료되면 두 서버는 다시 동일한 상태가 됩니다. 3개 이상의 서버 실제 운영 환경에서는 보통 3개의 Eureka Server를 사용합니다.
각 서버는 나머지 두 서버를 peer로 지정합니다. 예를 들어 peer1의 defaultZone은 http://peer2:8762/eureka/,http://peer3:8763/eureka/가 됩니다.
peer2는 peer1과 peer3을 바라보고, peer3은 peer1과 peer2를 바라봅니다. 이렇게 하면 한 서버가 죽어도 나머지 두 개가 작동하고, 두 서버가 동시에 죽어도(가능성은 매우 낮지만) 마지막 한 개가 버팁니다.
클라우드 환경 고려사항 AWS, GCP, Azure 같은 클라우드 환경에서는 여러 가용 영역(Availability Zone)에 Eureka Server를 분산 배치합니다. 예를 들어 AWS의 us-east-1a, us-east-1b, us-east-1c 세 곳에 각각 Eureka Server를 띄웁니다.
한 데이터센터 전체에 장애가 나도 나머지가 작동합니다. Eureka는 Zone Affinity 기능도 제공합니다.
클라이언트가 가능하면 같은 Zone의 서버를 우선적으로 사용하도록 합니다. 네트워크 지연을 줄이고 비용을 절감할 수 있습니다.
트레이드오프 김개발 씨가 물었습니다. "그럼 무조건 서버를 많이 띄우는 게 좋은 건가요?" "아니요.
서버가 많을수록 복제 오버헤드가 증가해요. 네트워크 트래픽도 늘어나고, 동기화 시간도 길어집니다." 보통 3개면 충분합니다.
5개 이상은 거의 필요하지 않습니다. 과도한 중복은 오히려 복잡도만 높입니다.
정리 박시니어 씨가 마무리했습니다. "고가용성은 운영 환경의 필수 요소예요.
개발할 때는 단일 서버로 하고, 스테이징과 프로덕션에서는 반드시 다중 서버를 사용하세요." Eureka의 고가용성 구성은 생각보다 간단합니다. 설정 파일 몇 줄만 바꾸면 됩니다.
하지만 그 효과는 엄청납니다. 장애에 강한, 안정적인 시스템을 만들 수 있습니다.
여러분도 지금 배운 내용을 바탕으로 로컬에서 여러 Eureka Server를 띄워보세요. 한 서버를 죽이고, 다시 살리고, 서비스를 등록하고...
직접 실험하면서 동작 원리를 체득하세요. 그것이 진정한 학습입니다.
실전 팁
💡 - 운영 환경에서는 최소 3대의 Eureka Server를 서로 다른 가용 영역에 배치하세요.
- 클라이언트의 defaultZone에는 모든 Eureka Server를 콤마로 구분하여 나열하세요. 한 서버가 죽어도 다른 서버로 자동 전환됩니다.
- Netflix는 내부적으로 region과 zone 개념을 사용하여 글로벌 규모의 서비스 디스커버리를 구현했습니다. AWS의 region/AZ 개념과 매핑됩니다.
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
관찰 가능한 마이크로서비스 완벽 가이드
마이크로서비스 환경에서 시스템의 상태를 실시간으로 관찰하고 모니터링하는 방법을 배웁니다. Resilience4j, Zipkin, Prometheus, Grafana, EFK 스택을 활용하여 안정적이고 관찰 가능한 시스템을 구축하는 실전 가이드입니다.
Prometheus 메트릭 수집 완벽 가이드
Spring Boot 애플리케이션의 메트릭을 Prometheus로 수집하고 모니터링하는 방법을 배웁니다. Actuator 설정부터 PromQL 쿼리까지 실무에 필요한 모든 내용을 다룹니다.
스프링 관찰 가능성 완벽 가이드
Spring Boot 3.x의 Observation API를 활용한 애플리케이션 모니터링과 추적 방법을 초급 개발자 눈높이에서 쉽게 설명합니다. 실무에서 바로 적용할 수 있는 메트릭 수집과 분산 추적 기법을 다룹니다.
Zipkin으로 추적 시각화 완벽 가이드
마이크로서비스 환경에서 분산 추적을 시각화하는 Zipkin의 핵심 개념과 활용 방법을 초급자도 쉽게 이해할 수 있도록 실무 스토리로 풀어낸 가이드입니다. Docker 실행부터 UI 분석까지 단계별로 배웁니다.
Micrometer Tracing 완벽 가이드
분산 시스템에서 요청 흐름을 추적하는 Micrometer Tracing의 핵심 개념과 실전 활용법을 초급 개발자도 쉽게 이해할 수 있도록 실무 스토리와 비유로 풀어낸 완벽 가이드입니다.