Java/외부 통신

[Java] Spring Cloud OpenFeign 이해하고 활용하기 -1 : 주요 개념 및 환경 구성, 활용 예시

adjh54 2024. 11. 26. 17:58
728x170
해당 글에서는 Spring Cloud OpenFeign을 활용하여 외부 통신을 활용하는 예시에 대해 알아봅니다.

 

 

💡 [참고] Java에서 외부 통신을 하는 방법들에 대해 궁금하시면 아래의 글을 참고하시면 도움이 됩니다
분류 주제 링크
RestTemplate Spring Boot Web 활용 : RestTemplate 이해하기 https://adjh54.tistory.com/234
WebClient Spring Boot Webflux 이해하기 -1 : 흐름 및 주요 특징 이해 https://adjh54.tistory.com/232
WebClient Spring Boot Webflux 이해하기 -2 : 활용하기 https://adjh54.tistory.com/233
Open Feign Spring Cloud OpenFeign 이해하고 활용하기 -1 : 주요 개념 및 환경 구성, 활용 예시 https://adjh54.tistory.com/616
Github 외부 통신의 활용 방법을 담은 예제 Repository https://github.com/adjh54ir/blog-codes/tree/main/spring-boot-external-network

 

 

1) Spring Cloud OpenFeign


💡 Spring Cloud OpenFeign

- Netflix에서 개발한 HTTP 클라이언트 라이브러리를 Spring Cloud에서 통합한 선언적 HTTP 클라이언트 라이브러리입니다.

- Spring Cloud에서는 Open Feign을 스프링 MVC 어노테이션을 사용하여 웹 서비스 클라이언트를 쉽게 작성할 수 있도록 통합했습니다.
- OpenFeign은 마이크로서비스 아키텍처에서 특히 유용하며, 코드를 더 간결하고 유지보수하기 쉽게 만듭니다.
 

Spring Cloud OpenFeign

Feign is a declarative web service client. It makes writing web service clients easier. To use Feign create an interface and annotate it. It has pluggable annotation support including Feign annotations and JAX-RS annotations. Feign also supports pluggable

docs.spring.io

 

1. 주요 특징


특징 설명
선언적 REST 클라이언트 인터페이스와 어노테이션만으로 HTTP API 클라이언트를 작성할 수 있습니다.
스프링 MVC 어노테이션 지원 @RequestMapping, @PathVariable, @RequestParam 등 스프링 MVC 어노테이션을 그대로 사용할 수 있습니다.
유연한 설정 인터셉터, 디코더, 인코더 등을 커스터마이징할 수 있습니다.
로드 밸런싱 Ribbon과 통합되어 클라이언트 사이드 로드 밸런싱을 지원합니다.
서킷 브레이커 Hystrix/Resilience4j와 통합하여 장애 허용 패턴을 구현할 수 있습니다.

 

 

2. 외부 통신 클라이언트 비교 : RestTemplate, WebClient, OpenFeign


💡 외부 통신 클라이언트 비교 : RestTemplate, WebClient, OpenFeign

- Spring Boot 환경에서 사용하는 외부 통신 클라이언트로는 RestTemplate, WebClient, OpenFeign를 이용합니다. 각각에 대해서 비교해 봅니다.

1. RestTemplate 
- Spring 3.0부터 제공된 전통적인 HTTP 클라이언트로 동기식으로 데이터 통신이 처리되며 응답을 받을 때까지 블로킹 방식으로 응답을 기다리는 통신이 이루어집니다.

2. WebClient
- WebFlux의 일부인 Webclient는 비동기적인 방식으로 HTTP 요청을 보내고 응답을 기다리지 않는 논-블로킹 방식으로 통신이 이루어집니다.

