상세 컨텐츠

본문 제목

[스프링 1팀] 12장. 서버 간 통신

24-25/Spring 1

by oze 2025. 1. 24. 12:06

본문

728x90

 

마이크로서비스 아키텍처 (MSA)

: 애플리케이션이 가지고 있는 기능(서비스)이 하나의 비즈니스 범위만 가지는 형태

 

📌 애플리케이션 : 자신의 기능을 API로 외부에 노출하고, 다른 서버가 API를 호출해서 사용할 수 있게 구성됨

⇒ 각 서버가 다른 서버의 클라이언트가 되는 경우가 많음

 

RestTemplate

: 스프링에서 HTTP 통신 기능을 손쉽게 사용하도록 설계된 템플릿으로 RESTful 원칙을 따르는 서비스를 편리하게 만들 수 있음

→ 주로 동기 방식으로 처리 / AsyncRestTemplate를 통해 비동기 방식 사용 가능 / 현재 지원 중단 상태

 

특징

  • HTTP 프로토콜의 메서드에 맞는 여러 메서드 제공
  • RESTful 형식을 갖춘 템플릿
  • HTTP 요청 후 JSON, XML, 문자열 등의 다양한 형식으로 응답 받을 수 있음
  • 블로킹 I/O 기반의 동기 방식 사용
  • 다른 API 호출 시 HTTP 헤더에 다양한 값 설정 가능

 

동작 원리

동작 방식

  • 애플리케이션 : 직접 작성하는 애플리케이션 코드 구현부
    • RestTemplate 선언, URI와 HTTP 메서드, Body 등 설정
  • 외부 API로 요청 보냄
    • RestTemplate에서 HttpMessageConverter를 통해 RequestEntitiy를 요청 메시지로 변환
    • RestTemplate에서 변환된 요청 메시지를 ClientHttpRequestFactory를 통해 ClientHttpRequest로 가져온 외부 API로 요청을 보냄
  • 외부에서 요청에 대한 응답 받음
    • RestTemplate은 ResponseErrorHandler로 오류 확인
    • 오류가 있으면 ClientHttpResponse에서 응답 데이터 처리
    • 오류가 없으면 HttpMessageConverter를 거쳐 자바 객체로 변환해서 애플리케이션으로 반환

 

대표적인 메서드

메서드 HTTP 형태 설명
getForObject  GET GET 형식으로 요펑한 결과를 객체로 반환
getForEntity  GET GET 형식으로 요청한 결괄를 ResponseEntity 결과를 반환
postForLocation  POST POST 형식으로 요청한 결과를 헤더에 저장된 URI로 반환
postForObject POST POST 형식으로 요청한 결과를 객체로 반환
postForEntity POST POST 형식으로 요청한 결과를 ResponseEntity 형식으로 반환
delete DELETE DELETE 형식으로 요청
put PUT PUT 형식으로 요청
patchForObject PATCH PATCH 형식으로 요청한 결과를 객체로 반환
optionsForAllow OPTIONS 해당 URI에서 지원하는 HTTP 메서드를 조회
 exchange 

any

HTTP 헤더를 임의로 추가할 수 있고,
어떤 메서드 형식에서도 사용할 수 있음
execute any 요청과 응답에 대한 콜백을 수정

 

 

RestTemplate 사용하기

서버 프로젝트 생성

한 컴퓨터 안에서 두 개의 프로젝트를 가동하기 위해 톰캣의 포트 변경 필요

  • 의존성 : Spring Web
  • 이름 : serverBox
  • 파일 : controller > CrudController / dto > MemberDto
  • 톰캣 포트 변경 : application.propertise 파일에 server.port=9090 추가

 

컨트롤러 클래스

→ GET, POST 메서드 형식의 요청을 받기 위한 코드

( + PUT, DELETE 메서드 : GET과 POST 형식과 각 구성 방식이 비슷하여 생략)

@RestController
@RequestMapping("/api/v1/crud-api")
public class CrudController {

    // 파라미터 없는 경우
    @GetMapping
    public String getName(){
        return "Flature";
    }

    // PathVariable 파라미터 사용하는 경우
    @GetMapping(value = "/{variable}")
    public String getVariable(@PathVariable String variable){
        return variable;
    }

