[Spring Boot 게시판 ②] CRUD API 구현 (2/4)

2025. 6. 23. 23:00·공부일기../Spring

 나의 개발 후기는 아래에~~~  ..!

더보기
더보기
더보기

스프링부트+JPA 처음써봤는데 진짜 넘너ㅓㄴ넘 넘 왕짱 쉬워서 놀랐다..ㅋ 

스프링은 내가 설정해줘야하는것도 많구해서 초기세팅만 반나절인데

뭐야이거 초기세팅 진짜 다해주고 할게없음..ㅋ

 

대신 커스터마이징 하기가 좀 어렵다는 단점이있다.

`Spring Framework`는 설정값을 세밀하게 제어가가능한데 `Spring Boot`는 starter로 의존성 자동구성이 되니까 진짜 넘넘 편했다. 따로 커스터마이징을 할게 아니라면 `Spring Boot` 쓰는것도 괜찮은것같다.

`JPA`도 첨써봤는데 뭐야 이거 ㅋ..

 

`Spring Boot` + `JPA` 이 조합 진짜 완전 밀키트임...이런식으로 개발해도되나 난이도 최최하됨..

그래서 그런지 crud 후다닥..해버렸다..ㅋ 

그래서 예외처리나 공통응답 클래스 같은걸 추가로 구현했다. (아직 완성은안됨ㅋ 낼해야지;;)

공통응답이나 예외처리를 한 이유는 아무래도 API로 쏘니까 비밀번호가 틀리다던가 조회하려는 게시물이없을때 다 예외로 던지면 서버 뻑나니까 걍 처리 해야겠다 싶었다.. 머.. 당연함..당연히해야댐..ㅠ 잘안댐.. 쩝 

 

JPA문법이나 정적메모리 메서드 등등 처음접한개념들이있었는데 그거는 추후에 포스팅을 새로 해야겠다.

 

 

구분  Spring Framework  Spring Boot
개념 스프링 기반 핵심 기능 제공 (DI, AOP, MVC 등) 스프링 설정을 자동화하고 쉽게 만들기 위한 프레임워크
설정 방식 XML 또는 Java 기반 수동 설정 필요 자동 설정 (Auto Configuration) 사용
빌드/배포 WAR 파일을 만들어 WAS(톰캣 등)에 배포 내장 Tomcat 포함 → JAR 실행만으로 서버 실행 가능
시작 프로젝트 구성 개발자가 의존성 직접 추가, 환경 구성 복잡 스타터 의존성 제공, 초기 세팅 간단
학습 난이도 높음 (설정 양이 많고 복잡) 낮음 (기본 설정이 자동으로 제공됨)
테스트 설정이 복잡하여 테스트 세팅 어려움 @SpringBootTest 등으로 쉬운 테스트 환경
커스터마이징 자유도가 높음 (직접 세부 조정 가능) 자동 설정 우선 → 커스터마이징은 오버라이드해야 함

 

 

시리즈 포스팅!!

SprintBoot로 게시판 만들기 ②📝(API명세서, ERD작성) - 1

SprintBoot로 게시판 만들기 ②📝(CRUD 구현_설정부) - 2

SprintBoot로 게시판 만들기 ②📝(CRUD 구현_개발) - 3

SprintBoot로 게시판 만들기 ②📝(CRUD 구현_테스트) - 4

 

 

 

3-1. `pom.xml`에 `dependency` 추가

우선 내가 추가한 Maven Dependency 목록 이다.

