[Spring boot] 게시판 만들기 - 게시판 CRUD 처리하기

2025. 3. 10. 18:47·Spring boot
반응형

"본 포스팅은 [원 블로그]의 내용을 참고하여 개인 학습 목적으로 작성되었습니다.

원 저작자의 권리를 존중하며,

내용 수정이나 삭제 요청이 있을 시 즉시 조치하겠습니다."

 

오늘은 소프트웨어 개발에서

데이터를 처리하는

가장 기본적인 작업인 CRUD 처리를

해볼 것입니다!

● CRUD 처리하기

○ CRUD란?

    -  CRUD는 Create , Read , Update , Delete 의 약어로 시스템에서 기본적인 데이터 관리 기능을 의미합니다

        CRUD는 대부분의 시스템에 적용되어 있는 가장 기본적인 개념이고 거의 모든 프로젝트들이

        CRUD 개념의 연장선이라고 볼 수 있다.

 

1. 테이블 생성하기

  우선 DBMS 툴인 DBeaver를 실행시킨 후 SQL 편집기에서 다음의 코드를 입력 후 실행합니다

CREATE TABLE `tb_post` (
    `id`            bigint(20)    NOT NULL AUTO_INCREMENT COMMENT 'PK',
    `title`         varchar(100)  NOT NULL COMMENT '제목',
    `content`       varchar(3000) NOT NULL COMMENT '내용',
    `writer`        varchar(20)   NOT NULL COMMENT '작성자',
    `view_cnt`      int(11)       NOT NULL COMMENT '조회 수',
    `notice_yn`     tinyint(1)    NOT NULL COMMENT '공지글 여부',
    `delete_yn`     tinyint(1)    NOT NULL COMMENT '삭제 여부',
    `created_date`  datetime      NOT NULL DEFAULT current_timestamp() COMMENT '생성일시',
    `modified_date` datetime               DEFAULT NULL COMMENT '최종 수정일시',
    PRIMARY KEY (`id`)
) COMMENT '게시글';

 

 테이블이 잘 생성되었는 지 확인해 보아야 합니다

SHOW FULL COLUMNS FROM tb_post

  

 위의 명령어를 입력하면 

테이블 확인

 이런 식으로 나오면 성공입니다!

 

2.  게시글 요청 클래스 생성

게시글 생성과 수정을 처리하기 위해서는 요청 클래스와 응답 클래스가 있어야 합니다

그 중 우선 요청 클래스를 생성해 보겠습니다

 

src/main/java/com.study 위치에 domain.post라는 패키지를 만들고 

만든 패키지 안에 PostRequest 클래스를 추가합니다

 

그 후 아래의 코드를 입력합니다.

package com.study.domain.post;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class PostRequest {

    private Long id;             // PK
    private String title;        // 제목
    private String content;      // 내용
    private String writer;       // 작성자
    private Boolean noticeYn;    // 공지글 여부
    
}

 

○ Getter , Setter 는 무엇인가?

 - Getter와 Setter는 객체 지향 프로그래밍에서 클래스의 속성(필드 즉, 멤버 변수)에

   안전하게 접근하고 수정할 수 있도록 도와주는 메서드입니다.

 

왜 사용할까?

 - Getter와 Setter를 사용하는 이유는 객체의 속성을 직접 접근하지 못하도록 보호하고

   외부에서 제한된 방식으로만 접근할 수 있도록 하기 위함입니다.

   또 값이 올바르게 들어갔는 지 검증하는 데에도 쓰여 잘못된 데이터 입력을 방지합니다.

 

그런데 저는 여기서 왜 객체의 속성에 직접 접근하지 않고 외부에서 접근하도록 하지?

라는 의문이 들었고 알아본 결과 제한된 방식으로 접근하면 원본 데이터의 무결성을 보장하고

특정 동작을 추가하거나 변경할 때 한 곳만 수정하면 되니까 유지보수 측면에서도

이점이 있다는 것을 알게되었습니다.

 

@Getter, @Setter 이 두 어노테이션은 Lombok 라이브러리에서 가장 많이 사용되는 어노테이션으로 클래스에 선언된 모든 멤버 변수에 대한 getter와 setter를 자동 생성 해주는 역할을 합니다.

   

 

3. 게시글 응답 클래스 생성

앞서 생성한 패키지에 PostRequest와 같은 위치에 PostResponse를 생성한 후 

다음의 코드를 입력합니다.

package com.study.domain.post;

import lombok.Getter;

import java.time.LocalDateTime;

@Getter
public class PostResponse {

    private Long id;                       // PK
    private String title;                  // 제목
    private String content;                // 내용
    private String writer;                 // 작성자
    private int viewCnt;                   // 조회 수
    private Boolean noticeYn;              // 공지글 여부
    private Boolean deleteYn;              // 삭제 여부
    private LocalDateTime createdDate;     // 생성일시
    private LocalDateTime modifiedDate;    // 최종 수정일시

}

 

