1. 게시판 Request, Model, Session 연습 및 해설
BoardController (Request 이용)
// get, post //Model model Request 객체이다.
@GetMapping("/board")
public String list(HttpServletRequest request) {
//view에 데이터를 전달 한 게 아니라 request 객체에서 보관되어있다가 musatche에서 찾아낸거다.
List<Board> boardList = boardRepository.findAll();
request.setAttribute("models", boardList);
//session
//HttpSession session = request.getSession();
//session.setAttribute("num", 1);
return "board/list";
}
- 게시판 목록을 데이터베스에서 조회하여 ‘boardList’ 라는 리스트를 만든다.
- 리스트를 ‘request’ 객체에 ‘models’라는 이름으로 저장한다.
- (주석 처리된) 코드로 session을 사용하여 데이터를 저장 할 수 있지만, 현재는 사용하지 않음.
- view 이름으로 ‘board/list’ 를 반환하여, 해당 뷰 파일(’board/list.jsp’)을 렌더링한다.
list.mustache
{{#models}}
<div class="card mb-3">
<div class="card-body">
<h4 class="card-title mb-3">{{title}}</h4>
<a href="/board/{{id}}" class="btn btn-primary">상세보기</a>
</div>
</div>
{{/models}}
Handlebars/Mustache:
- 사용한 문법이
{{#models}}
로 데이터 반복을 처리합니다.
- ’{{#models}}’와 ‘{{models}}’는 ‘models’ 리스트의 각 항목을 반복하여 출력한다.
- 각 항목의 ‘title’ 과 ‘id’를 사용하여 카드 형태로 표시하며, 상세보기 링크를 생성한다.
3. Spring Framework의 애플리케이션 구성(application.properties)
- 더미 데이터 생성하기!

insert into board_tb(title, content, created_at)
values ('제목1', '내용1', now());
insert into board_tb(title, content, created_at)
values ('제목2', '내용2', now());
insert into board_tb(title, content, created_at)
values ('제목3', '내용3', now());
insert into board_tb(title, content, created_at)
values ('제목4', '내용4', now());
insert into board_tb(title, content, created_at)
values ('제목5', '내용5', now());
# 4. Dummy
spring.sql.init.data-locations=classpath:db/data.sql
# 5. Mustache Setting
spring.mustache.servlet.expose-request-attributes=true
spring.mustache.servlet.expose-session-attributes=true
- 데이터베이스 초기화: ‘spring.sql.init.data-locations’ 설정을 통해 애플리케이션 시작 시 특정 SQL 파일을 실행하여 데이터베이스를 초기화 한다.
- Mustache 설정: ‘spring.mustache.servlet.expose-request-attributes’는 요청 속성을 Mustache 템플릿에서 사용 가능하게 한다.
- ’spring.mustache.servlet.expose-session-attributes’는 세션 속성을 Mustache 템플릿에서 사용 가능하게 한다.
4. 상세보기 만들기
BoardController
// 1. 메서드 : Get
// 2. 주소 : /board/1
// 3. 응답 : board/detail
@GetMapping("/board/{id}")
public String detail(@PathVariable("id") Integer id, HttpServletRequest request) {
Board board = boardRepository.findById(id);
request.setAttribute("model", board);
return "board/detail";
}
- 경로 변수 추출: ‘@GetMapping(”board/{id}”)’ 과 ‘@Pathvariable(”id”)’을 사용해 URL의 ‘id’ 값을 추출한다.
- 데이터 조회: ‘boardRepository.findById(id)’를 사용해 데이터베이스에서 해당 ‘id’의 게시글을 조회한다.
- 데이터 전달: 조회한 ‘board’ 객체를 ‘request.settAttribute(”model”, board) ‘ 로 ‘request’ 객체에 저장해서 뷰에 접근 가능하게 한다.
- 뷰 렌더링: ‘return “board/detail”; ‘ 을 통해 ‘board/detail’ 뷰를 반환하여 템플릿이 클라이언트에게 렌더딩됩니다.
detail.mustache
<div class="d-flex justify-content-end">
<a href="/board/{{model.id}}/update-form" class="btn btn-warning me-1">수정</a>
<!--
post를 쓰는 이유는 ajax,자바스크립트를 사용 하지 않고 기초적인 CRUD를 하기 위해
주소 설계 규칙 찾아보기
post로 쓰기,삭제,수정을 하기 위해 동사를 쓰지 않고 post를 쓴다.
-->
<form action="/board/{{model.id}}/delete" method="post">
<button class="btn btn-danger">삭제</button>
</form>
</div>
<div class="d-flex justify-content-end">
<b>작성자</b> : 익명
</div>
<!-- 게시글내용 -->
<div>
<h2><b>{{model.title}}</b></h2>
<hr/>
<div class="m-4 p-2">
{{model.content}}
</div>
</div>
</div>
- ‘{{model.title}}’: 서버에서 전달된 ‘model’ 객체의 ‘title’ 속성 값을 HTML에 출력합니다.
- 템플릿 엔진: Mustache를 사용하여 동적이 콘턴체를 생성한다.
- 사용위치: 이와 같은 표현은 ‘{{model.title}}’, ‘{{model.content}}’ 등 다양한 데이토 속성에 사용되고, 템플릿에서 서버 데이터를 쉽게 표시할 수 있게 해준다.!
BoardRepository
//Board class 자동으로 오브젝트 맵핑을 해준다.
public Board findById(int id){
Query query = em.createNativeQuery("select * from board_tb where id=?", Board.class);
query.setParameter(1, id);
try {
Board board = (Board) query.getSingleResult();
return board;
}
catch (Exception e) {
//내가 예외를 설정 할 수 있다. 익세션을 내가 잡은것 까지 배움 - 처리 방법은 v2에서 배우기
//자기가 처리 하기 싫으면 throw로 넘길 수 있다.
throw new RuntimeException("게시글 아이디를 찾을 수 없습니다.");
}
}
- 네이티브 SQL 쿼리를 사용해 ‘board_tb’ 테이블에서 주어진 ‘id’에 해당하는 레코드를 조회하며, 조회된 결과는 ‘Board’ 클래스의 인스턴스로 자동 매핑된다.
- 조회 과정에서 예외가 발생한다면, 사용자에게 “게시글을 찾을 수 없습니다.라는 메세질르 포함한 ‘RuntimeException’이 던져진다.
BoardRepositoryTest
@Test
public void findById_test() {
//given (가짜로 id를 만들어본다.)
int id = 110;
//when
Board board = boardRepository.findById(id);
//eye (잘 하지 못 해서 눈으로 확인 했습니다.)
System.out.println(board.getTitle());
System.out.println(board.getContent());
System.out.println(board.getContent());
}
}
- 테스트의 목적은 ‘findById’ 메소드가 특정 ‘id’를 통해 ‘board’ 객체를 올바르게 조회하는지 확인 하기 위해 작성
- Given(가짜 id를 만들어본다): 테스트할 가상의 ‘id’ 값(110)으로 설정
- When: ‘findById(id) 메소드를 호출해서 해당 ‘id’에 해당하는 ‘board’ 객체를 조회한다.
- Eye: 조회된 ‘Board’ 객체의 제목(’title’)과 내용(’content’)을 콘솔에 출력하여 수동으로 결과를 확인 할 수 있다.
Share article