· 오늘 공부한 것

RestTemplate으로 Get, Post 요청과 Header에 추가적인 정보를 전달할 때 exchange매서드 사용

Open API 네이버를 검색기능을 활용하여 실습

 

 

· 공부한 내용, 궁금한 내용, 부족한 내용

client에서 보통 서버로 요청을 해서 받은 데이터로 뭔가를 활용을 했다. 하지만 요청한 서버에서도 또 다른 서버로 요청을 보내서 응답을 받아 올 수 있다. 실습에서 client 서버와 server 서버를 만들었고 각 포트를 8080과 7070으로 사용했다. 그러면 Get과 Post 요청을 살펴보자.

Get 요청

1. 먼저 RestTemplate을 주입받는다.

private final RestTemplate restTemplate;

// RestTemplateBuilder의 build()를 사용하여 RestTemplate을 생성합니다.
public RestTemplateService(RestTemplateBuilder builder) {
    this.restTemplate = builder.build();
}

 

2. 요청받은 검색어를 Query String 방식으로 Server 입장의 서버로 RestTemplate를 사용하여 요청받는다.

public ItemDto getCallObject(String query) {
    // 요청 URL 만들기
    URI uri = UriComponentsBuilder
            .fromUriString("http://localhost:7070")
            .path("/api/server/get-call-obj")
            .queryParam("query", query)
            .encode()
            .build()
            .toUri();
    log.info("uri = " + uri);

    ResponseEntity<ItemDto> responseEntity = restTemplate.getForEntity(uri, ItemDto.class);

    log.info("statusCode = " + responseEntity.getStatusCode());

    return responseEntity.getBody();
}

위와 같은 방식으로 다른 서버로 요청할 uri를 만들어서 보내면 데이터를 받아올 수 있는데 만약 받아올 데이터가 1개가 아니라 여러 개일 경우는 아래와 같이 사용한다.

public List<ItemDto> getCallList() {
    // 요청 URL 만들기
    URI uri = UriComponentsBuilder
            .fromUriString("http://localhost:7070")
            .path("/api/server/get-call-list")
            .encode()
            .build()
            .toUri();
    log.info("uri = " + uri);

    ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);

    log.info("statusCode = " + responseEntity.getStatusCode());
    log.info("Body = " + responseEntity.getBody());

    return fromJSONtoItems(responseEntity.getBody());
}

단품 조회와 다르게 여러 개일 경우 일단 String값 그대로 가져온다. 일단 sever 입장 서버의 ItemResponseDto가 어떤 형태인지를 보면 다음과 같다.

{
"items":[
		{"title":"Mac","price":3888000},
		{"title":"iPad","price":1230000},
		{"title":"iPhone","price":1550000},
		{"title":"Watch","price":450000},
		{"title":"AirPods","price":350000}
	]
}

그렇기에 String으로 넘어온 값을 다시 JSON 형태로 만들어 줘야 하기 때문에 아래와 같은 과정을 거쳤다.

public List<ItemDto> fromJSONtoItems(String responseEntity) {
    JSONObject jsonObject = new JSONObject(responseEntity);
    JSONArray items  = jsonObject.getJSONArray("items");
    List<ItemDto> itemDtoList = new ArrayList<>();

    for (Object item : items) {
        ItemDto itemDto = new ItemDto((JSONObject) item);
        itemDtoList.add(itemDto);
    }

    return itemDtoList;
}

 

post 요청

위에서 주입은 했으니 다른 서버로 RestTemplate를 사용하여 요청하는 것은 아래와 같다.

public ItemDto postCall(String query) {
    // 요청 URL 만들기
    URI uri = UriComponentsBuilder
            .fromUriString("http://localhost:7070")
            .path("/api/server/post-call/{query}")
            .encode()
            .build()
            .expand(query)
            .toUri();
    log.info("uri = " + uri);

    User user = new User("Robbie", "1234");

    ResponseEntity<ItemDto> responseEntity = restTemplate.postForEntity(uri, user, ItemDto.class);

    log.info("statusCode = " + responseEntity.getStatusCode());

    return responseEntity.getBody();
}

여기서는 get에서는 첫 번째 uri 두 번째가 전달받은 데이터와 매핑하여 인스턴스화할 클래스의 타입이었는데 post요청의 경우 두 번째가 HTTP Body에 넣어줄 데이터이다.

 

그러면 Header에 정보를 추가하고 싶을 때 다음과 같이 exchange 매서드의 첫 번째 파라미터에 RequestEntity 객체를 만들어 전달해 주면 된다. 이 안에 uri, header, body의 정보를 모두 담아 전달할 수 있다.

