Spring Discovery Client

2025. 3. 14. 17:49Spring Microservice

🌐 Spring Discovery Client를 활용한 서비스 탐색과 호출 🚀

마이크로서비스 환경에서 서비스 탐색(Service Discovery) 은 필수적인 기능입니다.
Spring Cloud는 이를 위해 Spring Discovery Client 를 제공하며, 이를 활용하면 Eureka에 등록된 서비스 목록을 조회하고 동적으로 서비스 위치를 찾을 수 있습니다.

이번 글에서는 Spring Discovery Client를 활용하여 Organization Service를 탐색하고 호출하는 방법을 살펴보겠습니다.

🎯 1. Spring Discovery Client란?

Spring Discovery ClientSpring Cloud Load Balancer와 통합되어 서비스 목록을 조회할 수 있도록 도와주는 가장 낮은 수준의 API 입니다.

Discovery Client를 사용하면:

  • Eureka에 등록된 서비스 목록을 조회할 수 있음
  • 특정 서비스의 모든 인스턴스를 가져올 수 있음
  • 서비스의 동적인 위치를 탐색하여 직접 호출 가능

하지만 Discovery Client만 단독으로 사용하면 몇 가지 단점이 발생할 수 있습니다. 🤔
이에 대한 자세한 내용은 후반부에서 다루겠습니다.

🏗 2. Spring Discovery Client 설정

Spring Boot 애플리케이션에서 Spring Discovery Client를 사용하려면 @EnableDiscoveryClient를 추가해야 합니다.

📌 LicenseServiceApplication.java

package com.optimagrowth.license;

@SpringBootApplication
@RefreshScope
@EnableDiscoveryClient  // Discovery Client 활성화
public class LicenseServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(LicenseServiceApplication.class, args);
    }
}

@EnableDiscoveryClient

  • 해당 애플리케이션이 Eureka를 통해 서비스 탐색 기능을 사용할 수 있도록 설정
  • Spring Cloud Load Balancer를 활용할 준비 완료

이제 Discovery Client를 이용하여 Organization Service를 찾고 호출하는 코드를 작성해보겠습니다.

🔍 3. Discovery Client를 활용한 서비스 탐색 및 호출

📌 OrganizationDiscoveryClient.java

@Component
public class OrganizationDiscoveryClient {

    @Autowired
    private DiscoveryClient discoveryClient; // Eureka에서 서비스 탐색

    public Organization getOrganization(String organizationId) {
        RestTemplate restTemplate = new RestTemplate(); // RestTemplate 직접 생성

        // Eureka에서 "organization-service" 조회
        List<ServiceInstance> instances = discoveryClient.getInstances("organization-service");

        // 등록된 서비스 인스턴스가 없으면 null 반환
        if (instances.isEmpty()) return null;

        // 첫 번째 서비스 인스턴스를 선택하여 URL 생성
        String serviceUri = String.format("%s/v1/organization/%s",
                instances.get(0).getUri().toString(), organizationId);

        // RestTemplate을 이용한 서비스 호출
        ResponseEntity<Organization> restExchange = restTemplate.exchange(
                serviceUri, HttpMethod.GET, null, Organization.class, organizationId
        );

        return restExchange.getBody();
    }
}

discoveryClient.getInstances("organization-service")

  • Eureka에서 organization-service로 등록된 모든 인스턴스를 조회

첫 번째 서비스 인스턴스를 선택 (instances.get(0))

  • 여러 개의 인스턴스가 실행 중이라면 첫 번째 인스턴스만 사용
  • 즉, 로드 밸런싱이 적용되지 않음 🚨

RestTemplate을 이용해 직접 서비스 호출

  • 조회된 서비스 URI를 기반으로 Organization Service 호출

⚠️ 4. Discovery Client를 사용할 때 주의할 점

Discovery Client는 직접적인 서비스 탐색이 가능하지만 몇 가지 단점이 있습니다.

1️⃣ Spring Cloud Load Balancer를 활용하지 않음

💡 문제점:

  • Discovery Client를 사용하면 서비스 목록을 가져올 수 있지만, 어떤 인스턴스를 호출할지는 직접 결정해야 함
  • 즉, 클라이언트가 직접 로드 밸런싱을 구현해야 함 😥

💡 해결책:

  • Spring Cloud가 제공하는 로드 밸런싱 기능을 활용하는 것이 더 효율적
  • 예: Load Balanced RestTemplate, Feign Client 활용

2️⃣ 직접 URL을 생성해야 함

💡 문제점:

  • Discovery Client를 사용할 경우 직접 URL을 생성해서 요청을 보내야 함
  • 코드의 복잡성이 증가하고, 실수할 가능성이 높아짐

💡 해결책:

  • Load Balanced RestTemplate을 사용하면 자동으로 Eureka에서 올바른 서비스 인스턴스를 찾아줌
  • 또는 Feign Client를 사용하면 URL을 직접 지정할 필요가 없음

3️⃣ RestTemplate을 직접 생성하면 Interceptor가 적용되지 않음

💡 문제점:

  • Spring Boot에서는 RestTemplate을 @Autowired로 주입받아 사용하는 것이 일반적
  • 하지만 위 코드에서는 new RestTemplate()을 사용하여 Spring Cloud의 Load Balancer Interceptor가 적용되지 않음

💡 해결책:

  • RestTemplate을 Bean으로 등록하고 @LoadBalanced 애너테이션을 추가

📌 수정된 RestTemplate 등록 코드

@Bean
@LoadBalanced
public RestTemplate restTemplate() {
    return new RestTemplate();
}

✔ 이렇게 설정하면 RestTemplate이 Eureka와 연동되어 동적으로 서비스 인스턴스를 선택할 수 있음

🎯 5. Discovery Client 대신 더 좋은 방법이 있을까?

Discovery Client는 서비스 탐색 기능을 제공하지만, 더 효율적인 방법들이 있습니다.

Discovery Client → Load Balanced RestTemplate 사용하기

@Autowired
private RestTemplate restTemplate;

public Organization getOrganization(String organizationId) {
    return restTemplate.getForObject(
        "http://organization-service/v1/organization/{organizationId}",
        Organization.class, organizationId
    );
}

http://organization-serviceEureka에서 자동으로 해당 서비스의 위치를 찾음
로드 밸런싱이 자동으로 적용됨

Feign Client 사용하기 (가장 간단한 방법)

@FeignClient("organization-service")
public interface OrganizationFeignClient {
    @GetMapping("/v1/organization/{organizationId}")
    Organization getOrganization(@PathVariable("organizationId") String organizationId);
}

Feign Client는 인터페이스만 정의하면 Eureka 기반으로 자동 호출 가능

🏆 결론

이번 글에서는 Spring Discovery Client를 활용하여 Eureka에서 서비스 목록을 조회하고 호출하는 방법을 살펴봤습니다. 🚀

Discovery Client를 사용하면 특정 서비스의 인스턴스를 조회할 수 있음
하지만 직접 URL을 생성해야 하고, 로드 밸런싱이 적용되지 않음 😥
Load Balanced RestTemplate 또는 Feign Client를 사용하면 Eureka와의 연동이 훨씬 간편해짐 🎯