본문 바로가기
Spring Boot Project/Plming

[Plming] 게시판 CRUD 처리하기

by slchoi 2022. 3. 25.
728x90
SMALL

개발을 시작하기 전에

현재 생성된 DB 모델 안에서 게시판과 관련된 table을 확인한다.

1. post 테이블

post 테이블의 column

column 설명
id 게시글 id
user id 게시글을 작성한 사용자 id
title 게시글 제목
category 게시글 카테고리(스터디, 공모전, 프로젝트)
staus 게시글 상태 (모집 중, 모집 완료)
participant_num 참여 인원
period 진행 기간
view_count 게시글 조회수
create_date 게시글 생성 날짜
update_date 게시글 수정 날짜

 

2. post_tag 테이블

column 설명
id post_tag의 id
post_id tag가 붙은 post의 id
tag_id tag 테이블에서 post에 붙은 tag의 id

 

3. tag 테이블

column 설명
id tag의 id
name tag 이름

 

1. 도메인 클래스 생성하기

게시판(post)의 구조화 역할을 수행하는 클래스를 생성한다. 일반적으로 테이블 구조화 클래스는 xxxDTO 또는 xxxVO로 naming 하는데, VO는 Read Only의 특성을 갖는다고 한다.

따라서 post 테이블은 입력받은 데이터의 저장 및 전송을 의미하는 xxxDTO로 naming을 진행한다.

먼저 plming.board 패키지 안에 controller, domain, mapper, service 네 개의 패키지를 추가한다.

그다음, domain 패키지 안에 PostDTO 클래스를 추가하고, 아래의 코드를 작성한다.

package plming.board.domain;

import lombok.Getter;
import lombok.Setter;

import java.time.LocalDateTime;

@Getter @Setter
public class PostDTO {

    /** 게시글 번호 (PK) */
    private Long id;

    /** 작성자  */
    private String writer;

    /** 카테고리 */
    private String category;

    /** 모집 상태 */
    private String status;

    /** 진행 기간 */
    private Integer period;

    /** 제목 */
    private String title;

    /** 내용 */
    private String content;

    /** 조회수 */
    private int viewCnt;

    /** 생성 시간 */
    private LocalDateTime insertTime;

    /** 수정 시간 */
    private LocalDateTime updateTime;
    
    /** 삭제 여부 */
    private String deleteYn;
}

 

클래스 레벨에 지정된 @Getter, @Setter는 Lombok이라는 라이브러리가 제공해주는 기능이다. @Getter, @Setter를 사용하지 않을 경우 모든 변수들에 대해 getter와 setter 코드를 추가해주어야 한다. 이럴 경우 코드의 길이가 길어지기도 하고 보기에도 깔끔하지 않으므로 @Getter, @Setter 기능을 사용한다.

테스트용 DB 생성

plming에 connection 한 뒤 기존에 생성해둔 테이블을 모두 삭제한 뒤, post 테이블만 다시 생성한다.

