✅ Today's Review : 알라딘 API를 통해 가져온 책 정보를 DB에 저장
✅ JAVA 11, JSP, MySQL 8.0, HTML5
알라딘 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를 통해 확인해보자!
✅ 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
메서드 처리
- 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();
- 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);
}
✏️ : jsonObject
에 jsonParser
를 통해 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개의 정보를 제공하는데, 모두 잘 담긴 것을 확인할 수 있다!
✅ 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();
}
}
}
✅ 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 저장 시, 중복값 제거 프로세스가 필요할듯!