2026. 1. 4. 21:41ㆍSpring Microservice/Service Discovery
🔍 Spring Discovery Client를 사용한 서비스 인스턴스 조회하기
마이크로서비스 아키텍처(MSA)에서 서비스 간 통신은 항상 핵심적인 고민 거리입니다.
특히 서비스의 물리적 위치(IP, 포트) 가 동적으로 변하는 클라우드 환경에서는
서비스 디스커버리(Service Discovery) 없이는 안정적인 통신이 불가능합니다.
이번 챕터에서는 Spring Cloud Load Balancer 와 연동되는
👉 Spring Discovery Client 를 사용해
Eureka에 등록된 서비스 인스턴스를 직접 조회하고 호출하는 방식을 살펴봅니다.
🧠 Spring Discovery Client란?
Spring Discovery Client는
Spring Cloud Load Balancer 및 서비스 레지스트리(Eureka 등)에
접근할 수 있는 가장 낮은 수준(low-level)의 API를 제공합니다.
이를 통해 다음이 가능합니다.
- 📌 현재 등록된 모든 서비스 목록 조회
- 📌 특정 서비스의 모든 인스턴스(ServiceInstance) 정보 조회
- 📌 각 인스턴스의 URI, 호스트, 포트 정보 확인
즉, Load Balancer 내부 상태를 직접 들여다볼 수 있는 도구입니다.
🚀 예제 시나리오 개요
이번 예제의 목표는 다음과 같습니다.
- Licensing Service 에서
- Spring Discovery Client 를 사용해
- Eureka에 등록된 Organization Service 인스턴스를 조회하고
- 그중 하나의 인스턴스를 선택해
- RestTemplate 으로 직접 호출
🧩 1단계: Discovery Client 활성화
먼저, Licensing Service 애플리케이션에 Discovery Client 기능을 활성화해야 합니다.
📂 src/main/java/com/optimagrowth/license/LicenseServiceApplication.java
package com.optimagrowth.license;
@SpringBootApplication
@RefreshScope
@EnableDiscoveryClient
public class LicenseServiceApplication {
public static void main(String[] args) {
SpringApplication.run(LicenseServiceApplication.class, args);
}
}
🔑 핵심 포인트
- ✅
@EnableDiscoveryClient- Spring Cloud가 이 애플리케이션에서
- Discovery Client + Spring Cloud Load Balancer 를 사용할 수 있도록 트리거
- ✅ 이 설정이 있어야 Eureka와 연동 가능
🧩 2단계: Discovery Client를 이용한 서비스 호출 구현
이제 실제로 Discovery Client를 사용해 Organization Service를 호출하는 코드를 살펴봅니다.
📂 src/main/java/com/optimagrowth/license/service/client/OrganizationDiscoveryClient.java
@Component
public class OrganizationDiscoveryClient {
@Autowired
private DiscoveryClient discoveryClient;
public Organization getOrganization(String organizationId) {
RestTemplate restTemplate = new RestTemplate();
List<ServiceInstance> instances =
discoveryClient.getInstances("organization-service");
if (instances.size() == 0) return null;
String serviceUri = String.format(
"%s/v1/organization/%s",
instances.get(0).getUri().toString(),
organizationId
);
ResponseEntity<Organization> restExchange =
restTemplate.exchange(
serviceUri,
HttpMethod.GET,
null,
Organization.class,
organizationId
);
return restExchange.getBody();
}
}
🔎 코드 상세 분석
1️⃣ DiscoveryClient 사용
@Autowired
private DiscoveryClient discoveryClient;
DiscoveryClient는- Spring Cloud Load Balancer와 상호작용하는 핵심 클래스
- 서비스 레지스트리(Eureka)에 등록된 정보에 접근 가능
2️⃣ 서비스 인스턴스 조회
List<ServiceInstance> instances =
discoveryClient.getInstances("organization-service");
"organization-service"는 서비스 ID- 반환값:
List<ServiceInstance>
- 각
ServiceInstance는 다음 정보를 포함합니다.- 🌐 Hostname
- 🔌 Port
- 🔗 URI
3️⃣ 첫 번째 인스턴스 선택
if (instances.size() == 0) return null;
- 인스턴스가 없으면
null반환
instances.get(0)
- ⚠️ 로드 밸런싱 없이
- 무조건 첫 번째 인스턴스만 사용
4️⃣ 직접 URL 생성
String serviceUri = String.format(
"%s/v1/organization/%s",
instances.get(0).getUri().toString(),
organizationId
);
- Discovery Client로 얻은 URI를 기반으로
- 직접 호출 URL을 조합
5️⃣ RestTemplate으로 서비스 호출
ResponseEntity<Organization> restExchange =
restTemplate.exchange(
serviceUri,
HttpMethod.GET,
null,
Organization.class,
organizationId
);
- 일반적인
RestTemplate호출 방식 - 응답 Body를
Organization객체로 매핑
⚠️ Discovery Client의 현실적인 문제점
❌ 1. 클라이언트 사이드 로드 밸런싱 미사용
- Discovery Client를 직접 호출하면
- 단순히 서비스 목록만 제공
- ❗ 어떤 인스턴스를 호출할지는 개발자 책임
- Spring Cloud Load Balancer의
- 라운드 로빈
- 가중치
- 상태 기반 분산
👉 전혀 활용하지 못함
❌ 2. 불필요한 코드 증가
- 직접 해야 하는 작업들:
- 서비스 인스턴스 선택
- URL 직접 조합
- 호출 로직 관리
- ✋ “적을수록 좋은 코드” 원칙에 위배
🧠 RestTemplate 직접 생성에 대한 숨은 의도
눈치 빠른 Spring 개발자라면 다음 코드에서 의문을 가질 수 있습니다.
RestTemplate restTemplate = new RestTemplate();
🤔 왜 @Autowired를 사용하지 않았을까?
일반적으로는 이렇게 씁니다.
@Autowired
private RestTemplate restTemplate;
하지만 여기서는 의도적으로 직접 생성했습니다.
🔍 이유는 바로 이것입니다
@EnableDiscoveryClient가 활성화되면- Spring이 관리하는 모든 RestTemplate Bean 에는
- Load Balancer 인터셉터가 자동으로 주입됩니다
- 이 인터셉터는
http://organization-service/...- 같은 논리적 서비스 이름 기반 URL을
- 실제 인스턴스 주소로 변환합니다
👉 하지만 이번 예제는
Discovery Client의 “순수한 동작”을 보여주기 위한 것이므로
- ❌ Load Balancer 개입 제거
- ❌ 자동 URL 변환 제거
- ✅ Discovery Client 결과만 사용
그래서 RestTemplate을 직접 new로 생성한 것입니다.
🧾 정리 (Takeaway)
✔ Spring Discovery Client는 강력하지만 저수준 도구입니다.
✔ 서비스 메타데이터를 직접 다뤄야 할 때만 사용해야 합니다.
✔ 일반적인 서비스 호출에는:
- 🔥 LoadBalancer 기반 RestTemplate
- 🔥 OpenFeign
같은 고수준 추상화 도구가 훨씬 적합합니다.
👉 Discovery Client는
“서비스를 이해하기 위한 도구”이지
“일반적인 서비스 호출 도구”는 아닙니다.
'Spring Microservice > Service Discovery' 카테고리의 다른 글
| Invoking services with Netflix Feign client (0) | 2026.01.04 |
|---|---|
| Invoking services with a Load Balancer–aware Spring REST template (0) | 2026.01.04 |
| Using service discovery to look up a service (0) | 2026.01.04 |
| Registering services with Spring Eureka (0) | 2026.01.04 |
| Building our Spring Eureka service (0) | 2026.01.04 |