Dependency  설명 생성이유
`spring-boot-starter-data-jpa` JPA (Hibernate 기반)를 통해 객체와 관계형 데이터베이스 간 매핑을 지원하며, CRUD 쿼리를 간단하게 처리할 수 있게 도와줍니다. 필수
`spring-boot-starter-web` Spring MVC를 기반으로 REST API, 웹 애플리케이션, JSON 처리 등을 가능하게 하는 기본 웹 스타터입니다. 필수
`spring-boot-starter-validation` @Valid, @NotNull 등 Bean Validation (JSR-380, Hibernate Validator)을 통한 입력값 유효성 검사 기능을 제공합니다. 회원가입시 유효성 검사하기위해
`mysql-connector-j` Java에서 MySQL 데이터베이스와 연결할 수 있도록 해주는 JDBC 드라이버입니다. 필수
`lombok` @Getter, @Setter, @Builder, @NoArgsConstructor 등을 통해 반복적인 Java 코드를 줄여주는 코드 자동 생성 도구입니다. 편함 (직접 코드를 작성하지않아도됨)
`spring-boot-starter-thymeleaf` HTML 템플릿 엔진인 Thymeleaf를 통해 서버 사이드 렌더링 방식의 뷰(View)를 처리할 수 있게 해줍니다. api 구현인데 화면까지 처음에 만들었어서 추가를 했었다. 코드 수정 후 사용안하게됨
`spring-boot-starter-test` JUnit, Mockito 등을 포함하여 Spring 기반의 테스트 코드를 쉽게 작성하고 실행할 수 있게 해주는 스타터입니다. 테스트용
`springdoc-openapi-starter-webmvc-ui` Swagger UI 기반의 OpenAPI 3 문서 자동 생성을 지원하며, http://localhost:8080/swagger-ui/index.html에서 API 문서를 시각적으로 확인할 수 있게 합니다. Swagger 사용하기 위함
`spring-boot-starter-security` 로그인, 권한 인증, 세션 관리 등을 지원하는 Spring Security 기본 모듈로, 보안 설정을 적용할 수 있습니다. 로그인 시 인증설정

 

추후 보완사항 

`spring-boot-devtools` 추가하면 Hot reload 개발에 유리! 

자동으로 서버 재부팅해주는거같은데 운영상황이면 당연히꺼야한다. 코드 바꾸고 수정할떄 서버 계속 끄고켜면 귀찮으니까 하는것~

 

3-2. `application.properties` 설정 (DataBase 연결하기)

#애플리케이션 이름을 설정
spring.application.name=SpringBootStudy99

#데이터베이스 연결 URL
spring.datasource.url=jdbc:mysql://localhost:3306/DB명?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul

#데이터베이스 로그인에 사용할 사용자 이름,비번
spring.datasource.username= 사용자이름 (root 로 했음)
spring.datasource.password= 비밀번호

#사용할 JDBC 드라이버 클래스(MySQL 표준 드라이버 사용)
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

#Spring Boot 서버의 포트를 8082번으로 설정 (기본값은 8080)
server.port=8082

#PA가 @Entity 클래스를 보고 DB 테이블을 자동으로 생성하거나 수정하는 기능-> 추후 validate or none
spring.jpa.hibernate.ddl-auto=update

#JPA 실행 SQL을 콘솔에 출력함 (디버깅, 확인용)
spring.jpa.show-sql=true

#MySQL 8 버전에 맞는 SQL 문법을 사용하도록 지시
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

 

 

3-3. `@Entity` 생성 (도메인 객체 BoardVO, UserVO 생성)

BoardVO, UserVO 두가지 도메인을 생성했다. 테이블의 속성값대로 변수를 생성했다.

그리고 아래의 어노테이션을 달아줬는데 기본생성자와 매개변수가 있는 생성자를 직접 작성하지않아도 작성해줘서 좋았다.

@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor

 

해당하는 속성들을 정의하고 `@Id`로 PK를 지정 후 ` @GeneratedValue(strategy = GenerationType.IDENTITY) `를 사용해서 자동으로 게시판 일련번호의 숫자를 증가시켰다.

DB에도 ` AUTO_INCREMENT ` 설정을 했지만 JPA에서 같이 지정해줘야 올바르게 인식한다고 해서 추가해줬다. (둘다필수!)