3. OpenFeign
- Spring Cloud의 일부인 OpenFeign는 선언적 REST 클라이언트로, 인터페이스와 어노테이션만으로 HTTP API 클라이언트를 작성하며 동기식으로 데이터 처리되며 응답을 받을 때까지 블로킹 방식으로 응답을 기다리는 통신이 이루어집니다.
특징 RestTemplate WebClient OpenFeign
구현 방식 ‘명령형’ 방식으로 HTTP 요청을 직접 구현 ‘함수형’ 방식으로 체이닝 구현 ‘선언형’ 방식으로 인터페이스만 정의
코드 복잡도 URL, HTTP 메서드, 요청/응답 처리를 모두 직접 작성 메서드 체이닝으로 직관적 구현 어노테이션 기반으로 간단하게 정의
비동기 지원 동기-블로킹 방식만 지원 비동기-논블로킹 방식 지원 동기-블로킹 방식만 지원
유지보수성 코드가 길어지고 반복적인 작성 필요 모듈화된 코드로 유지보수 용이 인터페이스 수정만으로 변경 가능
테스트 용이성 MockRestServiceServer 사용 필요 WebTestClient로 쉽게 테스트 인터페이스 기반으로 쉽게 Mock 가능
오류 처리 try-catch로 직접 처리 필요 onError() 등으로 선언적 처리 ErrorDecoder로 중앙 집중적 처리 가능
로드밸런싱 별도 설정 필요 LoadBalancerExchange 통합 Ribbon과 통합되어 자동 지원
서킷브레이커 별도 구현 필요 Resilience4j와 쉽게 통합 Hystrix/Resilience4j와 쉽게 통합

 

 

💡[참고] 동기식 요청(Synchronous request) & 블로킹 요청(Blocking Request)

- 요청을 보내고 응답을 받을 때까지 블로킹되는 방식을 의미합니다.

 

 💡 비동기식 요청(Asynchrouse Request) & 논 블로킹 요청(Non-Blocking Request)

- 요청을 보내고 응답을 받지 않는 논 블로킹 방식을 의미합니다.

 

2.1. RestTemplate 예시


💡 RestTemplate 예시

- 명령형 방식으로 HTTP 요청을 직접 구현해야 합니다.

- 아래와 같이 URL, HTTP Method, 요청/응답 데이터 지정 및 모든 처리에 대해서 작성해야 하며, 이는 코드가 길어지고 반복적인 작성이 필요합니다.
- RestTemplate 인스턴스를 생성하고 .getForObject() 메서드를 통해서 HTTP 요청을 수행합니다.
- 첫 번째 인자로는 호출 엔드포인트를 지정하고, 두 번째는 전송데이터를 지정, 마지막은 반환되는 타입을 지정합니다.
// RestTemplate 예시
@Service
public class UserService {
    private final RestTemplate restTemplate;
    private final String baseUrl = "http://api.example.com";
    
    public User getUser(Long id) {
        return restTemplate.getForObject(baseUrl + "/users/" + id, User.class);
    }
}

 

💡[참고] RestTemplate에 대해 궁금하시면 아래의 글을 참고하시면 됩니다.
 

[Java] Spring Boot Web 활용 : RestTemplate 이해하기

해당 글에서는 RestTemplate에 대해 이해하고 활용 방법에 대해 확인해 봅니다. 1) RestTemplate 💡 RestTemplate - HTTP 통신을 위한 도구로 RESTful API 웹 서비스와의 상호작용을 쉽게 외부 도메인에서 데이터

adjh54.tistory.com

 

 

2.2. WebClient


💡 WebClient 예시

- 함수형 방식으로 HTTP 요청을 메서드 체이닝 방식을 통해서 구현해야 합니다

- 메서드 체이닝 방식을 사용하기에 직관적이고 간결한 코드를 확인할 수 있습니다.
- WebClient 인스턴스를 생성하고 .create 메서드를 통해서 통신하려는 도메인을 지정합니다.
- .get()는 HTTP Method를 지정하며, .url을 통해 엔드포인트를 지정하고 값을 전달하는 방식입니다.
// WebClient 예시
@Service
public class UserService {
    private final WebClient webClient;
    
    public UserService() {
        this.webClient = WebClient.create("http://api.example.com");
    }
    
    public Mono getUser(Long id) {
        return webClient.get()
                       .uri("/users/{id}", id)
                       .retrieve()
                       .bodyToMono(User.class);
    }
}

 

 

💡 [참고] 메서드 체이닝에 대해 궁금하시면 아래의 글을 참고하시면 도움이 됩니다.
 

[Java/디자인 패턴] 메서드 체이닝(Method Chaining) , 플루언트 인터페이스(Fluent Interface), 빌더 패턴(Bui

해당 글에서는 메서드 체이닝(Method Chaining), 플루언트 인터페이스(Fluent Interface), 빌더 패턴(Builder Pattern)에 대해서 알아봅니다. 1) 메서드 체이닝(Method Chaining) 💡 메서드 체이닝(Method Chaining) - 여

