※ [한코딩] 게시판 만들기 유튜브를 참고하여 진행하는 프로젝트입니다.

개발 환경
사용언어 : Java
프레임 워크 : Spring boot
통합 개발 환경 : IntelliJ
데이터베이스 : MariaDB
뷰 템플릿(템플릿 엔진) : Thymeleaf
프로젝트 진행 순서
[Spring boot] 게시판 만들기 (1주차 : 개발 환경 세팅, 프로젝트 생성)
※ [한코딩] 게시판 만들기 유튜브를 참고하여 진행하는 프로젝트입니다. 개발 환경사용언어 : Java프레임 워크 : Spring boot통합 개발 환경 : IntelliJ데이터베이스 : MariaDB뷰 템플릿(템플릿 엔진)
zprograming.tistory.com
1. 개발 환경 세팅
- IntelliJ Community 다운로드
- MariaDB 다운로드
- MySQL Workbench 다운로드
2. 프로젝트 생성
- IntelliJ Community에서 Spring Boot 프로젝트 생성 (https://start.spring.io/)
- MariaDB Database(스키마) 생성
3. 게시물 작성
- db에 board 테이블 및 필드 생성
※ workbench 접속 전 cmd 창에 net start mariadb로 실행하고 시작할 것.

board 테이블에 id, title, content를 생성한다. 각각 타입은 자동지정 되었고, id에는 PK를 체크. id, title, content 에는 NN을 체크해줬다.
- 게시글 작성 폼 생성
package com.study.board.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class BoardController {
@GetMapping("/board/write") // localhost:8090/board/write
public String boardwriteForm() {
return "boardwrite";
}
}
controller에 @GetMapping 으로 /board/write 주소와 매핑해준 뒤, boardwrite 파일을 return 해주는 코드 작성.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>게시물 작성 폼</title>
</head>
<style>
.layout {
width : 500px;
margin : 0 auto;
margin-top : 40px;
}
.layout input {
width : 100%;
box-sizing : boarder-box;
}
.layout textarea {
width : 100%;
margin-top : 10px;
min-height : 300px;
}
</style>
<body>
<div class = "layout">
<form action = "/board/writepro" method="post">
<input name = "title" type = "text">
<textarea name = "content"></textarea>
<button type = "submit">작성</button>
</form>
</div>
</body>
</html>
templates 패키지 안에 위의 @GetMapping("/board/write") 에서 return 해주는 boardwrtie.html 을 작성한다.

실행을 누르면 정상적으로 폼이 나타난다.
@PostMapping("/board/writepro")
public String boardWritePro(@RequestParam("title") String title,
@RequestParam("content") String content) {
System.out.println("제목 : " + title);
System.out.println("내용 : " + content);
return "";
}
그 후 System.out.println으로 html 태그에 name으로 지정해줬던 title과 content를 웹페이지에서 받아와 콘솔에 정상적으로 출력되는지 확인해준다. (이 때 발생한 문제는 포스트 아래 Trouble Shooting 부분에 자세히 적었다!)

localhost:8090/board/write 페이지에서 폼에 제목과 내용을 입력 후 저장하면 localhost:8090/board/wrtiepro 웹페이지로 넘어가고 404에러가 뜨지만,

데이터는 정상적으로 넘어온 것으로 확인할 수 있다.

코드 실행에 필요한 여러 패키지와 클래스를 생성한다.
entity 패키지 생성 > Board 클래스 생성 ☞ 데이터베이스 테이블과 매핑되는 클래스 (도메인 모델)
package com.study.board.entity;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Data;
@Entity // @Entity 는 테이블을 의미함. 이 class 가 db에 있는 table 을 의미한다는 것.
@Data
public class Board { // 테이블이름과 일치시키는 것이 좋음.
@Id // primary key
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String title;
private String content;
}
- 실제 데이터베이스에 저장될 데이터를 담는 객체.
- 각 필드는 DB 컬럼과 매핑됨.
- @Entity를 통해 JPA가 관리하는 엔티티로 지정.
repository 패키지 생성 > BoardRepository 인터페이스 생성 ☞ 데이터베이스 접근을 담당 (DAO 역할)
package com.study.board.repository;
import com.study.board.entity.Board;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface BoardRepository extends JpaRepository<Board, Integer> { // extends 상속받음. JpaRepository를 상속받아 타입지정.
}
- JPA를 통해 DB에 저장하거나 조회하는 작업을 함.
- save, findById, deleteById 같은 기본 메서드 제공.
- 복잡한 쿼리는 직접 메서드 이름으로 정의하거나 @Query로 작성 가능.
service 패키지 생성 > BoardService 클래스 생성 ☞ 비즈니스 로직 처리
package com.study.board.service;
import com.study.board.entity.Board;
import com.study.board.repository.BoardRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class BoardService {
@Autowired
private BoardRepository boardRepository; // @Autowired가 객체 알아서 생성해줌.
public void write(Board board) {
boardRepository.save(board);
}
}
- 컨트롤러와 리포지토리 사이의 중간 계층.
- DB 작업뿐만 아니라 로직 처리, 트랜잭션 처리 등도 여기에 위치.
- 코드를 깔끔하게 유지하고 재사용성도 높여줌.
이 때, entity, repository, service 계층을 나누는 건 역할 분리(Separation of Concerns) 원칙을 따르기 위해서라고 생각하면 될 듯 하다...!

코드 작성 완료 후 /board/write 페이지에서 제목과 내용을 저장하면 database에 정상적으로 들어오는 것을 확인할 수 있다.
4. 게시물 리스팅
use board;
DELIMITER $$
CREATE PROCEDURE testDataInsert()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i <= 120 DO
INSERT INTO board(title, content)
VALUES(concat('제목',i), concat('내용',i));
SET i = i + 1;
END WHILE;
END$$
DELIMITER $$
call testDataInsert;
테스트 데이터 생성해준다.

데이터들이 잘 생성되었다.
@GetMapping("/board/list")
public String boardList(Model model) { // 데이터를 담아서 페이지로 보낼 때 Model 사용
model.addAttribute("list", boardService.boardList()); // list라는 이름으로 보낼 건데, boardService에 boardList() >> 반환된 리스트를 list 라는 이름으로 넘기겠다는 뜻.
return "boardlist";
}
게시글 리스트 페이지를 나타내기 위해 controller에 위의 코드를 작성한다.
public List<Board> boardList() {
return boardRepository.findAll(); // Board 라는 class가 담긴 LIst 반환
}
BoardService에 list를 반환하는 코드를 작성한다.
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>게시글 리스트 페이지</title>
</head>
<style>
.layout {
width : 500px;
margin : 0 auto;
margin-top : 40px;
}
</style>
<body>
<div class = "layout">
<table>
<thead>
<tr>
<th>글번호</th>
<th>제목</th>
</tr>
</thead>
<tbody>
<tr th:each="board : ${list}"> <!-- >each 는 반복문 >> list에서 board가 없어질 때까지 반복함. -->
<td th:text="${board.id}">1</td>
<td th:text="${board.title}">제목입니다.</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
boardlist를 나타낼 html 코드를 작성한다.
Thymeleaf 템플릿 엔진을 쓸 때 필요한 네임스페이스 선언을 해주고, th 접두사를 써서 th:text, th:if, th:each 등 Thymeleaf 전용 속성을 사용한다.

게시글 리스트가 정상적으로 화면에 잘 나타난다.

5. 게시물 삭제
6. 게시물 수정
7. 게시물 리스트 페이징
Trouble Shooting
1. html 코드의 title 과 content 가 콘솔 창에 넘어오지 않는 문제
에러원인
IllegalArgumentException: Name for argument of type [java.lang.String] not specified, and parameter name information not available via reflection.
Ensure that the compiler uses the '-parameters' flag.
컨트롤러 메서드에서 String title, String content 이렇게 파라미터 이름만 썼는데, 자바 컴파일 시 -parameters 옵션 없이 컴파일돼서 파라미터 이름을 리플렉션으로 못 가져오는 상황.
해결방법
import org.springframework.web.bind.annotation.RequestParam;
컨트롤러 파일 상단에 import문 추가 후,
@PostMapping("/board/writepro")
public String boardWritePro(@RequestParam("title") String title,
@RequestParam("content") String content) {
System.out.println("제목 : " + title);
System.out.println("내용 : " + content);
return "";
}
@RequestParam 을 명시적으로 붙여준다.

이제 localhost:8090/board/write 에서 작성한 title과 content가 /board/writepro 로 잘 넘어오는 걸 확인할 수 있다!
2. lombok으로 데이터 받은 후 getTitle() 메서드가 동작하지 않는 문제
에러원인 : lombok 플러그인이 설치되어 있지 않았다.
해결방법 : 설정 > 플러그인 > lombok 설치

2주차 소감
javascript 강의 시간에 Get과 Post 방식 개념에 대해 배웠는데, 그 때는 이론적인 부분만 배우다 보니 머리에 잘 들어오지 않았다. @GetMapping 과 @PostMapping 어노테이션에 대해 공부하면서 개념을 확실히 짚고 넘어가야겠다고 생각했다.
그리고 데이터베이스야... 제발 오류 내지 말아줘......
'프로젝트 > 게시판 만들기' 카테고리의 다른 글
| [Spring boot] 게시판 만들기 (4주차 : 페이징 처리, 페이지 블럭 출력하기, 게시판 검색 기능 추가) (2) | 2025.05.22 |
|---|---|
| [Spring boot] 게시판 만들기 (3주차 : 게시글 상세 페이지, 게시글 삭제 및 수정, 메시지 띄우기, 파일 업로드) (3) | 2025.05.03 |
| [Spring boot] 게시판 만들기 (1주차 : 개발 환경 세팅, 프로젝트 생성) (3) | 2025.04.05 |