개발자's Life

[JAVA] Naver 검색 API 사용법 본문

Back-end/Java

[JAVA] Naver 검색 API 사용법

Rowen Jobs 2023. 5. 28. 18:31
728x90
반응형

오늘은 네이버 검색 API 관련하여 제공되는 Java 코드 참고하여 작성하겠습니다. 

역시나 일기형태(메모형태)로 작성하여 다로 끝나는 부분 양해 부탁드립니다.

<memo>

1. 네이버 개발자센터에서 애플리케이션을 등록

 

애플리케이션 - NAVER Developers

 

developers.naver.com

 위 링크로 들어가서 애플리케이션 등록을 한다. 

내용 입력은 아래 부부을 참고하여 등록을 하고 사용API 는 검색을 선택해주어야 정상적으로 연결이 되어 Response 값을 받을 수 있다. 

애플리케이션 등록 예시

2. Client-id, Client-pw 기록

애플리케이션 정보

등록되어 있는 Client ID 와 Client Secret 을 사용하게 된다. 

아래에는 해당 Client ID 를 사용하여 얼만큼 호출하였는지 알 수 있고 25000 호출 허용이 가능한것으로 확인이 된다.

 

3. 제공되는 Java 코드 설명

 

검색 > 블로그 - Search API

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

developers.naver.com

위의 링크를 가면 Java 코드가 친절히 안내되어 있다. 

// 네이버 검색 API 예제 - 블로그 검색
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

// ApiExamSearchBlog 라는 자바 메인메소드를 가지는 클래스이다.
public class ApiExamSearchBlog {