adjh54.tistory.com

 

 

2.3. OpenFeign


 💡OpenFeign

- 선언형 방식으로 인터페이스 내에 메서드와 어노테이션을 기반으로 HTTP 요청에 대한 구현을 합니다.

- 아래와 같이 구현한 인터페이스의 파라미터, 리턴타입을 지정하고 URL만 매핑하면 외부 통신을 수행할 수 있습니다.
- 자세한 내용은 해당 글의 아래의 예시에서 확인해 볼 수 있습니다.
// OpenFeign 예시
@FeignClient(name = "user-service", url = "http://api.example.com")
public interface UserClient {

    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") Long id);
}

 

 💡 [참고] RestTemplate과 Webflux에 대해 궁금하시면 아래의 글을 참고하시면 도움이 됩니다.
 

[Java] Spring Boot Web 활용 : RestTemplate 이해하기

해당 글에서는 RestTemplate에 대해 이해하고 활용 방법에 대해 확인해 봅니다. 1) RestTemplate 💡 RestTemplate - HTTP 통신을 위한 도구로 RESTful API 웹 서비스와의 상호작용을 쉽게 외부 도메인에서 데이터

adjh54.tistory.com

 

[Java] Spring Boot Webflux 이해하기 -1 : 흐름 및 주요 특징 이해

해당 글에서는 Spring Boot Webflux에 대해 이해하고 전체적인 흐름, 특징에 대해서 이해를 돕기 위해 작성한 글입니다. 1) Spring Boot Webflux💡 Spring Boot Webflux- 반응형 및 비동기적인 웹 애플리케이

adjh54.tistory.com

 

[Java] Spring Boot Webflux 이해하기 -2 : 활용하기

해당 페이지에서는 Spring Boot Webflux를 이용하여 실제 구현하고 활용하는 방법과 WebClient를 이용한 다른 도메인 호출 방법에 대해 공유합니다. 💡 [참고] 이전에 작성한 글을 읽고 오시면 크게 도

adjh54.tistory.com

 

3. 주요 어노테이션 확인하기


3.1. @EnableFeignClients


💡 @EnableFeignClients

- 주로 메인 애플리케이션 클래스나 구성 클래스 내에 선언하며, @ComponentScan과 유사하게 작동하여 @FeignClient가 선언된 인터페이스들을 찾아내는 역할을 수행합니다.
- 찾아낸 구현체를 Spring Bean에 등록하여 Open Feign 관련 자동구성을 활성화합니다.

 

💡 @EnableFeignClients 속성
속성 리턴 타입 설명
value Class<?><[]> FeignClient를 스캔할 패키지들을 지정
basePackages String[] value와 동일한 역할을 하며 FeignClient를 스캔할 패키지 지정
basePackageClasses Class<?><[]> 지정된 클래스들이 있는 패키지를 스캔
defaultConfiguration Class<?><[]> 모든 Feign 클라이언트에 적용될 기본 구성 클래스 지정
clients String[] 특정 FeignClient 클래스들만 등록하도록 명시적으로 지정

 

 

💡 @EnableFeignClients 어노테이션 속성 예시

- 아래와 같이 @FeignClient가 선언된 스캔을 위해 basePackages 속성으로 패키지를 지정하거나 defaultConfiguration 속성으로 특정 클래스를 지정합니다.
- 기본적으로 @EnableFeignClients 속성 없이 선언하는 경우 모든 패키지나 클래스를 스캔합니다.
@EnableFeignClients(
    basePackages = "com.example.clients",
    defaultConfiguration = DefaultFeignConfig.class
)
@SpringBootApplication
public class Application {
    // ...
}
 

EnableFeignClients - spring-cloud-openfeign-core 3.1.9 javadoc

Latest version of org.springframework.cloud:spring-cloud-openfeign-core https://javadoc.io/doc/org.springframework.cloud/spring-cloud-openfeign-core Current version 3.1.9 https://javadoc.io/doc/org.springframework.cloud/spring-cloud-openfeign-core/3.1.9 pa

javadoc.io

 

 

3.2. @FeignClient


