실습을 통해 이해해보자.
웹 브라우저의 '즐겨찾기(북마크)' 서비스를 만들어보는 실습이다.
아래와 같은 순서로 실습하며 코드 구조를 뜯어보자.
1. 일단! 코드 작성
2. 즐겨찾기 등록 기능 뜯어보기
3. 즐겨찾기 목록 조회 기능 뜯어보기
북마크 기능이라 하면, 실제로는 더 복잡한 형태이겠지만,
실습을 위해 다음과 같이 최소한의 기능만으로 구성해보자.
- 즐겨찾기는 이름과 URL로 구성한다.
- 즐겨찾기를 등로하는 기능이 있다.
- 즐겨찾기 목록을 조회하는 기능이 있다.
- 두 기능은 모두 AJAX 로 동작한다 = 즉, 새로고침 하지 않아도 내용이 바뀌어야한다!
이제 아래 단계를 밟으며 코드부터 작성해보자.
01. 즐겨찾기에 대한 JSON은 두가지 key 값을 가진다.
{
"name": "구글",
"url": "http://www.google.com/"
}
02. 즐겨찾기를 등록 및 조회하는 기능을 할 HTTP 메서드와 API의 경로를 정의한다.
- 등록 : POST 메서드, /bookmark
- 조회 : GET 메서드, /bookmarks
03. Bookmark 클래스를 추가하자. 이 클래스는 서버와 클라이언트가 데이터를 주고 받는데 사용된다.
//Bookmark.java
package com.example.demo;
public class Bookmark {
public String name;
public String url;
}
04. BookmarkAjaxRestController 클래스를 추가하자. 즐겨찾기 등록 api와 즐겨찾기 조회 api 모두 들어간다.
package com.example.demo;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
public class BookmarkAjaxController {
private List<Bookmark> bookmarks = new ArrayList<>();
@RequestMapping(method=RequestMethod.POST, path="/bookmark")
public String registerBookmark(@RequestBody Bookmark bookmark) {
bookmarks.add(bookmark);
return "registered";
}
@RequestMapping(method=RequestMethod.GET, path="/bookmarks")
public List<Bookmark> getBookmarks() {
return bookmarks;
}
}
@RequestBody 에서 Bookmark는 03번에서 만든 클래스를 쓰게 되어있다. 이는 앞에 애노테이션을 붙였기에 가능하다.
앞서 우리는 JSON 형태로 프론트와 데이터를 주고 받기로 했는데,
두 api 모두 JSON이 아닌 String, List 형태를 반환하고 있다.
JSON 문자열을 자바에서의 인스턴스로 만들거나 그 반대의 동작을 가능하게 하는 것은 'Jackson' 이라는 라이브러리이다.
스프링부트는 Jackson을 사용하는 스프링 프레임워크의 메세지 컨버터가 자동 등록되므로, JSON으로 자동 변환된다고 보면된다.
자세한 내용은 'Spring Http Message Converter'을 검색하여 확인할 수 있다.

Tip을 읽어보면,
Spring Boot application에는 WebMvcAutoConfiguration이 알아서 HttpMessageConverter을 추가한다고 되어있다.
WebMvcAutoConfiguration이 무엇인지 명확하지 않아, 챗지피티에게 물어봤다.
초반에 스프링 부트 initailizr을 만질때 추가한 spring-boot-starter-web 라이브러리와 관련된 것인가?
맞다고 한다.


05. 04에서 만든 두 api를 사용하는 프론트엔드 페이지를 추가하자. static-resources에 추가한다.
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<form onsubmit="return addBookmarkRequest();">
<label>즐겨찾기 이름 : </label><input type="text" name="name"><br>
<label>즐겨찾기 URL : </label><input type="text" name="url"><br>
<input type="submit"><br>
</form>
<button onclick="getBookmarkListRequest();">즐겨찾기 목록 가져오기</button>
<ol id="bookmark-list">
<!-- 여기에 즐겨찾기 목록이 나옵니다. -->
</ol>
<script>
function addBookmarkRequest() {
const name = document.querySelector('input[name=name]').value;
const url = document.querySelector('input[name=url]').value;
const requestObject = {name: name, url: url};
const requestJson = JSON.stringify(requestObject);
function onReadyStateChange(event) {
const currentAjaxRequest = event.currentTarget;
if (currentAjaxRequest.readyState === XMLHttpRequest.DONE) {
if (currentAjaxRequest.status === 200) {
alert("즐겨찾기가 등록되었습니다.");
} else {
console.error('request failed');
}
}
}
const ajaxRequest = new XMLHttpRequest();
ajaxRequest.onreadystatechange = onReadyStateChange;
ajaxRequest.open('POST', '/bookmark');
ajaxRequest.setRequestHeader('Content-Type', 'application/json');
ajaxRequest.send(requestJson);
return false;
}
function getBookmarkListRequest() {
function onReadyStateChange(event) {
const currentAjaxRequest = event.currentTarget;
if (currentAjaxRequest.readyState === XMLHttpRequest.DONE) {
if (currentAjaxRequest.status === 200) {
const bookmarkListDom = document.querySelector('#bookmark-list');
bookmarkListDom.innerHTML = '';
const bookmarks = JSON.parse(currentAjaxRequest.responseText);
bookmarks.forEach(bookmark => {
const liNode = document.createElement('li');
const textNode = document.createTextNode(bookmark.name + ' - ' + bookmark.url);
liNode.appendChild(textNode);
bookmarkListDom.appendChild(liNode);
});
} else {
console.error('request failed');
}
}
}
const ajaxRequest = new XMLHttpRequest();
ajaxRequest.onreadystatechange = onReadyStateChange;
ajaxRequest.open('GET', '/bookmarks');
ajaxRequest.send();
}
</script>
</body>
</html>
06. 05에서 만든 html페이지에 접속해보자.