    // RequestParam 파라미터 사용하는 경우
    @GetMapping("/param")
    public String getNameWithParam(@RequestParam String name){
        return "Hello" + name + "!";
    }

    // 요청 파라미터와 요청 바디 함꼐 받도록 구현
    @PostMapping
    public ResponseEntity<MemberDto> getMember(
            @RequestBody MemberDto request,
            @RequestParam String name,
            @RequestParam String email,
            @RequestParam String organization
    ) {
        System.out.println(request.getName());
        System.out.println(request.getEmail());
        System.out.println(request.getOrganization());

        MemberDto memberDto = new MemberDto();
        memberDto.setName(name);
        memberDto.setEmail(email);
        memberDto.setOrganization(organization);

        return ResponseEntity.status(HttpStatus.OK).body(memberDto);
    }

    // 임의의 HTTP 헤더를 받도록 구현
    @PostMapping(value = "/add-header")
    public ResponseEntity<MemberDto> addHeader(@RequestHeader("my-header") String header, @RequestBody MemberDto memberDto){
        System.out.println(header);

        return ResponseEntity.status(HttpStatus.OK).body(memberDto);
    }
}

 

MemeberDto 클래스

: name, email, organization으로 총 3개의 필드

public class MemberDto {
    private String name;
    private String email;
    private String organization;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getOrganization() {
        return organization;
    }

    public void setOrganization(String organization) {
        this.organization = organization;
    }

    @Override
    public String toString() {
        return "MemberDto{" +
                "name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", orgaization='" + organization + '\'' +
                '}';
    }
}

 

RestTemplate 구현하기

RestTemplate : 별도의 유틸리티 클래스로 생성하거나 서비스 or 비즈니스 계층에 구현됨

⇒ 앞에서 생성한 서버 프로젝트에 요청 날리기 위해 클라이언트 역할도 수행할 새로운 서버 프로젝트가 필요

앞에서 생성한 서버 프로젝트 = 서버2 / 클라이언트 : 서버를 대상으로 요청을 보내고 응답 받는 역할

 

서버 프로젝트 생성

  • groupId: com.springboot
  • artifactId: rest
  • name: rest
  • Developer Tools: Lombok, Spring Configuration Processor
  • Web: Spring Web

 

의존성

  • RestTemplate : 이미 spring-boot-starter-web 모듈에 포함된 기능 ⇒ 의존성 추가x
  • Swagger : 클라이언트 요청 구현을 위해 SwaggerConfiguration 클래스 파일과 의존성 추가 필요
 <dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger2</artifactId>
	<version>2.9.2</version>
</dependency>
<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger-ui</artifactId>
	<version>2.9.2</version>
</dependency>

 

 

GET, POST 형식의 RestTemplate 작성하기

RestTemplate 생성 및 사용 방법 ⇒ UriComponentsBuilder 사용

 

📌UriComponentsBuilder : 스프링 프레임워크에서 제공하는 클래스

  • 여러 파라미터를 연결해 URI 형식으로 만드는 기능 수행
  • 빌더 형식으로 객체 생성
@Service
public class RestTemplateService {

    // GET 부분
    // PathVariable or 파라미터를 사용하지 않는 호출 및 getForEntity로 파라미터 전달
    public String getName(){
        // uri-> restTemplate이 외부 API 요청하는데 사용 
        URI uri = UriComponentsBuilder
                .fromUriString("http://localhost:9090") // 호출부의 URL 입력
                .path("/api/v1/crud-api") // 세부 경로 입력
                .encode() // 인코딩 문자셋 설정 -> 기본값(StandardCharsets.UTF_8)
                .build() // 빌더 생성 종류 및 UriComponents 타입 리턴
                .toUri(); // URI타입으로 리턴, String 타입 리턴=> toUriString() 사용

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class); // URI와 응답받는 타입을 매개변수로 사용


