💡 오늘 학습 키워드
- Service Discovery
- Spring Cloud LoadBalancer
🎯 학습 내용 정리
마이크로서비스 아키텍처에서는 하나의 서비스가 다른 서비스를 호출하는 일이 매우 빈번하게 발생한다. 예를 들어 주문 서비스는 상품 정보를 조회하기 위해 상품 서비스를 호출해야 하며, 회원 서비스의 정보도 함께 조회할 수 있다.
하지만 서비스가 여러 대의 서버에서 실행되고 있다면 어느 서버로 요청을 보내야 할까?
서비스가 새로 생성되거나 종료될 때마다 변경되는 IP 주소를 애플리케이션이 직접 관리해야 할까?
이러한 문제를 해결할 수 있는 기술에 대해서 알아보자.
MSA에서는 하나의 서비스가 여러 개의 인스턴스로 실행되는 경우가 많다.
예를 들어 Product Service가 다음과 같이 실행될 수 있다.
Product Service
192.168.0.10:8080
192.168.0.11:8080
192.168.0.12:8080
Order Service는 Product Service를 호출해야 하지만 어떤 서버가 살아있는지 알 수 없다. 더 큰 문제는 서버가 계속 생성되고 종료된다는 점이다. 클라우드 환경에서는 Auto Scaling이 수행되면서 서비스 인스턴스가 실시간으로 변경된다. IP 주소를 직접 관리하는 방식으로는 이러한 환경을 대응하기 어렵다.
이 문제를 해결하기 위해 등장한 것이 Service Discovery이다.
Eureka는 Netflix에서 개발한 Service Discovery Server이다. 서비스들의 위치(IP, Port)를 중앙에서 관리하는 역할을 수행한다. 모든 서비스는 실행되면 Eureka 서버에 자신의 정보를 등록한다. 다른 서비스는 Eureka에게 필요한 서비스의 위치를 물어본 뒤 해당 서비스와 통신한다.
즉, Eureka는 서비스들의 전화번호부 역할을 수행한다고 이해하면 된다.
서비스 등록과 조회는 다음과 같은 구조로 이루어진다.
Eureka Server
│
┌───────────────┼───────────────┐
│ │ │
User Service Order Service Product Service
각 서비스는 실행 시 Eureka에 자신의 정보를 등록한다. Order Service는 Product Service를 호출하기 전에 Eureka에서 Product Service의 위치를 조회한다.
Eureka 서버는 다음과 같이 구성한다.
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
여기서 중요한 옵션은 다음과 같다.
- register-with-eureka : 자기 자신을 등록하지 않는다.
- fetch-registry : 다른 Eureka 서버 정보를 가져오지 않는다.
즉, 해당 서버는 서비스 등록만 담당하는 중앙 서버가 된다.
서비스는 Eureka Client 의존성을 추가하면 쉽게 등록할 수 있다.
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
이후 application.yml을 작성한다.
spring:
application:
name: product-service
eureka:
client:
service-url:
defaultZone: <http://localhost:8761/eureka>
애플리케이션이 실행되면 자동으로 Eureka 서버에 등록된다.
서비스가 실행되면 다음과 같은 과정이 진행된다.
Product Service 실행
↓
Eureka Server 등록
↓
Heartbeat 전송
↓
Registry 저장
이후 일정 시간마다 Heartbeat를 보내면서 살아있음을 알린다.
Heartbeat가 일정 시간 동안 도착하지 않으면 Eureka는 해당 서비스를 Registry에서 제거한다.
Order Service가 Product Service를 호출하는 과정을 살펴보자.
Order Service
↓
Eureka 조회
↓
Product Service 주소 획득
↓
HTTP 요청
개발자는 Product Service의 IP를 알 필요가 없다.
서비스 이름만 알고 있으면 된다.
Spring에서는 RestTemplate으로 다른 서비스를 호출할 수 있다.
먼저 Bean을 등록한다.
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
여기서 가장 중요한 부분은
@LoadBalanced
이다.
이 어노테이션이 있어야 Eureka와 연동하여 서비스 이름으로 호출할 수 있다.
실제 호출 코드는 다음과 같다.
@RestController
@RequiredArgsConstructor
public class OrderController {
private final RestTemplate restTemplate;
@GetMapping("/orders")
public String getOrders() {
return restTemplate.getForObject(
"<http://product-service/products>",
String.class
);
}
}
여기서
product-service
는 IP 주소가 아니다.
Eureka에 등록된 서비스 이름이다.
RestTemplate은 비교적 단순하지만 다음과 같은 단점이 존재한다.
- URL을 직접 작성해야 한다.
- HTTP Method를 직접 관리해야 한다.
- 코드가 길어진다.
- 인터페이스 기반 개발이 어렵다.
이러한 문제를 해결하기 위해 등장한 것이 OpenFeign이다.
OpenFeign은 선언형 HTTP Client이다.
인터페이스만 작성하면 Spring이 자동으로 구현체를 생성해준다. 개발자는 일반 메서드를 호출하는 것처럼 다른 서비스를 사용할 수 있다.
OpenFeign 의존성
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
그리고
@EnableFeignClients
를 추가한다.
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
}
먼저 인터페이스를 작성한다.
@FeignClient(name = "product-service")
public interface ProductClient {
@GetMapping("/products")
List<ProductResponse> getProducts();
}
이제 일반 객체처럼 사용할 수 있다.
@Service
@RequiredArgsConstructor
public class OrderService {
private final ProductClient productClient;
public List<ProductResponse> products() {
return productClient.getProducts();
}
}
HTTP 호출이라는 사실을 거의 느끼지 못할 정도로 코드가 간결해진다.
둘의 차이점을 정리해보면 다음과 같다.
| 항목 | RestTemplate | OpenFeign |
| 사용 방식 | 직접 HTTP 호출 | 인터페이스 기반 |
| 코드 양 | 많음 | 적음 |
| 가독성 | 낮음 | 높음 |
| 유지보수 | 불편 | 편리 |
| Eureka 연동 | 가능 | 가능 |
| LoadBalancer | 가능 | 가능 |
최근 Spring Cloud에서는 대부분 OpenFeign을 사용하는 것이 일반적이다.
2. Spring Cloud LoadBalancer
Spring Cloud LoadBalancer를 알아보기 전에 LoadBalancer가 무엇인지 먼저 알아보자.
LoadBalancing은 클라이언트의 요청을 여러 서버에 적절하게 분산하여 처리하는 기술이다.
예를 들어 Product Service가 3개의 인스턴스로 실행 중이라고 가정해보자.
Client
|
Load Balancer
┌──────┼──────┐
Product-1 Product-2 Product-3
로드 밸런서는 요청을 각 서버에 적절히 분배하여 특정 서버에만 부하가 집중되는 것을 방지한다.
이를 통해
- 성능 향상
- 서버 과부하 방지
- 높은 가용성
- 수평 확장
을 얻을 수 있다.
로드 밸런싱은 크게 두 가지 방식으로 나뉜다.
Server Side Load Balancing
로드 밸런서가 서버 앞에서 요청을 분산한다.
대표적으로
- Nginx
- HAProxy
- AWS ALB
등이 있다.
Client
|
Nginx
├── Server1
├── Server2
└── Server3
클라이언트는 실제 서버 위치를 알지 못한다.
Client Side Load Balancing
클라이언트가 직접 서버를 선택한다.
MSA에서는 대부분 이 방식을 사용한다.
Client(Service)
↓
Service Discovery
↓
Server 선택
↓
요청 전송
Spring Cloud LoadBalancer가 바로 이 역할을 수행한다.
Ribbon은 Netflix에서 개발한 Client Side Load Balancer이다.
서비스 인스턴스가 여러 개 존재할 때 어느 서버를 호출할지 결정하는 역할을 수행한다.
예를 들어
Product Service
Server A
Server B
Server C
세 개의 인스턴스가 있다면
Ribbon이
- A
- B
- C
순서로 요청을 분배한다.
기본 알고리즘은 Round Robin이다.
Netflix OSS 프로젝트가 유지보수 종료되면서 Ribbon도 함께 더 이상 개발되지 않는다.
Spring Cloud는 Ribbon을 제거하고 자체적으로 Spring Cloud LoadBalancer를 제공하기 시작했다. 현재 Spring Boot 3.x와 Spring Cloud 최신 버전에서는 Ribbon 대신 Spring Cloud LoadBalancer를 사용하는 것이 표준이다.
즉,
- 과거 → Ribbon
- 현재 → Spring Cloud LoadBalancer
라고 이해하면 된다.
Spring Cloud LoadBalancer는 Ribbon과 동일한 역할을 수행한다.
차이점은 Spring Cloud에서 공식적으로 관리하는 컴포넌트라는 것이다.
대표적인 기능은 다음과 같다.
- Round Robin
- 서비스 인스턴스 선택
- Eureka 연동
- 확장 가능한 Load Balancing 전략
개발자가 별도의 설정 없이도 Eureka와 함께 사용할 수 있다.
Order Service가 Product Service를 호출하는 과정을 순서대로 살펴보자.
Client
↓
Order Service
↓
OpenFeign
↓
Spring Cloud LoadBalancer
↓
Eureka 조회
↓
Product Service 선택
↓
HTTP 호출
↓
응답 반환
즉,
- OpenFeign이 호출된다.
- LoadBalancer가 서비스 목록을 가져온다.
- 적절한 인스턴스를 선택한다.
- Product Service를 호출한다.
- 응답을 반환한다.
이 과정에서 개발자는 서비스의 실제 주소를 알 필요가 없다.
다음과 같은 환경을 가정해 보자.
Order Service : 1대
Product Service : 3대
Product Service는 다음과 같이 실행되고 있다.
Product-1
Product-2
Product-3
Order Service에서 Product Service를 6번 호출하면
1 → Product-1
2 → Product-2
3 → Product-3
4 → Product-1
5 → Product-2
6 → Product-3
처럼 Round Robin 방식으로 요청이 분배된다.
이 덕분에 특정 서버에 부하가 집중되지 않는다.
MSA에서는 서비스의 위치가 계속 변경되기 때문에 IP 주소를 직접 관리하는 방식으로는 안정적인 서비스 운영이 어렵다. Eureka는 이러한 문제를 해결하기 위해 서비스 등록과 검색 기능을 제공하며, OpenFeign과 Spring Cloud LoadBalancer는 이를 기반으로 서비스 간 통신과 로드 밸런싱을 자동으로 처리한다.
덕분에 개발자는 서비스의 실제 주소를 신경 쓰지 않고 서비스 이름만으로 안정적인 통신을 구현할 수 있으며, 변화하는 클라우드 환경에서도 유연하게 대응할 수 있다.
📚 한줄 정리
1. Service Discovery는 서비스의 위치를 동적으로 관리하여 마이크로서비스 간 통신을 가능하게 하는 핵심 기술이다.
2. Spring Cloud LoadBalancer는 여러 서비스 인스턴스에 요청을 효율적으로 분산하여 성능과 가용성을 높이는 로드 밸런서이다.
'Bootcamp > Fundamentals' 카테고리의 다른 글
| API Gateway와 OAuth2 / JWT (0) | 2026.07.03 |
|---|---|
| Circuit Breaker와 Resilience4j (0) | 2026.07.02 |
| MSA와 Spring Cloud (0) | 2026.06.30 |
| MSA 요약 (0) | 2026.06.29 |
| Spring 심화 (0) | 2026.06.26 |