사전 지식


오픈 API란

서비스를 제공하는 업체에서 외부 개발자가 자사 서비스의 기능을 간단히 호출해 이용할 수 있도록 공개해둔 API를 말합니다. 자사의 서비스를 다른 업체의 앱이나 서비스에서도 제공하게 하여 사용자를 늘리고 영향력을 확대하는 것이 주된 목적으로, 수많은 인터넷 업체가 서비스 일부를 앞다투어 오픈 API로 제공하고 있습니다.

 

주로 HTTP 프로토콜로 통신하며, 응답 데이터의 형태는 JSON 포맷을 가장 많이 씁니다. 과거에는 XML을 많이 이용했지만  JSON이 더 가볍고 사람이 읽기에도 편하며, 무엇보다 웹 프로그래밍의 표준 언어 격인 자바스크립트에서 바로 읽고 쓸 수 있어 많은 사랑을 받고 있습니다.

 

네이버 검색 API는 검색 결과를 XML이나 JSON으로 반환합니다. 우리는 JSON을 사용할 것이므로, 코드를 살펴보기 전에 JSON이 무엇인지부터 알아보겠습니다. 

 

JSON기초

JSON은 javaScript Object Notation의 약자로, 자바스크립트에서 객체나 배열을 만들 때 사용하는 표현 방식입니다. 작성하기 쉽고 용량을 적게 차지해서 XML을 대체하는 데이터 전송 및 저장 수단으로 많이 쓰입니다.

 

JSON의 형식에는 다음과 같이 모두 2가지가 있습니다. 중괄호 { }는 객체를 뜻하고, 대괄호 [ ]는 배열을 뜻합니다. 혼합해서 사용할 수도 있습니다

{"name": "홍길동", "age": 45} /* 객체 */
["HTML5", "CSS3", "JavaScript", "JQuery"] /* 배열 */

프로젝트 시작


오픈 API 이용 신청

네이버 검색 API를 사용하려면 먼저 네이버 개발자센터에서 이용 신청을 해야 합니다.

  1. 네이버에서 접속하고 로그인합니다.
  2. 네이버 검색창에서 "네이버 개발자센터"를 검색합니다.
  3. 검색 결과에서 "네이버 개발자센터" 링크를 클릭합니다.
  4. [Products] -> [검색] 메뉴를 클릭합니다.
  5. 화면을 아래로 스크롤하여 [오픈 API 이용 신청] 버튼을 클릭합니다.
  6. 오픈 API 이용약관에 동의하면 [애플리케이션 등록] 페이지로 이동되는데 다음과 같이 입력합니다
    • 애플리케이션 이름 : 원하는 이름을 입력합니다
    • 사용 API : '검색'을 선택합니다
    • 환경 추가 : WEB 설정
    • 웹 서비스 URL : http://localhost:8080
  7. [등록하기]를 클릭하고, [Client ID]와 [Client Secret] 항목의 값을 메모장에 기록해둡니다. 검색 API를 사용하기 위해 발급된 키입니다

API 문서를 살펴보면 API를 활용하는 예제코드API 기본 정보, 요청 변수 등등 검색 API에 대한 설명이 자세히 나와있습니다

서블릿 구현

API 설명 문서의 호출 예제를 복사해서 알맞게 수정해보겠습니다

package api;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/NaverSearchAPI.do")
public class SearchAPI extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // 1. 인증 정보 설정
        String clientId = "발급 받은 ID";
        String clientSecret = "발급 받은 Secret";

        // 2. 검색 조건 설정
        int startNum = 0;    // 검색 시작 위치
        String text = null;  // 검색어
        try {
             startNum = Integer.parseInt(req.getParameter("startNum"));
             String searchText = req.getParameter("keyword");
             text = URLEncoder.encode(searchText, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("검색어 인코딩 실패", e);
        }

        // 3. API URL 조합
        String apiURL = "https://openapi.naver.com/v1/search/blog?query=" + text
                        + "&display=10&start=" + startNum;  // json 결과
        //String apiURL = "https://openapi.naver.com/v1/search/blog.xml?query=" + text;  // xml 결과

        // 4. API 호출
        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);

        // 5. 결과 출력
        System.out.println(responseBody);  // 콘솔에 출력

        resp.setContentType("text/html; charset=utf-8");
        resp.getWriter().write(responseBody);  // 서블릿에서 즉시 출력
    }

    private static String get(String apiUrl, Map<String, String> requestHeaders){
        // (긁어온 예제와 변경사항 없음)
    }


    private static HttpURLConnection connect(String apiUrl){
    	// (긁어온 예제와 변경사항 없음)
    }


    private static String readBody(InputStream body){
        // (긁어온 예제와 변경사항 없음)
    }
}

Point

  • 검색어는 한글 깨짐을 방지하기 위해 UTP-8로 인코딩합니다.

검색 결과를 웹 브라우저에 출력

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>검색 API</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

<script>
// [검색 요청] 버튼 클릭 시 실행할 메서드를 정의합니다.
$(function() {
    $('#searchBtn').click(function() {
      $.ajax({
        url : "../NaverSearchAPI.do",  // 요청 URL
        type : "get",                  // HTTP 메서드
        data : {                       // 매개변수로 전달할 데이터
            keyword : $('#keyword').val(),                   // 검색어
            startNum : $('#startNum option:selected').val()  // 검색 시작 위치
        },
        dataType : "json",      // 응답 데이터 형식
        success : sucFuncJson,  // 요청 성공 시 호출할 메서드 설정
        error : errFunc         // 요청 실패 시 호출할 메서드 설정
      });
    });
});

// 검색 성공 시 결과를 화면에 뿌려줍니다.
function sucFuncJson(d) {
    var str = "";
    $.each(d.items, function(index, item) {
        str += "<ul>";
        str += "    <li>" + (index + 1) + "</li>";
        str += "    <li>" + item.title + "</li>";
        str += "    <li>" + item.description + "</li>";
        str += "    <li>" + item.bloggername + "</li>";
        str += "    <li>" + item.bloggerlink + "</li>";
        str += "    <li>" + item.postdate + "</li>";
        str += "    <li><a href='" + item.link + "' target='_blank'>바로가기</a></li>";
        str += "</ul>";
    });
    $('#searchResult').html(str);
}

// 실패 시 경고창을 띄워줍니다.
function errFunc(e) {
    alert("실패: " + e.status);
}
</script>

<style>
    ul{border:2px #cccccc solid;}
</style>
</head>
<body>
<div>
    <div>
        <form id="searchFrm">
            한 페이지에 10개씩 출력됨 <br />
            <select id="startNum">
                <option value="1">1페이지</option>
                <option value="11">2페이지</option>
                <option value="21">3페이지</option>
                <option value="31">4페이지</option>
                <option value="41">5페이지</option>
            </select>
            <input type="text" id="keyword" placeholder="검색어를 입력하세요." />
            <button type="button" id="searchBtn">검색 요청</button>
        </form>
    </div>
    <div class="row" id="searchResult">
        여기에 검색 결과가 출력됩니다.
    </div>
</div>
</body>
</html>

참고한 문헌

성낙현의 JSP 웹 프로그래밍

 

+ Recent posts