이제 즐겨찾기 등록 기능의 작동 원리 먼저 뜯어보겠다.
즐겨찾기 등록 기능
1.구글, https://www.google.com 제출
2. form 태그에 지정된 onsumbit 이벤트 발생
3. addBookmarkRequest() 호출
function addBookmarkRequest() {
const name = document.querySelector('input[name=name]').value;
//querySelector을 통해 name란의 내용 가져옴
const url = document.querySelector('input[name=url]').value;
//querySelector을 통해 url란의 내용 가져옴
const requestObject = {name: name, url: url};
//request object객체 생성.
const requestJson = JSON.stringify(requestObject);
//자바스크립트 객체를 json 문자열로 바꿈.
function onReadyStateChange(event) {
const currentAjaxRequest = event.currentTarget;
if (currentAjaxRequest.readyState === XMLHttpRequest.DONE) {
if (currentAjaxRequest.status === 200) {
alert("즐겨찾기가 등록되었습니다.");
} else {
console.error('request failed');
}
}
}
const ajaxRequest = new XMLHttpRequest();
//XHR객체 생성
ajaxRequest.onreadystatechange = onReadyStateChange;
//함수를 변수에 등록
ajaxRequest.open('POST', '/bookmark');
//등록이니 POST 요청으로.
ajaxRequest.setRequestHeader('Content-Type', 'application/json');
//요청 헤더에 'Content-Type'을 넣어 'application/json'으로 보냄
//이는 JSON이 포함된 요청을 보낼 때, 위와 같이 헤더를 설정하여 보내도록 약속했기 때문.
ajaxRequest.send(requestJson);
//send()함수의 인자로 JSON 문자열을 넣었음
return false;
}
즐겨찾기 목록 조회 기능
<button onclick="getBookmarkListRequest();">즐겨찾기 목록 가져오기</button>
<ol id="bookmark-list">
<!-- 여기에 즐겨찾기 목록이 나옵니다. -->
</ol>
function getBookmarkListRequest() {
function onReadyStateChange(event) {
const currentAjaxRequest = event.currentTarget;
if (currentAjaxRequest.readyState === XMLHttpRequest.DONE) {
if (currentAjaxRequest.status === 200) {
const bookmarkListDom = document.querySelector('#bookmark-list');
bookmarkListDom.innerHTML = '';
const bookmarks = JSON.parse(currentAjaxRequest.responseText);
bookmarks.forEach(bookmark => {
const liNode = document.createElement('li');
const textNode = document.createTextNode(bookmark.name + ' - ' + bookmark.url);
liNode.appendChild(textNode);
bookmarkListDom.appendChild(liNode);
});
} else {
console.error('request failed');
}
}
}
const ajaxRequest = new XMLHttpRequest();
ajaxRequest.onreadystatechange = onReadyStateChange;
ajaxRequest.open('GET', '/bookmarks');
ajaxRequest.send();
}
getBookMarks()는
element를 생성해 bookmark-list에 추가하는 코드하는 코드를 제외하고는 큰 차이점이 없다.
'스터디 > Server' 카테고리의 다른 글
상품 관리 애플리케이션 만들기 4 - DTO와 getter, setter (0) | 2024.08.30 |
---|---|
상품 관리 애플리케이션 만들기 (1) - 3 프로젝트 전체 구조 잡기 (0) | 2024.08.29 |
비동기 상호작용이란? (2) | 2024.08.27 |
[백엔드 개발에 필요한 최소한의 js 지식] 자바스크립트에서의 함수 (0) | 2024.08.27 |
nodejs (0) | 2024.08.23 |