INDEX 페이지에 데이터를 뿌리자
더미 데이터에 들어있는 이 친구들은 가방에 담지 말고, 디자인으로만 뿌릴 것이다!
[ index.mustache ]
{{> layout/header}} <div class="container p-5"> <table class="table table-striped"> <!-- 컬럼 --> <thead> <tr> <th>번호</th> <th>제목</th> <th>내용</th> <th>작성자</th> <th></th> </tr> </thead> <tbody> <!-- 반복 될 부분 INDEX 요청 시 이것만 줄 것--> <tr> <td>5</td> <td>제목5</td> <td>내용5</td> <td>홍길동</td> <td> <div class="d-flex"> <form action="#"> <button class="btn btn-danger">삭제</button> </form> <form action="/board/1/updateForm" method="get"> <button class="btn btn-warning">수정</button> </form> </div> </td> </tr> </tbody> </table> </div> {{> layout/footer}}
애를 function에 넣어놓고 CSR로 그림을 그릴 것! -> for문으로 뿌려진다. (때문에 중복되는 다른 코드들이 있으면 지워주고 하나만 살려놓자)
[ html 코드는 return으로 받자 ]
{{> layout/header}} <div class="container p-5"> <table class="table table-striped"> <!-- 컬럼 --> <thead> <tr> <th>번호</th> <th>제목</th> <th>내용</th> <th>작성자</th> <th></th> </tr> </thead> <tbody> </tbody> </table> </div> <script> function render(board) { return`<tr id="board-5"> <td>5</td> <td>제목5</td> <td>내용5</td> <td>홍길동</td> <td> <div class="d-flex"> <form action="#"> <button class="btn btn-danger">삭제</button> </form> <form action="/board/1/updateForm" method="get"> <button class="btn btn-warning">수정</button> </form> </div> </td> </tr>`; } </script> {{> layout/footer}}
이렇게!! return에 넣어준다!! +) 삭제를 위해서 id를 꼭! 넣어주자!!
그런데 왜 html 코드를 return문에 넣는걸까?
자바스크립트를 사용해서 웹 페이지를 동적으로 업데이트하기 위함! 새로운 데이터를 받아서 웹 페이지에 표시해야 하는데, 그 데이터에 맞는 HTML 코드를 자바스크립트로 만들고 반환한다. 그러면 이 코드를 웹 페이지의 특정 부분에 추가할 수 있고, 사용자는 전체 페이지를 새로고침하지 않고도 새로운 내용을 볼 수 있게 된다. 예를 들어 게시판에 새 글을 추가할 때, 사용자가 바로 그 글을 볼 수 있도록 하는 것! 자바스크립트로 AJAX 요청과 같은 비동기 통신을 통해 서버로부터 새로운 데이터를 받은 후, 이 데이터를 기반으로 HTML을 생성하고 DOM (Document Object Model)에 동적으로 추가하여 웹 페이지의 내용을 갱신하는 데 return문을 사용
[ 화면 확인 ]
처음엔 이런 뼈대만 나온다. 이 뼈대에 데이터들을 받아와서 뿌리면 된다!
그럼 템플릿 엔진이 없어도 되는구나?
→ 순수한 html에 자바 스크립트로 발동 시키면 되니까!!
BoardApiController 생성 → AJAX 통신을 위한 컨트롤러 생성!
index 게시글 목록보기 페이지는 버튼을 눌리지 않아도 자동으로 다운 받아야져야 한다. json 데이터를 받아야하는데, API가 없다. -> 만들어주자 데이터를 응답하는 컨트롤러를 API 컨트롤러라고 부른다! -> 이걸 만들어주자
[ BoardController ] [ BoardApiController ] 컨트롤러가 2개!!
api 를 하는 순간 주소는 보통 '복수형'으로 쓰인다. -> @GetMapping("/api/boards") /api/boards 보드들 줘! 1건은 /api/boards/1 이런 식으로!
[ 실패했을 때 상태 코드와 메세지는 무조건 적어주자! ]
if(boardList().size() > 0) 이렇게 작성하면, null을 받으면 실패일까, 0을 받으면 실패일까? 데이터가 없으면 실패인가? 뭐가 잘못 된건진 아냐? ㄴㄴ!! 때문에 상태코드나 메세지를 같이 응답해준다! -> 프런트를 위해서 담아주자! status 코드와 msg를 보면 이게 어떤 오류가 났는지, 실패인지, 아닌지 알 수 있으니까! (ex. 200 == 성공 / 400 == 클라이언트 잘못) response 헤더 데이터만 줄 수는 없다!!! response가 null이면... 실패인가? 장담 못함 때문에 성공했을 때 메세지는 안 적어도, 실패했을 때 상태코드와 메세지는 무조건 적어주자!
success가 false 일 때만 이 메세지를 보면 된다.
ApiUtil → 응답의 공통 DTO 필요!! 만들자!
여러가지 유효성 검사에 실패하면 다 잡아줄 필요 없이 일단 하나만 잡아서 주면 된다. -> 당연함. (유효성 검사에서 필터를 하나 거치면 팅기고 그러니까)
package shop.mtcoding.blog.board; import lombok.AllArgsConstructor; import lombok.Data; @AllArgsConstructor @Data public class ApiUtil<T> { private Integer status; // 200, 400, 404, 405 private String msg; //성공, 실패시 -> 정확한 메세지 private T body; //바디 데이터는 타입이 여러가지니까 //일단 지금은 고정 값으로 적어주자 public ApiUtil(T body) { this.status = 200; this.msg = "성공"; this.body = body; } public ApiUtil(Integer status, String msg) { this.status = status; this.msg = msg; this.body = null; } }
원래는…
생성자로 new해서 만드는 것 보단 이렇게 success(), fail() 메소드로 만드는 걸 선호
package shop.mtcoding.blog.board; import lombok.Data; @Data public class ApiUtil<T> { @여기 뭐들어갓지? public static class ApiResult<T> { private Integer status; // 200, 400, 404, 405 private String msg; //성공, 실패시 -> 정확한 메세지 private T body; //바디 데이터는 타입이 여러가지니까 제네릭으로 받는다 } public static <T> ApiUtil<T> success(T body) { return new ApiResult<>(200, "성공", body); } public static ApiUtil fail() { } }
제네릭을 쓰면 return을 이렇게만 적어줘도 됨!!! 그러나 지금은 사용 X 제네릭을 더 배워야 할 수 있다 때문에 쉬운 버전으로 (생성자ver) 가자고 하심
[ 이 버전으로 가자! ]
package shop.mtcoding.blog.board; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RequiredArgsConstructor @RestController public class BoardApiController { private final BoardRepository boardRepository; @GetMapping("/api/boards") public ApiUtil<List<Board>> findAll() { // <?>로 와일드 카드 타입으로 사용해도 됨! //애는 데이터만 주는거니 애를 그냥 응답하는건 x! 상태코드나 메세지를 같이 응답하는게 좋다! List<Board> boardList = boardRepository.selectAll(); return new ApiUtil<>(boardList); } }
[ 결과 ]
스프링이 자동으로 json 데이터로 바꿔서 보내줬다
Object면 @RestController나 @ResponseBody가 붙으면 다 json으로 바꿔줌!! 그러나!! @RestController가 있으면 @ResponseBody가 없어도 알아서 붙여줌!! (링크)
[ MessageConverter가 발동해서 json으로 바꿔줌 ]
1. @RestController (or @ResponseBody)를 사용하면서 2. 오브젝트를 반환할 때 MessageConverter라는 클래스가 작동하여 자동으로 JAVA 객체를 JSON으로 변환해준다.
여기까진 스프링이었습니다!!
Share article