응답 클래스에서는 Setter 생성을 할 필요가 없습니다

그 이유는 응답 데이터는 한 번 생성되면 변경되지 않는 것이 원칙이기 때문에

굳이 만들 이유가 없는 것입니다.

4. Mapper 인터페이스 생성

앞서 생성한 두개의 클래스와 같은 위치에 PostMapper 클래스를 추가하고

다음의 코드를 입력합니다.

package com.study.domain.post;

import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface PostMapper {

    /**
     * 게시글 저장
     * @param params - 게시글 정보
     */
    void save(PostRequest params);

    /**
     * 게시글 상세정보 조회
     * @param id - PK
     * @return 게시글 상세정보
     */
    PostResponse findById(Long id);
    
    /**
     * 게시글 수정
     * @param params - 게시글 정보
     */
    void update(PostRequest params);

    /**
     * 게시글 삭제
     * @param id - PK
     */
    void deleteById(Long id);

    /**
     * 게시글 리스트 조회
     * @return 게시글 리스트
     */
    List<PostResponse> findAll();

    /**
     * 게시글 수 카운팅
     * @return 게시글 수
     */
    int count();

}

 

@Mapper Mapper클래스에서는 이 어노테이션을 필수적으로 선언을 해주어야 합니다. Mapper와 뒤에 만들 XML Mapper를 연결하는 데에 사용됩니다. 
save() 게시글을 생성하는 INSERT 쿼리를 호출합니다.
파라미터로 저장할 게시글 정보를 받습니다
findById() 특정 게시글을 조회하는 SELECT 쿼리를 호출합니다
파라미터로 id를 입력받아 결과값(게시글 정보)이 PostResponse 타입으로 나옵니다.
update() 게시글 정보를 수정하는 UPDATE 쿼리를 호출합니다
파라미터로 수정할 게시글 정보를 받습니다.
deleteByld() 게시글을 삭제하는 UPDATE 쿼리를 호출합니다
파라미터로 id를 받아 쿼리가 실행되면 삭제여부를 나타내는
delete_yn 값을 0(삭제되지 않은 상태)에서 1(삭제된 상태)
로 변경합니다.
findAll() 게시글 목록을 조회하는 SELECT 쿼리를 호출합니다
findByID메서드와 달리 여러 개의 게시글을 리스트 타입으로 리턴받습니다.
count() 전체 개시글 수를 조회하는 SELECT 쿼리를 호출합니다
추후에 다룰 예정입니다.

 

5. Mybatis 플러그인 설치

 

Mybatis 플러그인을 사용하면 Mapper와 XML Mapper 사이의 연동이 쉽고 오류 찾기에 유용합니다

 

인텔리제이에서 Ctrl + Alt + S를 누르면  Settings 창이 나오는데 mybatis를 검색해서

나오는 MybatisX를 Install합니다

 

그 후 XML Mapper를 생성해야 하는데 우선 DatabaseConfig 클래스에서

39번 줄에 주석처리된 부분을 제거합니다

주석처리됐던 부분은 선언된 경로에서 XML Mapper를 찾아 읽는다는 의미입니다.

 

이제 XML Mapper를 만들어야 합니다

src/main/resources 디렉터리에 mappers 폴더를 생성하고 PostMapper.xml 파일을 생성합니다

그 후 다음의 코드를 입력합니다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.study.domain.post.PostMapper">

    <!-- tb_post 테이블 전체 컬럼 -->
    <sql id="postColumns">
          id
        , title
        , content
        , writer
        , view_cnt
        , notice_yn
        , delete_yn
        , created_date
        , modified_date
    </sql>


    <!-- 게시글 저장 -->
    <insert id="save" parameterType="com.study.domain.post.PostRequest">
        INSERT INTO tb_post (
            <include refid="postColumns" />
        ) VALUES (
              #{id}
            , #{title}
            , #{content}
            , #{writer}
            , 0
            , #{noticeYn}
            , 0
            , NOW()
            , NULL
        )
    </insert>


    <!-- 게시글 상세정보 조회 -->
    <select id="findById" parameterType="long" resultType="com.study.domain.post.PostResponse">
        SELECT
            <include refid="postColumns" />
        FROM
            tb_post
        WHERE
            id = #{value}
    </select>


    <!-- 게시글 수정 -->
    <update id="update" parameterType="com.study.domain.post.PostRequest">
        UPDATE tb_post
        SET
              modified_date = NOW()
            , title = #{title}
            , content = #{content}
            , writer = #{writer}
            , notice_yn = #{noticeYn}
        WHERE
            id = #{id}
    </update>


    <!-- 게시글 삭제 -->
    <delete id="deleteById" parameterType="long">
        UPDATE tb_post
        SET
            delete_yn = 1
        WHERE
            id = #{id}
    </delete>


    <!-- 게시글 리스트 조회 -->
    <select id="findAll" resultType="com.study.domain.post.PostResponse">
        SELECT
            <include refid="postColumns" />
        FROM
            tb_post
        WHERE
            delete_yn = 0
        ORDER BY
            id DESC
    </select>

