티스토리 뷰

목차


    반응형
    NAVER API 연동하기

    NAVER API를 사용하기 위해서는 이용 신청을 해야함

     

    네이버 지역 서비스에 등록된 각 지역별 업체 및 상호 검색 결과를 출력해주는 REST API

    GET으로 호출할 때 HTTP Header에 애플리케이션 등록 시 발급받은 Client ID와 Client Secret값을 전송 

     

    <예시>

    curl "https://openapi.naver.com/v1/search/local.xml?query=%EC%A3%BC%EC%8B%9D&display=10&start=1&sort=random" \
        -H "X-Naver-Client-Id: {애플리케이션 등록 시 발급받은 client id 값}" \
        -H "X-Naver-Client-Secret: {애플리케이션 등록 시 발급받은 client secret 값}" -v

    연동 후 Talend API 실행 화면

     

    <네이버 지역검색 API를 활용한 맛집 List 만들기>

    • NaverClient 클래스
    package com.example.restaurant.naver;
    
    import com.example.restaurant.naver.dto.SearchImageReq;
    import com.example.restaurant.naver.dto.SearchImageRes;
    import com.example.restaurant.naver.dto.SearchLocalReq;
    import com.example.restaurant.naver.dto.SearchLocalRes;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.core.ParameterizedTypeReference;
    import org.springframework.http.HttpEntity;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpMethod;
    import org.springframework.http.MediaType;
    import org.springframework.stereotype.Component;
    import org.springframework.web.client.RestTemplate;
    import org.springframework.web.util.UriComponentsBuilder;
    
    @Component
    public class NaverClient {
    
        @Value("${naver.client.id}")
        private String naverClientId;
    
        @Value("${naver.client.secret}")
        private String naverClientSecret;
    
        @Value("${naver.url.search.local}")
        private String naverLocalSearchUrl;
    
        @Value("${naver.url.search.image}")
        private String naverImageSearchUrl;
    
        public SearchLocalRes searchLocal(SearchLocalReq searchLocalReq){
            var uri = UriComponentsBuilder.fromUriString(naverLocalSearchUrl)
                    .queryParams(searchLocalReq.toMultiValueMap())
                    .build()
                    .encode()
                    .toUri();
    
            var headers = new HttpHeaders();
            headers.set("X-Naver-Client-Id", naverClientId);
            headers.set("X-Naver-Client-Secret", naverClientSecret);
            headers.setContentType(MediaType.APPLICATION_JSON);
    
            var httpEntity = new HttpEntity<>(headers);
            var responseType = new ParameterizedTypeReference<SearchLocalRes>(){};
    
    
            var responseEntity = new RestTemplate().exchange(
                    uri,
                    HttpMethod.GET,
                    httpEntity,
                    responseType
            );
    
            return responseEntity.getBody();
        }
    
        public SearchImageRes searchImage(SearchImageReq searchImageReq){
            var uri = UriComponentsBuilder.fromUriString(naverImageSearchUrl)
                    .queryParams(searchImageReq.toMultiValueMap())
                    .build()
                    .encode()
                    .toUri();
    
            var headers = new HttpHeaders();
            headers.set("X-Naver-Client-Id", naverClientId);
            headers.set("X-Naver-Client-Secret", naverClientSecret);
            headers.setContentType(MediaType.APPLICATION_JSON);
    
            var httpEntity = new HttpEntity<>(headers);
            var responseType = new ParameterizedTypeReference<SearchImageRes>(){};
    
    
            var responseEntity = new RestTemplate().exchange(
                    uri,
                    HttpMethod.GET,
                    httpEntity,
                    responseType
            );
    
            return responseEntity.getBody();
        }
    }
    • WishListDto 클래스
    package com.example.restaurant.wishlist.dto;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import java.time.LocalDateTime;
    
    @NoArgsConstructor
    @AllArgsConstructor
    @Data
    public class WishListDto {
        private Integer index;
        private String title;                   // 음식명, 장소명
        private String category;                // 카테고리
        private String address;                 // 주소
        private String roadAddress;             // 도로명
        private String homePageLink;            // 홈페이지 주소
        private String imageLink;               // 음식, 가게 이미지 주소
        private boolean isVisit;                // 방문여부
        private int visitCount;                 // 방문 카운트
        private LocalDateTime lastVisitDate;    // 마지막 방문일자
    }
    • WishListEntity 클래스
    package com.example.restaurant.wishlist.entity;
    
    import com.example.restaurant.db.MemoryDbEntity;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import java.time.LocalDateTime;
    
    @NoArgsConstructor
    @AllArgsConstructor
    @Data
    public class WishListEntity extends MemoryDbEntity {
    
        private String title;                   // 음식명, 장소명
        private String category;                // 카테고리
        private String address;                 // 주소
        private String roadAddress;             // 도로명
        private String homePageLink;            // 홈페이지 주소
        private String imageLink;               // 음식, 가게 이미지 주소
        private boolean isVisit;                // 방문여부
        private int visitCount;                 // 방문 카운트
        private LocalDateTime lastVisitDate;    // 마지막 방문일자
    }
    • WishListRepository 클래스
    package com.example.restaurant.wishlist.repository;
    
    import com.example.restaurant.db.MemoryDbRepositoryAbstract;
    import com.example.restaurant.wishlist.entity.WishListEntity;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public class WishListRepository extends MemoryDbRepositoryAbstract<WishListEntity> {
    }
    • WishListService 클래스
    package com.example.restaurant.wishlist.service;
    
    import com.example.restaurant.naver.NaverClient;
    import com.example.restaurant.naver.dto.SearchImageReq;
    import com.example.restaurant.naver.dto.SearchLocalReq;
    import com.example.restaurant.wishlist.dto.WishListDto;
    import com.example.restaurant.wishlist.entity.WishListEntity;
    import com.example.restaurant.wishlist.repository.WishListRepository;
    import lombok.RequiredArgsConstructor;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    import java.util.stream.Collectors;
    
    @Service
    @RequiredArgsConstructor
    public class WishListService {
    
        private final NaverClient naverClient;
        private final WishListRepository wishListRepository;
    
        public WishListDto search(String query){
            // 지역검색
            var searchLocalReq = new SearchLocalReq();
            searchLocalReq.setQuery(query);
            var searchLocalRes = naverClient.searchLocal(searchLocalReq);
    
            if(searchLocalRes.getTotal() > 0){
                var localItem = searchLocalRes.getItems().stream().findFirst().get();
                var imageQuery = localItem.getTitle().replaceAll("<[^>]*>","");
                var searchImageReq = new SearchImageReq();
                searchImageReq.setQuery(imageQuery);
    
                // 이미지 검색
                var searchImageRes = naverClient.searchImage(searchImageReq);
    
                if(searchImageRes.getTotal() > 0){
                    var imageItem = searchImageRes.getItems().stream().findFirst().get();
    
                    // 결과를 리턴
                    var result = new WishListDto();
                    result.setTitle(localItem.getTitle());
                    result.setCategory(localItem.getCategory());
                    result.setAddress(localItem.getAddress());
                    result.setRoadAddress(localItem.getRoadAddress());
                    result.setHomePageLink(localItem.getLink());
                    result.setImageLink(imageItem.getLink());
                    return result;
                }
            }
    
            return new WishListDto();
        }
    
        public WishListDto add(WishListDto wishListDto) {
            var entity = dtoToEntity(wishListDto);
            var saveEntity = wishListRepository.save(entity);
            return entityToDto(saveEntity);
        }
    
        private WishListEntity dtoToEntity(WishListDto wishListDto){
            var entity = new WishListEntity();
            entity.setIndex(wishListDto.getIndex());
            entity.setTitle(wishListDto.getTitle());
            entity.setCategory(wishListDto.getCategory());
            entity.setAddress(wishListDto.getAddress());
            entity.setRoadAddress(wishListDto.getRoadAddress());
            entity.setHomePageLink(wishListDto.getHomePageLink());
            entity.setImageLink(wishListDto.getImageLink());
            entity.setVisit(wishListDto.isVisit());
            entity.setVisitCount(wishListDto.getVisitCount());
            entity.setLastVisitDate(wishListDto.getLastVisitDate());
            return entity;
        }
    
        private WishListDto entityToDto(WishListEntity wishListEntity){
            var dto = new WishListDto();
            dto.setIndex(wishListEntity.getIndex());
            dto.setTitle(wishListEntity.getTitle());
            dto.setCategory(wishListEntity.getCategory());
            dto.setAddress(wishListEntity.getAddress());
            dto.setRoadAddress(wishListEntity.getRoadAddress());
            dto.setHomePageLink(wishListEntity.getHomePageLink());
            dto.setImageLink(wishListEntity.getImageLink());
            dto.setVisit(wishListEntity.isVisit());
            dto.setVisitCount(wishListEntity.getVisitCount());
            dto.setLastVisitDate(wishListEntity.getLastVisitDate());
            return dto;
        }
    
        public List<WishListDto> findAll() {
            return wishListRepository.findAll()
                    .stream()
                    .map(it -> entityToDto(it))
                    .collect(Collectors.toList());
        }
    
        public void delete(int index) {
            wishListRepository.deleteById(index);
        }
    
        public void addVisit(int index){
            var wishItem = wishListRepository.findById(index);
            if(wishItem.isPresent()){
                var item = wishItem.get();
                item.setVisit(true);
                item.setVisitCount(item.getVisitCount()+1);
            }
        }
    }
    • ApiController 클래스
    package com.example.restaurant.controller;
    
    import com.example.restaurant.wishlist.dto.WishListDto;
    import com.example.restaurant.wishlist.service.WishListService;
    import lombok.RequiredArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    
    @Slf4j
    @RestController
    @RequestMapping("/api/restaurant")
    @RequiredArgsConstructor
    public class ApiController {
    
        private final WishListService wishListService;
    
        @GetMapping("/search")
        public WishListDto search(@RequestParam String query){
            return wishListService.search(query);
        }
    
        @PostMapping("")
        public WishListDto add(@RequestBody WishListDto wishListDto){
            log.info("{}", wishListDto);
            return wishListService.add(wishListDto);
        }
    
        @GetMapping("/all")
        public List<WishListDto> findAll(){
            return wishListService.findAll();
        }
    
        @DeleteMapping("/{index}")
        public void delete(@PathVariable int index){
            wishListService.delete(index);
        }
    
        @PostMapping("/{index}")
        public void addVisit(@PathVariable int index){
            wishListService.addVisit(index);
        }
    }
    • PageController 클래스
    package com.example.restaurant.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    
    @Controller
    @RequestMapping("/pages")
    public class PageController {
    
        @GetMapping("/main")
        public ModelAndView main(){
            return new ModelAndView("aaaa/main");
        }
    }

     

    반응형