💡 @FeignClient

- HTTP 클라이언트를 생성하기 위한 인터페이스를 선언하는 어노테이션입니다. 이 어노테이션을 사용하면 REST API를 호출하는 인터페이스를 쉽게 정의할 수 있습니다.

- 선언만으로 REST 클라이언트를 정의하며, Spring Runtime 단계에서 해당 인터페이스의 구현체를 자동으로 생성합니다.
- @GetMapping, @PostMapping 등의 Spring MVC 어노테이션을 그대로 사용할 수 있습니다.

 

 

 💡 [참고] @FeignClient 속성
속성 리턴 타입 default value 설명
name String - FeignClient의 이름을 지정합니다. (필수)
url String "" 대상 서버의 URL을 지정합니다.
configuration Class<?>[] FeignClientsConfiguration.class FeignClient에 대한 사용자 정의 구성 클래스 지정합니다.
fallback Class<?> void.class 장애 발생 시 대체할 구현 클래스 지정합니다.
fallbackFactory Class<?> void.class 동적 fallback 객체 생성을 위한 Factory 클래스 지정합니다.
path String "" 모든 메서드에 적용될 공통 prefix 경로를 지정합니다.
decode404 boolean false 404 응답을 에러로 처리할지 여부를 지정합니다.
primary boolean true 동일한 타입의 여러 빈이 있을 때 우선 선택할지 여부를 지정합니다.

 

 

FeignClient - spring-cloud-openfeign-core 3.1.9 javadoc

Latest version of org.springframework.cloud:spring-cloud-openfeign-core https://javadoc.io/doc/org.springframework.cloud/spring-cloud-openfeign-core Current version 3.1.9 https://javadoc.io/doc/org.springframework.cloud/spring-cloud-openfeign-core/3.1.9 pa

javadoc.io

 

Spring Cloud OpenFeign

Feign is a declarative web service client. It makes writing web service clients easier. To use Feign create an interface and annotate it. It has pluggable annotation support including Feign annotations and JAX-RS annotations. Feign also supports pluggable

docs.spring.io

 

💡@FeignClient 어노테이션 속성 예시

- name 속성: name = "user-service": Feign 클라이언트의 이름을 지정
- url 속성: url = "http://api.example.com": 요청을 보낼 대상 서버의 기본 URL을 지정
- @GetMapping("/users/{id}"): HTTP GET 요청을 위한 메서드로, 특정 사용자 정보를 조회
- @PostMapping("/users"): HTTP POST 요청을 위한 메서드로, 새로운 사용자를 생성
@FeignClient(name = "user-service", url = "http://api.example.com")
public interface UserClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") Long id);
    
    @PostMapping("/users")
    User createUser(@RequestBody User user);
}

 

 

 

 

2) Spring Cloud OpenFeign 환경설정


 

1. 개발 환경


개발 환경 버전
java 17
spring boot 3.3.6
spring-boot-starter-web 3.3.6
spring-cloud-starter-openfeign 4.1.3
spring-cloud-dependencies 2023.0.3
lombok -

 

 

💡[참고] 무료로 REST API를 테스트해볼 수 있는 JSONPlaceholder 페이지를 통해서 데이터 통신 테스트를 수행합니다.

- 공통 도메인 주소는 https://jsonplaceholder.typicode.com/입니다. REST API 형태로 테스트를 위해 호출이 가능합니다.
엔드포인트 HTTP Method 설명
/posts GET, POST, PUT, DELETE 게시글 데이터 조회
/comments GET, POST, PUT, DELETE 댓글 데이터 조회
/albums GET, POST, PUT, DELETE 앨범 데이터 조회
/photos GET, POST, PUT, DELETE 사진 데이터 조회
/todos GET, POST, PUT, DELETE 할일 데이터 조회
/users GET, POST, PUT, DELETE 사용자 데이터 조회

 

 

JSONPlaceholder - Guide

Guide Below you'll find examples using Fetch API but you can JSONPlaceholder with any other language. You can copy paste the code in your browser console to quickly test JSONPlaceholder. Getting a resource fetch('https://jsonplaceholder.typicode.com/posts/

jsonplaceholder.typicode.com

 

2. 의존성 추가


💡 의존성 추가

