[북이지] 알라딘 api 데이터를 DB에 저장하기

진예·2023년 9월 26일
1

Code

목록 보기
1/3
post-thumbnail

🔓 서론


포폴 쓰면서 1, 2차 프로젝트에서 내가 짰던 코드들을 다시 봤는데, 내가 짰는데도 이게 뭔 소린지.. 싶은거 보면 시간에 쫓겨서 급하게 짜느라 정작 내가 짠 코드를 내 걸로 못 만든 것 같다. 그래서 이제라도 리뷰를 통해 내 걸로 만들어 보려고 한다. 리팩토링도 할 수 있으면 더 좋고!


💻 Review

Today's Review : 알라딘 API를 통해 가져온 책 정보를 DB에 저장

🛠️ Tech Stack

JAVA 11, JSP, MySQL 8.0, HTML5


📚 알라딘 API


  • 알라딘 API알라딘에 등록된 책들의 정보를 제공하는 API이다. 자세한 사항은 알라딘 Open API 매뉴얼을 통해 확인 가능! 매뉴얼을 읽어보면 책 한 권에 대해 정말 많은 정보를 제공하는데, 나는 이 중 상품 검색 API를 통해 제목, 작가, 책번호(isbn13), 출판사, 정가 를 가져왔다.

  • API를 사용하기 위해 필요한 ttb key여기서 발급 가능! 키 발급까지 이틀 정도 걸렸던 것 같다.


💡 코드

✅ 알라딘 API는 데이터를 XML 형식으로 제공하기 때문에, JSON 형식으로 파싱하여 DB에 저장

✏️ : 알라딘 API를 사용하면 결과값을 이와 같은 형태로 제공한다. 처음 보면 굉장히 당황스럽지만.. 자~세히 살펴보면 나름의 규칙이 있다!

{"version":"20131101","logo":"http://image.aladin.co.kr/img/header/2011/aladin_logo_new.gif","title":"알라딘 검색결과 - 자바", ... ,

"item":[

{"title":"XML 프로그래밍 (JSP와 Mobile 플랫폼 기반) 캠퍼스 특강 - 기초와 프로젝트, 개정판",
"link":"http:\/\/www.aladin.co.kr\/shop\/wproduct.aspx?ItemId=15392713&partner=openAPI&start=api",
"author":"김영기, 안형근 (지은이)",
"pubDate":"2012-03-05",
...
},

{"title":"예제로 쉽고 빠르게 배우는 서블릿 & JSP","link":"http:\/\/www.aladin.co.kr\/shop\/wproduct.aspx?ItemId=11565777&partner=openAPI&start=api","author":"이현주 (지은이)","pubDate":"2011-04-18", ... },

...
]}

제일 윗부분은 API 정보를 담고 있고, 이후 item[] 이라는 JSONArray 안에 제목에 "자바"가 포함된 책 정보들을 JSONObject ({}) 형태로 담고 있다! 이를 파싱하는 자세한 과정은 BookListInfo.java를 통해 확인해보자!


📝 bookDTO.java

DB에 저장할 데이터 : book_id (책 번호), title (제목), author (작가), publisher (출판사)

import lombok.Data;

@Data
public class bookDTO {
	
	private String book_id; // 책 번호
	private String title; // 제목
	private String author; // 작가
	private String publisher; 출판사
	private int price; // 
	
}	

✏️ : lombok@Data 를 통해 getter/setter 메서드 처리


📝 BookInfoList.java

  1. URL 클래스 사용 : 알라딘 API는 url을 통해 데이터를 가져오는 형식이므로, URL 클래스의 openStream() 메서드를 활용하여 데이터를 읽음. 읽어 온 결과값String 타입 result에 저장하기 위해 BufferedReader 사용

    (URL 사용 방식은 알라딘 Open API 매뉴얼 참고)
// 인증키(ttbkey)
String key = "발급받은 ttb key"; 
				
// 파싱할 데이터 저장할 변수
String result = "";
		