	// 자바 실행 메인 메소드
    public static void main(String[] args) {
        String clientId = "YOUR_CLIENT_ID"; //애플리케이션 클라이언트 아이디
        String clientSecret = "YOUR_CLIENT_SECRET"; //애플리케이션 클라이언트 시크릿

		// 검색하는 내용의 변수이다.
        String text = null;
        try {
        	// 그린팩토리 부분이 검색하는 키워드가 들어가는 자리이고 UTF-8 로 인코딩을 시켜준다.
            text = URLEncoder.encode("그린팩토리", "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("검색어 인코딩 실패",e);
        }

		// 친절히 API URL 이 제공이 되고 필수인 query 가 Param 으로 되어있다. 
        String apiURL = "https://openapi.naver.com/v1/search/blog?query=" + text;    // JSON 결과
        //String apiURL = "https://openapi.naver.com/v1/search/blog.xml?query="+ text; // XML 결과

		// Map 형태의 requestHeaders 를 변수로 만들고 애플리케이션에서 만든 Client ID와 Client Secret 이 여기서 사용이 된다.
        Map<String, String> requestHeaders = new HashMap<>();
        requestHeaders.put("X-Naver-Client-Id", clientId);
        requestHeaders.put("X-Naver-Client-Secret", clientSecret);
        // URL 을 연결해준다.
        String responseBody = get(apiURL,requestHeaders);


        System.out.println(responseBody);
    }

	
    // 메인 메소드에서 get 이라는 URL 연결해주는 메소드이다.
    private static String get(String apiUrl, Map<String, String> requestHeaders){
    	// 해당 URL 을 HttpURLConnection 타입으로 연결해준다.(아래 connect 라는 메소드 참고) 
        HttpURLConnection con = connect(apiUrl);
        try {
        	// GET 방식으로 연결이 가능하다
            con.setRequestMethod("GET");
            // 애플리케이션에서 만들 Client ID 와 Client Secret 을 셋팅해준다
            for(Map.Entry<String, String> header :requestHeaders.entrySet()) {
                con.setRequestProperty(header.getKey(), header.getValue());
            }

			// 연결이 된 상태를 resonse code 를 int 타입으로 받아준다.
            int responseCode = con.getResponseCode();
            // response code 상태가 200 인지 확인한다. 
            if (responseCode == HttpURLConnection.HTTP_OK) { // 정상 호출
                return readBody(con.getInputStream());
            } else { // 오류 발생
                return readBody(con.getErrorStream());
            }
        } catch (IOException e) {
            throw new RuntimeException("API 요청과 응답 실패", e);
        } finally {
            con.disconnect();
        }
    }


    private static HttpURLConnection connect(String apiUrl){
        try {
            URL url = new URL(apiUrl);
            return (HttpURLConnection)url.openConnection();
        } catch (MalformedURLException e) {
            throw new RuntimeException("API URL이 잘못되었습니다. : " + apiUrl, e);
        } catch (IOException e) {
            throw new RuntimeException("연결이 실패했습니다. : " + apiUrl, e);
        }
    }


    private static String readBody(InputStream body){
        InputStreamReader streamReader = new InputStreamReader(body);


        try (BufferedReader lineReader = new BufferedReader(streamReader)) {
            StringBuilder responseBody = new StringBuilder();


            String line;
            while ((line = lineReader.readLine()) != null) {
                responseBody.append(line);
            }


            return responseBody.toString();
        } catch (IOException e) {
            throw new RuntimeException("API 응답을 읽는 데 실패했습니다.", e);
        }
    }
}

4. 제공되는 Java 코드 Controller 단에 맞추어 코드 작성

제공되는 Java 코드를 MVC 패턴으로 사용하기위해 Controller 단에서 처리를 해보는 코드를 작성한다. 

예시이기 때문에 참고하여 Service 단에 작성할 수 있다.

package com.example.api_test.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * Naver API
 * client-id : Your ID
 * client-pw : Your PW
 */
@Controller
public class TestApiController {
	
    
    // GET 방식의 어노테이션을 사용
    @GetMapping("/api_test")
    public void postApiTest(@RequestParam("query") String query){
        String clientId = "Your ID"; //애플리케이션 클라이언트 아이디
        String clientSecret = "Your PW"; //애플리케이션 클라이언트 시크릿

		// query 라는 Parameter 를 받음
        String text = query;
        try {
            text = URLEncoder.encode(text, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("검색어 인코딩 실패",e);
        }


        String apiURL = "https://openapi.naver.com/v1/search/blog?query=" + text;    // JSON 결과
        //String apiURL = "https://openapi.naver.com/v1/search/blog.xml?query="+ text; // XML 결과

        Map<String, String> requestHeaders = new HashMap<>();
        requestHeaders.put("X-Naver-Client-Id", clientId);
        requestHeaders.put("X-Naver-Client-Secret", clientSecret);
        String responseBody = get(apiURL,requestHeaders);
		
        //여기서 반환되는 값 확인.(콘솔에서 확인)
        System.out.println(responseBody)
    }


    private static String get(String apiUrl, Map<String, String> requestHeaders){
        HttpURLConnection con = connect(apiUrl);
        try {
            con.setRequestMethod("GET");
            for(Map.Entry<String, String> header :requestHeaders.entrySet()) {
                con.setRequestProperty(header.getKey(), header.getValue());
            }

            int responseCode = con.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) { // 정상 호출
                return readBody(con.getInputStream());
            } else { // 오류 발생
                return readBody(con.getInputStream());
            }
        } catch (IOException e) {
            throw new RuntimeException("API 요청과 응답 실패", e);
        } finally {
            con.disconnect();
        }
    }


    private static HttpURLConnection connect(String apiUrl){
        try {
            URL url = new URL(apiUrl);
            return (HttpURLConnection)url.openConnection();
        } catch (MalformedURLException e) {
            throw new RuntimeException("API URL이 잘못되었습니다. : " + apiUrl, e);
        } catch (IOException e) {
            throw new RuntimeException("연결이 실패했습니다. : " + apiUrl, e);
        }
    }