호옥시 JPA가 board_no컬럼에 null을 넣을수도있으니까..!

//속성
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "board_no")
private Long boardNo;

@Column(name = "writer", length = 10, nullable = false)
private String writer;

@Column(name = "title", length = 100, nullable = false)
private String title;

(생략).....

 

그리구 `@NoArgsConstructor` , `@AllArgsConstructor` 를 추가해줬지만 이거는 기본생성자와, 모든 매개변수를 받는 생성자를 구현해주는것이다.

나는 몇개의 매개변수만 받고싶었고 작성일자와 수정일자는 `LocalDateTime.now()`로 자동세팅 해주고 싶었기때문에 커스텀 생성자를 추가 구현했다.

// 생성자
public BoardVO(String writer, String title, String content ,String boardPwd) {
    this.writer = writer;
    this.title = title;
    this.content = content;
    this.boardPwd = boardPwd;
    this.rgstDt = LocalDateTime.now();
    this.udtDt = LocalDateTime.now();
}

 

그리고 대망의 **정적 메서드(static factory method)**

DTO → Entity 변환을 하기위해서 적어줬다.

엄청 가독성 쩌는 코드!! `from()` 말그대로 DTO를 VO로 변환한다~ (dto로부터 entity를 만든다)

리턴은 새롭게 만든 VO 할거야~

나중에 암호화처리같은걸 해도 `encrypt(dto.getBoardPwd()) ` 이런식으로 해당 메서드만 수정하면된다.

생성자에는 최소한의 필드 초기화만 남기고 외부에서 변화는 `from()`에서 하면된다.

// 정적메서드 방식
public static BoardVO from(BoardCreateRequestDto dto) {
    return new BoardVO(
            dto.getWriter(),
            dto.getTitle(),
            dto.getContent(),
            dto.getBoardPwd()
    );
}

 

해당 게시판 객체의 기능도 작성했다.

조회수 증가나 게시글 수정같은 객체 본질이 변하는 행위 자체는 객체에서 기능구현을 해야한다.

`Service`는 트렌잭션/비지니스 로직 구현!

//기능
//조회수 증가
public void addViewCount() {
    this.viewCnt = (this.viewCnt == null ? 1 : this.viewCnt + 1);
}

//수정 메서드
public void update(String title, String writer, String content) {
        this.title = title;

    if (writer != null && !writer.trim().isEmpty()) {
        this.writer = writer;
    }
        this.content = content;
        this.udtDt = LocalDateTime.now();
}

 

3-4 ceateDTO, listDTO, reponseDTO, updateDTO 생성

 `@Entity` 변환용 정적 팩토리 메서드이다.

실무에서는 보통 DTO안만들고 Map<>으로 만들어서 대강 사용했던거같은데 기초부터 공부하려고 정석으로 만들었다.

 

`@Entity`는 실제 DB테이블과 매핑되는 값이기 때문에 Repository, Service 내부에서 사용된다.

DTO는 걍 getter/setter만 있는 순수 데이터 보관용이라 로직도없다. Controller ↔ Service 간 요청/응답에서 사용한다. 오직 전달만을 위한 아이다.

 

필요한 필드만 선택해서 노출가능하기때문에 DB정보를 노출하지않아도되고 API변경시 DTO만 수정하면된다.

클라이언트 → Controller → [DTO로 요청 받음]
                  → Service → [DTO를 Entity로 변환 후 저장]
                                    → Repository (Entity로 DB 조작)
                  ← Service → [Entity → DTO 변환 후 응답]
← Controller ← 클라이언트에게 DTO로 응답

 

 `ceateDTO`(게시글 저장시) , ` listDTO`(목록조회) , `reponseDTO`(응답시) , `UpdateDTO`(수정시) 이렇게 4가지 생성했다.

근데 수정이랑 저장시에 넘기는 request가 같아서 이름을 requestDTO로 변경하고 한개로 통일했어도 될뻔했음!! 