        return responseEntity.getBody();
    }

    public String getNameWithPathVariable(){
        URI uri = UriComponentsBuilder
                .fromUriString("http://localhost:9090")
                .path("/api/v1/crud-api/{name}") // 중괄호에 변수명 입력
                .encode()
                .build()
                .expand("Flature") // path의 변수명에 해당하는 값을 순서대로 입력, 복수의 값을 넣어야할 경우 ',' 추가하여 구분
                .toUri();

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);

        return responseEntity.getBody();
    }

    public String getNameWithParameter(){
        URI uri = UriComponentsBuilder
                .fromUriString("http://localhost:9090")
                .path("/api/v1/crud-api/param")
                .queryParam("name", "Flature") // (키, 값) 형식으로 파라미터 추가
                .encode()
                .build()
                .toUri();

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);

        return responseEntity.getBody();
    }

    // POST 부분 -> 오부 API 요청할 떄 Body 값과 파라미터 값을 담는 방법
    public ResponseEntity<MemberDto> postWithParamAndBody(){
        // 파라미터에 값 추가하는 방법
        URI uri = UriComponentsBuilder
                .fromUriString("http://localhost:9090")
                .path("/api/v1/crud-api")
                .queryParam("name", "Flature")
                .queryParam("email", "flature@wikibooks.co.kr")
                .queryParam("organization", "Wikibooks")
                .encode()
                .build()
                .toUri();

        // RequestBody에 값을 담는 방법 -> 데이터 객체 생성 후 값을 담음
        MemberDto memberDto = new MemberDto();
        memberDto.setName("flature!!");
        memberDto.setEmail("flature@gmail.com");
        memberDto.setOrganization("Around Hub Studio");

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<MemberDto> responseEntity = restTemplate.postForEntity(uri, memberDto, MemberDto.class); // 파라미터로 데이터 객처 넣기

        // postForEntity() 메서드로 API 호출 -> 서버 프로젝트 콘솔 로그에 RequsetBody 값 출력 및 파라미터 값이 결괏값으로 리턴
        return responseEntity;
    }

    // 헤더 추가 -> 대부분 외부 API의 토큰값을 헤더에 담아 전달하는 방식
    public ResponseEntity<MemberDto> postWithHeader(){
        URI uri = UriComponentsBuilder
                .fromUriString("http://localhost:9090")
                .path("/api/v1/crud-api/add-header")
                .encode()
                .build()
                .toUri();

        MemberDto memberDto = new MemberDto();
        memberDto.setName("flature!!");
        memberDto.setEmail("flature@gmail.com");
        memberDto.setOrganization("Around Hub Studio");

        // RequestEntity -> 헤더 설정하기에 가장 편한 방법
        RequestEntity<MemberDto> requestEntity = RequestEntity
                .post(uri) // uri 설정
                .header("my-header", "Wikibooks API") // 헤더의 키 이름과 값을 설정하는 코드 -> API 명세서에 헤더에 필요한 키 값 요구하면 제시함
                .body(memberDto);

        RestTemplate restTemplate = new RestTemplate();
        // 모든 형식의 HTTP 요청 생성 가능 => RequestEntity 설정을 post가 아닌 다른 형식의 메서드 정의만으로도 쉽게 사용 가능
        ResponseEntity<MemberDto> responseEntity = restTemplate.exchange(requestEntity, MemberDto.class); 

        return responseEntity;
    }
}

 

  • URI : restTemplate가 외부 API 요청하는데 사용
  • fromUriString : 호출부의 URL 입력
  • path : 세부 경로 입력, 변수명 → 중괄호 이용해 입력
  • encode : 인코딩 문자셋 설정 → 기본값 : StandardCharsets.UTF_8
  • build : 빌더 생성 종류 및 UriComponents 타입 리턴
  • toUri : URI타입으로 리턴, String 타입 리턴=> toUriString() 사용
  • getForEntity : URI와 응답받는 타입을 매개변수로 사용
  • expand : path의 변수명에 해당하는 값을 순서대로 입력 (복수의 값 ⇒ ‘ , ‘를 이용해 구분)
  • queryParam : (키, 값) 형식으로 파라미터 추가

 

Swagger 설정 코드

: 프로젝트에서 쉽게 API를 호출할 수 있게 Swagger 설정

@Configuration
@EnableSwagger2
public class SwaggerConfiguration {
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.springboot.rest"))
                . paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                .title("Spring Boot Open API Test with Swagger")
                .description("설명 부분")
                .version("1.0.0")
                .build();
    }
}

 

 

컨트롤러 코드

@RestController
@RequestMapping("/rest-template")
public class RestTemplateController {

