이번에는 RestTemplate통신에서 FeignClient로 프로젝트에 필요한 로직을 직접 넣어 보며 업데이트 해보겠습니다.
Feign은 어노테이션 기반의 Web Service Client로,
어노테이션 방식으로 동작함에 따라 Web Service Client를 쉽게 구성할 수 있습니다.Spring MVC을 지원하고, Spring Web에서 사용되는 HttpMessageConverters도 지원합니다.
요약하자면, OpenFeign은 어노테이션 기반으로 Spring MVC 및 HttpMesageConverters를 지원함에 따라 기존 Spring MVC에서 어노테이션 기반으로 HTTP 통신을 했던 방식과 유사하게 구현할 수 있습니다.
따라서 다른 방식과 비교해서 비교적 간단하게 구현이 가능합니다.
또한 Spring Cloud에서 제공되기 때문에 다른 기술들(Eureka, Circuit Breaker, Load Balancer)와 통합이 쉽습니다.
Rest Call을 추상화 한 spring Cloud Netfilx 라이브러리
사용 방법
Load Balanced 지원
서비스 간 통신에 OpenFeign을 적용해봅시다.
// openfeign
implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-openfeign', version: '4.1.0'
@SpringBootApplication
@EnableFeignClients
public class BankServiceApplication {
public static void main(String[] args) {
SpringApplication.run(BankServiceApplication.class, args);
}
}
@FeignClient(name = "kb-bank")
public interface KbBankFeignClient {
@PostMapping("/api/kb-bank/mydata")
AccountInfoResponseListDTO connectMyDataKbBank(
@RequestHeader(value = "Authorization") String tokenHeader);
@GetMapping("/api/kb-bank")
AccountInfoResponseListDTO getMyDataKbBank(
@RequestHeader(value = "Authorization", required = false) String tokenHeader);
}
인터페이스를 생성하고, @FeignClient를 붙여서 활성화 해줍니다
메소드로는 통신할 kb-bank Controller API를 그대로 작성해줍니다.
@Service
@RequiredArgsConstructor
public class ChalletBankServiceImpl implements ChalletBankService {
private final ChalletBankRepository challetBankRepository;
private final Environment env;
private final JwtUtil jwtUtil;
private final KbBankClient kbBankClient;
@Override
public MyDataBankAccountInfoResponseDTO getMyDataAccounts(String tokenHeader) {
AccountInfoResponseListDTO kbBanks = kbBankFeignClient.getMyDataKbBank(tokenHeader);
AccountInfoResponseListDTO nhBanks = nhBankFeignClient.getMyDataKbBank(tokenHeader);
AccountInfoResponseListDTO shBanks = shBankFeignClient.getMyDataKbBank(tokenHeader);
return getMyDataAccounts(kbBanks, nhBanks, shBanks);
}
private MyDataBankAccountInfoResponseDTO getMyDataAccounts(AccountInfoResponseListDTO kbBanks,
AccountInfoResponseListDTO nhBanks, AccountInfoResponseListDTO shBanks) {
return MyDataBankAccountInfoResponseDTO
.builder()
.kbBanks(kbBanks)
.nhBanks(nhBanks)
.shBanks(shBanks)
.build();
}
}
@RestController
@RequestMapping("/api/ch-bank")
@Tag(name = "ChalletBankController", description = "챌렛 은행 컨트롤러")
@RequiredArgsConstructor
public class ChalletBankController {
private final ChalletBankService challetBankService;
@GetMapping("/mydatas")
@Operation(summary = "마이데이터 조회", description = "마이 데이터 조회")
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "마이데이터 조회 성공"),
@ApiResponse(responseCode = "400", description = "마이데이터 조회 실패", content = @Content(schema = @Schema(implementation = Exception.class))),
})
public ResponseEntity<MyDataBankAccountInfoResponseDTO> getMyDataBanks(
@RequestHeader(value = "Authorization") String tokenHeader) {
MyDataBankAccountInfoResponseDTO myDataAccounts = challetBankService.getMyDataAccounts(
tokenHeader);
return ResponseEntity.status(HttpStatus.OK).body(myDataAccounts);
}
}
