[24.01.19] 110차
<<진도>>
[Back-end] Spring Boot
/ Open API (Naver OpenAPI)
/ Metadata
Spring Boot project 생성
Naver open api 실습
https://developers.naver.com/docs/common/openapiguide/
API 공통 가이드 - Open API 가이드
API 공통 가이드 네이버 오픈API는 네이버 플랫폼의 기능을 외부 개발자가 쉽게 이용할 수 있게 웹 또는 SDK 형태로 공개한 기술들입니다. 네이버 오픈API로 활용할 수 있는 기술에는 네이버 로그인
developers.naver.com
open api는 특정 url로 요청을 하는데
네이버는 로그인 방식 / 비로그인 방식이 있다
실습은 비로그인 방식 오픈 api
애플리케이션 등록
뉴스 검색 api
: 뉴스 검색은 검색 API를 사용해 네이버 검색의 뉴스 검색 결과를 반환하는 RESTful API입니다. 뉴스 검색 결과를 XML 형식 또는 JSON 형식으로 반환합니다. API를 호출할 때는 검색어와 검색 조건을 쿼리 스트링(Query String) 형식의 데이터로 전달합니다.
뉴스 검색은 검색 API를 사용하며, 검색 API의 하루 호출 한도는 25,000회입니다.
query는필수 나머지는 선택
URL 스타일
POST MAN 활용 실습
new collection : Naver open API
new requesrt를 만들고
필수 parameter인 query (검색어)를 넣고
클라이언트 id와 secret이 request header에 필수로 들어가야한다
응답 속성들
items { } 안의 개별요소들의 리스트 List형
2가 우리가 실제 가져다쓸 Data
1은 Data들의 Data => [ Metadata ]
(book 검색)
실제 spring boot 실습
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>도서 검색</title>
<link href="css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="text-center">
<h1 class="mt-5 fw-bold">* 도서 검색 *</h1>
<h2>검색하고 싶은 도서 명을 입력하세요!</h2>
</div>
<div class="container d-flex justify-content-center mt-5">
<form action="/book/list" class="form">
<div class="row">
<label class="col-auto col-form-label">검색어 : </label>
<div class="col-auto">
<input class="form-control" type="text" name="query" placeholder="검색어를 입력하세요...">
</div>
<div class="col-auto">
<input type="submit" value="검색" class="btn btn-primary">
</div>
</div>
</form>
</div>
</body>
</html>
index.html
list.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>[OpenAPI] Book List</title>
<link href="../../static/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div id="wrap" class="container text-center">
<h1 class="mt-5">Book List</h1>
<table class="table table-hover mt-5">
<thead>
<tr>
<th>ISBN</th>
<th>이미지</th>
<th>도서 제목</th>
<th>저자/출판사</th>
<th>출간일</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td><img alt="" src=""></td>
<td><a href=""></a></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
로컬에서 실행
list.html를 서버실행 시키기 위해 컨트롤러 생성
@Controller
public class BookController {
@GetMapping("/book/list")
public String list() {
return "book/list";
}
}
**local에서 볼때와 다르게 부트스트랩 적용이 안됨
** 서버에서 실행시 static은 자동으로 인식되는 영역이므로
로컬 기준
<link href="../../static/css/bootstrap.min.css" rel="stylesheet">
서버실행 기준
<link href="../../css/bootstrap.min.css" rel="stylesheet">
**Spring Boot도 실제 서버에서 실행이되기위해 실행되는 파일의 위치가 있음
Java Build Path
bin 파일의 실제위치에 가보면 build용 파일들이 있다
OpenAPI에서 받아오는 데이터 data들을
java에서 사용하기 위해 type을 만들어줘야하는데 1. 실제 사용할 data와 2. metadata 2가지로 만듦
API data는 꺼내다 쓰는 형태기 때문에 값이 고정되어있어 고정 불변의 값을 가진 [ VO ] (Value Object)
: 생성자로 값이 정해지고 꺼내쓰는 getter만 있지 setter는 없음
* [VO] Value Object
* 값 자체를 표현하는 객체
*
* setter 없음 -> 변경(수정) 불가능
* constructor를 통해서 초기값 설정 후 변경 불가능 -> 리터럴 개념
*
* 읽기만 가능한 read-only 속성을 가진 객체
*
* 값 비교를 위해, equals(), hashcode()를 오버라이딩 overriding 해줘야 함!
* : @EqualsAndHashCode로 해결 - 값비교까지 해줘야 완벽한 VO
먼저 메타데이터 VO
NaverBookMetaVo.java
@ToString
@NoArgsConstructor
@Getter
@EqualsAndHashCode
public class NaverBookMetaVo {
private String lastBuildData;
private int total;
private int start;
private int display;
private List<NaverBookVo> items;
}
items 리스트의 item들의 데이터 VO
NaverBookVo.java
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Getter
@EqualsAndHashCode
public class NaverBookVo {
private String title;
private String link;
private String image;
private String author;
private Integer discount;
private String publisher;
private Integer isbn;
private String description;
private String pubdate;
}
VO들의 변수명은 실제와 받아오는 데이터명과 동일해야함!!
BookController.java
@Controller
@Slf4j
public class BookController {
@GetMapping("/book/list")
public String list(@RequestParam(value = "query") String query, Model model) {
log.info(query);
return "book/list";
}
}
**Depencies가 아닌 lombok.jar 파일을 STS4에 넣어줘야 log.info 사용가능
install
검색어 query가 로그가 찍힘
[ 네이버 검색 API 요청 ]
import java.net.URI;
import java.util.List;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import himedia.spring.ver1.vo.NaverBookMetaVo;
import himedia.spring.ver1.vo.NaverBookVo;
import lombok.extern.slf4j.Slf4j;
@Controller
@Slf4j
public class BookController {
@GetMapping("/book/list")
public String list(@RequestParam(value = "query") String query, Model model) {
log.info(query);
// [네이버 검색 API 요청] =============================================
String clientId = "KXGNDbIRHplSzeo_Vfb3";
String clientSecret = "FQK8LmcsDO";
log.info("1. uri 생성");
URI uri = UriComponentsBuilder
.fromUriString("https://openapi.naver.com")
.path("/v1/search/book")
.queryParam("query", query)
.queryParam("display", 10)
.queryParam("start", 1)
.queryParam("sort", "sim")
.encode()
.build()
.toUri();
// - [Spring Framewor 제공] HttpEntity class ====================================
// : HTTP 요청(request) 또는 응답(response)에 해당하는 HttpHeader와 HttpBody 포함
// : 자식 클래스 : RequestEntity, ResponseEntity
//
// : RequestEntity(요청 준비) -> RestTemplate(요청) -> ResponseEntity(응답)
// ----------------------------------------------- --------------------
// request (요청) response(응답)
log.info("2. requset 요청 준비");
RequestEntity<Void> requestEntity = RequestEntity
.get(uri)
.header("X-Naver-Client-Id", clientId)
.header("X-Naver-Client-Secret", clientSecret)
.build();
// 요청
log.info("3. RestTemplate 객체 생성");
RestTemplate restTemplate = new RestTemplate();
log.info("4. restTemplate.exchange() 요청 후 응답");
// 응답은 responseEntity로 옴
ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);
log.info("responseEntity : {}", responseEntity);
log.info("responseEntity.getBody() : {}", responseEntity.getBody());
//JSON 파싱 (JSON 문자열을 객체로 변환)
log.info("5. json -> 객체 변환");
ObjectMapper objectMapper = new ObjectMapper();
NaverBookMetaVo naverBookMetaVo = null;
try {
naverBookMetaVo = objectMapper.readValue(responseEntity.getBody(), NaverBookMetaVo.class);
log.info("naverBookMetaVo : {}", naverBookMetaVo);
log.info("naverBookMetaVo.total : {}", naverBookMetaVo.getTotal());
} catch (JsonProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// List로 items 정보 담기
List<NaverBookVo> books = naverBookMetaVo.getItems();
// view에 넘기기
model.addAttribute("books", books);
return "book/list";
}
}
** 실제 요청은 RestTemplate을 통해 요청하게 된다.
@ToSting 영향 제외 items
* Thymeleaf문법 사용하여 view에 출력
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>[OpenAPI] Book List</title>
<link href="../../css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div id="wrap" class="container text-center">
<h1 class="mt-5">Book List</h1>
<table class="table table-hover mt-5">
<thead>
<tr>
<th>ISBN</th>
<th>이미지</th>
<th>도서 제목</th>
<th>저자/출판사</th>
<th>출간일</th>
</tr>
</thead>
<tbody>
<tr th:each="book:${books}">
<td>[[${book.isbn}]]</td>
<td><img th:alt="${book.title}" th:src="${book.image}" width="100"></td>
<td><a th:href="${book.link}" target="_blank">[[${book.title}]]</a></td>
<td>[[${book.author}]] / [[${book.publisher}]]</td>
<td>[[${book.pubdate}]]</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
list.html에서
태그의 content로 thymeleaf 문법을 바로 사용 하기위해 [[]] 사용
'Back-end (Spring Boot , JPA, JSP) > 필기일지' 카테고리의 다른 글
240125 [Back-end] Spring Security 스프링 시큐리티 -2 (로그인, 회원가입, role ) / JPA / Entity (1) | 2024.01.25 |
---|---|
240121 [Back-end] Spring Security스프링 시큐리티 (인증 / 접근제한) (1) | 2024.01.23 |
240118 [Back-end] git / github / Source Tree 소스트리 (0) | 2024.01.18 |
240116 [Back-end] CLI, GUI / Source Tree 소스트리 / git / github (0) | 2024.01.16 |
240115 [Back-end] Spring Boot 배포 / 로컬 Docker 배포 / AWS 배포 (0) | 2024.01.15 |