이 포스트에서 만드는 Spring Boot 프로젝트의 의존성(dependency)은 아래와 같다
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation' //valid를 사용하기 위해 추가해준다.
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

spring:
jpa:
show-sql: true
properties:
format_sql: true
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
hibernate:
ddl-auto: validate
datasource:
url: jdbc:mysql://localhost:3306/simple_board?useSSL=false&useUnicode=true&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root1234!!
여기까지 하면 MySQL과 연결이 된다.
이제 전체 패키지와 파일을 생성해보자.

Board부분을 그림으로 도식화 하면 아래와 같이 설명할 수 있다.

먼저 이번 포스트에서는 Board에 대한 설명만을 한다.
package org.example.simpleboard.board.controller;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.example.simpleboard.board.db.BoardEntity;
import org.example.simpleboard.board.model.BoardRequest;
import org.example.simpleboard.board.service.BoardService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("api/board")
@RequiredArgsConstructor
public class BoardApiController {
private final BoardService boardService;
@PostMapping("")
public BoardEntity create(
//유효성 검사. BoardRequest를 따라가보면 Not blank로 Not Null을 지정해줬다.
@Valid
@RequestBody
BoardRequest boardRequest
){
//Post가 들어오면 boardService를 boardRequest넣어서 생성한다.
return boardService.create(boardRequest);
}
}
@RestController
: 클래스가 RESTful 웹 서비스의 컨트롤러임을 나타내며, 반환 값이 직접 HTTP 응답 본문으로 매핑됩니다.
@RequestMapping
: 특정 URI에 대한 요청을 처리하는 메서드를 매핑하는 데 사용됩니다. 클래스 또는 메서드 레벨에서 사용할 수 있습니다.
@RequiredArgsConstructor
: Lombok 라이브러리의 어노테이션으로, final 또는 @NonNull 어노테이션이 붙은 필드에 대한 생성자를 자동으로 생성합니다. 주로 의존성 주입에 사용됩니다.
@Valid
: 요청의 본문이나 폼 데이터 등의 객체를 검증할 때 사용됩니다. 검증 규칙을 위반할 경우 예외가 발생합니다.
@RequestBody
: HTTP 요청 본문을 Java 객체로 매핑할 때 사용되며, 주로 JSON이나 XML 데이터를 처리하는 데 사용됩니다.
이제 요청 본문(Request Body)을 받아 매핑할 때 사용하는 BoarderRequest에 대해서 알아보자.
코드는 간단하다.
package org.example.simpleboard.board.model;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import jakarta.validation.constraints.NotBlank;
import lombok.*;
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class BoardRequest {
@NotBlank //Not null을 위함 이름이 반드시 있어야 한다.
private String boardName;
}
간단하다.
무수히 많은 어노테이션들이 클래스를 휘감고 있지만 하나하나 알아보자.
@Getter
: 자동으로 데이터를 읽어오는 기능을 만들어줍니다.
@Setter
: 자동으로 데이터를 변경하는 기능을 만들어줍니다.
@Builder
: 복잡한 객체를 단계별로 쉽게 만들 수 있게 도와주는 도구입니다.
@AllArgsConstructor
: 모든 데이터를 한 번에 설정할 수 있는 생성자를 만들어줍니다.
@NoArgsConstructor
: 데이터 없이 객체를 만들 수 있는 기본 생성자를 만들어줍니다.
@ToString
: 객체를 문자열로 표현해주는 기능을 만들어줍니다. 이를 통해 객체에 어떤 데이터가 들어있는지 쉽게 알 수 있습니다.
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
: Java 객체와 JSON 데이터 사이에서 이름을 맞추어줄 때, 단어 사이를 밑줄(_)로 연결하는 방식(snake case)을 사용하게 합니다.
@NotBlank
: 문자열 필드가 채워져있음을 보장하는 어노테이션. 만약 Null, 공백, 띄어쓰기만으로 이루어지지 않았는지 확인한다.
package org.example.simpleboard.board.service;
import lombok.RequiredArgsConstructor;
import org.example.simpleboard.board.db.BoardEntity;
import org.example.simpleboard.board.db.BoardRepository;
import org.example.simpleboard.board.model.BoardRequest;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class BoardService {
private final BoardRepository boardRepository; //final을 붙여줘야 기본 생성자에 해당 값이 들어가서 생성됨.
public BoardEntity create(
BoardRequest boardRequest
){
var entity =BoardEntity
.builder()
.boardName(boardRequest.getBoardName())
.status("REGISTERED")
.build();
return boardRepository.save(entity);
}
}
이 서비스 부분은 조금은 복잡한데 위에서부터 차근차근 알아보자.
private final BoardRepository boardRepository : JpaRepository를 상속하는 레포지토리 객체를 생성해준다.
create 메서드는 또 요청본문을 받기 위해 BoarderRequest를 매개변수로 받는다.
var형 entity객체에 BoardEntity를 넣어준다. 넣어줄 때 생성은 Builder 형식을 사용해서 생성했다.
아까 만들어준 (JpaRepository를 상속하는)boardRepository의 save 메서드(JpaRepository에서 제공하는)를 사용해서 데이터베이스에 보낸다.
@Service
: 클래스가 서비스레이어의 구성요서임을 나타내고, Spring에 명시적으로 서비스 로직을 담당한다고 알려주고 자동으로 Bean에 저장하도록 한다.
@RequiredArgsConstructor
: final 또는 @NonNull 어노테이션이 붙은 모든 필드에 대한 생성자를 자동으로 생성해준다.
대망의 엔티티
package org.example.simpleboard.board.db;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.*;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity(name = "board")
@ToString
public class BoardEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String boardName;
private String status;
}
BoarderService에서 생성했던 것... 회상
var entity =BoardEntity
.builder()
.boardName(boardRequest.getBoardName())
.status("REGISTERED")
.build();
JpaRepository로 넘겨줄 때 객체를 넘겨주는데 그때 사용될 클래스이다.
내부의 id는 @Id 어노테이션을 붙여서 ID임을 알려주고, strategy를 설정해줌으로써 ID를 지정해주지 않아도 자동으로 생성해준다.
boardName은 게시판의 이름이다.
status는 builder에서 보이는 것처럼 제대로 들어갔을 때 REGISTERED로 설정해준다.
@Getter, @Setter: 클래스 필드의 읽기/쓰기 메서드 자동 생성.
@NoArgsConstructor: 인자 없는 생성자 자동 생성.
@AllArgsConstructor: 모든 필드 포함한 생성자 자동 생성.
@Builder: 객체 생성 시 빌더 패턴 제공.
@Entity(name = "board"): 클래스를 "board" 테이블과 연결하는 엔티티로 선언.
@ToString: 객체를 문자열로 표현하는 메서드 자동 생성.
@Id: 필드를 테이블의 기본 키로 지정.
@GeneratedValue(strategy = GenerationType.IDENTITY): 기본 키 값 자동 생성 설정.