CREATE TABLE `post` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user` varchar(50) NOT NULL COMMENT '작성자',
  `title` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '제목',
  `category` enum("study", "project", "contest") NOT NULL COMMENT '카테고리',
  `status` enum("모집 중", "모집 완료") NOT NULL COMMENT '모집상태',
  `participant_num` tinyint(4) COMMENT '모집인원수',
  `period` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '예상모임기간',
  `content` varchar(500) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '내용',
  `view_cnt` mediumint(9) NOT NULL COMMENT '조회수',
  `create_date` datetime NOT NULL COMMENT '생성일자',
  `update_date` datetime NULL COMMENT '마지막수정일자',
  `delete_yn`, varchar(5) NOT NULL DEFAULT 'N' COMMENT '삭제여부',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

 

delete_yn 칼럼은 실제로 데이터를 삭제하지 않고, 칼럼의 상태를 'Y', 'N'으로 지정해 상태 값이 'N'으로 지정된 데이터만 노출하게 하는 역할이다.

정말 중요한 데이터가 테이블에서 DELETE 되어버리면 손실이 크기 때문에 최근에는 이런 방법을 많이 사용한다고 한다.

기존에 생성해둔 테이블에서 테스트 코드를 돌리려면 외래키 등 설정해야 할 것이 많아 우선은 post 테이블만 생성한 DB 환경에서 테스트를 진행한다.


2. Mapper 인터페이스 생성하기

Mapper 인터페이스는 데이터베이스와의 통신 역할을 수행한다.

mapper 패키지에 PostMapper 인터페이스를 생성하고, 아래 코드를 작성한다.

package plming.board.mapper;

import org.apache.ibatis.annotations.Mapper;
import plming.board.domain.PostDTO;

import java.util.List;

@Mapper
public interface PostMapper {

    public int insertPost(PostDTO post);

    public int updatePost(PostDTO post);

    public int deletePost(Long id);

    public PostDTO selectPostDetail(Long id);

    public List<PostDTO> selectPostList();

    public int selectPostTotalCount();
}

 

애너테이션 및 메서드 설명
@Mapper 기존 스프링은 DAO(Data Access Object) 클래스에 @Repository를 선언해 해당 클래스가 데이터베이스와 통신하는 클래스임을 나타냈다.

마이바티스는 인터페이스에 @Mapper만 지정해주면 XML Mapper에서 메서드의 이름과 일치하는 SQL문을 찾아 실행한다.

Mapper 영역은 SQL 쿼리를 호출하는 것이 전부이며 다른 로직에서는 필요하지 않다.
insertPost 게시글을 생성하는 INSERT 쿼리를 호출하는 메서드

파라미터로는 PostDTO 클래스가 post라는 이름으로 지정되고 params에는 게시글의 정보가 담긴다.
updatePost 게시글을 수정하는 UPDATE 쿼리를 호출하는 메서드

파라미터로 PostDTO 클래스가 post라는 이름으로 들어오고, insertPost 메서드와 마찬가지로 post에 게시글의 정보가 담긴다.
deletePost 게시글을 삭제하는 DELETE 쿼리를 호출하는 메서드

post 테이블에서 delete_yn 컬럼을 활용해 게시글 삭제 상태를 관리

파라미터로 게시글 번호(id)를 전달받으며 WHERE 조건으로 id를 사용해 특정 게시글을 삭제(상태 값 변경)한다.
selectPostDetail 하나의 게시글을 조회하는 SELECT 쿼리를 호추하는 메서드

SELECT 쿼리가 실행되면, 각 컬럼에 해당하는 결과값이 PostDTO 클래스의 멤버 변수에 매핑되어 리턴된다.

파라미터로는 게시글 번호(id), 즉 PK를 전달받으며, WHERE 조건으로 id를 사용해 특정 게시글을 조회한다. 
selectPostList 게시글 목록을 조회하는 SELECT 쿼리를 호출하는 메서드

리턴 타입으로 List<PostDTO>를 지정해 List에 모든 게시글 정보를 담아 반환한다.
selectBoardTitalCount 삭제 여부(delete_yn)가 'N'으로 지정된 게시글의 개수를 조회하는 SELECT 쿼리를 호출하는 메서드

나중에 페이징 처리를 진행하면서 사용된다.

리턴 타입

게시글 생성, 수정, 삭제 메서드의 리턴 타입을 int로 지정했다. 일반적으로는 void를 리턴 타입으로 같은 경우가 많다.

하지만, service 영역에서 Mapper 영역의 메서드를 호출하고, SQL 실행에 대한 결괏값을 확실하게 전달받기 위해 int로 처리한다.


PostMapper 인터페이스와 SQL문 연결을 위해 XML Mapper에 SQL문을 작성한다.

'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="plming.board.mapper.PostMapper">
    <sql id="postColumns">
        id, user, title, category, status, participant_num, period,
        content, view_cnt, create_date, update_date, delete_yn
    </sql>

    <insert id="insertPost" parameterType="PostDTO">
        INSERT INTO post (<include refid="postColumns" />)
        VALUES (
                #{id}, #{user}, #{title}, #{category}, #{status}, 0, #{period},
                #{content}, 0, NOW(), NULL, 'N'
        )
    </insert>

    <select id="selectPostDetail" parameterType="long" resultType="PostDTO">
        SELECT <include refid="postColumns" />
        FROM post
        WHERE delete_yn = 'N'
        AND id = #{id}
    </select>

    <update id="updatePost" parameterType="PostDTO">
        UPDATE post
        SET update_date = NOW(), title = #{title},
            content = #{content}, user = #{user}
        WHERE id = #{id}
    </update>

    <update id="deletePost" parameterType="long">
        UPDATE post
        SET delete_yn = 'Y'
        WHERE id = #{id}
    </update>

    <select id="selectPostList" parameterType="PostDTO" resultType="PostDTO">
        SELECT <include refid="postColumns"/>
        FROM post
        WHERE delete_yn = 'N'
        ORDER BY id DESC, create_date DESC
    </select>

    <select id="selectPostTotalCount" parameterType="PostDTO" resultType="int">
        SELECT COUNT(*)
        FROM post
        WHERE delete_yn = 'N'
    </select>

</mapper>

 

코드 작성 후에 <statement> or DELIMITER expected, got 'id'라는 오류가 발생했다.

File > Settings > Language Injections의 "MyBatis sql|select|insert|update|delete​" 파일에 들어가서 XML Tag의 Local name을 'select|insert|update|delete'로 변경('sql|' 삭제)해주면 오류가 사라졌다.

 

코드를 살펴보면

태그 및 속성 설명
<mapper> MyBatis에서 SQL 쿼리 문이 정의되어 있는 파일을 XML Mapper라고 한다.

태그의 시작과 끝 사이에는 쿼리문과 관련된 여러 태그가 존재하는데, 이 중 <mapper> 태그를 여는 부분의 namespace 속성에는 PostMapper 인터페이스의 경로가 지정되어 있다.

namespace는 XML Mapper의 SQL 쿼리문과 Mapper 인터페이스의 메서드를 매핑하기 위해 지정하는 속성이다. 
<sql> MyBatis는 <sql> 태그를 이용해 태그의 시작과 끝 사이에 공통으로 사용되거나, 반복적으로 사용되는 SQL 조각을 정의할 수 있다.

게시판 테이블의 전체 컬럼을 SQL 조각으로 정의해서 PostColumns라는 이름으로 사용한다.
<include> <sql> 태그에 정의한 PostColumns SQL 조각의 include에 사용되는 태그
parameterType 쿼리의 실행에 필요한 파라미터의 타입을 지정
resultType 쿼리의 실행 결과를 매핑할 타입을 지정
파라미터 표현식 전달받은 파라미터는 #{ } 표현식을 사용해서 처리한다.

3. MyBatis SELECT 칼럼과 DTO 멤버 변수 매핑하기

MyBatis에서 SELECT 쿼리의 결과 칼럼은 DTO 클래스의 멤버 변수와 매핑된다.

XML Mapper의 PostColumns SQL 조각은 Alias(별칭) 처리를 하지 않고, 테이블의 칼럼명과 같이 '_'로 연결하는 스네이크 케이스를 사용한다.

하지만, 자바에서 변수의 이름은 소문자로 시작하고, 단어가 이어지는 경우는 이어지는 단어의 앞 글자만 대문자로 처리하는 카멜 케이스를 사용한다.

이런 경우, MyBatis의 map-underscore-to-camel-case 설정을 사용해 자동으로 매핑되도록 처리할 수 있다.

application.properties에 아래 설정을 추가한다.

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

 

DBConfiguration 클래스 처리하기

MyBatis 설정이 추가되었으니 해당 설정을 처리할 빈(Bean)을 정의해야 한다.

DBConfiguration 클래스를 더보기의 코드와 같이 변경한다.

더보기
package plming.board.configuration;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

@Configuration
@PropertySource("classpath:/application.properties")
public class DBConfiguration {

    @Autowired
    private ApplicationContext applicationContext;

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public HikariConfig hikariConfig() {
        return new HikariConfig();
    }

    @Bean
    public DataSource dataSource() {
        return new HikariDataSource(hikariConfig());
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource());
		factoryBean.setMapperLocations(applicationContext.getResources("classpath:/mappers/**/*Mapper.xml"));
        factoryBean.setTypeAliasesPackage("plming.board.domain");
        factoryBean.setConfiguration(mybatisConfig());
        return factoryBean.getObject();
    }

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

    @Bean
    public SqlSessionTemplate sqlSession() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory());
    }

}

 

메서드  설명
serMapperLocations 기존에 주석 처리되어 있던 부분

getResources 메서드의 인자로 지정된 패턴에 포함되는 XML Mapper를 인식하도록 하는 역할

기존에는 XML Mapper가 없었지만, 이제 PostMapper XML이 추가되었기 때문에 해당 파일을 인식할 수 있도록 주석을 해제했다.
setTypeAliasesPackage BoardMapper XML에서 parameterType과 resultType은 클래스의 풀 패키지 경로가 포함되어야 한다.

코드에서는 PostDTO와 같이 클래스의 이름만 지정했는데, 이 메서드를 사용하면 풀 패키지 경로를 생략할 수 있다.
mybatisConfig applicattion.properties에서 mybatis.configuration으로 시작하는 모든 설정을 읽어들여 bean으로 등록한다.
setConfiguration mybatisConfig에서 추가된 마이바티스 설정과 관련된 bean을 설정 파일로 지정한다.

4. CRUD 테스트하기

4.1. CREATE 테스트

게시글을 생성하는 insertPost 메서드를 테스트할 것이다.

Mapper 영역의 테스트를 진행하기 위해 'src/test/java/' 디렉터리의 'plming/board' 패키지에 MapperTest 클래스를 생성하고, 아래 코드를 작성한다.

package plming.board;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import plming.board.domain.PostDTO;
import plming.board.mapper.PostMapper;

@SpringBootTest
public class MapperTest {

    @Autowired
    private PostMapper postMapper;

    @Test
    public void createPostTest() {
        PostDTO post = new PostDTO();
        post.setTitle("1번 게시글 제목");
        post.setContent("1번 게시글 제목");
        post.setUser("사용자1");
        post.setCategory("study");
        post.setPeriod("1개월");
        post.setStatus("모집 중");

        int result = postMapper.insertPost(post);
        System.out.println("결과는 " + result + "입니다.");
    }
}

 

테스트를 실행해보면 잘 돌아가는 것을 확인할 수 있다.

createPost 메서드 테스트 결과

 

DB에 들어가서 post 테이블의 모든 내용을 SELECT 해보면 입력한 내용에 맞게 잘 들어간 것을 확인할 수 있다. (테스트를 2번 실행해서 값이 두 개가 들어갔다.)

post table 확인

 

MapperTest 코드를 살펴보면 

변수 및 메서드 설명
postMapper @Autowired를 이용해 PostMapper 인터페이스 bean을 주입한다.
createTest 게시글 생성을 처리하는 메서드

태이블 구조화 클래스인 PostDTO 객체를 생성하고, set 메서드를 이용해 게시글에 들어갈 정보를 지정한다.

PostMapper 인터페이스의 insertPost 메서드의 인자로 게시글 정보가 저장된 post를 전달한다.

PostMapper XML에서 insertPost의 id는 insertPost, parameterType은 PostDTO로 지정되어 있다. 여기서의 id는 <mapper> 태그의 namespace 속성에 지정된 PostMapper 인터페이스의 insertPost 메서드를 의미하며, parameterType은 쿼리의 실행에 필요한 파라미터의 타입을 의미한다. (여기서는 PostDTO)

Values에서 PostDTO 객체를 생성하고, set 메서드를 이용해 값을 지정한 게시글 정보가 파라미터 표션식 '#{ }'으로 처리된다.

#{id}의 경우, DB에서 post 테이블을 생성하면서 AUTO_INCREMENT 속성을 지정해 PK가 자동으로 1씩 증가하게 설정해두었기 때문에 따로 값을 지정해주지 않아도 된다.

 

4.2. READ Case 1 테스트

게시글을 조회하는 경우는 두 가지가 있다.

  • Case 1: 하나의 게시글을 조회하는 selectPostDetail 메서드
  • Case 2: 전체 게시글을 조회하는 selectPostList 메서드

Case 2에서는 삭제되지 않은 게시글을 전부 조회하도록 해야 하므로 게시글을 삭제하는 deletePost 메서드를 테스트한 후에 selectPostList 메서드를 테스트할 것이다.

지금은 하나의 게시글을 조회하는 기능을 하는 selectPostDetail 메서드를 테스트한다.

조금 전에 생성한 MapperTest에 메서드 하나를 추가한다.

@Test
    public void selectPostDetailTest() {
        PostDTO post = postMapper.selectPostDetail((long) 2);
        try {
            String postJson = new ObjectMapper().registerModule(new JavaTimeModule())
                                .writeValueAsString(post);

            System.out.println("=====================");
            System.out.println("boardJson = " + postJson);
            System.out.println("=====================");

        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

 

테스트를 실행해보면 결과로 게시글 id가 2번인 게시글의 정보를 잘 불러오는 것을 확인할 수 있다.

selectPostDetail 메서드 테스트

테스트 코드를 살펴보면

메서드 설명
selectPostDetail PostDTO 타입의 객체 변수인 post에 selectPostDetail 메서드의 결과를 저장한다.

인자로 지정된 '(long) 2'는 createPost 메서드를 테스트할 때 추가한 2번 게시글의 PK에 해당하는 id를 의미한다.

try 문에서는 post에 저장된 게시글 정보를 Jackson 라이브러리를 이용해 JSON 문자열로 변경한 뒤 콘솔에 출력한다.

PostMapper XML에서 selectPostDetail의 parameterType은 long, resultType은 PostDTO로 지정되어 있다. parameterType은 post 테이브의 PK인 id의 타입이고, resultType은 post 테이블의 구조화 클래스인 PostDTO를 의미한다.

 

4.3. UPDATE 테스트

등록되어 있는 게시글의 정보를 수정하는 udatePost 메서드를 테스트할 것이다.

게시글 생성과 수정의 차이는 없었던 데이터를 생성해 새로운 게시글을 등록(INSERT)하는 것인지 아님 기존에 있던 데이터를 갱신한 뒤 수정된 게시글을 등록(UPDATE)하는 것인지의 차이이다. INSERT와 UPDATE는 PK의 유무로 구분할 수 있다. 

UPDATE와 INSERT의 차이는 크지 않기 때문에 일반적으로 서비스 영역에 게시글 등록을 처리하는 비즈니스 로직은 하나의 메서드로 INSERT와 UPDATE를 구분해서 처리한다.

updatePost 메서드를 테스트하기 위해 MapperTest 코드에 아래 메서드를 추가한다.

   @Test
   public void updatePostTest() {
        PostDTO post = new PostDTO();
        post.setTitle("2번 게시글 제목 수정");
        post.setContent("2번 게시글 내용 수정");
        post.setUser("사용자2");
        post.setId((long) 2);

        int result = postMapper.updatePost(post);
        if (result == 1) {
            PostDTO cpPost = postMapper.selectPostDetail((long) 2);
            try {
                String postJson = new ObjectMapper()
                        .registerModule(new JavaTimeModule())
                        .writeValueAsString(cpPost);
                System.out.println("================");
                System.out.println(postJson);
                System.out.println("================");
            }
            catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }

 

테스트를 실행해보면 2번 게시글의 정보가 변경되었고, 변경된 내용을 콘솔에 출력해주는 것을 확인할 수 있다.

updatePostTest 메서드 테스트 결과

DB에서도 정보가 잘 변경된 것을 확인할 수 있다.

update 전
update 후

테스트 코드를 살펴보면

메서드 설명
updatePostTest 게시글 생성과 똑같이 PostDTO 객체를 생성하고, set 메서드를 이용해 수정할 제목, 내용, 작성자, 게시글 번호 지정한다.

result에는 UPDATE 쿼리가 실행된 횟수가 저장된다.

if 안의 로직은 selectPostDetailTest 메서드와 동일하다. 게시글이 수정되면, 수정된 게시글 정보를 JSON 문자열로 출력한다.

 

4.4. DELETE 테스트

게시글 삭제를 처리하는 deletePost 메서드를 테스트해볼 것이다.

deletePost는 실제로 데이터를 삭제하는 것이 아니라 delete_yn의 값만 변경하는 것이므로 PostMapper XML에서 deletePost는 <update> 태그를 사용한다.

deletePost 메서드를 테스트하기 위해 MapperTest 코드에 아래 메서드를 추가한다.

@Test
public void deletePostTest() {
    int result = postMapper.deletePost((long) 2);
    if (result == 1) {
        PostDTO post = postMapper.selectPostDetail((long) 2);
        try {
            String postJson = new ObjectMapper()
                    .registerModule(new JavaTimeModule())
                    .writeValueAsString(post);

            System.out.println("======================");
            System.out.println(postJson);
            System.out.println("======================");
        }
        catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}

 

테스트를 실행해보면 결괏값이 null이므로 잘 실행된 것을 확인할 수 있다.

deletePostTest 메서드 테스트 결과

DB에서 2번 게시물의 결과를 보면 delete_ys의 값이 'N'에서 'Y'로 잘 변경된 것을 확인할 수 있다.

delete 전
delete 후

 

코드를 살펴보면

메서드 설명
deletePostTest deletePost 메서드의 인자로 게시글 번호(id)를 지정한다.

if문 안의 로직은 selectPostDetailTest 메서드와 동일하다.

selectPostDetail 메서드의 WHERE 절에는 delete_yn='N' 조건이 자동으로 적용되어 있기 때문에 boardJson은 null을 반환한다.

 

4.5. READ Case 2 테스트

현재는 게시글이 2개밖에 없기 때문에 for문을 이용해 게시글을 여러 개 추가한 뒤 테스트를 진행할 것이다.

우선 createPostTest 메서드를 아래 코드로 변경한 뒤 메서드를 실행시키고 DB에서 데이터가 잘 추가되었는지 확인한다.

@Test
public void createPostTest() {
    for(int i = 3; i <= 50; i++) {
        PostDTO post = new PostDTO();
        post.setTitle(i + "번 게시글 제목");
        post.setContent(i + "번 게시글 내용");
        post.setUser("사용자" + i);
        post.setCategory("study");
        post.setPeriod(i + "개월");
        post.setStatus("모집 중");
        postMapper.insertPost(post);
    }
}

 

DB에서 테스트 결과 확인

이제 deletePost 메서드를 테스트하기 위해 MapperTest 코드에 아래 코드를 추가한다.

@Test
public void selectPostListTest() {
    int postTotalCount = postMapper.selectPostTotalCount();
    if (postTotalCount > 0) {
        List<PostDTO> postList = postMapper.selectPostList();
        if (CollectionUtils.isEmpty(postList) == false) {
            for(PostDTO post : postList){
                System.out.println("=================");
                System.out.println(post.getTitle());
                System.out.println(post.getContent());
                System.out.println(post.getUser());
                System.out.println("=================");
            }
        }
    }
}

 

테스트를 실행시켜보면 deletePostTest에서 제거한 2번 게시물을 제외하고 나머지 모든 게시물이 출력되는 것을 확인할 수 있다.

selectPostListTest 메서드 테스트 결과

 

테스트 코드를 살펴보면

메서드 설명
selectPostListTest postTotalCount에 삭제되지 않은 전체 게시글의 수를 저장해서 카운팅하고, 게시글이 한 개 이상이면 제네릭 타입의 변수인 postList에 selectPostList 메서드의 실행 결과에 해당하는 게시글 목록을 저장한다.

if 문에서는 스프링에서 지원해주는 CollectionUtil의 isEmpty 메서드를 이용해 boardList가 비어있지 않은지 체크하고, forEach를 실행해서 boardList에 저장된 게시글의 순서대로 게시글 제목, 내용, 작성자를 출력한다.

 

본 프로젝트는 아래 블로그 링크를 참고해 개발했습니다.
https://congsong.tistory.com/15?category=749196
728x90
LIST

댓글