- Spring Cloud OpenFeign을 이용하기 위한 “spring-cloud-starter-openfeign”라이브러리를 추가해야 합니다.

- 또한, org.springframework.cloud:spring-cloud-dependencies도 함께 추가해야 합니다. 이를 추가하는 이유는 OpenFeign의 경우 Spring Cloud의 다른 컴포넌트들과 함께 작동하기 위해서 추가해야 합니다.
- 해당 프로젝트에서는 3.3.6 버전을 기준으로 구성하였기에 2023.0.3을 버전을 사용합니다.
plugins {
    id 'java'
    id 'org.springframework.boot' version '3.3.6'
    id 'io.spring.dependency-management' version '1.1.6'
}
ext {
    set('springCloudVer', "2023.0.3")
}

dependencies {
    implementation "org.springframework.cloud:spring-cloud-starter-openfeign:4.1.3"
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVer}"
    }
}

Maven Repository: org.springframework.cloud » spring-cloud-starter-openfeign

 

 

💡 [참고] org.springframework.cloud:spring-cloud-dependencies는 무슨 버전으로 받아야 할까?

- 공식 사이트의 표에 따르면 아래와 같이 Spring Boot Version에 따라서 Spring Cloud 지원 버전이 달라집니다.
- 해당 글에서는 가장 최신 버전이 되는 Spring Boot 3.4.0 버전을 사용하기에 2023.0.3 버전을 이용하여 의존성을 추가하였습니다.

https://spring.io/projects/spring-cloud

 

Spring Cloud

Spring Cloud provides tools for developers to quickly build some of the common patterns in distributed systems (e.g. configuration management, service discovery, circuit breakers, intelligent routing, micro-proxy, control bus, short lived microservices and

spring.io

 

Maven Repository: org.springframework.cloud » spring-cloud-dependencies

 

3. xxApplication.java 설정


💡 xxApplication.java 설정

- @FeignClient 어노테이션이 적용된 인터페이스들을 스캔하여 빈으로 등록합니다.
- @FeignClient 어노테이션의 속성 basePackages 설정하여 특정 패키지만 스캔하도록 basePackages 속성을 통해 스캔 범위를 지정할 수 있습니다.
package com.adjh.springbootexternalcmnc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableFeignClients // FeignClient 사용을 선언합니다.
@SpringBootApplication
public class SpringBootExternalCmncApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootExternalCmncApplication.class, args);
    }

}

 

 

 

4. xxSerivce.java(interface) 설정


💡 xxSerivce.java(interface) 설정

- Spring Cloud OpenFeign을 사용하여서 “https://jsonplaceholder.typicode.com”와의 외부 통신을 위해 interface를 구성하였습니다.
- 해당 서비스 페이지에서 함수 구성 및 통신을 함께 진행합니다.
package com.adjh.springbootexternalnetwork.service;

import com.adjh.springbootexternalnetwork.dto.PostResponseDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.List;

/**
 * json placeholder 외부 통신을 하는 예시
 *
 * @author : jonghoon
 * @fileName : OpenFeignService
 * @since : 11/23/24
 */
@FeignClient(
        name = "json placeholder",
        url = "<https://jsonplaceholder.typicode.com>"
)
public interface OpenFeignService {
    @GetMapping("/posts")
    List getPosts();

    @GetMapping("/posts/{id}")
    PostResponseDto getPostById(@PathVariable("id") String id);
}

 

 

5. xxController.java 설정


💡 xxController.java 설정

- 특정 엔드포인트를 OpenFeign을 이용한 인터페이스 서비스를 호출하여 반환해 주는 Controller가 구성되었습니다.
package com.adjh.springbootexternalnetwork.controller;

import com.adjh.springbootexternalnetwork.service.OpenFeignService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

/**
 * OpenFeign 테스트 Controller
 *
 * @author : jonghoon
 * @fileName : OpenFeignController
 * @since : 11/24/24
 */
@RestController
@RequestMapping("api/v1/openFeign")
public class OpenFeignController {

    private final OpenFeignService openFeignService;

    public OpenFeignController(OpenFeignService openFeignService) {
        this.openFeignService = openFeignService;
    }

    /**
     * 게시물을 전체를 조회합니다.
     *
     * @return
     */
    @PostMapping("/getPosts")
    public ResponseEntity<Object> getPosts() {
        Object resultObj = openFeignService.getPosts();
        return new ResponseEntity<>(resultObj, HttpStatus.OK);
    }

