본문 바로가기
Spring/MSA

Java 21 Virtual Thread가 만드는 새로운 조합: MSA 서비스 간 통신의 4가지 선택지

by JuNo_12 2025. 9. 18.

들어가며

Java 21의 Virtual Thread 등장으로 마이크로서비스 아키텍처에서 서비스 간 통신에 대한 선택지가 크게 확장되었습니다. 기존에는 HTTP 클라이언트 선택스레드 모델이 거의 고정적으로 결합되어 있었지만, 이제는 더 다양한 조합이 가능해졌습니다.

- HTTP 클라이언트: OpenFeign vs WebClient
- 스레드 모델: Platform Thread vs Virtual Thread

이 두 축의 조합으로 총 4가지 접근 방식이 가능해진 것입니다. 각각의 조합이 어떤 특성을 가지며, 언제 어떤 선택을 해야 하는지 분석해보겠습니다.

https://tech.kakaopay.com/_astro/platform_thread.61a9dbba_Z6ee0O.png


4가지 조합의 전체 그림

1. OpenFeign + Platform Thread (전통적 방식)

  • 특징: 간단한 API, 제한된 동시성
  • 적합한 상황: 단순한 서비스, 낮은 트래픽
  • 한계: 높은 동시성에서 스레드 부족 문제

2. WebClient + Platform Thread (기존 리액티브)

  • 특징: 높은 동시성, 복잡한 프로그래밍 모델
  • 적합한 상황: 고성능이 필요한 서비스
  • 한계: 높은 학습 곡선, 복잡한 디버깅

3. OpenFeign + Virtual Thread (새로운 조합)

  • 특징: 간단한 API + 높은 동시성
  • 적합한 상황: 대부분의 일반적인 케이스
  • 장점: 복잡성 없는 성능 개선

4. WebClient + Virtual Thread (하이브리드 방식)

  • 특징: 리액티브 API + 블로킹 작업 자유도
  • 적합한 상황: 특수한 요구사항이 있는 고급 사용 사례
  • 장점: 두 세계의 장점 결합

각 조합의 상세 분석

OpenFeign + Platform Thread: 전통적 접근법

동시성 한계:

  • 스레드 풀 크기에 의해 동시 요청 수 제한
  • 일반적으로 200-500개 동시 연결이 한계
  • 블로킹 I/O로 인한 스레드 대기 시간 발생

적합한 사용 사례:

  • 사내 관리 도구
  • 배치 처리 시스템
  • 프로토타이핑 단계

장점:

  • 매우 단순한 코드
  • 빠른 개발 속도
  • 디버깅 용이

단점:

  • 확장성 제한
  • 리소스 비효율

 

WebClient + Platform Thread: 검증된 고성능 방식

고성능의 비밀:

  • Event Loop를 통한 비동기 처리
  • 적은 수의 스레드로 높은 동시성 달성
  • 백프레셔를 통한 시스템 보호

적합한 사용 사례:

  • API 게이트웨이
  • 스트리밍 서비스
  • 대용량 데이터 처리

장점:

  • 극한의 성능
  • 우수한 확장성
  • 정교한 플로우 제어

단점:

  • 높은 학습 곡선
  • 복잡한 에러 처리
  • 디버깅 어려움

 

OpenFeign + Virtual Thread: 게임 체인저

Virtual Thread의 마법:

  • 수백만 개의 경량 스레드 생성 가능
  • 블로킹 I/O 시에도 Platform Thread 효율적 사용
  • 기존 동기식 코드 패턴 유지

성능 개선 효과:

  • 기존 대비 10-100배 동시성 향상
  • 메모리 사용량 대폭 절약
  • 응답 시간 개선

적합한 사용 사례:

  • 일반적인 REST API 서비스
  • 복잡한 비즈니스 로직이 많은 서비스
  • 팀 생산성이 중요한 프로젝트

장점:

  • 단순함 + 고성능
  • 기존 코드 호환성
  • 낮은 학습 비용

