[클론 코딩] 네이버 카페 - (통합게시판) 게시글 작성

2024. 5. 30. 23:26Project/Naver Cafe

  통합 게시판을 구현해 두었으니 해당 게시판에 게시글을 작성할 수 있도록 '게시글 작성' 기능을 구현할 것이다. 그리고 더불어 사용자가 게시글을 작성할 수 있게 양식을 제공할 때 사용되는 기본 데이터를 전달하는 기능 또한 구현할 생각이다.

 

  게시판 - 게시글의 관계는 네이버 카페 시스템을 기준으로 하면 게시판 보다 게시글이 더 자유롭다. 무슨 말이냐면 게시글이 있는 게시판은 기능에 제한이 생긴다. 간단한 예로 게시글이 있는 게시판은 삭제가 불가능하다. 그리고 게시판은 다양한 정보를 수정할 순 있지만 게시판의 타입은 수정할 수 없다. 이러한 부분 때문에 두 엔티티의 연관관계를 설정하지 않고 각각의 엔티티를 Cafe 엔티티와 연관관계를 지었다.


Normal

package CloneCoding.NaverCafe.domain.article.normal;

import java.time.LocalDateTime;

@Entity
@Table(name = "NORMAL_ARTICLE")
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Normal {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "MENU_ID")
    private Long menuId;

    @Column(name = "TITLE")
    private String title;

    @Column(name = "TITLE_HEADER")
    private String titleHeader;

    @Column(name = "BODY")
    private String body;

    @Column(name = "NOTICE")
    private boolean notice;

    @Column(name = "ALLOW_COMMENT")
    private boolean allowComment;

    @Column(name = "ACCOUNT_ID")
    private String accountId;

    @Column(name = "NICKNAME")
    private String nickname;

    @Column(name = "CREATE_AT")
    private LocalDateTime createAt;

    @Column(name = "VIEW_COUNT")
    @Builder.Default
    private int viewCount = 0;

    @Column(name = "COMMENT_COUNT")
    @Builder.Default
    private int commentCount = 0;

    @Column(name = "FAVORITE_COUNT")
    @Builder.Default
    private int favoriteCount = 0;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "CAFE_ID")
    private Cafe cafeId;

    public static Normal create(RequestWriteNormal request, CafeMember cafeMember) {

        LocalDateTime now = LocalDateTime.now();

        return Normal.builder()
                .menuId(request.getMenuId())
                .title(request.getTitle())
                .titleHeader(request.getTitleHeader())
                .body(request.getBody())
                .notice(request.isNotice())
                .allowComment(request.isAllowComment())
                .accountId(cafeMember.getAccountId())
                .nickname(cafeMember.getNickname())
                .createAt(now)
                .cafeId(cafeMember.getCafeId())
                .build();
    }

}

 

  • create() : 요청 정보와 카페 회원 정보로 Normal 객체를 생성하고 반환

ResponseWriteFormNormal

package CloneCoding.NaverCafe.domain.article.normal.dto;

import static CloneCoding.NaverCafe.domain.article.normal.enums.BasicData.*;

@Getter
public class ResponseWriteFormNormal {

    public ResponseWriteFormNormal() {
        this.menu = MENU.getValue();
        this.titleHeader = TITLE_HEADER.getValue();
        this.title = TITLE.getValue();
        this.body = BODY.getValue();
        this.tag = TAG.getValue();
    }

    private final String menu;

    private final String titleHeader;

    private final String title;

    private final String body;

    private final String tag;

}

 

  일반 타입의 게시글 양식에 필요한 데이터를 전달하는 DTO 클래스이다.


BasicData

package CloneCoding.NaverCafe.domain.article.normal.enums;

@Getter
@RequiredArgsConstructor
public enum BasicData {

    CURRENT_ACTIVITY("카페 글쓰기"),
    MENU("게시판을 선택해 주세요."),
    TITLE_HEADER("말머리 선택"),
    TITLE("제목을 입력해 주세요."),
    BODY("내용을 입력하세요."),
    TAG("# 태그를 입력해 주세요. (최대 10개)"),
    ;