URL url = new URL("http://www.aladin.co.kr/ttb/api/ItemSearch.aspx?ttbkey=" + key + 
						  "&Query=검색키워드&QueryType=Title&MaxResults=50&start=1&output=js&Version=20131101");
		
BufferedReader bf = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
result = bf.readLine();

  1. XML ➡️ JSON 파싱 : json-simple-1.1.1.jar 라이브러리 필요

  • JSONParser : String 객체 ➡️ JSON 객체 변환
  • JSONObject : JSON 객체를 저장
  • JSONArrray : JSONObject배열 형태로 저장
JSONParser jsonParser = new JSONParser();
JSONObject jsonObject = (JSONObject) jsonParser.parse(result);
JSONArray item = (JSONArray) jsonObject.get("item");

// DB에 저장할 정보를 담을 ArrayList
ArrayList<bookDTO> itemList = new ArrayList<bookDTO>();
		
for(int i=0;i<item.size();i++) {
	bookDTO dto = new bookDTO(); 
			
	JSONObject itemInfo = (JSONObject) item.get(i);
			
	dto.setAuthor((String)itemInfo.get("author"));
	dto.setTitle((String)itemInfo.get("title"));
	dto.setBook_id((String)itemInfo.get("isbn13"));
	dto.setPublisher((String)itemInfo.get("publisher"));
	dto.setPrice(Integer.parseInt(String.valueOf(itemInfo.get("priceStandard"))));
			
	itemList.add(dto);
}

✏️ : jsonObjectjsonParser를 통해 JSON 형태로 변환된 result 값을 저장하고, 그 중 책에 대한 정보를 담고 있는, 이름이 item인 객체를 가져와 item배열 형태로 저장한다.

item에 저장된 값 중, 최종적으로 DB에 저장해야 할 값을 추출해야 하기 때문에 이를 담을 bookDTO 타입 itemList를 선언하고, for문을 통해 item 안에서 각 책의 정보를 담은 객체를 꺼내 JSONObject itemInfo에 저장하여 bookDTO 객체필요한 데이터를 꺼내 담아준다.

이 때, JSONObject 형태를 각 테이터 타입에 맞춰 형변환 해줘야 한다. 또한, bookDTO 타입 객체for문 안에서 선언해야 모든 객체를 담을 수 있다!


전체 코드

import java.io.*;
import java.net.URL;
import java.util.ArrayList;

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

public class BookInfoList {

	public ArrayList<bookDTO> getBookList() throws UnsupportedEncodingException, IOException, ParseException {
		
		// 인증키(ttbkey)
		String key = "발급받은 ttb key"; 
				
		// 파싱할 데이터 저장할 변수
		String result = "";
		ArrayList<bookDTO> itemList = new ArrayList<bookDTO>();
		
		
		URL url = new URL("http://www.aladin.co.kr/ttb/api/ItemSearch.aspx?ttbkey=" + key + 
						  "&Query=검색키워드&QueryType=Title&MaxResults=50&start=1&output=js&Version=20131101");
		
		BufferedReader bf = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
		
		result = bf.readLine();
		
		JSONParser jsonParser = new JSONParser();
		JSONObject jsonObject = (JSONObject) jsonParser.parse(result);
		
		JSONArray item = (JSONArray) jsonObject.get("item");
		
		for(int i=0;i<item.size();i++) {
			bookDTO dto = new bookDTO(); 
			
			JSONObject itemInfo = (JSONObject) item.get(i);
			
			dto.setAuthor((String)itemInfo.get("author"));
			dto.setTitle((String)itemInfo.get("title"));
			dto.setBook_id((String)itemInfo.get("isbn13"));
			dto.setPublisher((String)itemInfo.get("publisher"));
			dto.setPrice(Integer.parseInt(String.valueOf(itemInfo.get("priceStandard"))));
			
			itemList.add(dto);
		
		}
       
       // 데이터가 잘 담겼는지 확인
       System.out.println(itemList.size() + "\n");
       for(int i=0;i<itemList.size();i++) {
		  System.out.println(itemList.get(i));
	   }
		
		return itemList;
	}
}