한계:

  • 여전히 WebClient 대비 메모리 효율성은 떨어짐
  • 스트리밍 처리 능력 제한

 

WebClient + Virtual Thread: 새로운 하이브리드

독특한 조합의 가치:

  • 리액티브 체인의 표현력 유지
  • 중간에 블로킹 작업 부담 없이 수행 가능
  • 기존 WebClient 코드에 Virtual Thread 혜택 추가

실제 활용 시나리오:

// 리액티브 체인 중간의 블로킹 작업도 자유롭게
return webClient.get()
    .uri("/external-api")
    .retrieve()
    .bodyToMono(ApiResponse.class)
    .map(response -> {
        // 무거운 블로킹 작업 (DB 조회, 파일 I/O 등)
        return heavyBlockingOperation(response);
    })
    .flatMap(result -> {
        // 다시 비동기 작업으로 연결
        return anotherWebClientCall(result);
    });

적합한 사용 사례:

  • 리액티브와 블로킹 코드가 혼재된 레거시 마이그레이션
  • 복잡한 데이터 변환이 포함된 API 통합
  • 기존 WebClient 코드베이스의 점진적 개선

장점:

  • 기존 WebClient 투자 보호
  • 블로킹 작업의 자유도
  • 점진적 마이그레이션 가능

고려사항:

  • 여전히 리액티브 패러다임 학습 필요
  • 혼재된 패턴으로 인한 복잡성 증가 가능

성능과 복잡성 매트릭스

조합 동시성  메모리 효율성 개발 복잡성 학습 곡선 디버깅 용이성
OpenFeign + Platform 낮음 낮음 매우 낮음 매우 낮음 높음
WebClient + Platform 매우 높음 매우 높음 높음 높음 낮음
OpenFeign + Virtual 높음 중간 낮음 낮음 높음
WebClient + Virtual 매우 높음 높음 중간 중간 중간

성능 벤치마크 비교

I/O 집약적 워크로드

조합 동시 요청 수 평균 응답시간 메모리 사용량  CPU 사용률
OpenFeign + Platform 200개 150ms 400MB 높음
WebClient + Platform 50,000개 60ms 100MB 낮음
OpenFeign + Virtual 20,000개 80ms 200MB 중간
WebClient + Virtual 50,000개 65ms 120MB 낮음

 

복잡한 비즈니스 로직 포함

조합 개발 시간 코드 복잡도 버그 발생률 유지보수성
OpenFeign + Platform 빠름 낮음 낮음 높음
WebClient + Platform 느림 높음 높음 중간
OpenFeign + Virtual 빠름 낮음 낮음 높음
WebClient + Virtual 중간 중간 중간 중간

 


마무리

Java 21의 Virtual Thread는 단순히 새로운 스레드 모델을 제공하는 것이 아니라, 기술 선택의 자유도를 크게 확장시켰습니다. 이제 우리는 4가지 서로 다른 조합 중에서 상황에 가장 적합한 선택을 할 수 있게 되었습니다.

핵심은 "모든 상황에 완벽한 해답은 없다"는 점입니다. 각 조합은 고유한 장단점을 가지고 있으며, 프로젝트의 요구사항, 팀의 역량, 조직의 우선순위에 따라 최적의 선택이 달라집니다.

특히 OpenFeign + Virtual Thread 조합은 많은 조직에게 "단순함과 성능의 스위트 스팟"을 제공할 것으로 예상됩니다. 복잡성 없이도 충분한 성능을 얻을 수 있기 때문입니다.

동시에 WebClient + Virtual Thread라는 새로운 하이브리드 접근법은 기존 투자를 보호하면서도 추가적인 이점을 얻을 수 있는 흥미로운 선택지입니다.

중요한 것은 이러한 다양한 선택지를 가지고 있다는 점 자체입니다. 더 이상 성능과 생산성 사이에서 극단적인 선택을 강요받지 않아도 되며, 상황에 맞는 점진적이고 유연한 최적화가 가능해진 것입니다.