게시글 카테고리 기능 설계 - ttasjwi/board-system GitHub Wiki

요구사항

  • 게시글들은 모두 어떤 게시판에 속해 있어야한다.
  • 게시글에는 카테고리가 반드시 필요하다.
  • 각 게시판 별로 '게시글 카테고리'를 여러 개 생성할 수 있다.
    • 게시판 별로 가질 수 있는 게시글 카테고리 갯수 제약이 추가될 가능성이 있긴한데 서비스 구현의 간단화를 위해 일단 당장 고려하지 않는다.

데이터베이스 테이블 설계

CREATE TABLE IF NOT EXISTS article_categories(
    article_category_id    BIGINT      NOT NULL PRIMARY KEY,
    name                   VARCHAR(20) NOT NULL,
    slug                   VARCHAR(8)  NOT NULL,
    board_id               BIGINT      NOT NULL,
    allow_write            BOOLEAN     NOT NULL,
    allow_self_edit_delete BOOLEAN     NOT NULL,
    allow_comment          BOOLEAN     NOT NULL,
    allow_like             BOOLEAN     NOT NULL,
    allow_dislike          BOOLEAN     NOT NULL,
    created_at             DATETIME    NOT NULL,

    CONSTRAINT uq_board_id_and_name UNIQUE (board_id, name),
    CONSTRAINT uq_board_id_and_slug UNIQUE (board_id, slug)
);
  • article_category_id : 식별자
  • name : 이름
  • slug : 구분 영문자(게시판 내에서 카테고리 구분)
    • 예) general -> https://board-system.com/b/animal?category=general
  • board_id : 소속 게시판
  • allow_write : 일반 사용자가 게시글을 작성할 수 있는 지 여부
  • allow_self_edit_delete : 일반 사용자가 자신의 게시글을 수정/삭제할 수 있는 지 여부
    • 대표적인 활용례: 질문글을 올려놓고, 사용자들의 답을 받은 뒤 질문글을 삭제하는 악성 유저들을 방지하기 위한 정책
  • allow_comment : 일반 사용자의 댓글 허용 여부
  • allow_like : 일반 사용자의 좋아요 가능 여부
  • allow_dislike : 일반 사용자의 싫어요 가능 여부
  • created_at 생성일
  • 유니크 제약조건
    • (board_id, name) : 게시판별로 게시글 카테고리 이름은 내부적으로 중복 허용 x
    • (board_id, slug) : 게시판별로 게시글 카테고리 슬러그는 내부적으로 중복 허용 x

도메인 엔티티


class ArticleCategory(
    val articleCategoryId: Long,
    val boardId: Long,
    name: String,
    val slug: String,
    allowWrite: Boolean,
    allowSelfEditDelete: Boolean,
    allowComment: Boolean,
    allowLike: Boolean,
    allowDislike: Boolean,
    val createdAt: AppDateTime
) {

    var name: String = name
        private set

    var allowWrite: Boolean = allowWrite
        private set

    var allowSelfEditDelete: Boolean = allowSelfEditDelete
        private set

    var allowComment: Boolean = allowComment
        private set

    var allowLike: Boolean = allowLike
        private set

    var allowDislike: Boolean = allowDislike
        private set

    companion object {

        fun create(
            articleCategoryId: Long,
            boardId: Long,
            name: String,
            slug: String,
            allowWrite: Boolean,
            allowSelfEditDelete: Boolean,
            allowComment: Boolean,
            allowLike: Boolean,
            allowDislike: Boolean,
            createdAt: AppDateTime
        ): ArticleCategory {
            return ArticleCategory(
                articleCategoryId = articleCategoryId,
                boardId = boardId,
                name = name,
                slug = slug,
                allowWrite = allowWrite,
                allowSelfEditDelete = allowSelfEditDelete,
                allowComment = allowComment,
                allowLike = allowLike,
                allowDislike = allowDislike,
                createdAt = createdAt
            )
        }

        fun restore(
            articleCategoryId: Long,
            boardId: Long,
            name: String,
            slug: String,
            allowWrite: Boolean,
            allowSelfEditDelete: Boolean,
            allowComment: Boolean,
            allowLike: Boolean,
            allowDislike: Boolean,
            createdAt: LocalDateTime
        ): ArticleCategory {
            return ArticleCategory(
                articleCategoryId = articleCategoryId,
                boardId = boardId,
                name = name,
                slug = slug,
                allowWrite = allowWrite,
                allowSelfEditDelete = allowSelfEditDelete,
                allowComment = allowComment,
                allowLike = allowLike,
                allowDislike = allowDislike,
                createdAt = AppDateTime.from(createdAt)
            )
        }
    }

    override fun toString(): String {
        return "ArticleCategory(articleCategoryId=$articleCategoryId, name='$name', slug='$slug', boardId=$boardId, allowWrite=$allowWrite, allowSelfEditDelete=$allowSelfEditDelete, allowComment=$allowComment, allowLike=$allowLike, allowDislike=$allowDislike, createdAt=$createdAt)"
    }
}