    /**
     * 특정 게시물을 조회합니다.
     *
     * @param postId
     * @return
     */
    @PostMapping("/getPost/{postId}")
    public ResponseEntity<Object> getPostById(@PathVariable String postId) {
        Object resultObj = openFeignService.getPostById(postId);
        return new ResponseEntity<>(resultObj, HttpStatus.OK);
    }
}

 

 

6. 결과 확인


 

💡 결과 확인

- 아래와 같이 API 호출을 하였을 때, 아래와 같이 결과를 반환해 줌을 확인하였습니다.

 

 

 

 

3) Spring Cloud OpenFegin 활용하기 -1 : 추가 비즈니스 로직 처리


💡 Spring Cloud OpenFegin 활용하기 -1 : 추가 비즈니스 로직 처리

- 기존의 인터페이스 형태로 받아온 응답 값에 대해서 추가적인 비즈니스 로직 처리를 수행하여 사용자에게 반환해 주는 부분을 추가합니다.

 

 

1. xxService.java : interface


💡 xxService.java : interface

- https://jsonplaceholder.typicode.com와 통신하여 받아오는 OpenFeign을 정의하였습니다.
package com.adjh.springbootexternalnetwork.service;

import com.adjh.springbootexternalnetwork.dto.PostResponseDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.List;

/**
 * json placeholder 외부 통신을 하는 예시
 *
 * @author : jonghoon
 * @fileName : OpenFeignService
 * @since : 11/23/24
 */
@FeignClient(name = "json-placeholder", url = "<https://jsonplaceholder.typicode.com>")
public interface OpenFeignService {

    @GetMapping("/posts")
    List getPosts();

    @GetMapping("/posts/{id}")
    PostResponseDto getPostById(@PathVariable("id") String id);
}

 

 

2. 추가 비즈니스 로직 처리 : class


 💡 추가 비즈니스 로직 처리 : class

- OpenFeignService 인터페이스의 인스턴스를 생성하여서 해당 서비스의 값을 받아서 추가적인 비즈니스 로직을 구성합니다.

- getFilteredPosts()의 경우는 게시물 id가 30 초과인 경우로 필터링을 적용하여 비즈니스 로직 처리를 하였습니다.
- getFilterBodySummary() 경우는 body 값이 100자가 초과되는 경우 “…” 처리를 수행하며, 초과되지 않는 경우는 기존의 값을 그대로 리턴합니다.
package com.adjh.springbootexternalnetwork.service;

import com.adjh.springbootexternalnetwork.dto.PostResponseDto;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * OpenFeign 통신을 통해 가져온 응답 값을 통해 비즈니스 로직을 처리합니다.
 */
@Service
public class OpenFeignBusinessService {
    private final OpenFeignService openFeignService;

    public OpenFeignBusinessService(OpenFeignService openFeignService) {
        this.openFeignService = openFeignService;
    }

    // 특정 조건으로 게시물 필터링
    public List<PostResponseDto> getFilteredPosts() {
        List<PostResponseDto> posts = openFeignService.getPosts();
        return posts.stream()
                .filter(post -> post.getId() > 30)
                .collect(Collectors.toList());
    }

    // 게시물 데이터 가공
    public PostResponseDto getFilterBodySummary(String id) {
        PostResponseDto post = openFeignService.getPostById(id);
        // 컨텐츠 요약 추가
        if (post.getBody().length() > 100) {
            post.setBody(post.getBody().substring(0, 100) + "...");
        } else {
            post.setBody(post.getBody());
        }
        // 추가 데이터 처리 로직
        return post;
    }
}

 

 

3. 결과 확인


💡결과 확인

- 아래와 같이 게시물 아이디가 30 초과인 리스트 값만 출력하도록 필터링에 대한 비즈니스로직을 구성하였습니다.

 

 

💡 아래와 같이 게시물 문자열 길이가 100자 초과인 경우 “…”을 적용하여 출력하도록 하였습니다.

 

 

4) Spring Cloud OpenFeign 활용하기 -2 : Header 설정


💡 Spring Cloud OpenFeign Header 설정

