"본 포스팅은 [원 블로그]의 내용을 참고하여 개인 학습 목적으로 작성되었습니다.
원 저작자의 권리를 존중하며,
내용 수정이나 삭제 요청이 있을 시 즉시 조치하겠습니다."
오늘은 소프트웨어 개발에서
데이터를 처리하는
가장 기본적인 작업인 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 |
