Feign
- 스프링 환경에서 간편하게 외부 api를 호출할 수 있는 라이브러리
- build.gradle(Spring boot 3.2 기준 spring-cloud-dependencies:2023.0.0, openfeign:4.1.0)
repositories {
mavenCentral()
}
dependencies(
implementation 'org.springframework.cloud:spring-cloud-starter-config'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
implementation("org.springframework.cloud:spring-cloud-starter-openfeign:4.1.0")
)
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:2023.0.0"
}
}
- 사용법
- https://api.github.com/repos/{owner}/{feign}/contributors 에 GET 요청을 보내는 예시
@
EnableFeignClients
어노테이션
@SpringBootApplication()
@EnableFeignClients
@PropertySource("classpath:/application.properties")
public class StudyApplication {
public static void main(String[] args) {
SpringApplication.run(StudyApplication.class, args);
}
}
@FeignClient
인터페이스 등록
@FeignClient(name = "feign", url = "https://api.github.com/repos")
public interface GithubFeignClient {
@RequestMapping(method = RequestMethod.GET, value="/{owner}/{repo}/contributors")
List<Contributor> getContributors(@PathVariable("owner") String owner, @PathVariable("repo") String repo);
}
@RequestMapping
, @PathVariable
, @RequestParam
등으로 url 매핑- 서비스에서 인터페이스 호출 → Entity를 생성하여 컨트롤러에 전달해준다.
@RequiredArgsConstructor
@Service
@Slf4j
public class GithubFeignService {
private final GithubFeignClient githubFeignClient;
public List<Contributor> getContributors(String owner, String repo) {
List<Contributor> contributors = githubFeignClient.getContributors(owner, repo);
for (Contributor c : contributors) {
//log.info("id: {}", c.getId());
}
log.info("!! contributors !! : {}", contributors);
return contributors;
}
}
Trouble Shooting
- feign으로 응답 가져올 시 302 Not Found 에러
@FeignClient(name = "test", url = "http://t-data.seoul.go.kr/apig/apiman-gateway/tapi/v2xSignalPhaseTimingInformation/1.0")
public interface LightFeign {
@RequestMapping(method = RequestMethod.GET)
public List<LightResponse> call(@RequestParam("apiKey") String apiKey, @RequestParam("itstId") String itstId, @RequestParam("pageNo") String pageNo, @RequestParam("numOfRows") String numOfRows);
}
feign.FeignException: [302 Found] during [GET] to [http://t-data.seoul.go.kr/apig/apiman-gateway/tapi/v2xSignalPhaseTimingInformation/1.0?apiKey=b2a72569-9548-4d0d-bd01-8fca5d2740df&itstId=22904&pageNo=1&numOfRows=1]
[LightFeign#call(String,String,String,String)]: [<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML><HEAD>
<TITLE> 302 Found </TITLE>
</HEAD><BODY>
<H1>Found</H1>
<HR>
</BODY></HTML>
]] with root cause
- Http 302 Found
- 일단, 302 Found는 정상적으로 응답 데이터를 받아왔다는 의미이다.
- 클라이언트가 임시적으로 리다이렉션을 발생시킨 것이다.
- 왜 리다이렉션이 일어났나?
- 요청을 https가 아닌 http로 보냈는데,
t-data.seoul.go.kr
에서 http로 요청이 오면 https로 자동 리다이렉션이 되도록 해놨기 때문이다. - http 요청 → 302 Found, https로 리다이렉션
- https 요청 → 200 ok


- 해결
- 요청 url을 http에서 https로 변경한다.
- 인증서 에러 발생할 경우 - https://velog.io/@dev_yong/PKIX-path-building-failed
https Error - PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException
→ 해당 사이트의 인증서가 JVM이 신뢰하는 인증서 목록에 없어서 발생함
- 위 블로그를 참고하여
InstallCert
를 통해 해당 사이트의 인증서를 jvm keystore에 등록한다.
- 등록 후 서버 재시작하면 문제가 해결된다.
javac InstallCert.java
java -cp ./ InstallCert t-data.seoul.go.kr
Added certificate to keystore 'jssecacerts' using alias 't-data.seoul.go.kr'
sudo keytool -importcert -keystore ${JAVA_HOME}/lib/security/cacerts -storepass changeit -file output.cert -alias letsencrypt
ref
Share article