RestClient는 어떻게 생성이 될까?

2026. 1. 31. 03:06·Backend/Spring Boot

Introduce

Spring Boot 애플리케이션에서 외부 API를 호출하는 일은 매우 흔하다.

 

Spring 6부터는 기존 RestTemplate을 대체하는 새로운 HTTP 클라이언트로 RestClient가 도입되었고, 비교적 단순한 API 덕분에 빠르게 적용할 수 있다는 장점이 있다.

 

하지만 실제로 RestClient를 사용하다 보면 이런 궁금증이 생긴다.

  • RestClient.create()는 내부적으로 무엇을 만들까?
  • builder() 방식과는 어떤 차이가 있을까?
  • 매번 새로 만들어도 괜찮을까, 아니면 재사용해야 할까?

 

이 글에서는 RestClient가 생성되는 방식과 내부 동작 구조를 직접 뜯어보며 살펴본다.

 


RestClient Construction

RestClient는 두 가지 API로 생성할 수 있다. 둘 다 내부적으로는 DefaultRestClientBuilder를 사용하지만, 커스터마이징이 필요한지 여부에 따라 선택 기준이 갈린다.

 

📌 create - 기본값 빠른 생성

 

겉보기에는 RestClient.create() 같은 정적 메서드로 바로 생성되는 것처럼 보이지만, 실제로 RestClient는 빌더를 통해서만 생성되는 객체다. create() 역시 내부적으로는 다음과 같은 흐름을 가진다.

  1. DefaultRestClientBuilder 생성
  2. 기본 설정 주입
  3. build() 호출
  4. 최종 RestClient 반환

즉, RestClient 생성의 중심에는 항상 Builder가 존재한다.


 

📌 builder() - 커스터마이징 가능

 

DefaultRestClientBuilder는 RestClient를 구성하기 위한 모든 설정을 필드로 보관한다. 대표적으로 다음과 같은 요소들이 있다.

  • ClientHttpRequestFactory
  • HttpMessageConverter
  • Header
  • Interceptor
  • baseUrl

이 시점에서는 아직 HTTP 호출을 할 수 있는 객체가 아니다. 단지 “어떤 설정으로 RestClient를 만들 것인가”에 대한 정의만 존재한다.


Internal Configuration

📌 DefaultRestClientBuilder

 

build()는 요청을 보낼 때 필요한 기본 구성 요소들을 한 번에 조립하고 있다.

 

ClientHttprequestFactory 로 실제 HTTP 전송 엔진을 결정하고, UriBuilderFactory 로 baseUrl, 템플릿 기반의 최종 URI를 생성하며 HttpMessageConverter 를 통해 바디의 직렬화와 역직렬화를 처리한다.


📌 Request Factory

HttpMessageConverter 는 스프링을 사용하다 보면 필연적으로 접하는 클래스라 어떤 역할을 하는지 알고 있고, UriBuilderFactory 는 최종 URI를 생성한다는 것이 직관적으로 잘 이해가 된다.

 

하지만 ClientHttprequestFactory 로 실제 HTTP 전송 엔진을 결정한다는 것이 잘 이해가 되지 않는다.

결정한다라는 말의 의미는 “여러가지의 case 중 1가지를 선택한다” 와 같은 의미이다.

 

그렇다면 ClientHttprequestFactory 로 결정할 수 있는 전송 엔진은 어떤 것이 있고, 어떤 식으로 결정될까?

 

REST Clients :: Spring Framework

You can define an HTTP Service as a Java interface with @HttpExchange methods, and use HttpServiceProxyFactory to create a client proxy from it for remote access over HTTP via RestClient, WebClient, or RestTemplate. On the server side, an @Controller class

docs.spring.io

이는 문서에서 확인할 수 있다.

 

❗️ 구현체에 대한 설명은 AI에 도움을 받았습니다.
  1. JdkClientHttpRequestFactory : JDK HttpClient를 쓰는 표준 구현체
  2. HttpComponentsClientHttpRequestFactory : Apache HttpClient 기반의 고급 튜닝, 풀링 구현체
  3. JettyClientHttpRequestFactory: Jetty HttpClient를 사용하는 구현체
  4. ReactorNettyClientRequestFactory : Reactor Netty HttpClient로 전송하는 구현체
  5. SimpleClientHttpRequestFactory :HttpURLConnection 기반의 가장 단순한 구현체

5가지의 구현체들이 등록될 수 있는데 그렇다면 어떤 것이 어떤 기준으로 선택되는 것일까?

공식 문서에 결정 순서가 명시돼 있다.

 

Request Factory를 지정하지 않았다면 클래스패스 존재 여부를 체크한다.
그리고 `HttpComponents` → `Jetty`→ `Reactor` -> `Netty` → `JDK` -> `Simple` 순서로 결정된다고 한다.

그리고 이는 내부 구현 코드에서도 명확하게 알 수 있는데

static 블록에서 ClassLoader로 각 HTTP 클라이언트 구현체의 존재 여부를 한번만 확인하고, 그 결과를 플래그로 캐싱한다. 그러므로 클래스가 최초로 메모리에 로드될때 static 블록으로 인해 클래스 패스가 존재하는지 여부가 결정되는 것이다.

 


Conclusion

결과적으로 build() 가 호출되는 순간에 실제 RestClient 인스턴스가 생성된다.

이는 Builder에 누적된 설정값을 기반으로 내부 요소들을 조립하고, 이후에는 설정을 변경할 수 없는 실행 전용 객체로 완성되는 것이다.


Spring 문서에서는 이렇게 생성된 RestClient 인스턴스가 여러 스레드에서 안전하게 사용될 수 있다고 명시하고 있다.

'Backend > Spring Boot' 카테고리의 다른 글

자바와 스프링의 비동기 처리 - 2편: CompletableFuture의 예외 처리와 타임 아웃  (4) 2025.08.01
자바와 스프링의 비동기 처리 - 1편: CompletableFuture 톺아보기  (3) 2025.07.11
스프링 이벤트를 발행하여 트랜잭션과 관심사 분리하기  (2) 2025.04.29
동시성 문제에 대한 고찰, 점진적으로 접근하기  (0) 2025.03.17
'Backend/Spring Boot' 카테고리의 다른 글
  • 자바와 스프링의 비동기 처리 - 2편: CompletableFuture의 예외 처리와 타임 아웃
  • 자바와 스프링의 비동기 처리 - 1편: CompletableFuture 톺아보기
  • 스프링 이벤트를 발행하여 트랜잭션과 관심사 분리하기
  • 동시성 문제에 대한 고찰, 점진적으로 접근하기
WooJJam
WooJJam
  • WooJJam
    우쨈의 개발 블로그
    WooJJam
  • 전체
    오늘
    어제
    • 분류 전체보기 (17)
      • 끄적끄적 (1)
      • Backend (7)
        • Spring Boot (5)
        • MySQL (1)
        • Java (1)
      • DevOps (6)
        • Monitoring (3)
        • Deployment (1)
        • Github Actions (2)
      • Computer Science (3)
        • Network (1)
        • Operating System (0)
        • Database (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 공지사항

  • 인기 글

  • 태그

    공간인덱스
    GitHub Actions
    동시성
    TransactionalEventListener
    promtail
    스프링 이벤트
    non repeatable
    비관적 락
    CompletableFuture
    트랜잭션 분리
    모니터링
    로깅 시스템
    List.of
    낙관적 락
    비동기
    self-hosted runner
    plg stack
    devops
    격리 수준
    GitHub hosted runner
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
WooJJam
RestClient는 어떻게 생성이 될까?
상단으로

티스토리툴바