뽈뽈뽈 프로젝트의 끝이 얼마 안 남았기 때문에 전체적인 완성도를 위해
맛집 페이지 작업을 시작했다.
작업하면서 정리하기!
기존 작업 결과물
기존에 작업했던 한국관광공사_국문 관광정보 서비스_GW는 공공데이터 API를 호출해서
각각의 해당하는 엔드포인트에 입력값을 넣어서 원하는 정보들을 받아서
최종적으로는 DB에 저장되게 작업했었다.
위 정보들을 활용해서 만든 페이지
이런 방식으로 맛집에 관한 API를 가져와서 DB에 저장하고 사용하면 되지 않을까 생각했다.
결론 먼저 말하면
그렇게 할 시간도 없고 그 방식도 어려워서 다른 방식으로 접근해서 어느정도 마무리는 해놨다.
시행착오
시행착오 시작!
일단 병아리 입장에서 서울관광재단에서 주는 API 사용법들은 굉장히 불친절하다.
필요한 정보들이 있는 API 찾는것도 시간을 많이 잡아먹었는데
그렇게 찾은 API 정의서가 굉장히 불친절하고 어렵다...
사용하려고 하는 음식관광 데이터베이스 (서울관광재단 제공)
토큰 받는건 쉽지..
API URL은 이렇게 제공한다고 한다.
바로 API 정의서 다운받아서 읽어봤다.
일단 필요한건 식당이름, 주소, 구글 맵에 찍을 위도+경도, 식당 전화번호, 음식점 소개, 음식점 사진+음식 사진
정도였다.
이걸 얻으려면 어디로 url을 요청해야하나 해서 봤더니
여기서 이렇게 필요한 값들을 어느정도 주고 있었다.
그리고 이미지를 얻으려면 RSTR_ID와 RSTR_NM이 필요해서 여기서 일단 얻고
다음 호출페이지에서 얻은 RSTR_ID, RSTR_NM으로 이미지들을 얻으려고 했다.
항목구분에 1이 들어간게 필수 값들이라 이걸 어디서 얻어야하지 찾다가
제대로 안나와있어서 그냥 없이 찍었는데 값이 뜬다.. 뭐지 이거?
그리고 값도 엄청많이 떠서 급하게 30개로 줄였다..
어쨌든.. 필요한 음식점 ID가 떴으니 이걸로 해당하는 음식점 사진 얻으려고 URL 찾아보는데
뭐.. 주소 어케찍는데...
rest보면 다 비슷하다 인증키 하나만 들어가고 필수값들을 어떻게 넣는지 자세히 알려주지 않는다.
비교를 위한 친절친절 공공데이터포털의 한국관광공사 제공 정보
한국관광공사에서는 엔드포인트에 어떤 값들을 넣고 어떻게 URL을 보내야 하는지 아~~~~주 친절하게 잘 되어있다.
지금 상태에서는 음식점ID와 음식점 이름 없이도 계속 값은 받지만 이미지 조회도 안되고 numOfRows도 30개로 정해놓고 URL을 호출했지만 만오천개? 정도 받아와서 강제로 데이터 표시를 30개로 하게 해서 쓰고 불편한게 너무 많았다.
어케하지.. 고민하다가 목적은 DB에 저장하려고 하는거니까
데이터 받아서 쓰자.. 생각하고 이곳저곳 찾아보다가
공공데이터포털의 음식이미지정보를 찾았다.
(진짜 이만한 사이트가 없어요..😢)
식당ID가 눈에 익어서 보니까 서울관광재단에서 얻은 ID들이랑 비슷했다
그럼 공공데이터포털의 서울관광재단_음식이미지정보 파일이랑
서울관광재단의 음식점 정보들이랑 합친 데이터를 만들어서 그걸 쓰면 된다고 생각하고 다음 작업 시작!
일단 공공데이터포털의 서울관광재단_음식이미지정보를 받아서 식당ID에 오름차순을 줘서 확인해봤다.
일단 다시 돌아가서 음식점 정보 300개 호출하기
(필요한 값 없이 호출해도 호출이 됨)
서울관광재단에서 쓰는 음식점ID가
공공데이터포털에서 주는 음식점ID와 같으면 매칭해서 사진 쓸 수 있다! 제발!
찾았다 내 원조한치...... 음식점ID가 똑같다.
그럼 서울관광재단에서 주는 저 정보들을 테이블에 저장하고
컬럼에다가 이미지 값은 공공데이터포털에서 주는 이미지 url을 insert 하면 된다!!!!!
일단 그전에 서울관광재단 호출하면 값이 16만개 뜨는거 먼저 수정하고.. (1.5만개가 아니라 16만개..)
일단 가져오고 그 안에서 필터링으로 입력받은 값만 뜨게 하고 DB에 저장하고 이미지 합치기로 구상하고 시작!
{
"header": {
"resultCode": "00",
"resultMsg": "NORMAL_SERVICE",
"numOfRows": 1000,
"pageNo": 1,
"totalCount": 168155
},
값이 168155가 뜬다 ㅋㅋ
아무리 numOfRows : 30 주고 pageNo : 1 해도 16만개 나와서 그냥 전체 다 가져오고 필터링으로 하려고 했다.
(부족한 실력 이슈)
일단 사용자한테 입력받은 다음 그 값을 넘겨서 해당하는 값만 페이지에 출력하게 구성했다.
<body>
<div class="container">
<h1>뽈뽈뽈</h1>
<h1>서울 맛집 API DB 조회, 저장</h1>
<form action="${pageContext.request.contextPath}/Matzip/processMatzipCodeApi" method="post">
<label for="regionCode">음식점 ID :</label>
<input type="text" id="restaurantIds" name="restaurantIds" placeholder="예: 1583, 1917, 5216" required>
<br>
<label for="restaurantNames">음식점 이름 :</label>
<input type="text" id="restaurantNames" name="restaurantNames" placeholder="예: 원조한치, 미성옥, 삼호복집" required>
<button class="inputApi" type="submit">API 데이터 조회하기</button>
</form>
</div>
</body>
음식점 ID랑 음식점 이름을 restaurantsIds, restaurantsNames로 받아서 processMatzipCodeApi로 넘겼다.
그 다음에 processMatzipCodeApi에서는
스크립틀릿으로
결과 저장할 리스트를 만들면서 Map을 담을 ArrayList를 만들었고
List<Map<String, String>> restaurantList = new ArrayList<>();
입력받은 값이 비어 있지 않은지 체크한 후 음식점ID랑 음식점 이름을 쉼표 분리하고 공백 지워서 배열로 저장시켰다.
//null 찾고
if (restaurantIdsParam != null && !restaurantIdsParam.isEmpty() && restaurantNamesParam != null && !restaurantNamesParam.isEmpty()) {
//쉼표 빼기
String[] restaurantIds = restaurantIdsParam.split(",");
String[] restaurantNames = restaurantNamesParam.split(",");
이제 나온 값으로 각 음식점 ID랑 이름에 대해 반복문 돌리면서 찾게 했다.
body로 잡고 다 찾은 restaurantList를 restaurants 속성으로 바꿔서 쓸 수 있게 했다.
// 각 음식점 ID와, 이름 반복문 돌리기
for (int j = 0; j < restaurantIds.length; j++) {
String id = restaurantIds[j].trim(); // 음식점 ID
String name = restaurantNames[j].trim(); // 음식점 이름
boolean found = false; // 해당 음식점을 찾았는지 여부 추적
int pageNo = 1; // 페이지 번호 초기화 (API 결과는 페이지 단위로 나옴)
// 원하는 데이터를 찾을 때까지 반복하여 페이지를 조회
while (!found) {
try {
// API 호출 URL 구성: serviceKey, pageNo, numOfRows를 파라미터로 포함
URL url = new URL(apiUrl + "?serviceKey=" + apiKey + "&pageNo=" + pageNo + "&numOfRows=1000");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET"); // HTTP 메서드 = GET
// 응답 코드 확인 (200이면 정상 응답, 아니면 에러 응답)
int responseCode = conn.getResponseCode();
BufferedReader rd = new BufferedReader(new InputStreamReader(
(responseCode == 200) ? conn.getInputStream() : conn.getErrorStream(), "UTF-8"
));
// StringBuilder로 저장
StringBuilder sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) sb.append(line); // 한 줄씩 StringBuilder에 추가
rd.close(); // BufferedReader 닫기
// API로부터 받은 JSON 응답을 파싱
JSONObject jsonObject = new JSONObject(sb.toString());
// JSON 응답의 "body" 키가 있는지 확인
if (jsonObject.has("body")) {
JSONArray bodyArray = jsonObject.getJSONArray("body"); // "body" 배열을 가져옴
// 각 항목을 확인하며 원하는 데이터가 있는지 필터링
for (int i = 0; i < bodyArray.length(); i++) {
JSONObject item = bodyArray.getJSONObject(i); // "body" 배열의 각 요소를 가져옴
String rstrId = item.optString("RSTR_ID"); // "RSTR_ID" 값 추출
String rstrNm = item.optString("RSTR_NM"); // "RSTR_NM" 값 추출
// 입력받은 ID와 이름이 일치하는지 확인
if (rstrId.equals(id) && rstrNm.equals(name)) {
// 일치하는 경우, 음식점의 정보를 Map에 저장
Map<String, String> restaurant = new HashMap<>();
restaurant.put("title", rstrNm); // 이름 저장
restaurant.put("addr1", item.optString("RSTR_RDNMADR", "정보 없음")); // 주소 저장
restaurant.put("id", rstrId); // ID 저장
restaurant.put("overview", item.optString("RSTR_INTRCN_CONT", "정보 없음")); // 소개 저장
restaurant.put("mapx", item.optString("RSTR_LO", "정보 없음")); // 경도 저장
restaurant.put("mapy", item.optString("RSTR_LA", "정보 없음")); // 위도 저장
restaurant.put("tel", item.optString("RSTR_TELNO", "정보 없음")); // 전화번호 저장
restaurantList.add(restaurant); // 리스트에 저장
found = true; // 데이터를 찾았으므로 found를 true로 설정하고 루프 종료
break; // 내부 for 루프 종료
}
}
}
// 못 찾았어? 다음 페이지
if (!found) {
pageNo++; // 페이지 ++
if (pageNo > 1000) break; // 페이지가 1000을 넘으면 무한 루프 방지를 위해 종료
}
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("errorMessage", "API 호출 오류: " + e.getMessage());
break;
}
}
}
}
최종적으로는 이렇게 구성하고 검색해봤다.
결과
검색한 값들만 잘 뜬다!
이제 이 받아온 값들을 DB에 저장시키고
csv로 받은 이미지 URL들을 테이블에 insert 시켜주면 끝날거 같다!
저장하는건 카페가서 카페인과 함께 할 예정... 다하고 또 정리해야지!
앞으로 남은 할일
받아온 값 DB에 저장하는 백엔드 구성
DB에 저장된 구성에 csv로 받은 이미지URL들 넣어서 가공하기
기존 맛집 페이지에 DB 불러와서 페이지 구성하기
이러면 끝난다.. 오늘안에 다 끝내고 싶다!!!
'Develop > JSP' 카테고리의 다른 글
중간보고 피드백 (12) (4) | 2024.11.22 |
---|---|
공공데이터 API - 서울 맛집 API로 DB저장 구현하기 (2) (3) | 2024.10.27 |
OpenWeatherMap API, canvas 사용하기 (4) | 2024.10.24 |
구글 지도 API 써서 일정 페이지 만들기 (4) | 2024.10.22 |
메인 페이지 정리, 페이지 하나로 DB 총 관리하기 (1) (3) | 2024.10.14 |