Feign + 공공데이터
Feign 이란?
Feign은 Netflix에 의해 처음 만들어진 Declarative(선언적인) HTTP Client 도구로써, 외부 API 호출을 쉽게 할 수 있도록 도와준다.
“선언적인” 이란 어노테이션 사용을 의미하는데, 소스코드가 아닌 어노테이션 선언만으로 트랜잭션을 적용할 수 있는 기술이다.
공공데이터란?
공공데이터란 공공기관이 만들어내는 모든 자료나 정보, 국민 모두의 소통과 협력을 이끌어내는 공적인 정보를 말한다.
공공데이터 중 OpenAPI로 정보를 제공하는 것들이 있다.
캠퍼에서는 ↗ 한국관광공사_고캠핑 정보 조회서비스_GW의 정보를 OpenAPI를 통해 호출하여 이용하였다.
JSON + XML을 통해 관련 정보들을 제공하는데, Json을 하나하나 파싱 하기에는 코드가 너무 번잡스럽다는 생각을 하게 되었다.
더 나아가 제공하는 Json의 형식이 유사하므로 다른 정보도 같이 사용할 때 효율적인 파싱방식은 외부 API를 쉽게 해주는 feign을 적용하는 것이 좋지 않을까?라는 판단을 하게 되었다.
Feign 설정 및 구현
- build.gradle
dependencies {
...
// FEIGN
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
...
}
- FeignConfig
@Configuration
// Feign을 빈으로 등록할 수 있도록 하는 어노테이션
@EnableFeignClients(basePackages = "com.campper")
@Import(FeignClientsConfiguration.class)
public class FeignConfig {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
@Bean
public ErrorDecoder errorDecoder() {
return new FeignClientExceptionErrorDecoder();
}
@Bean
public Retryer retryer() {
// period: 실행 주기, maxPeriod: interval 이 더 클 경우 반환 maxAttempts: 최대 몇번 실행
return new Retryer.Default(1000, 2000, 3);
}
}
- CampInfoClient | API 호출을 실행하는 부분
// 요청을 날릴 주소
@FeignClient(url = "https://apis.data.go.kr/B551011/GoCamping",
name = "campInfo",
configuration = FeignConfig.class)
public interface CampInfoClient {
@GetMapping(value = "/basedList", produces = "application/json", consumes = "application/json")
CampDto callOpenApi(
// Api 호출에 필요한 값
@RequestParam("serviceKey") String serviceKey,
@RequestParam("numOfRows") Long rows,
@RequestParam("pageNo") Long pageNo,
@RequestParam("MobileOS") String mobileOs,
@RequestParam("MobileApp") String mobileApp,
@RequestParam("_type") String type
);
}
- CampDto | Json 파싱을 위해 반환 값 구조대로 생성
@Data
public class CampDto {
@JsonProperty("response")
private Response response;
@Data
public static class Response {
@JsonProperty("body")
private Body body;
@Data
public static class Body {
@JsonProperty("items")
private Items items;
@Data
public static class Items {
private final List<Item> list;
@JsonCreator
public Items(@JsonProperty("item") List<Item> list) {
this.list = list;
}
@Data
public static class Item {
private String facltNm;
private String lineIntro;
private String firstImageUrl;
private String doNm;
private String sigunguNm;
private String mapX;
private String mapY;
...
}
}
}
}
}
- FeignController | Feign을 호출할 컨트롤러 생성
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/infra")
@Api(tags = "인프라")
public class FeignController {
private final FeignService feignService;
@GetMapping("/camp-open-api")
@Operation(summary = "공공 API 데이터 DB 추가 요청", description = "공공 API 데이터 DB 추가 요청, 관리자만 실행 가능합니다.")
public void postOpenApi(@AuthenticationPrincipal User user){
feignService.loadOpenApi(user);
}
}
- FeignServiceImpl
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class FeignServiceImpl implements FeignService{
private final CampInfoClient campInfoClient;
private final CampRepository campRepository;
private final VoteCampRepository voteCampRepository;
private static final String mobileOs = "ETC";
@Value("${SERVICE_NAME}")
private String serviceName;
@Value("${SERVICE_KEY}")
private String serviceKey;
@Override
@Transactional
public void loadOpenApi(User user) {
...
// Feign 로직 호출
CampDto campDto = campInfoClient.callOpenApi(serviceKey, 3467L, 1L, mobileOs, serviceName, "json");
// 받아온 값을 camp 객체화 시켜 저장
ArrayList<Camp> camps = new ArrayList<>();
for (CampDto.Response.Body.Items.Item item : campDto.getResponse().getBody().getItems().getList()) {
Camp camp = CampDto.toEntity(item);
camps.add(camp);
}
campRepository.saveList(camps);
...
}
}
'💻 프로젝트 > 🏕 캠퍼' 카테고리의 다른 글
[Campper] Redis template 사용하여 용량 개선하기 (1) | 2023.10.15 |
---|---|
[Campper] SpringSecurity + JWT + 로컬로그인 인증 구현하기 (0) | 2023.10.09 |