    private final RestTemplateService restTemplateService;

    public RestTemplateController(RestTemplateService restTemplateService) {
        this.restTemplateService = restTemplateService;
    }

    @GetMapping
    public String getName(){
        return restTemplateService.getName();
    }

    @GetMapping("/path-variable")
    public String getNameWithPathVariable(){
        return restTemplateService.getNameWithPathVariable();
    }

    @GetMapping("/parameter")
    public String getNameWithParameter(){
        return restTemplateService.getNameWithParameter();
    }

    @GetMapping
    public ResponseEntity<MemberDto> postDto(){
        return restTemplateService.postWithParamAndBody();
    }

    @GetMapping("/header")
    public ResponseEntity<MemberDto> postWithHeader(){
        return restTemplateService.postWithHeader();
    }
}

 

⇒ 애플리케이션 실행 후 POST API 호출에 따른 출력 결과

flature!!
flature@gamil.com
Around Hub Studio

 

RestTemplate 커스텀 설정

RestTemplate : HTTPClient를 추상화하고 있음

 

📌 HTTPClient : 종류에 따라 기능 차이가 존재 → 가장 큰 차이 : 커넥션 풀(Connection Pool)


📌 RestTemplate는 커넥션 풀 지원x → 매번 호출할 때마다 포트를 열어 커넥션 생성

  • 문제점 : TIME_WAIT 상태가 소켓을 다시 사용하려고 접근하려면 재사용하지 못하게 됨
  • 해결방법 : 커넥션 풀 기능을 활성화해 재사용 가능하도록 함
    기능 활성화하는 대표적인 방법 : 아파치에서 제공하는 HttpClient로 대체해서 사용

의존성 추가

→ HttpClient 추가하면 RestTemplate 설정 쉽게 추가, 변경 가능

<dependency>
	<groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>

 

커스텀 RestTemplate 객체 생성 메서드

public RestTemplate restTemplate(){
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();

        HttpClient client = HttpClientBuilder.create()
                .setMaxConnTotal(500)
                .setMaxConnPerRoute(500)
                .build();

        CloseableHttpClient httpClient = HttpClients.custom()
                .setMaxConnTotal(500)
                .setMaxConnPerRoute(500)
                .build();

				// HttpClient 생성하면 setHttpClient()통해 인자 전달해 설정 가능
        factory.setHttpClient(httpClient);
        factory.setConnectTimeout(2000);
        factory.setReadTimeout(5000);

        RestTemplate restTemplate = new RestTemplate(factory);

        return restTemplate;
    }

 

📌 ClientHttpRequestFactory : 함수형 인터페이스로 대표적인 구현체
⇒ SimpleClientHttpRequestFactory와 HttpComponentsClientHttpRequestFactory가 있음

  • 별도의 구현체 설정해서 전달x ⇒ HttpAccessor에 구현돼 있는 내용에 의해 SimpleClientHttpRequestFactory 사용
  • HttpComponentsClientHttpRequestFactory 객체 생성해 ClientHttpRequestFactory 사용 시 RestTemplate의 Timeout 설정 가능
    • HttpComponentsClientHttpRequestFactory → 커넥션 풀 설정을 위해 HttpClient를 HttpComonentsClientHttpRequestFactory 설정할 수 있음
    • HttpClient 설정 방법 ⇒ HttpClientBuilder.create() or HttpClients.custom() 사용
    • HttpClient 생성하면 setHttpClient()통해 인자 전달해 설정 가능
    ⇒ 설정된 factory 객체를 RestTemplate을 초기화하는 과정에서 인자 전달됨

WebClient란?

: 리액트 기반으로 동작하는 API로 스레드와 동시성 문제 벗어나 비동기 형식으로 사용 가능

→ RestTemplate 지원 중단으로 WebClient 사용을 권고하며 Spring WebFlux가 HTTP 요청을 수행하는 클라이언트로 WebClient 제공

 

특징

  • 논블로킹 I/O wldnjs
  • 리액티브 스트림의 백 프레셔 지원
  • 적은 하드웨어 리소스로 동시성 지원
  • 함수형 API 지원
  • 동기, 비동기 상호작용 지원
  • 스트리밍 지원

 

WebClient 구성

의존성 추가 

