오늘 만들 것
이번 글에서는 게시글을 불러오는 예제를 진행합니다.
게시글 작성보다 예제가 훨씬 간단합니다.
이미 지난 글에서 데이터 호출을 한 차례 작성해보았기 때문에 설명을 줄이고, 빠르게 진행합니다.
시작
이번 글은 Lab04의 코드에 게시물 호출 API를 추가하는 예제입니다.
Lab04는 이전 글에서 확인할 수 있습니다.
별도의 프로젝트에서 진행하고자 하면, Lab04와 동일하게 프로젝트를 생성한 뒤 코드를 복사해서 준비합니다.
Lab04의 코드를 그대로 사용한다면 아래 예제 코드의 패키지명에 유의합니다.
아래 예제 코드는 별도의 프로젝트를 생성하는 방식으로 진행합니다.
DAO 수정
다음 경로의 파일을 아래와 같이 편집합니다: /src/main/java/YOUR/DOMAIN/ARTIFACT/dao/BoardDAO.java
package net.jetalab.spreinglab05.dao;
import net.jetalab.spreinglab05.dto.BoardDTO;
public interface BoardDAO {
int newBoard(BoardDTO param) throws Exception;
BoardDTO getBoard(int param) throws Exception;
}
7번째 줄: 게시물을 호출하여 반환하는 getBoard()
메소드가 추가되었습니다.
SQL Mapper 수정
다음 경로의 파일을 아래와 같이 편집합니다: /src/main/resources/mappers/UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="net.jetalab.spreinglab05.dao.BoardDAO">
<insert id="newBoard" parameterType="net.jetalab.spreinglab05.dto.BoardDTO" useGeneratedKeys="true" keyProperty="seq">
INSERT INTO lab05(`title`, `contents`, `author`, `password`)
VALUES (#{title}, #{contents}, #{author}, #{password})
</insert>
<select id="getBoard" parameterType="Integer" resultType="net.jetalab.spreinglab05.dto.BoardDTO">
SELECT `seq`, `title`, `contents`, `author`, `reads`
FROM lab05
WHERE `seq` = #{param}
AND `deleted` = 'N'
</select>
</mapper>
11번째 줄부터 16번째 줄까지가 추가되었습니다.
11번째 줄: 파라미터로 정수를 받고, BoardDTO
객체를 반환하도록 선언합니다.
14번째 줄: 요청한 seq
에 해당하는 글을 조회합니다.
15번째 줄: deleted
가 N인 글, 즉 삭제되지 않은 글만 조회합니다.
Controller 생성
POST로 새 글 내용을 받을 Controller를 생성합니다.
다음 경로에 아래 코드를 작성하여 저장합니다: /src/main/java/YOUR/DOMAIN/ARTIFACT/controller/BoardController.java
package net.jetalab.spreinglab05.controller;
import net.jetalab.spreinglab05.dao.BoardDAO;
import net.jetalab.spreinglab05.dto.BoardDTO;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@EnableAutoConfiguration
@MapperScan(basePackages = "net.jetalab.spreinglab05.dao")
public class BoardController {
@Autowired
private BoardDAO boardDAO;
@RequestMapping(value = "/board", method = RequestMethod.POST)
public BoardDTO board(BoardDTO board) throws Exception {
boardDAO.newBoard(board);
return board;
}
@RequestMapping(value = "/board/{param}", method = RequestMethod.GET)
public BoardDTO board(@PathVariable("param") final int param) throws Exception {
/* TODO: 조회수 증가 */
BoardDTO board = boardDAO.getBoard(param);
return board;
}
}
27번째 줄부터 32번째 줄까지가 추가되었습니다.
27번째 줄: GET 방식으로 요청을 받도록 합니다. 또한 경로를 이용해 변수 param
을 받습니다.
28번째 줄: 경로를 이용해 받은 변수 param
을 정수형 변수 param
으로 선언합니다.
29번째 줄: 추후 게시물 조회수 증가를 처리할 부분입니다. 게시물 수정을 할 때 처리하겠습니다.
30번째 줄: 전달받은 변수 param
을 이용해 호출한 데이터를 BoardDTO
형 객체 board
에 담습니다.
23번째 줄: 호출한 board
객체를 사용자에게 전송합니다.
테스트
MySQL엔 Lab04에서 작성한 글이 그대로 저장되어 있습니다.
서버를 실행하고 API를 호출하면 아래와 같이 응답을 받을 수 있습니다.
한 가지 더
정말 간단하게 게시글을 성공적으로 불러오도록 완성했습니다.
하지만 존재하지 않는 글을 호출하면 어떻게 될까요?
아무 결과를 보여주지 않게 됩니다.
이렇게 반환하게 되면 이게 존재하지 않는 글인지, 서버에 오류가 발생한 것인지 Client는 알 수가 없습니다.
이 문제를 해결하는 가장 세련된 방법은 HTTP 상태 코드를 이용하는 것입니다.
Postman에서는 결과창 위에 있습니다.
이제 존재하지 않는 글은 존재하지 않는다는 응답을 상태코드를 함께 전달해보겠습니다.
Controller 코드를 아래와 같이 수정합니다.
package net.jetalab.spreinglab05.controller;
import net.jetalab.spreinglab05.dao.BoardDAO;
import net.jetalab.spreinglab05.dto.BoardDTO;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@EnableAutoConfiguration
@MapperScan(basePackages = "net.jetalab.spreinglab05.dao")
public class BoardController {
@Autowired
private BoardDAO boardDAO;
@RequestMapping(value = "/board", method = RequestMethod.POST)
public ResponseEntity<BoardDTO> postBoard(BoardDTO board) throws Exception {
if ((board.getAuthor() == null) || (board.getContents() == null) || (board.getPassword() == null) || (board.getTitle() == null)) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
boardDAO.newBoard(board);
return new ResponseEntity<>(board, HttpStatus.OK);
}
@RequestMapping(value = "/board/{param}", method = RequestMethod.GET)
public ResponseEntity<BoardDTO> getBoard(@PathVariable("param") final int param) throws Exception {
/* TODO: 조회수 증가 */
BoardDTO board = boardDAO.getBoard(param);
if (board == null) return new ResponseEntity<>(HttpStatus.NOT_FOUND);
else return new ResponseEntity<>(board, HttpStatus.OK);
}
}
34번째 줄: BoardDTO
형 객체가 아니라 ResponseEntity
객체를 반환하도록 변경되었습니다. ResponseEntity
는 API 응답을 정의하는 객체입니다.
38번째 줄: 불러온 데이터가 없다면 404 Not Found 코드를 반환합니다.
39번째 줄: 불러온 데이터가 있다면 board
를 반환하고, 200 OK 코드를 반환합니다.
25번째 줄 ~ 27번째 줄: 마찬가지로 사용자가 게시글을 입력할만한 충분한 데이터를 전달하지 않았다면 403 Bad Request 코드를 반환하도록 수정했습니다.
위와 같이 수정하면 존재하지 않는 글을 호출했을 때의 응답이 달라집니다.
동일하게 응답은 비어있지만, 상태 코드가 404로 달라진 것을 확인할 수 있습니다.
예제 코드
본 포스트의 예제 코드는 GitHub에 공개되어 있습니다.
https://github.com/jETA-Kor/sp-re-ing/tree/master/lab05