    private final String value;

}

 

  일반 타입의 게시글 양식에 필요한 기본 데이터를 상수로 갖는 Enum 클래스이다.


RequestWriteNormal

package CloneCoding.NaverCafe.domain.article.normal.dto;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class RequestWriteNormal {

    @NotNull
    private Long menuId;

    @NotNull
    private String title;

    @NotNull
    private String titleHeader;

    @NotNull
    private String body;

    @NotNull
    private List<String> tags = new ArrayList<>();

    @NotNull
    private boolean notice;

    @NotNull
    private boolean allowComment;

}

 

  일반 타입 게시글 작성 정보를 전달하는 DTO 클래스이다.


NormalController

package CloneCoding.NaverCafe.domain.article.normal.controller;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/cafe/{cafe_url}")
public class NormalController {

    private final NormalService normalService;

    @GetMapping("/write")
    public ResponseWriteFormNormal getWriteForm(@PathVariable("cafe_url") String url,
                                                @RequestHeader("Authorization") String token) {
        log.info("게시글 기본 작성양식 가져오기 요청");
        return normalService.createWriteForm(url, token);
    }

    @PostMapping("/write")
    public String writeArticle(@PathVariable("cafe_url") String url,
                               @RequestBody @Valid RequestWriteNormal request,
                               @RequestHeader("Authorization") String token) {
        log.info("게시글 등록 요청");
        return normalService.createNormal(request, url, token);
    }

}

 

  • getWriteForm() : 카페 url 정보와 토큰 정보로 NormalService의 createWriteForm()을 호출하고 결과 값을 반환
  • writeArticle() : 카페 url 정보, 요청 정보, 토큰 정보들로 NormalService의 createNormal()을 호출, 결과 메시지를 반환

NormalServiceImpl

package CloneCoding.NaverCafe.domain.article.normal.service;

import static CloneCoding.NaverCafe.message.SystemMessage.WRITE_COMPLETE;

@Service
@RequiredArgsConstructor
public class NormalServiceImpl implements NormalService {

    private final NormalRepository normalRepository;
    private final CafeRepository cafeRepository;
    private final CafeMemberRepository cafeMemberRepository;
    private final AesUtil aesUtil;

    @Override
    public ResponseWriteFormNormal createWriteForm(String url, String token) {
        checkAuth(url, token);
        return new ResponseWriteFormNormal();
    }

    @Override
    public String createNormal(RequestWriteNormal request, String url, String token) {

        CafeMember cafeMember = checkAuth(url, token);

        Normal normal = Normal.create(request, cafeMember);

        normalRepository.save(normal);

        return WRITE_COMPLETE.getMessage();

    }

    private CafeMember checkAuth(String url, String token) {
        Cafe cafe = cafeRepository.findByUrl(url);
        String accountId = aesUtil.aesDecode(token);

        return cafeMemberRepository.findByAccountId(cafe, accountId);
    }

}

 

  • createWriteForm() : ResponseWriteFormNormal 객체를 생성하고 해당 객체 반환
  • createNormal() : Normal 객체를 생성하고 엔티티 저장 후, 결과 메시지를 반환
  • checkAuth() : 카페 정보와 카페 회원 정보가 유효한지 확인 후 CafeMember 객체를 반환

API TEST

API TEST - 일반 게시글 양식 가져오기

 

  일반 게시글 작성 양식에 필요한 기본 정보 요청 결과, 필요한 기본 정보들이 잘 반환 되었다.

 

API TEST - 일반 게시글 작성

 

DB - 통합게시판, 일반 게시글 작성

 

  일반 게시글 작성(등록) 요청에 따른 결과이다. 등록이 완료되었다는 결과 메시지가 반환되었고 DB를 봐도 엔티티 정보가 테이블에 잘 반영된 것을 확인할 수 있다.