WebClient 사용 가능한 환경 구성을 위해선  WebFlux 모듈에 대한 의존성 추가가 필요

 

📌WebFlux : 클라이언트와 서버 간 리액티브 애플리케이션 개발을 지원하기 위해 스프링 프레임워크5에 새롭게 추가된 모듈

 <dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

WebClient 사용하기

WebClient 구현

생성 방법 → create() 메서드를 이용한 생성 or builder()를 이용한 생성

@Service
public class WebClientService {

    public String getName() {
		// WebClient -> 객체 생성 후 요청 전달하는 방식으로 동작 => WebClient 객체 이용 시 객체 생성 후 재사용하는 방식으로 구현
        WebClient webClient = WebClient.builder()
            .baseUrl("http://localhost:9090") // 기본 URL 설정
            .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) // 헤더의 값 설정
            .build();

        return webClient.get() // HTTP 메서드를 get(), post(), put(), delete() 등 네이밍이 명확한 메서드 설정 가능
            .uri("/api/v1/crud-api") // URI확장 방법
            .retrieve() // 요청에 대한 응답을 받았을 떄 그 값을 추출하는 방법 
            // Mono : Flux와 비교되는 개념 -> 리액티브 스트림에서 데이터를 제공하는 발행자 역할 수행하는 Publicsher의 구현체
            .bodyToMono(String.class) // 리턴 타입을 설정해 문자열 객체 받아옴
            .block(); // 블로킹 형식으로 동작하게 설정 -> WebClient가 논블로킹 방식으로 동작하기 떄문
    }

    public String getNameWithPathVariable() {
        WebClient webClient = WebClient.create("http://localhost:9090");

        ResponseEntity<String> responseEntity = webClient.get()
            .uri(uriBuilder -> uriBuilder.path("/api/v1/crud-api/{name}")
                .build("Flature")) // parthVariable 추가하는 방법 
            .retrieve().toEntity(String.class).block(); 

				// 간략하게 작성하는 방법
        ResponseEntity<String> responseEntity1 = webClient.get()
            .uri("/api/v1/crud-api/{name}", "Flature")
            .retrieve()
            .toEntity(String.class) // ResponseEntity 타입으로 응답 전달받음
            .block();

        return responseEntity.getBody();
    }

    public String getNameWithParameter() {
        WebClient webClient = WebClient.create("http://localhost:9090");

			 // 쿼리 파라미터를 요청에 담기위해 uriBuilder 사용
        return webClient.get().uri(uriBuilder -> uriBuilder.path("/api/v1/crud-api")
                .queryParam("name", "Flature") // queryParam() 메서드로 전달하려는 값 설정
                .build())
                // exchange 지원 중단으로 exchangeToMono나 exchangeTFlux 사용 => 응답 결과 코드에 따라 다르게 응답 설정
            .exchangeToMono(clientResponse -> {
                if (clientResponse.statusCode().equals(HttpStatus.OK)) {
                    return clientResponse.bodyToMono(String.class);
                } else {
                    return clientResponse.createException().flatMap(Mono::error);
                }
            })
            .block();
    }

    public ResponseEntity<MemberDto> postWithParamAndBody() {
        WebClient webClient = WebClient.builder()
            .baseUrl("http://localhost:9090")
            .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
            .build();

        MemberDto memberDTO = new MemberDto();
        memberDTO.setName("flature!!");
        memberDTO.setEmail("flature@gmail.com");
        memberDTO.setOrganization("Around Hub Studio");

				// post() 메서드로 POST 메서드 통신 정의, uri()는 uriBuilder로 path와 parameter 설정
        return webClient.post().uri(uriBuilder -> uriBuilder.path("/api/v1/crud-api")
                .queryParam("name", "Flature")
                .queryParam("email", "flature@wikibooks.co.kr")
                .queryParam("organization", "Wikibooks")
                .build())
            .bodyValue(memberDTO) // HTTP바디 값을 설정 => 일반적으로 데이터 객체를(DTO, VO) 파라미터로 전달
            .retrieve()
            .toEntity(MemberDto.class)
            .block();
    }

    public ResponseEntity<MemberDto> postWithHeader() {
        WebClient webClient = WebClient.builder()
            .baseUrl("http://localhost:9090")
            .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
            .build();

        MemberDto memberDTO = new MemberDto();
        memberDTO.setName("flature!!");
        memberDTO.setEmail("flature@gmail.com");
        memberDTO.setOrganization("Around Hub Studio");

        return webClient
            .post()
            .uri(uriBuilder -> uriBuilder.path("/api/v1/crud-api/add-header")
                .build())
            .bodyValue(memberDTO)
            .header("my-header", "Wikibooks API") // 헤더에 값 추가 -> 외부 API사용을 위해 인증된 토큰값 담아 전달함
            .retrieve()
            .toEntity(MemberDto.class)
            .block();
    }

		// 빌드된 WebClient는 변경 x 복사 후 사용o
    public void cloneWebClient() {
        WebClient webClient = WebClient.create("http://localhost:9090");

        WebClient clone = webClient.mutate().build();
    }
}

 

  • getName() : builder() 활용해 WebClient 만들고 다른 두 개의 메서드에서 create() 활용해 WebClient 생성
  • WebClient.builder() 이외 사용할 경우 확장 가능한 메서드
    • defaultHeader() : WebClient의 기본 헤더 설정
    • defaultCookie() : WebClient의 기본 쿠키 설정
    • defaulUriVariable(): WebClient의 기본 URI 확장값 설정
    • filter() : WebClient에서 발생하는 요청에 대한 필터 설정

 