- OpenFeign를 통해 데이터 통신을 수행할 때, 추가적인 Header를 보내야 하는 경우도 있습니다. 이 경우를 위해서 Header를 설정하는 방법에 대해서 알아봅니다.

 

1. @RequestHeader 사용하는 방법


💡@RequestHeader 사용하는 방법

- 메서드 별로 직접 헤더를 지정하는 방식을 의미합니다. 이는 각 API 호출마다 다른 헤더값이 필요한 경우에 유용합니다.
- @RequestHeader 어노테이션을 통해 메서드 파라미터로 헤더값을 전달할 수 있습니다. 인증 토큰과 같이 동적으로 변하는 헤더값을 처리하기에 적합합니다.

 

 

💡 @RequestHeader 해당 예시

- https://jsonplaceholder.typicode.com 사이트에 Header를 전달하는 방식입니다.
- /todos 엔드포인트에서는 header로 Authorization 값을 전달합니다.
- todos/{id} 엔드포인트에서는 header로 Authorization, x-refresh-token를 전달하고, todos/{id} 형태로 id 값을 전달합니다.
package com.adjh.springbootexternalnetwork.service;

import com.adjh.springbootexternalnetwork.dto.PostResponseDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;

import java.util.List;

/**
 * json placeholder 외부 통신을 하는 예시
 *
 * @author : jonghoon
 * @fileName : OpenFeignService
 * @since : 11/23/24
 */
@FeignClient(name = "json-placeholder", url = "<https://jsonplaceholder.typicode.com>")
public interface OpenFeignService {

    @GetMapping("/todos")
    List getTodosAddHeader(@RequestHeader("Authorization") String token);

    @GetMapping("/todos/{id}")
    PostResponseDto getTodoAddHeader(
            @RequestHeader("Authorization") String authToken,
            @RequestHeader("x-refresh-token") String refreshToken,
            @PathVariable("id") String id);
}

 

💡OpenFeignController

- 두 개의 엔드포인트는 동일하게 @RequestHeader를 클라이언트로부터 받아오도록 구성하였습니다.
package com.adjh.springbootexternalnetwork.controller;

import com.adjh.springbootexternalnetwork.service.OpenFeignBusinessService;
import com.adjh.springbootexternalnetwork.service.OpenFeignService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

/**
 * OpenFeign 테스트 Controller
 *
 * @author : jonghoon
 * @fileName : OpenFeignController
 * @since : 11/24/24
 */
@RestController
@RequestMapping("api/v1/openFeign")
public class OpenFeignController {

    private final OpenFeignService openFeignService;
    private final OpenFeignBusinessService openFeignBusinessService;

    public OpenFeignController(OpenFeignService openFeignService, OpenFeignBusinessService openFeignBusinessService) {
        this.openFeignService = openFeignService;
        this.openFeignBusinessService = openFeignBusinessService;
    }    

    /**
     * 게시물을 전체를 조회합니다.
     *
     * @return
     */
    @PostMapping("/getTodos")
    public ResponseEntity<Object> getPostsAddHeader(@RequestHeader("Authorization") String token) {
        Object resultObj = openFeignService.getTodosAddHeader(token);
        return new ResponseEntity<>(resultObj, HttpStatus.OK);
    }

    /**
     * 특정 게시물을 조회합니다.
     *
     * @param postId
     * @return
     */
    @PostMapping("/getTodo/{postId}")
    public ResponseEntity<Object> getPostByIdAddHeader(
            @RequestHeader("Authorization") String token,
            @RequestHeader("x-refresh-token") String refreshToken,
            @PathVariable String postId) {
        Object resultObj = openFeignService.getTodoAddHeader(token, refreshToken, postId);
        return new ResponseEntity<>(resultObj, HttpStatus.OK);
    }

}

 

 

💡사용 결과 확인 : @GetMapping("/todos")

- todos 해당 API 호출 시 Authorization가 필요하다는 전제로 header에 추가하여 전송하여 통신에 성공하였습니다.

 

 

💡 사용 결과 확인: @GetMapping("/todos/{id}")

- todos 해당 API 호출 시 Authorization와 커스텀 해더인 “x-refresh-token”가 필요하다는 전제로 header에 추가하여 전송하여 통신에 성공하였습니다.

 

 

오늘도 감사합니다. 😀

 

 

 

 

 

 

 

그리드형