on my way

네이버 API로 도서 조회 프로그램 만들기 본문

Computer Science/Spring

네이버 API로 도서 조회 프로그램 만들기

wingbeat 2024. 6. 20. 02:17
반응형

 

프로그램 동작 원리

 

 

 

Naver API를 받아와야 한다.

 

아래는 사용 예제

 

// NaverAPI.java

package util;

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;

public class NaverAPI {
    // 네이버 책 검색 API를 호출하여 결과를 받아오는 메서드
    public String getBookList(String searchWord) {
        // 애플리케이션 클라이언트 아이디와 시크릿
        String clientId = "";
        String clientSecret = "";

        String text = null;
        try {
            // 검색어를 UTF-8 형식으로 인코딩
            text = URLEncoder.encode("월드컵", "UTF-8");
        } catch (UnsupportedEncodingException e) {
            // 인코딩 실패 시 예외 처리
            throw new RuntimeException("검색어 인코딩 실패", e);
        }

        // API URL 설정 (JSON 결과 형식으로 요청)
        String apiURL = "https://openapi.naver.com/v1/search/book?query=" + text;

        // 요청 헤더 설정
        Map<String, String> requestHeaders = new HashMap<>();
        requestHeaders.put("X-Naver-Client-Id", clientId);
        requestHeaders.put("X-Naver-Client-Secret", clientSecret);
        
        // API 호출 및 응답 받기
        String responseBody = get(apiURL, requestHeaders);

        return responseBody;
    }

    public static void main(String[] args) {
        // NaverAPI 인스턴스 생성 및 책 검색 메서드 호출
        NaverAPI n = new NaverAPI();
        System.out.println(n.getBookList("평균의 종말"));
    }

    // HTTP GET 요청을 보내고 응답을 받는 메서드
    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.getErrorStream());
            }
        } catch (IOException e) {
            throw new RuntimeException("API 요청과 응답 실패", e);
        } finally {
            con.disconnect();
        }
    }

    // URL을 기반으로 HttpURLConnection을 생성하는 메서드
    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);
        }
    }
}

 

// BookList.java Servlet

package book;

import java.io.IOException;
import java.io.PrintWriter;

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

import util.NaverAPI;

// 서블릿 어노테이션을 이용하여 '/book/list.do' URL에 대한 요청을 처리하는 서블릿을 정의함.
@WebServlet("/book/list.do")
public class BookList extends HttpServlet {
    // serialVersionUID는 클래스의 버전 관리에 사용되는 UID입니다.
    private static final long serialVersionUID = 1L;

    // GET 요청을 처리하기 위한 메소드입니다.
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 클라이언트로부터 'searchWord' 파라미터 값을 가져옵니다.
        String searchWord = request.getParameter("searchWord");
        // NaverAPI 인스턴스를 생성합니다.
        NaverAPI n = new NaverAPI();
        // NaverAPI를 통해 받은 책 목록 결과를 문자열로 가져옵니다.
        String result = n.getBookList(searchWord); 
        // 응답의 내용 유형을 "text/html;charset=UTF-8"로 설정합니다. 이를 통해 한글이 제대로 표시될 수 있도록 합니다.
        response.setContentType("text/html;charset=UTF-8");
        // 응답에 쓰기 위한 PrintWriter 객체를 생성합니다.
        PrintWriter w = response.getWriter();
        // 가져온 결과를 클라이언트에게 전송합니다.
        w.println(result);
    }
}

 

// book.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%> <!-- 페이지 기본 설정: Java 언어 사용, 컨텐츠 타입과 페이지 인코딩을 UTF-8로 설정 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"> <!-- 문서의 문자 인코딩을 UTF-8로 설정 -->
<title>Insert title here</title> <!-- 웹페이지 타이틀 설정 -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <!-- jQuery 라이브러리를 CDN을 통해 가져옴 -->
<script>
	$(function(){
		$("#btn").click(function() { // 버튼 클릭 이벤트 핸들러 설정
			//alert(1);
			if ($("#searchValue").val() == '') { // 검색어 입력 여부 확인
				alert('검색어를 입력하세요'); // 검색어 미입력시 알림
				$("#searchValue").focus(); // 검색어 입력란에 포커스 설정
				return; // 이벤트 핸들러 종료
			}
			$.ajax({ // AJAX 요청 설정 및 전송
				url : '/bookSearch/book/list.do', // 요청할 서버의 URL
				data : { // 서버로 전송할 데이터
					searchWord:$("#searchValue").val() // 검색어 데이터
				},
				dataType : 'json', // 서버로부터 받을 데이터의 타입
				success : function(res) { // 요청 성공시 실행할 콜백 함수
					// 도서 정보를 테이블 형태로 출력하기 위한 HTML 문자열 생성 시작
					var html = "<table border='1'>";
					html += "<tr>";
					html += "	<th>이미지</th>"; // 테이블 헤더 - 이미지
					html += "	<th>제목</th>"; // 테이블 헤더 - 제목
					html += "	<th>저자</th>"; // 테이블 헤더 - 저자
					html += "</tr>";
					res.items.forEach(item=>{ // 받은 데이터의 아이템별로 반복 처리
						console.log(item); // 콘솔에 아이템 정보 출력 (디버깅용)
						html += "<tr>";
						html += "	<td><a href='"+item.link+"' target='_blank'><img width='100' src='"+item.image+"'></a></td>"; // 이미지와 링크
						html += "	<td>"+item.title+"</td>"; // 제목
						html += "	<td>"+item.author+"</td>"; // 저자
						html += "</tr>";
					});
					html += "</table>"; // HTML 문자열 종료
					$("#bookArea").html(html); // 생성된 HTML을 페이지에 삽입
				}
			});
		});
	});