</mapper>

 

XML Mapper와 자바 Mapper가 연동되는 방식

<mapper namespace="com.study.domain.post.PostMapper"> 

 

xml 파일의 mapper 태그에서 namespace 속성에 자바 Mapper 인터페이스의 경로를 선언해주면 연동됩니다

DatabaseConfig 클래스에서 39번째 줄에 선언된 경로가 xml 파일로 연결되고 

xml 파일의 namespace에 선언된 경로로 자바 Mapper로 연동되며

xml 파일에 id와 동일한 이름의 자바 Mapper 인터페이스에 메서드로 연결되어

xml 파일의 sql 쿼리가 실행되는 구조입니다.

DB 테이블 칼럼명과 멤버 변수 이름 매핑

 

xml 파일에서 SELECT 하는 쿼리들은 PostResponse 클래스와 연동되는데

이 때 xml 파일의 칼럼명은 언더바로 연결된 스네이크 케이스이고

PostResponse 클래스의 멤버 변수는 카멜 케이스를 사용해 연동에 어려움이 있습니다

 

그래서 application.properties 파일에 다음의 설정을 추가하여 해결합니다

# column name to camel case
mybatis.configuration.map-underscore-to-camel-case=true

 

6. DatabaseConfig 클래스 수정

스프링이 application.properties에서 바로 위에서 설정한 mybatis 설정을 읽을 수 있도록

DatabaseConfig 클래스를 통해 Bean을 선언해야합니다

 

DatabaseConfig 클래스에서 우선 sqlSessionFactory 메서드에 다음의 한 줄을 추가합니다

factoryBean.setConfiguration(mybatisConfig());

Bean을 이용해 mybatis옵션을 설정한다는 의미입니다

 

그 후 아래 메서드를 추가합니다

 @Bean
    @ConfigurationProperties(prefix = "mybatis.configuration")
    public org.apache.ibatis.session.Configuration mybatisConfig() {
        return new org.apache.ibatis.session.Configuration();
    }

prefix로 선언된 mybatis.configuration으로 시작되는 모든 설정을 읽어

Bean으로 등록한다는 의미입니다

수정된 코드 구성입니다

 

마무리

 - 여기까지가 CRUD와 관련된 작업이였고 처음에는 코드 이해하는 데에도 한참 걸렸는데

   하나씩 차근차근 읽어나가니까 전체적인 흐름도 알게되고 궁금한 것도 생기는 것 같습니다

   sql 쿼리도 처음 봤는데 명확하면서도 복잡한? 그런 느낌이였다

   어림잡아 해석은 가능하지만 공부 해보면 이면에 더 많은게 있을 것 같았다.

   다음에는 MVC 패턴을 처리해볼 것이다!

반응형

'Spring boot' 카테고리의 다른 글

[Spring boot] 게시판 만들기 - MVC 처리하기 (2)  (0) 2025.03.21
[Spring boot] 게시판 만들기 - 게시판 MVC 처리하기 (1)  (0) 2025.03.17
[Spring boot] 게시판 만들기 - 게시판 데이터베이스(Maria DB) 연동하기  (0) 2025.03.04
[Spring boot] 게시판 만들기 - 게시판 프로젝트 구조  (0) 2025.03.01
'Spring boot' 카테고리의 다른 글
  • [Spring boot] 게시판 만들기 - MVC 처리하기 (2)
  • [Spring boot] 게시판 만들기 - 게시판 MVC 처리하기 (1)
  • [Spring boot] 게시판 만들기 - 게시판 데이터베이스(Maria DB) 연동하기
  • [Spring boot] 게시판 만들기 - 게시판 프로젝트 구조
20puddle
20puddle
20puddle 님의 블로그 입니다.
  • 20puddle
    20puddle 님의 블로그
    20puddle
  • 전체
    오늘
    어제
    • 분류 전체보기 (100)
      • Spring boot (5)
      • git & github (5)
      • algorithm (47)
        • theory (3)
        • 배열 (7)
        • 연결 리스트 (3)
        • 스택 (5)
        • 큐 (3)
        • 덱 (2)
        • 기초 코드 (19)
        • BFS (5)
      • AI (43)
        • Machine Learning (35)
        • Deep Learning (8)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

    백준
    Spring Boot
    연결리스트
    홀드아웃 검증
    딥러닝
    인공지능
    게시판
    list
    그레디언트 클리핑
    git
    오프라인 학습
    ML
    주성분변환
    DL
    AI
    머신러닝
    알고리즘
    Aimers
    Java
    github
  • 최근 댓글

  • 최근 글

  • 반응형
  • hELLO· Designed By정상우.v4.10.3
20puddle
[Spring boot] 게시판 만들기 - 게시판 CRUD 처리하기
상단으로

티스토리툴바