Mybatis/실전 프로젝트 예제
게시판 구현 (페이징, 검색 포함)
DEVLIB
2025. 4. 17. 10:13
728x90
1. 프로젝트 구조 개요
src/
├── controller ← BoardController.java
├── domain ← Board.java, BoardSearchCondition.java
├── mapper ← BoardMapper.java, BoardMapper.xml
└── service ← BoardService.java
2. Board 도메인 클래스
public class Board {
private Long id;
private String title;
private String content;
private String writer;
private LocalDateTime createdAt;
}
3. 검색 + 페이징 조건 DTO
public class BoardSearchCondition {
private String keyword;
private String writer;
private int page = 1;
private int size = 10;
public int getOffset() {
return (page - 1) * size;
}
}
4. Mapper 인터페이스
@Mapper
public interface BoardMapper {
List<Board> search(BoardSearchCondition condition);
int count(BoardSearchCondition condition);
void insert(Board board);
Board findById(Long id);
void update(Board board);
void delete(Long id);
}
5. Mapper XML (BoardMapper.xml)
<mapper namespace="com.example.board.mapper.BoardMapper">
<select id="search" resultType="Board" parameterType="BoardSearchCondition">
SELECT * FROM board
<where>
<if test="keyword != null and keyword != ''">
AND title LIKE CONCAT('%', #{keyword}, '%')
</if>
<if test="writer != null and writer != ''">
AND writer = #{writer}
</if>
</where>
ORDER BY created_at DESC
LIMIT #{size} OFFSET #{offset}
</select>
<select id="count" resultType="int" parameterType="BoardSearchCondition">
SELECT COUNT(*) FROM board
<where>
<if test="keyword != null and keyword != ''">
AND title LIKE CONCAT('%', #{keyword}, '%')
</if>
<if test="writer != null and writer != ''">
AND writer = #{writer}
</if>
</where>
</select>
<insert id="insert" parameterType="Board">
INSERT INTO board (title, content, writer, created_at)
VALUES (#{title}, #{content}, #{writer}, NOW())
</insert>
<select id="findById" resultType="Board" parameterType="long">
SELECT * FROM board WHERE id = #{id}
</select>
<update id="update" parameterType="Board">
UPDATE board
SET title = #{title}, content = #{content}
WHERE id = #{id}
</update>
<delete id="delete" parameterType="long">
DELETE FROM board WHERE id = #{id}
</delete>
</mapper>
6. 서비스 클래스
@Service
@RequiredArgsConstructor
public class BoardService {
private final BoardMapper boardMapper;
public List<Board> search(BoardSearchCondition condition) {
return boardMapper.search(condition);
}
public int count(BoardSearchCondition condition) {
return boardMapper.count(condition);
}
public void create(Board board) {
boardMapper.insert(board);
}
public Board get(Long id) {
return boardMapper.findById(id);
}
public void update(Board board) {
boardMapper.update(board);
}
public void delete(Long id) {
boardMapper.delete(id);
}
}
7. REST Controller
@RestController
@RequestMapping("/api/boards")
@RequiredArgsConstructor
public class BoardController {
private final BoardService boardService;
@GetMapping
public Map<String, Object> list(BoardSearchCondition condition) {
List<Board> list = boardService.search(condition);
int total = boardService.count(condition);
return Map.of(
"total", total,
"list", list
);
}
@PostMapping
public void create(@RequestBody Board board) {
boardService.create(board);
}
@GetMapping("/{id}")
public Board detail(@PathVariable Long id) {
return boardService.get(id);
}
@PutMapping("/{id}")
public void update(@PathVariable Long id, @RequestBody Board board) {
board.setId(id);
boardService.update(board);
}
@DeleteMapping("/{id}")
public void delete(@PathVariable Long id) {
boardService.delete(id);
}
}
8. 테이블 구조 (MySQL 기준)
CREATE TABLE board (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200),
content TEXT,
writer VARCHAR(100),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
전체 기능 요약
기능 | URL | HTTP | 설명 |
게시글 목록 조회 (검색+페이징) | /api/boards?keyword=공지&page=1&size=10 | GET | 조건부 목록 |
게시글 상세 조회 | /api/boards/{id} | GET | 개별 게시글 |
게시글 작성 | /api/boards | POST | 새 게시글 등록 |
게시글 수정 | /api/boards/{id} | PUT | 제목/내용 수정 |
게시글 삭제 | /api/boards/{id} | DELETE | 삭제 처리 |
확장 아이디어
- 댓글 기능 추가 (1:N 매핑)
- 파일 업로드 연동 (S3, 로컬)
- 정렬 조건 추가 (작성일, 조회수 등)
- 페이지네이션 응답 포맷 개선 (totalPages, hasNext 등)
LIST