2026. 1. 4. 21:27ㆍSpring Microservice/Service Discovery
🔍 Service Discovery를 이용한 서비스 조회 (Eureka 기반)
마이크로서비스 아키텍처(MSA)에서 서비스 간 통신은 가장 핵심적인 요소 중 하나입니다.
특히 서비스의 물리적인 위치(IP, 포트)를 직접 알지 않고도 다른 서비스를 호출할 수 있어야 진정한 클라우드 네이티브 구조라고 할 수 있습니다 ☁️
이번 챕터에서는 Licensing Service가 Organization Service를 호출하는 과정을 통해
📌 Spring Cloud Eureka 기반 Service Discovery가 실제로 어떻게 동작하는지 자세히 살펴보겠습니다.
🎯 목표: 서비스 위치를 모른 채 서비스 호출하기
이번 섹션의 핵심 목표는 다음과 같습니다 👇
Licensing Service가 Organization Service의 실제 위치를 전혀 알지 못한 상태에서,
Eureka를 통해 Organization Service를 조회하고 호출하는 방법 이해하기
이를 위해 Licensing Service는 Eureka를 통해 Organization Service의 물리적 위치를 조회합니다.
🧩 사용되는 Spring / Netflix Client 라이브러리들
Spring Cloud에서는 Spring Cloud Load Balancer를 통해
여러 방식의 서비스 호출 추상화를 제공합니다.
이번 예제에서는 추상화 수준이 낮은 것부터 높은 것까지
총 3가지 클라이언트 라이브러리를 비교하며 살펴봅니다 🔄
📚 이번에 다룰 3가지 클라이언트
아래 순서대로 점점 사용이 쉬워지는 구조입니다 👇
1️⃣ Spring Discovery Client
2️⃣ Discovery Client가 적용된 RestTemplate
3️⃣ Netflix Feign Client
각각의 특징은 다음과 같습니다.
🔹 1. Spring Discovery Client
- 가장 낮은 수준의 추상화
- 개발자가 직접 서비스 인스턴스 목록을 조회하고 선택
- 유연하지만 코드가 다소 복잡해질 수 있음
🔹 2. Discovery Client–enabled RestTemplate
- Spring이 제공하는 향상된 RestTemplate
- Load Balancer가 자동으로 서비스 인스턴스를 선택
- 코드 복잡도 ↓, 생산성 ↑
🔹 3. Netflix Feign Client
- 가장 높은 수준의 추상화
- 인터페이스 선언만으로 서비스 호출 가능
- 마치 로컬 메서드 호출처럼 사용 가능 ✨
🧪 하나의 엔드포인트로 모든 방식 테스트하기
이번 예제의 핵심 설계 포인트 중 하나는 💡
세 가지 클라이언트 방식을 하나의 API 엔드포인트에서 모두 테스트할 수 있도록 구성했다는 점입니다.
이를 위해 Licensing Service에 헬퍼(helper)용 라우트를 추가했습니다.
🚏 LicenseController에 추가된 새로운 라우트
📂 경로
src/main/java/com/optimagrowth/license/controller/LicenseController.java
🧾 새로 추가된 API 코드
@RequestMapping(value="/{licenseId}/{clientType}",
method = RequestMethod.GET)
public License getLicensesWithClient(
@PathVariable("organizationId") String organizationId,
@PathVariable("licenseId") String licenseId,
@PathVariable("clientType") String clientType) {
return licenseService.getLicense(organizationId,
licenseId,
clientType);
}
🧠 이 라우트의 핵심 역할
clientType파라미터를 통해
👉 어떤 방식의 클라이언트를 사용할지 결정- 하나의 API로 Discovery / Rest / Feign 방식 모두 테스트 가능
- 실습 및 비교에 매우 유용한 구조 👍
🔑 clientType으로 전달 가능한 값들
라우트에서 전달 가능한 clientType 값은 다음과 같습니다 👇
| clientType 값 | 설명 |
|---|---|
discovery |
Discovery Client + 기본 RestTemplate 사용 |
rest |
Load Balancer가 적용된 RestTemplate 사용 |
feign |
Netflix Feign Client 사용 |
⚠️ NOTE (중요)
하나의 코드베이스에서 3가지 방식을 모두 사용하기 때문에,
실제 설명상 필요 없어 보이는 어노테이션이 존재할 수 있습니다.
예를 들어 👇
@EnableDiscoveryClient@EnableFeignClients
👉 특정 클라이언트만 설명하는 부분에서도
👉 모든 예제를 한 코드베이스에서 실행 가능하도록 유지하기 위해 포함되어 있습니다.
💡 실제 프로젝트에서는 자신의 목적에 맞는 방식 하나만 선택하면 됩니다.
🧠 LicenseService의 핵심 로직
📂 경로
src/main/java/com/optimagrowth/license/service/LicenseService.java
이 클래스에서는 clientType에 따라 Organization Service를 조회하는 로직이 추가되었습니다.
🔁 retrieveOrganizationInfo() 메서드
clientType값을 기준으로- 어떤 방식의 클라이언트를 사용할지 결정
- Organization Service 인스턴스 조회 수행
🧾 getLicense() 메서드 전체 코드
public License getLicense(String licenseId,
String organizationId,
String clientType){
License license = licenseRepository
.findByOrganizationIdAndLicenseId(organizationId, licenseId);
if (null == license) {
throw new IllegalArgumentException(String.format(
messages.getMessage("license.search.error.message", null, null),
licenseId, organizationId));
}
Organization organization =
retrieveOrganizationInfo(organizationId, clientType);
if (null != organization) {
license.setOrganizationName(organization.getName());
license.setContactName(organization.getContactName());
license.setContactEmail(organization.getContactEmail());
license.setContactPhone(organization.getContactPhone());
}
return license.withComment(config.getExampleProperty());
}
🔍 이 메서드의 처리 흐름 요약
1️⃣ 라이선스 정보 조회 (Postgres DB)
2️⃣ clientType에 따라 Organization Service 호출
3️⃣ Organization 정보가 존재하면 License 객체에 병합
4️⃣ 최종 License 객체 반환
📦 각 클라이언트 구현 위치
각 방식별 클라이언트 구현체는 다음 경로에 위치합니다 📁
src/main/java/com/optimagrowth/license/service/client
이 패키지 안에 다음과 같은 구현들이 존재합니다 👇
- Discovery Client 기반 구현
- RestTemplate 기반 구현
- Feign Client 기반 구현
🌐 실제 호출 테스트용 엔드포인트
각 방식의 클라이언트를 테스트하기 위해
다음 GET 요청을 사용할 수 있습니다 🚀
http://<licensing service Hostname/IP>:<licensing service Port>/v1/
organization/<organizationID>/license/<licenseID>/<client type>
✅ client type 예시
feigndiscoveryrest
🎉 마무리 정리
이번 글에서는 다음 내용을 살펴봤습니다 ✅
✔ Eureka를 활용한 서비스 디스커버리 개념
✔ Licensing Service → Organization Service 호출 구조
✔ 3가지 Spring/Netflix 클라이언트 방식 비교
✔ clientType 기반 동적 클라이언트 선택 구조
✔ 실습용 헬퍼 라우트 설계 의도
'Spring Microservice > Service Discovery' 카테고리의 다른 글
| Invoking services with a Load Balancer–aware Spring REST template (0) | 2026.01.04 |
|---|---|
| Looking up service instances with Spring Discovery Client (1) | 2026.01.04 |
| Registering services with Spring Eureka (0) | 2026.01.04 |
| Building our Spring Eureka service (0) | 2026.01.04 |
| Service discovery in the cloud (0) | 2026.01.04 |