: API에서 한 번에 최대 50개의 정보를 제공하는데, 모두 잘 담긴 것을 확인할 수 있다!

📝 BookDAO.java

BookInfoList.java를 통해 얻은 itemList를 대입하여 DB에 책 정보 저장!

public class bookDAO {
	
    // DB 연결을 위한 메서드 getCon(), closeDB() 메서드 생략
	public void insertInfo(ArrayList itemList) {
		try {
			// 1+2. DB 연결
			con = getCon();
			
			// 3. sql 작성 & pstmt 객체 생성
			sql = "insert into books(book_id, title, author, publisher, price) values(?,?,?,?,?)";
			pstmt = con.prepareStatement(sql);
			
			for(int i=0;i<itemList.size();i++) {
				
				bookDTO dto = (bookDTO) itemList.get(i);
				
				pstmt.setString(1,dto.getBook_id());
				pstmt.setString(2, dto.getTitle());
				pstmt.setString(3, dto.getAuthor());
				pstmt.setString(4, dto.getPublisher());
				pstmt.setInt(5, dto.getPrice());
				
				// 4. sql 실행
				pstmt.executeUpdate();
			
			}
			
			System.out.println("DB 저장 성공!");
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			closeDB();
		}
	}
}

📝 checkDB.jsp

jsp 페이지를 실행하여 책 정보를 DB에 저장하고, 동시에 저장된 책의 정보 목록을 출력함.

<!-- body 부분만 가져옴! -->
<%	
   	// itemList를 가져옴
	BookInfoList bi = new BookInfoList();
	ArrayList<bookDTO> itemList = bi.getBookList();
	
  	// 책 정보를 DB에 저장
	bookDAO dao = new bookDAO();	
	dao.insertInfo(itemList);
%>

<h1>저장된 책 확인하기!</h1>
<h3>총 <%=itemList.size() %>권의 책이 저장되었습니다! </h3>

<hr>

<table border="1">
	<tr>
		<th>책 번호</th>
		<th>제목</th>
		<th>저자</th>
		<th>출판사</th>
		<th>정가</th>
	</tr>
<%
	for(int i=0;i<itemList.size();i++) { %>
		<tr>
			<td><%=itemList.get(i).getBook_id() %></td>
			<td><%=itemList.get(i).getTitle() %></td>
			<td><%=itemList.get(i).getAuthor() %></td>
			<td><%=itemList.get(i).getPublisher() %></td>
			<td><%=itemList.get(i).getPrice() %></td>
		</tr>
<% } %>	
</table>


⚠️ 개선점

  • 책 정보를 저장할 때 BookInfoList.java에서 url의 검색키워드start직접 바꿔줘야 한다는 점 / jsp 페이지특정 기능을 포함하고 있는 것이 아니라, 단순히 DB 저장을 위해 만들어진 것

✏️ : 페이지에서 키워드를 입력하면 해당 키워드를 가지는 책을 저장할 수 있도록 수정하면 좋을 것 같다!

  • 저장하려는 책 목록 중 이미 저장된 책이 존재하는 경우, 페이지는 정상적으로 실행되지만 SQL에서 기본키가 중복되어 오류가 발생하는 점

✏️ : DB 저장 시, 중복값 제거 프로세스가 필요할듯!


🔒 마무리


알라딘 api 파싱 작업은 1차 프로젝트(중고책 거래 웹사이트) 중 제일 머리 아팠던 작업이였다. 이 작업만 거의 일주일을 넘게 붙잡고 있었는데, DB에 데이터를 저장하는 작업이다 보니 정작 완성된 사이트에는 해당 작업을 눈으로 확인할 수 없다는 점이 좀 아쉬웠던 것 같다. 이왕 ttb key도 발급 받았으니 개선점에 적었던 프로젝트Spring으로 진행해 보는 것도 좋을 것 같다!
profile
백엔드 개발자👩🏻‍💻가 되고 싶다

0개의 댓글