(흠 근데 나중에 호옥시 수정할수도있으니까 유지보수성을 위해서는 쪼개는게 맞는거같기도하고..)

 

마찬가지로 속성을 정의하고 아래 from()으로 Entity를 받아서 DTO로 변경가능하다.

이때 람다를 사용했는데 `.map(대상::변환할메서드)` 이렇게 사용하면된다!

// 게시글 응답 DTO (단건 조회용)
public class BoardResponseDto {
    private Long boardNo;
    private String title;
    private String writer;
    private String content;
    private Integer viewCnt;
    private LocalDateTime rgstDt;
    private LocalDateTime udtDt;

    // 정적 팩토리 메서드
    public static BoardResponseDto from(BoardVO boardVO) {
        return new BoardResponseDto(
                boardVO.getBoardNo(),
                boardVO.getTitle(),
                boardVO.getWriter(),
                boardVO.getContent(),
                boardVO.getViewCnt(),
                boardVO.getRgstDt(),
                boardVO.getUdtDt()
        );
    }

 

그리고 필수값을 사용하기위해서는 아래처럼 `@NotBlank` 어노테이션을 붙혀봤다.

// 게시글 작성 요청 DTO
public class BoardCreateRequestDto {
    @NotBlank(message = "제목은 필수입니다.")
    private String title;
    @NotBlank(message = "작성자는 필수입니다.")
    private String writer;
    @NotBlank(message = "비밀번호는 필수입니다.")
    private String boardPwd;
    @NotBlank(message = "내용은 필수입니다.")
    private String content;
    private LocalDateTime rgstDt;
    private LocalDateTime udtDt;
}

'공부일기.. > Spring' 카테고리의 다른 글

[Spring Boot 게시판 ] JWT 로그인 구현 하기  (0) 2025.07.01
[Spring Boot 게시판 ②] CRUD API , Postman 테스트(4/4)  (0) 2025.06.24
[Spring Boot 게시판 ②] CRUD API 개발(3/4)  (0) 2025.06.24
[Spring Boot 게시판 ②] CRUD API 설계 (1/3)  (0) 2025.06.20
[Spring Boot 게시판 만들기①] 테크스펙, 환경설정, 유스케이스  (0) 2025.06.19
'공부일기../Spring' 카테고리의 다른 글
  • [Spring Boot 게시판 ②] CRUD API , Postman 테스트(4/4)
  • [Spring Boot 게시판 ②] CRUD API 개발(3/4)
  • [Spring Boot 게시판 ②] CRUD API 설계 (1/3)
  • [Spring Boot 게시판 만들기①] 테크스펙, 환경설정, 유스케이스
s0-0mzzang
s0-0mzzang
공부한것을 기록합니다...
  • s0-0mzzang
    승민이의..개발일기..🐰
    s0-0mzzang
  • 전체
    오늘
    어제
    • 전체~ (108)
      • 마음가짐..! (10)
      • 공부일기.. (76)
        • weekly-log (6)
        • Spring (19)
        • Java (18)
        • DataBase (10)
        • git (2)
        • JPA (6)
        • kafka (1)
        • Backend Architecture (3)
        • Troubleshooting (삽질..ㅋ) (2)
        • Cloud (1)
        • Docker (2)
        • 알고리즘 (1)
        • 리액트 (2)
        • Infra (3)
      • 하루일기.. (22)
        • 그림일기 (8)
        • 생각일기 (14)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 깃허브
  • 공지사항

  • 인기 글

  • 태그

    항해99
    TDD
    항해플러스
    다짐
    인프라 기초
    MySQL
    Paging
    BufferedReader
    StringTokenizer
    리팩토링
    spring boot
    ERD
    React
    spring
    SpringBoot
    JPA
    스프링부트
    ADC 환경
    자바
    swagger
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
s0-0mzzang
[Spring Boot 게시판 ②] CRUD API 구현 (2/4)
상단으로

티스토리툴바