ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • <프리보드 게시판> RestController - Service - Repository & CommandLineRunner 연결하기
    토이프로젝트/프리보드 게시판 (Spring Boot) 2022. 12. 22. 17:21

    https://github.com/kjm99d/FreeBoard-Backend

     

    GitHub - kjm99d/FreeBoard-Backend: 프리보드 게시판

    프리보드 게시판. Contribute to kjm99d/FreeBoard-Backend development by creating an account on GitHub.

    github.com

     

    이 프로젝트는 Spring Boot로 만들어보는 게시판이다.

    RestAPI를 통해 API 요청을 받고, 게시글 작성 및 수정, 삭제 기능을 제공한다.

    해당 게시판은 단순 게시글을 보여주는 목적이 아닌, 다양한 데이터 포맷을 기반으로하는 새로운 API 게이트웨이 역할을 한다.

     

     

    기본적인 시나리오는 다음과 같다.

    일반적인 커뮤니티와 마찬가지로,

     

    1. 사용자는 회원가입을 진행한다.

    2. A사용자는 로그인을 한다.

    3. A사용자는 게시글을 발행한다.

    4. 비밀글 발행 옵션를 선택한다.

    5. 해당 게시글은 단독적인 API키가 존재한다.

    6. 해당 API키를 사용하여 데이터를 요청할 경우, 데이터를 응답하고, API가 일치하지 않는 경우 에러코드를 응답한다.

     

    이러한 로직으로써 게시판에 작성된 글 하나를 단독적인 API 응답데이터 처럼 사용할 수 있도록 한다.

     

    우선적으로 큰 스켈레톤을 구성했다.

    게시글을 작성하는 사용자 정보

    더보기
    package com.project.freeboard.domain.entity;
    
    import jakarta.persistence.*;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;
    
    @Entity(name = "MEMBER")
    @Getter
    @Setter
    @NoArgsConstructor
    public class MemberEntity {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        @Column(unique = true)
        private String username;
    
        @Column
        private String password;
    
        @Column(unique = true)
        private String email;
    
        public MemberEntity(String username, String password, String email) {
            this.username = username;
            this.password = password;
            this.email = email;
        }
    }

    게시글이 작성될 게시판 카테고리

    더보기
    package com.project.freeboard.domain.entity;
    
    
    import jakarta.persistence.*;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;
    
    import java.util.List;
    
    @Entity(name = "CATEGORY")
    @Getter
    @Setter
    @NoArgsConstructor
    public class CategoryEntity {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        @Column
        private String name;
    
        @OneToMany
        private List<PostEntity> postList;
    
        public CategoryEntity(String name) {
            this.name = name;
        }
    }

    하나의 카테고리에 작성될 게시글

    더보기
    package com.project.freeboard.domain.entity;
    
    import com.project.freeboard.domain.ContentType;
    import jakarta.persistence.*;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;
    
    @Entity(name = "POST")
    @Getter
    @Setter
    @NoArgsConstructor
    public class PostEntity {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        @ManyToOne
        @JoinColumn(name = "CATEGORY_ID")
        private CategoryEntity category;
    
        @ManyToOne
        @JoinColumn(name = "MEMBER_ID")
        private MemberEntity writer;
    
        @Column
        private boolean secret; // 비밀글 여부
    
        @Column
        private String subject;
    
        @Column
        @Enumerated(EnumType.STRING)
        private ContentType contentType;
    
        @Column
        private String content;
    
        public PostEntity(CategoryEntity category, MemberEntity writer, boolean secret, String subject, ContentType contentType, String content) {
            this.category = category;
            this.writer = writer;
            this.secret = secret;
            this.subject = subject;
            this.contentType = contentType;
            this.content = content;
        }
    
        // 댓글 .. ?
    
    }

    3개의 Entity를 구성하였다.

     

    이후 Repository는 추가적인 작업 없이 기본 JpaRepository를 사용했다.

    이후에, CommandLineRunner의 경우 다음과 같이 작성되었다.

    @Order(1)
    @Component
    @RequiredArgsConstructor
    .
    .
    .
    memberRepository.save(new MemberEntity("userA", "userApassword", "userA@naver.com"));
    memberRepository.save(new MemberEntity("userB", "userBpassword", "userB@naver.com"));
    memberRepository.save(new MemberEntity("userC", "userCpassword", "userC@naver.com"));
            postRepository.save(new PostEntity(
                    categoryRepository.findByName("Category1").get(),
                    memberRepository.findByUsername("userA").get(),
                    false,
                    "Hello World",
                    ContentType.TYPE_STRING,
                    "abcdefgh"
                    ));

     

    Order 어노테이션을 통해, CommandLineRunner가 실행되는 순서를 정의하여,

    임시사용자 추가 → 임시 카테고리 추가 → 임시 게시글 추가

    해당 순서대로 하여 Runtime Crash를 방지하였다.

     

    Component 어노테이션 사용을 통해, 컴포넌트스캔의 대상이 되도록 지정하였고,

    RequireArgsConstructor 어노테이션 사용을 통해, private | @NotNull 처리가 된 필드변수에 대하여 AutoInjection이 동작하도록 하였다.

     

    일단 ER다이어그램은 저런 형태로 나왔다.

    각 카테고리에서는 글을 조회하고, 각 글은 하나의 카테고리에 존재하니,

    카테고리 상에서도 게시글을 조회해야하고, 게시글 내에도 카테고리에 대한 정보가 존재해야한다.

     

    그러므로 1:N & N:1 양방향 관계를 취했다.

    이후 각각의 멤버는 글을 쓸 수 있으므로, 게시글 엔티티와 연관관계를 맺어주었다.

     

     

    ---

    뭔가 여기까지 하면서 느낀건 테스트코드를 Runner에다가 작성하는 듯한 느낌이 든다..

    조금 귀찮긴해도 테스트코드를 테스트영역을 나눠서 직접 만들어 줘야할 것 같다.

    댓글

Designed by Tistory.