QUIZ

  1. ( 마이크로서비스 아키텍처 )는 애플리케이션이 가지고 있는 기능(서비스)이 하나의 비즈니스 범위만 가지는 형태이다.
  2. ( RestTemplate )이란 스프링에서 HTTP 통신 기능을 손쉽게 사용하도록 설계된 템플릿으로 RESTful 원칙을 따르는 서비스를 편리하게 만들 수 있다.
  3. ( UriComponentsBuilder )는 스프링 프레임워크에서 제공하는 클래스로 여러 파라미터를 연결해 URI 형식으로 만드는 기능 수행한다.
  4. ( Swagger )를 이용해 프로젝트에서 쉽게 API를 호출할 수 있도록 한다.
  5. RestTemplate의 재사용 가능하도록 커넥션 풀 기능을 활성화하는 대표적인 방법으로는 ( HttpClient )로 대체해서 사용하는 방법이 있다.
  6. ( WebClient )이란 리액트 기반으로 동작하는 API로 스레드와 동시성 문제를 벗어나 비동기 형식으로 사용 가능하다.

 

PROGRAMMING QUIZ

  1. PathVariable을 사용하는 GET 방식의 RestTemplate 코드를 작성하세요.
    → 세부 경로 : /api/v1/crud-api, name 변수에 "Test"라는 값 대입
public String getNameWithPathVariable(){
        URI uri = // 빈칸
                .fromUriString("http://localhost:9090")
                //  빈칸
                .encode()
                .build()
                //  빈칸
                .toUri();

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);

        return responseEntity.getBody();
    }

 

정답:

더보기

public String getNameWithPathVariable(){
        URI uri = UriComponentsBuilder
                .fromUriString("http://localhost:9090")
                .path("/api/v1/crud-api/{name}") 
                .encode()
                .build()
                .expand("Test") 
                .toUri();

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);

        return responseEntity.getBody();
    }

 

2. WebClient를 이용하여 PathVariable을 사용하는 GET 방식의 코드를 작성하세요. (필요한 값은 위 문제와 동일)

   public String getNameWithPathVariable() {
        WebClient webClient = // 빈칸
        
        ResponseEntity<String> responseEntity1 = webClient.get()
            // 빈칸
            .retrieve()
            .toEntity(String.class)
            .block();

        return responseEntity.getBody();
    }

 

정답:

더보기

   public String getNameWithPathVariable() {
        WebClient webClient = WebClient.create("http://localhost:9090");
        
        ResponseEntity<String> responseEntity1 = webClient.get()
            .uri("/api/v1/crud-api/{name}", "Test")
            .retrieve()
            .toEntity(String.class)
            .block();

        return responseEntity.getBody();
    }


[출처] 장정우, 『스프링 부트 핵심 가이드』, 위키북스(2022), p.349~372

Corner Spring 1
Editor:  Luna

728x90

관련글 더보기