2025. 3. 14. 17:31ㆍSpring Microservice
🌐 Eureka를 활용한 서비스 탐색(Service Discovery)과 마이크로서비스 호출 🚀
마이크로서비스 아키텍처(MSA)에서는 서비스 간의 동적인 탐색과 통신이 필수적입니다.
이번 글에서는 Licensing Service가 Organization Service를 직접적인 위치 정보 없이 호출하는 방법을 알아보겠습니다. 💡
🔹 목표
- Licensing Service가 Eureka를 활용하여 Organization Service의 물리적 위치를 찾는 방법
- Spring Cloud Load Balancer를 활용하는 3가지 방식
- 실제 코드 예제와 서비스 호출 방법
🎯 1. 서비스 탐색(Service Discovery)란?
Eureka를 사용하면 서비스의 위치(IP & 포트)를 직접 설정하지 않아도 됩니다.
이렇게 하면 서비스가 자동 확장(Auto Scaling)되거나 장애 조치(Failover)될 때도 동적으로 위치를 탐색할 수 있습니다.
✅ Licensing Service가 Organization Service를 호출하는 과정
1️⃣ Licensing Service는 Eureka에 등록된 Organization Service의 위치를 탐색
2️⃣ Eureka는 해당 서비스의 IP & 포트 정보를 반환
3️⃣ Licensing Service는 반환된 정보를 기반으로 Organization Service에 요청 전송
🔹 직접적인 서비스 위치를 알 필요 없이 Eureka를 통해 탐색 가능 → 유연한 서비스 호출 가능!
🔗 2. Spring Cloud Load Balancer를 활용한 3가지 방식
Spring Boot에서는 Eureka를 활용하여 다른 서비스의 위치를 탐색하는 여러 가지 방법을 제공합니다.
이번 글에서는 3가지 클라이언트 라이브러리를 활용한 서비스 호출 방법을 살펴보겠습니다.
방식 | 사용 라이브러리 | 특징 |
---|---|---|
Discovery Client | DiscoveryClient |
가장 낮은 수준의 API |
RestTemplate (Load Balanced) | RestTemplate + LoadBalancer |
중간 수준의 추상화 |
Feign Client | OpenFeign |
가장 높은 수준의 추상화 |
💡 클라이언트가 Eureka를 활용하여 Organization Service를 찾는 방법은 다르지만,
결과적으로 모두 Eureka Server에서 등록된 서비스의 위치를 가져와서 호출하는 것이 핵심입니다.
🏗 3. LicenseController에서 동적 클라이언트 호출
먼저, LicenseController
에서 3가지 클라이언트 유형 중 하나를 선택하여 요청을 처리할 수 있도록 설정합니다.
📌 LicenseController.java
@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);
}
✔ 요청 경로 예시:
GET http://localhost:8082/v1/organization/123/license/456/discovery
GET http://localhost:8082/v1/organization/123/license/456/rest
GET http://localhost:8082/v1/organization/123/license/456/feign
✔ clientType
을 통해 호출 방식 선택:
discovery
→ Spring Discovery Client 활용rest
→ Load Balancer가 적용된 RestTemplate 활용feign
→ Netflix Feign Client 활용
⚙️ 4. LicenseService에서 클라이언트 유형에 따라 서비스 호출
LicenseService
에서 클라이언트 유형에 따라 Organization Service를 호출하도록 구현합니다.
📌 LicenseService.java
public License getLicense(String licenseId, String organizationId, String clientType) {
License license = licenseRepository.findByOrganizationIdAndLicenseId(organizationId, licenseId);
if (license == null) {
throw new IllegalArgumentException(
String.format(messages.getMessage("license.search.error.message", null, null),
licenseId, organizationId)
);
}
Organization organization = retrieveOrganizationInfo(organizationId, clientType);
if (organization != null) {
license.setOrganizationName(organization.getName());
license.setContactName(organization.getContactName());
license.setContactEmail(organization.getContactEmail());
license.setContactPhone(organization.getContactPhone());
}
return license.withComment(config.getExampleProperty());
}
✔ retrieveOrganizationInfo(organizationId, clientType)
를 호출하여 Organization Service 정보를 가져옴
✔ clientType에 따라 적절한 방식으로 Eureka에서 Organization Service 정보를 조회
🔍 5. 3가지 방법을 활용한 서비스 호출 방식
1️⃣ Discovery Client 활용 (DiscoveryClient
)
📌 DiscoveryClient 기반 Eureka 탐색
@Autowired
private DiscoveryClient discoveryClient;
public String getOrganizationServiceUrl() {
List<ServiceInstance> instances = discoveryClient.getInstances("organization-service");
if (instances.isEmpty()) return null;
return instances.get(0).getUri().toString();
}
✔ DiscoveryClient
를 사용하여 Eureka에서 "organization-service"의 인스턴스를 조회
✔ 서비스가 여러 개 실행 중이라면 첫 번째 인스턴스를 반환
2️⃣ Load Balanced RestTemplate 활용
📌 RestTemplate
을 사용하여 Eureka 기반 서비스 호출
@Autowired
private RestTemplate restTemplate;
public Organization getOrganization(String organizationId) {
return restTemplate.getForObject(
"http://organization-service/v1/organizations/{organizationId}",
Organization.class, organizationId
);
}
✔ "organization-service"라는 논리적 이름을 사용하여 Eureka에서 서비스 위치를 동적으로 조회
✔ 실제 HTTP 요청이 발생할 때 Eureka에서 적절한 서비스 인스턴스를 선택하여 요청을 보냄
📌 Spring Boot 설정 (@LoadBalanced
)
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
✔ @LoadBalanced
를 추가하면 RestTemplate이 Eureka와 연동되어 자동으로 서비스 위치를 탐색
3️⃣ Feign Client 활용
📌 Feign Client 인터페이스 정의
@FeignClient("organization-service")
public interface OrganizationFeignClient {
@GetMapping("/v1/organizations/{organizationId}")
Organization getOrganization(@PathVariable("organizationId") String organizationId);
}
✔ Feign을 사용하면 인터페이스만 정의하면 Eureka 기반으로 서비스를 호출할 수 있음
✔ 실제 HTTP 요청 없이 자동으로 Eureka에서 "organization-service"의 위치를 탐색하고 호출
📌 Feign Client 활성화 (@EnableFeignClients
)
@EnableFeignClients
@SpringBootApplication
public class LicenseServiceApplication {
}
✔ Feign을 활성화하면 Eureka와 자동으로 연동되어 REST 요청을 간결하게 작성 가능
🎯 6. 서비스 호출 예제
✅ Discovery Client 방식
GET http://localhost:8082/v1/organization/123/license/456/discovery
✅ Load Balanced RestTemplate 방식
GET http://localhost:8082/v1/organization/123/license/456/rest
✅ Feign Client 방식
GET http://localhost:8082/v1/organization/123/license/456/feign
📌 모든 방식은 Eureka에서 Organization Service의 위치를 탐색하여 자동으로 적절한 인스턴스를 호출
🏆 결론
이번 글에서는 Eureka를 활용하여 마이크로서비스를 동적으로 탐색하는 방법을 살펴봤습니다. 🚀
✔ Spring Discovery Client → 가장 직접적인 방법
✔ RestTemplate + LoadBalancer → 중간 수준의 추상화
✔ Feign Client → 가장 간결하고 직관적인 방식
'Spring Microservice' 카테고리의 다른 글
Load Balancer를 지원하는 Spring RestTemplate을 활용한 서비스 호출 (0) | 2025.03.14 |
---|---|
Spring Discovery Client (0) | 2025.03.14 |
Spring Boot 마이크로서비스를 Eureka Server에 등록하기 (0) | 2025.03.14 |
Spring Cloud & Netflix Eureka를 활용한 서비스 디스커버리 구현 (0) | 2025.03.14 |
클라우드 기반 서비스 디스커버리 아키텍처 분석 (0) | 2025.03.14 |