public List<ItemDto> exchangeCall(String token) {
    // 요청 URL 만들기
    URI uri = UriComponentsBuilder
            .fromUriString("http://localhost:7070")
            .path("/api/server/exchange-call")
            .encode()
            .build()
            .toUri();
    log.info("uri = " + uri);

    User user = new User("Robbie", "1234");

    RequestEntity<User> requestEntity = RequestEntity
            .post(uri)
            .header("X-Authorization", token)
            .body(user);

    ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);

    return fromJSONtoItems(responseEntity.getBody());
}

 

 

Naver Open ApI

이번 실습에서 네이버 open api를 활용했는데 여기에서 제공하는 것들은 아래와 같다. 나는 이 중에서 검색기능을 사용하였다.

네이버에서 제공하는 Open API

 

일단 사이트에서 애플리케이션을 로컬로 등록하는 과정을 거쳤다.

그리고 JSON 형태로 반환받기 위해 요청 URL은 아래에 있는 것을 사용했다.

curl "https://openapi.naver.com/v1/search/shop.json?query=%EC%A3%BC%EC%8B%9D&display=10&start=1&sort=sim" \
    -H "X-Naver-Client-Id: {애플리케이션 등록 시 발급받은 클라이언트 아이디 값}" \
    -H "X-Naver-Client-Secret: {애플리케이션 등록 시 발급받은 클라이언트 시크릿 값}" -v

query에 검색할 검색어가 들어가게 되고 요청 시 헤더에 애플리케이션 등록할 때 발급받은 아이디 값과 시크릿 값도 들어가야 한다.

그러면 위에서 사용한 RestTemplate으로 코드를 아래와 같이 구현하였다.

먼저 controller에서 NaverApiService를 주입한다.

@RestController
@RequestMapping("/api")
public class NaverApiController {

    private final NaverApiService naverApiService;

    public NaverApiController(NaverApiService naverApiService) {
        this.naverApiService = naverApiService;
    }

    @GetMapping("/search")
    public List<ItemDto> searchItems(@RequestParam String query)  {
        return naverApiService.searchItems(query);
    }
}

그리고 service에서 네이버 검색 api를 보낸다.

@Slf4j(topic = "NAVER API")
@Service
public class NaverApiService {

    private final RestTemplate restTemplate;

    public NaverApiService(RestTemplateBuilder builder) {
        this.restTemplate = builder.build();
    }

    public List<ItemDto> searchItems(String query) {
        // 요청 URL 만들기
        URI uri = UriComponentsBuilder
                .fromUriString("https://openapi.naver.com")
                .path("/v1/search/shop.json")
                .queryParam("display", 15)
                .queryParam("query", query)
                .encode()
                .build()
                .toUri();
        log.info("uri = " + uri);

        RequestEntity<Void> requestEntity = RequestEntity
                .get(uri)
                .header("X-Naver-Client-Id", "Client-Id")
                .header("X-Naver-Client-Secret", "Client-Secret")
                .build();

        ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);

        log.info("NAVER API Status Code : " + responseEntity.getStatusCode());

        return fromJSONtoItems(responseEntity.getBody());
    }

여기서 exchange 메서드를 사용해서 헤더에 아이디와 시크릿 값을 넣어서 보내주고 있다. 그리고 받아온 값이 String이므로 fromJSONtoItems 매서드로 변환하는 과정을 거쳐 itemDto 형태의 리스트로 값을 가져오고 있다.

 

 

 

· 오늘 서칭 한 자료

https://developers.naver.com/docs/serviceapi/search/shopping/shopping.md#%EC%87%BC%ED%95%91

 

검색 > 쇼핑 - Search API

검색 > 쇼핑 쇼핑 검색 개요 개요 검색 API와 쇼핑 검색 개요 검색 API는 네이버 검색 결과를 뉴스, 백과사전, 블로그, 쇼핑, 영화, 웹 문서, 전문정보, 지식iN, 책, 카페글 등 분야별로 볼 수 있는 API

developers.naver.com

 

 

· 느낀 점

- 만든 서버로 모든 요청을 해결하는 것이 아니라 외부 서버로 다시 요청을 해서 받아오는 형태로 개발해도 된다. (개발 범위의 확장)

- 이미 만들어져 있는 오픈 api를 활용해서 프로젝트 개발에 사용할 수 있을 거 같다.

- 특히 거의 모든 페이지에서 로그인의 경우 카카오, 네이버, 구글 로그인을 포함하고 있기 때문에 필수적으로 사용할 줄 알아야 한다고 느꼈다.

반응형

'Today I Learned' 카테고리의 다른 글

2023-11-27 TIL  (0) 2023.11.27
2023-11-16 TIL  (0) 2023.11.16
2023-11-14 TIL  (0) 2023.11.14
2023-11-13 TIL  (0) 2023.11.13
2023-11-07 TIL  (0) 2023.11.07

+ Recent posts