</script>
</head>
<body>
<input type="text" id="searchValue"> <!-- 검색어 입력란 -->
<input type="button" id="btn" value="도서 검색"> <!-- 검색 버튼 -->
<div id="bookArea"></div> <!-- 검색 결과를 출력할 영역 -->
</body>
</html>

 

 

 


// bookList.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%> <!-- 현재 페이지의 언어를 자바로 설정하고, 콘텐츠 타입을 HTML로, 문자 인코딩을 UTF-8로 설정합니다. -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!-- JSP 페이지에서 JSTL 코어 태그 라이브러리를 사용하기 위한 선언입니다. -->

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"> <!-- 문서의 문자 인코딩을 UTF-8로 설정합니다. -->
<title>Insert title here</title> <!-- 웹 페이지의 제목을 설정합니다. 제목은 탭에 표시됩니다. -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <!-- jQuery 라이브러리를 포함합니다. -->
<script>
// 여기에 자바스크립트 코드를 추가할 수 있습니다.
</script>
</head>
<body>
총 검색 건수 : ${map.total } <!-- 서버로부터 받은 총 검색 건수를 표시합니다. -->
<table border="1">
	<tr>
		<th>이미지</th> <!-- 테이블의 헤더 셀을 정의합니다. -->
		<th>제목</th>
		<th>저자</th>
	</tr>
	<c:forEach var="item" items="${map.items }"> <!-- map.items 컬렉션을 순회하며 각 아이템에 대해 반복합니다. -->
		<tr>
			<td>
				<a href="${item.link }" target="_blank"> <!-- 아이템의 링크를 새 탭에서 열도록 설정합니다. -->
				<img src="${item.image }" width="100"></a> <!-- 아이템의 이미지를 표시합니다. -->
			</td>
			<td>${item.title }</td> <!-- 아이템의 제목을 표시합니다. -->
			<td>${item.author }</td> <!-- 아이템의 저자를 표시합니다. -->
		</tr> 
	</c:forEach>
		
</table>

</body>
</html>

 

// BookList2.java

package book;

// 필요한 패키지와 클래스를 임포트합니다.
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

import util.NaverAPI;

// "/book/list2.do" URL 요청을 처리하는 서블릿을 정의합니다.
@WebServlet("/book/list2.do")
public class BookList2 extends HttpServlet {
	private static final long serialVersionUID = 1L;

    // GET 요청을 처리하는 메소드입니다.
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 요청 파라미터로부터 'searchWord'를 가져옵니다.
		String searchWord = request.getParameter("searchWord");
		// NaverAPI 객체를 생성하고 책 목록을 검색합니다.
		NaverAPI n = new NaverAPI();
		String result = n.getBookList(searchWord);
		
		// 검색 결과를 파싱하여 Map > List > Map 구조로 변환합니다.
		try {
			Map<String, Object> map = new HashMap<>();
			JSONParser parser = new JSONParser();
			JSONObject obj = (JSONObject) parser.parse(result);

			// 검색 결과로부터 'lastBuildDate'와 'total' 정보를 Map에 저장합니다.
			map.put("lastBuildDate", obj.get("lastBuildDate"));
			map.put("total", obj.get("total"));

			// 'items' JSONArray에서 책 정보를 추출하여 List에 저장합니다.
			JSONArray items = (JSONArray) obj.get("items");
			List<Map<String, Object>> list = new ArrayList<>();

			for (int i = 0; i < items.size(); i++) {
				JSONObject item = (JSONObject) items.get(i); // 책 하나의 정보가 담긴 JSONObject입니다.
				Map<String, Object> map2 = new HashMap<>();
				// 책의 제목, 링크, 저자, 이미지 정보를 Map에 저장합니다.
				map2.put("title", item.get("title"));
				map2.put("link", item.get("link"));
				map2.put("author", item.get("author"));
				map2.put("image", item.get("image"));
				// Map을 List에 추가합니다.
				list.add(map2);
			}
			// 최종적으로 구성된 List를 'items' 키로 Map에 저장합니다.
			map.put("items", list);
			// 구성된 Map을 request 속성으로 추가합니다.
			request.setAttribute("map", map);
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 결과를 보여줄 JSP 페이지로 요청을 전달합니다.
		RequestDispatcher rd = request.getRequestDispatcher("/bookList.jsp");
		rd.forward(request, response);
	}

}
반응형