v6 게시판을 다른 옷으로 입혀본다
REST API 로 만들면 이 모든 게 풀립니다. 같은 게시판을 「다른 옷」으로.
모든 메서드 반환값을 자동으로 JSON 으로 변환해 응답 바디로 보내는 컨트롤러. View 박스가 흐름에서 빠짐.
package com.smhrd.controller;
@Controller
@RequestMapping("/board")
public class BoardController {
@Autowired
private BoardService service;
@GetMapping("/list")
public String list(Model model) {
model.addAttribute("boards", service.selectList());
return "board/list"; // → JSP
}
@GetMapping("/view")
public String view(@RequestParam int num, Model model) {
model.addAttribute("board", service.selectOne(num));
return "board/view"; // → JSP
}
}
👉 결과를 Model 에 담고 ViewName 을 반환 — JSP 가 화면을 그림.
@PostMapping("/write")
public String write(Board b, HttpSession s) {
Member u = (Member) s.getAttribute("loginUser");
b.setWriter(u.getId());
service.insert(b);
return "redirect:/board/list";
}
}
👉 폼 데이터를 객체로 바인딩, 저장 후 목록 페이지로 redirect.
package com.smhrd.controller;
@RestController // ⭐ 변경 1
@RequestMapping("/api/boards") // ⭐ URL prefix 변경
public class BoardApiController {
@Autowired
private BoardService service;
@GetMapping // GET /api/boards
public List<Board> list() {
return service.selectList(); // ⭐ 객체 반환 → 자동 JSON
}
@GetMapping("/{num}") // GET /api/boards/3
public Board view(@PathVariable int num) {
return service.selectOne(num);
}
}
👉 Model 도 ViewName 도 사라짐. 객체를 그대로 반환하면 JSON.
@PostMapping // POST /api/boards
public Board create(@RequestBody Board b,
HttpSession s) {
Member u = (Member) s.getAttribute("loginUser");
b.setWriter(u.getId());
service.insert(b);
return b;
}
}
👉 폼 바인딩 대신 @RequestBody 로 JSON 을 받고, 저장 결과를 JSON 으로 응답.
| 자리 | v6 | v8 |
|---|---|---|
| 클래스 어노테이션 | @Controller | @RestController |
| URL prefix | /board | /api/boards |
| 반환 타입 | String (ViewName) | 객체 또는 List |
| Model | 매개변수로 받음 | 없음 |
| 파라미터 | 폼 바인딩 | @RequestBody JSON |
| 동작 | v6 (전통) | v8 (REST) |
|---|---|---|
| 목록 | GET /board/list | GET /api/boards |
| 상세 | GET /board/view?num=3 | GET /api/boards/3 |
| 작성 | POST /board/write | POST /api/boards |
| 수정 | POST /board/update | PUT /api/boards/3 |
| 삭제 | POST /board/delete | DELETE /api/boards/3 |
👉 REST 는 「리소스(boards)」를 URL 로, 「동작」을 HTTP 메서드로 표현.
@PostMapping
public Board create(@RequestBody Board b, ...) {
// b 는 클라이언트가 보낸 JSON 이 자동 변환된 객체
}
http://localhost:8080/.../api/boards[{"num":1,"title":"첫 글",...}, ...]Content-Type: application/jsonhttp://localhost:8080/.../api/boards/1 — 단일 객체브라우저 주소창은 GET 만 가능. POST 는 다른 방법:
fetch('/api/boards', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({title: '테스트', content: 'hello'})
}).then(r => r.json()).then(console.log);curl -X POST -H "Content-Type: application/json" \
-d '{"title":"테스트","content":"hello"}' \
http://localhost:8080/.../api/boards둘 중 하나만 만들 수 있는 게 아닙니다. 같은 Service 를 공유하면서 두 가지 형태로:
실무에서도 흔합니다. 관리자 화면은 JSP, 사용자 모바일 앱과는 REST API.
@Controller
@RequestMapping("/board")
public class BoardController {
@GetMapping("/view")
public String view(
@RequestParam int num,
Model model
) {
model.addAttribute(
"board",
service.selectOne(num)
);
return "board/view";
}
}
👉 데이터 → Model → ViewName → JSP 화면.
@RestController
@RequestMapping("/api/boards")
public class BoardApiController {
@GetMapping("/{num}")
public Board view(
@PathVariable int num
) {
return service.selectOne(num);
}
}
👉 같은 일 — 다른 도구. Service 호출 부분은 똑같고, 반환 객체가 곧 JSON.
👉 v8 는 모든 현대 웹 개발의 출발점.
v8 부터 우리 사이트는 두 얼굴을 가집니다:
다음 차시 v9 에서는 JS 가 우리 REST API 를 호출해 새로고침 없는 화면을 만듭니다.
JSP 기반 게시판이 동작. 매 동작마다 화면 깜빡.
같은 게시판이 REST API 로도 동작. 다른 시스템이 사용 가능. 화면 새로고침 제거의 토대.
다음: v9 비동기 댓글 — 이 REST API 를 fetch 로 호출해 새로고침 없는 화면.