    private static String readBody(InputStream body){
        InputStreamReader streamReader = new InputStreamReader(body);


        try (BufferedReader lineReader = new BufferedReader(streamReader)) {
            StringBuilder responseBody = new StringBuilder();


            String line;
            while ((line = lineReader.readLine()) != null) {
                responseBody.append(line);
            }


            return responseBody.toString();
        } catch (IOException e) {
            throw new RuntimeException("API 응답을 읽는 데 실패했습니다.", e);
        }
    }
}

간단하게 작성이 가능하다. 

우선 제공되는 Java 코드의 메인 메소드 부분을 Controller 단에서 Mapping 이 호출이 되어야 실행 가능하게 변경하였고 

나머지는 틀을 거의 변경하지 않았다. 

 

5. 정상적으로 작동확인

포스트맨을 사용하여 확인해보았다. 

콘솔은 이쁘게 찍히지 않아

http://json.parser.online.fr/

 

Json Parser Online

 

json.parser.online.fr

JSON 정렬 웹사이트로 정렬한 내용입니다.

반환되는 값

{

  • "lastBuildDate":"Sun, 28 May 2023 17:59:19 +0900",
  • "total":40694,
  • "start":1,
  • "display":10,
  • "items":[
    1. {
      • "title":"행복했던 <b>압구정로데오 맛집<\/b>",
      • "link":"https:\/\/blog.naver.com\/yeb0111\/223113352366",
      • "description":"<b>압구정<\/b>점에서 식사권을 제공받아 솔직하게 작성한 글입니다. * 진짜 솔직하게 적은 거랍니다. <b>압구정<\/b> <b>맛집<\/b> 추천은 룸으로 예약해서 가족 모임, 기념일 데이트 즐기세요! 행복했던 <b>압구정로데오 맛집<\/b> 끝!!!",
      • "bloggername":"윤궁금의 매일궁금",
      • "bloggerlink":"blog.naver.com\/yeb0111",
      • "postdate":"20230527"
      },
    2. {
      • "title":"고급졌던 <b>압구정로데오 맛집<\/b>",
      • "link":"https:\/\/blog.naver.com\/yangha84\/223087803360",
      • "description":"와인과 음식뿐만 아니라 분위기 <b>맛집<\/b>이라고 해도 손색없었네요. 주소 : 서울 강남구 선릉로160길 7 2층 영업시간 : 월~토 18:00 ~ 01:00 문의전화 : 0507-1479-1047 페어링지라는 곳인데 <b>압구정 로데오<\/b>역에서 가까운... ",
      • "bloggername":",",
      • "bloggerlink":"blog.naver.com\/yangha84",
      • "postdate":"20230428"
      },
    3. {
      • "title":"[<b>압구정 로데오 맛집<\/b>]핫한 클랩피자 청담에서 슭돈슭산 피맥타임",
      • "link":"https:\/\/blog.naver.com\/ujin996\/223062047762",
      • "description":"찾아온 <b>압구정 로데오 맛집<\/b>, 클랩피자 청담점. 도산공원 바로 앞에 위치해 있는 클랩피자 청담점. 처음가보는 <b>압구정 로데오<\/b> 피자집이라 네이버 후기를 보고 한적한 곳이겠거니 생각하고 갔더니 웨이팅이 있는... ",
      • "bloggername":"뚜벅뚜벅 뚜벅이생활",
      • "bloggerlink":"blog.naver.com\/ujin996",
      • "postdate":"20230401"
      },
    4. {
      • "title":"<b>압구정로데오 맛집<\/b> 바빌리안테이블 서울 분위기 좋은... ",
      • "link":"https:\/\/blog.naver.com\/haha1152\/223097184045",
      • "description":"오늘은 예전에 오빠와 #기념일데이트 다녀왔던 #<b>압구정로데오<\/b>데이트 코스로 유명한 #바빌리안테이블... #서울파인다이닝 #강남파인다이닝 #청담파인다이닝 #<b>압구정로데오맛집<\/b> #<b>압구정<\/b><b>맛집<\/b>... ",
      • "bloggername":"주야의 기록장",
      • "bloggerlink":"blog.naver.com\/haha1152",
      • "postdate":"20230509"
      },
    5. {
      • "title":"<b>압구정로데오<\/b> 브런치 <b>맛집<\/b> 호호식당 도산공원, 오순도순",
      • "link":"https:\/\/blog.naver.com\/ninamath\/223080941058",
      • "description":"Japanese brunch Hoho Sikdang Prologue 친구와 힐링을 하러 방문한 이곳, <b>압구정로데오<\/b> 브런치 <b>맛집<\/b> 호호식당... 'Menu' 메뉴 <b>압구정로데오 맛집<\/b> 호호식당은 메뉴가 생가보다 훨씬 다양했는데 로스카츠 정식부터... ",
      • "bloggername":"어푸어푸 맛집 여행",
      • "bloggerlink":"blog.naver.com\/ninamath",
      • "postdate":"20230421"
      },
    6. {
      • "title":"<b>압구정로데오<\/b> 대막 : 깔끔한 일식 도산공원 <b>맛집<\/b>",
      • "link":"https:\/\/blog.naver.com\/suulggu\/223050908495",
      • "description":"대막 ⋆ 위치 서울 강남구 <b>압구정<\/b>로46길 75, 수인분당선 <b>압구정로데오<\/b>역 ⋆ 운영시간 매일 12:00-21:00... 답 #<b>압구정로데오맛집<\/b> #도산공원<b>맛집<\/b> #대막 #마제소바 #후토마끼 #지라시스시 #대막메뉴 #대막웨이팅... ",
      • "bloggername":"스쳐간 것들의 기록",
      • "bloggerlink":"blog.naver.com\/suulggu",
      • "postdate":"20230321"
      },
    7. {
      • "title":"<b>압구정로데오 맛집<\/b> 신서울 <b>압구정<\/b>, 라면요리와 퓨전 한식!",
      • "link":"https:\/\/blog.naver.com\/kyoonsun7\/223079749145",
      • "description":"<b>압구정로데오<\/b>역 5번출구에서 도보 6분거리에 있는 단독 신축 건물 2층에 위치한 신서울 <b>압구정<\/b>. 3월 25일부터 가오픈 기간을 가지고 4월 1일에 정식 오픈을 했다고 해요. <b>압구정로데오 맛집<\/b> 상호는 짧게 '신서울... ",
      • "bloggername":"Hello, Delicious",
      • "bloggerlink":"blog.naver.com\/kyoonsun7",
      • "postdate":"20230419"
      },
    8. {
      • "title":"<b>압구정로데오 맛집<\/b> :서울 파인다이닝 도쿄등심 디너c 기념일... ",
      • "link":"https:\/\/blog.naver.com\/ad_yu2016\/223099317242",
      • "description":"활용해서 <b>압구정로데오<\/b> 카페거리 좀 거닐다가 저녁 약속 시간이 되어 슬슬 걸어 도착했어요. 서울... <b>압구정 로데오 맛집<\/b> 도쿄등심은 이름은 도쿄등심이지만 해산물부터 다양한 요리가 나와서 좋더라고요 광어... ",
      • "bloggername":"욜영의찬란한순간들",
      • "bloggerlink":"blog.naver.com\/ad_yu2016",
      • "postdate":"20230511"
      },
    9. {
      • "title":"<b>압구정로데오 맛집<\/b> 도쿄등심 기념일 <b>압구정<\/b> 데이트 장소로 추천",
      • "link":"https:\/\/blog.naver.com\/hyeronjr\/223110541461",
      • "description":"<b>압구정<\/b>점은 <b>압구정로데오<\/b>역에서 10분정도 거리에 있어요. CGV와 쉑쉑버거 사이 골목으로 들어가면 3층에 위치한 도쿄등심이 보여요. 찾기는 엄청 쉬워요. 매장 외관 & 내부 <b>압구정로데오 맛집<\/b> 도쿄등심... ",
      • "bloggername":"맛있는 여행",
      • "bloggerlink":"blog.naver.com\/hyeronjr",
      • "postdate":"20230524"
      },
    10. {
      • "title":"<b>압구정로데오 맛집<\/b> 우돈청, 테라스 좌석 있는 고기집",
      • "link":"https:\/\/blog.naver.com\/hyunjin0427\/223088760816",
      • "description":"그리고 눈에 띄는 김희철의 싸인 ㅋㅋㅋ 좌석 규모도 넓고 연예인도 많이 방문하는 <b>맛집<\/b>인가보다. 빛깔... 최대한 빠른 시간내로 찾아가보길 추천! #<b>압구정로데오맛집<\/b> #<b>압구정로데오<\/b>고기집 #<b>압구정로데오<\/b>회식",
      • "bloggername":"시시콜콜한 이야기",
      • "bloggerlink":"blog.naver.com\/hyunjin0427",
      • "postdate":"20230429"
      }
    ]

}

 

정상적으로 JSON 형태의 정보를 받을것을 알 수 있다.

</memo>

 

궁금하신 점이나 틀린부분 있을 경우 댓글로 꼭!! 남겨주세요

 

읽어주셔서 감사합니다. 

 

Rowen.

728x90
Comments