๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Spring

[Spring] OpenFeign์„ ์ด์šฉํ•˜์—ฌ API ํ†ต์‹ ํ•ด๋ณด๊ธฐ (feat. ๊ณ ์–‘์ด ์‚ฌ์ง„ ๊ฒ€์ƒ‰)

by young-ji 2023. 4. 25.

OpenFeign์„ ์ด์šฉํ•˜์—ฌ API ํ†ต์‹ ํ•ด๋ณด๊ธฐ (feat. ๊ณ ์–‘์ด ์‚ฌ์ง„ ๊ฒ€์ƒ‰)

 

ํ•ด๋‹น ์ฝ”์Šค์˜ ๊ณผ์ œ๋ฅผ ์ˆ˜ํ–‰ํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

[Java/Spring]๊ณ ์–‘์ด ์‚ฌ์ง„ ๊ฒ€์ƒ‰ ์‚ฌ์ดํŠธ API ๊ณผ์ œ ํ’€์–ด๋ณด๊ธฐ

 

[Java/Spring]๊ณ ์–‘์ด ์‚ฌ์ง„ ๊ฒ€์ƒ‰ ์‚ฌ์ดํŠธ API ๊ณผ์ œ ํ’€์–ด๋ณด๊ธฐ

[Java/Spring]๊ณ ์–‘์ด ์‚ฌ์ง„ ๊ฒ€์ƒ‰ ์‚ฌ์ดํŠธ API ๊ณผ์ œ ํ’€์–ด๋ณด๊ธฐ ์ฝ”์Šค ๋‚œ์ด๋„ ์ดˆ๊ธ‰ ์‚ฌ์šฉ ์–ธ์–ด # java ๊ฐ•์˜ ์†Œ๊ฐœ ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๊ณผ์ œํ…Œ์ŠคํŠธ ์—ฐ์Šต์— ์žˆ๋Š” ๊ณ ์–‘์ด ์‚ฌ์ง„ ๊ฒ€์ƒ‰ ์‚ฌ์ดํŠธ์—์„œ ์‚ฌ์šฉ๋œ API๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•ด

school.programmers.co.kr

 

์ œ๊ฐ€ ์—ฐ๋™ํ•  ์™ธ๋ถ€ API๋Š” ๊ณ ์–‘์ด ์‚ฌ์ง„์„ ์กฐํšŒํ•˜๋Š” The Cat API์ž…๋‹ˆ๋‹ค.

https://thecatapi.com/

 

The Cat API - Cats as a Service.

A public service API all about Cats, free to use when making your fancy new App, Website or Service.

TheCatAPI.com

 


Feign

Feign์€ Netflix์— ์˜ํ•ด ์ฒ˜์Œ ๋งŒ๋“ค์–ด์ง„ declarative(์„ ์–ธ์ ์ธ) web service client์ด๋ฉฐ ์›น ์„œ๋น„์Šค ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‰ฝ๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค€๋‹ค.

 

โ€œ์„ ์–ธ์ โ€์ด๋ž€ annotation์˜ ์‚ฌ์šฉ์„ ์˜๋ฏธํ•˜๋ฉฐ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์–ด๋…ธํ…Œ์ด์…˜์„ ์„ ์–ธํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ์™ธ๋ถ€ API๋ฅผ ์‰ฝ๊ฒŒ ํ˜ธ์ถœ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๋งˆ์น˜ Spring Data JPA์—์„œ ์‹ค์ œ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ  ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ์ง€์ •ํ•˜๋ฉด ์ฟผ๋ฆฌ ์‹คํ–‰ ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋Š” ๊ฒƒ๊ณผ ์œ ์‚ฌํ•˜๋‹ค!

 

Spring Cloud๊ฐ€ Open Feign์„ ์Šคํ”„๋ง ํด๋ผ์šฐ๋“œ ์ƒํƒœ๊ณ„๋กœ ํ†ตํ•ฉ ์‹œํ‚ค๋ฉฐ Spring MVC ์–ด๋…ธํ…Œ์ด์…˜์„ ์ง€์›ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

 

Spring Cloud OpenFegin

https://cloud.spring.io/spring-cloud-openfeign/reference/html/

 

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

cloud.spring.io

 

์‚ฌ์šฉํ•ด๋ณด๊ธฐ

 

์˜์กด์„ฑ ์ถ”๊ฐ€(Gradle)

 

Spring Cloud ์˜์กด์„ฑ ์ถ”๊ฐ€

plugins {
  id 'java'
  id 'org.springframework.boot' version '3.0.5'
  id 'io.spring.dependency-management' version '1.1.0'
}

ext {
  set('springCloudVersion', "2022.0.1")
}

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

 

OpenFeign ์˜์กด์„ฑ ์ถ”๊ฐ€

implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'

 

 

 

OpenFeign ํ™œ์„ฑํ™”

 

Main ํด๋ž˜์Šค์— ๋ถ™์—ฌ์ค˜๋„ ๋˜์ง€๋งŒ ๋ณ„๋„์˜ Config ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค. (์ฐธ๊ณ ํ•œ ๊ด€๋ จ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. https://mangkyu.tistory.com/243)

@Configuration
@EnableFeignClients("com.search.cat_picture") // ์ €์˜ ํ”„๋กœ์ ํŠธ ํŒจํ‚ค์ง€ ๊ฒฝ๋กœ์ž…๋‹ˆ๋‹ค
public class OpenFeignConfig {
}

@EnableFeignClients์„ ์ถ”๊ฐ€ํ•˜๋ฉด ์ง€์ •๋œ ๊ฒฝ๋กœ ์ดํ•˜์˜ ํŒจํ‚ค์ง€๋ฅผ ํƒ์ƒ‰ํ•˜๋ฉด์„œ @FeignClient ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

 

 

 

๊ตฌํ˜„ํ•˜๊ธฐ

 

ํ˜„์žฌ ์š”๊ตฌ ์‚ฌํ•ญ์— ๋”ฐ๋ผ GET ์š”์ฒญ๋งŒ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์•„๋ž˜์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

@FeignClient(name = "TheCatImageClient", url = "${THE_CAT_CLIENT_URL}/images")
@Headers("x-api-key: ${THE_CAT_CLIENT_KEY}")
public interface TheCatImageClient {

	@GetMapping(value = "/search")
	List<TheCatSimpleImageResponse> findRandomPictures(@RequestParam("limit") Integer limit);

	@GetMapping(value = "/{imagesId}")
	TheCatImageResponse findCatPictureById(@PathVariable String imagesId);

	@GetMapping(value = "/search")
	List<TheCatSimpleImageResponse> findPicturesByBreed(@RequestParam("breed_ids") String breedId);
}
  • ํ•„์š”ํ•œ ํ•„๋“œ๋งŒ ๋ฐ›์•„์™€ ๋งคํ•‘๋  ์ˆ˜ ์žˆ๊ฒŒ DTO๋ฅผ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • The Cat API ์š”์ฒญ์‹œ ๊ฐ€์ž…ํ• ๋•Œ ์ œ๊ณต๋ฐ›์€ key๋ฅผ ์ „๋‹ฌ ํ•ด์ค˜์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ณตํ†ต Header๋ฅผ ์ถ”๊ฐ€ํ•ด ์ค๋‹ˆ๋‹ค.

 

 

๋กœ๊น… ์ฒ˜๋ฆฌ

 

Fegin ๋กœ๊น…์€ ์˜ค์ง DEBUG ๋ ˆ๋ฒจ์—์„œ๋งŒ ๋™์ž‘ํ•˜๋ฉฐ ํด๋ผ์ด์–ธํŠธ๋ณ„๋กœ Logger.Level ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

  • NONE : ๋กœ๊น…ํ•˜์ง€ ์•Š์Œ.(default)
  • BASIC : Request Method์™€ URL ๊ทธ๋ฆฌ๊ณ  Reponse ์ƒํƒœ ์ฝ”๋“œ์™€ ์‹คํ–‰ ์‹œ๊ฐ„์„ ๋กœ๊น…
  • HEADERS : Request, Response Header ์ •๋ณด์™€ ํ•จ๊ป˜ BASIC ์ •๋ณด๋ฅผ ๋กœ๊น…
  • FULL : Request์™€ Response์˜ Header, Body ๊ทธ๋ฆฌ๊ณ  ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๊น…

 

๋กœ๊น…์€ ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ application.yml์„ ์ด์šฉํ•˜๊ฑฐ๋‚˜ Configuratin ์„ค์ •์„ ์ด์šฉํ•ด์„œ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” Configuratin์„ ํ†ตํ•ด ์„ค์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

 

์šฐ์„  ํ•ด๋‹น ํŒจํ‚ค์ง€์˜ ๋กœ๊น… ๋ ˆ๋ฒจ์„ DEBUG level๋กœ ์„ค์ • (application.yml)

logging:
  level:
    com.search.cat_picture.global.openFeign: DEBUG

 

API ๋กœ๊น… ๋ ˆ๋ฒจ์€ BASIC์œผ๋กœ ์ง€์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

@Configuration
@EnableFeignClients("com.search.cat_picture")
public class OpenFeignConfig {

	@Bean
	Logger.Level feignLoggerLevel(){
		return Logger.Level.BASIC;
	}
}

 

๋กœ๊ทธ ํ™•์ธ

 

 

 

์˜ˆ์™ธ ์ฒ˜๋ฆฌ

 

Feign์˜ ๊ธฐ๋ณธ ์—๋Ÿฌ ์ฒ˜๋ฆฌ๊ธฐ์ธ ErrorDecoder.default ๋Š” ํ•ญ์ƒ FeignException ์„ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

ErrorDecoder๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ํ•ด๋‹น ์˜ˆ์™ธ๋“ค์„ ์‚ฌ์šฉ์ž ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import feign.codec.ErrorDecoder;

public class FeignErrorDecider implements ErrorDecoder {

	@Override
	public Exception decode(String methodKey, Response response) {
		return switch (response.status()) {
			case 400 -> new BadRequestException();
			case 404 -> new ResourceNotFoundException();
			default -> new OpenFeignServerException();
		};
	}
}

์ƒˆ๋กœ ๋˜์ง„ ์˜ˆ์™ธ ๋ชจ๋‘ ์ œ๊ฐ€ ๋งŒ๋“  Custom Exception์ž…๋‹ˆ๋‹ค. ์˜ˆ์™ธ ์ƒํ™ฉ์— ๋Œ€ํ•ด ๊ฐœ๋ฐœ์ž๊ฐ€ ์ข€๋” ์ˆ˜์›”ํ•˜๊ฒŒ ํ†ต์ œํ•  ์ˆ˜ ์žˆ๋„๋ก ์‚ฌ์šฉ์ž ์ •์˜ Exception์„ ๊ตฌ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

Configuratin์„ ํ†ตํ•ด ๊ตฌํ˜„ํ•œ ErrorDecoder ๋“ฑ๋ก.

@Configuration
@EnableFeignClients("com.search.cat_picture")
public class OpenFeignConfig {

	@Bean
	Logger.Level feignLoggerLevel(){ // ๋กœ๊น…
		return Logger.Level.BASIC;
	}

	@Bean
	public FeignErrorDecider commonFeignErrorDecoder() { // ์˜ˆ์™ธ ์ฒ˜๋ฆฌ
		return new FeignErrorDecider();
	}
}

 

 

 

์†Œ์Šค์ฝ”๋“œ

 

https://github.com/youngjijang/cat_picture_search

 

GitHub - youngjijang/cat_picture_search: OpenFeign์„ ์ด์šฉํ•œ API ์—ฐ๋™ ์‹ค์Šต

OpenFeign์„ ์ด์šฉํ•œ API ์—ฐ๋™ ์‹ค์Šต. Contribute to youngjijang/cat_picture_search development by creating an account on GitHub.

github.com

 

 

๋งˆ๋ฌด๋ฆฌ

OpenFeign์˜ ์‚ฌ์šฉ๋ฒ•์€ ๊ทธ๋ฆฌ ์–ด๋ ต์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ• ๋•Œ ์™ธ๋ถ€ API๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด, ์–ด๋–ค์‹์œผ๋กœ ํ•ด๋‹น API์— ๋Œ€ํ•œ ์˜์กด์„ฑ์„ ์ค„์ผ ์ˆ˜ ์žˆ์„๊นŒ ๊ณ ๋ฏผํ•˜๊ฒŒ ๋˜๋Š”๋ฐ OpenFeign์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ API๋ฅผ ๊ฐˆ์•„๋ผ์šฐ๊ธฐ๊ฐ€ ํ›จ์”ฌ ์ˆ˜์›”ํ•ด์กŒ์œผ๋‹ˆ ์œ ์ง€๋ณด์ˆ˜ ์ธก๋ฉด์—์„œ๋„ ๋ถ„๋ช… ์žฅ์ ์ด ์žˆ์–ด๋ณด์ด๋„ค์š”.

ํ›„์— ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ๋„ ์™ธ๋ถ€ API๋ฅผ ์—ฐ๋™ํ•ด๋ณด๊ณ  ๋น„๊ตํ•˜๋Š” ๊ธ€์„ ์จ๋ด๋„ ์žฌ๋ฏธ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์–ด์จŒ๋“  OpenFeign์„ ๊ฒฝํ—˜ํ•ด๋ณด๊ณ  ์‹ถ๊ฑฐ๋‚˜ ํ˜„์—…์ž์˜ ์ฝ”๋“œ๋ฆฌ๋ทฐ๋ฅผ ๋ฐ›์•„๋ณด๊ณ  ์‹ถ์œผ์‹œ๋‹ค๋ฉด ํ•ด๋‹น ์ฝ”์Šค๋ฅผ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค. ์žฌ๋ฏธ์žˆ์—ˆ์–ด์š”. ๐Ÿ˜‡

 

 

 

 

Reference.

https://www.baeldung.com/spring-cloud-openfeign

๋Œ“๊ธ€