팀 프로젝트 - 커뮤니티

chrkb1569·2022년 9월 14일

한 일주일정도 velog에 글을 작성 안했었는데요,

그 동안 UMC 3기에 지원로 인하여 좀 바빴습니다.

어떻게 운이 좋아서 서류는 붙었는데 면접에서 떨어졌습니다 ㅋㅋ

면접때 말을 잘 못한것 같아서 떨어질거라고 짐작은 했는데 막상 진짜로 떨어지니까 싱숭생숭하더라구요...

뭐 추석이랑 날이 좀 겹쳐서 떨어진 겸 놀다가 왔습니다.

놀다가 왔으니까 이제 공부해야죠ㅇㅇ

오늘부터 동아리 팀원과 함께 협업 프로젝트를 진행해보고자 하는데, 이번에 진행해볼 프로젝트는 커뮤니티 사이트를 만들어 보기로 하였습니다.

대충 이러한 방향으로 나아가기로 구상하였으며, 오늘은 일단 Board 부분 CRUD와 조회수 기능을 추가해보도록 하겠습니다.

package com.example.community_board.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.NotNull;

@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Board {

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

    @NotNull
    private String title;

    @NotNull
    private String content;

    @Column(name = "view", columnDefinition = "int default 0")
    private long viewCount;
}

일단은 간단하게 Board Entity를 구현해주었는데, 조회수를 저장하기 위한 컬럼 viewCount 컬럼을 만들어주었습니다.

컬럼의 이름은 view로 지정하고, columnDefinition 옵션을 통하여 기본값을 0으로 설정해주었습니다.

package com.example.community_board.repository;

import com.example.community_board.entity.Board;
import org.springframework.data.jpa.repository.JpaRepository;

public interface BoardRepository extends JpaRepository<Board, Long> {
    
}

Repository 부분은 아직까지 특별하게 설명할 부분은 없는 것 같습니다.

package com.example.community_board.contoller;

import com.example.community_board.dto.board.CreateBoardRequestDto;
import com.example.community_board.dto.board.EditRequestDto;
import com.example.community_board.response.Response;
import com.example.community_board.service.BoardService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
public class BoardController {

    private final BoardService boardService;

    @GetMapping("/boards")
    @ResponseStatus(HttpStatus.OK)
    public Response getBoards() {
        return Response.success(boardService.getBoards());
    }

    @GetMapping("/boards/{id}")
    @ResponseStatus(HttpStatus.OK)
    public Response getBoard(@PathVariable Long id) {
        return Response.success(boardService.getBoard(id));
    }

    @PostMapping("/boards")
    @ResponseStatus(HttpStatus.CREATED)
    public Response saveBoard(@RequestBody @Valid CreateBoardRequestDto requestDto) {
        return Response.success(boardService.save(requestDto));
    }

    @PutMapping("/boards/{id}")
    @ResponseStatus(HttpStatus.OK)
    public Response editBoard(@PathVariable Long id, @RequestBody @Valid EditRequestDto requestDto) {
        return Response.success(boardService.edit(id, requestDto));
    }

    @DeleteMapping("/boards/{id}")
    @ResponseStatus(HttpStatus.OK)
    public Response deleteBoard(@PathVariable Long id) {
        boardService.delete(id);
        return Response.success("id == " + id + " 게시물을 삭제하였습니다.");
    }
}
package com.example.community_board.service;

import com.example.community_board.dto.board.*;
import com.example.community_board.entity.Board;
import com.example.community_board.exception.board.BoardNotFoundException;
import com.example.community_board.exception.board.ListNotFoundException;
import com.example.community_board.repository.BoardRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class BoardService {

    private final BoardRepository boardRepository;

    @Transactional(readOnly = true)
    public List<BoardListResponseDto> getBoards() {

        List<BoardListResponseDto> lst = boardRepository.findAll().stream()
                .map(s -> new BoardListResponseDto().toDto(s)).collect(Collectors.toList());

        if(lst.isEmpty()) {
            throw new ListNotFoundException();
        }

        return lst;
    }

    @Transactional
    public BoardResponseDto getBoard(Long id) {
        Board board = boardRepository.findById(id).orElseThrow(BoardNotFoundException::new);

        board.setViewCount(board.getViewCount() + 1); // 조회수 증가

        return new BoardResponseDto().toDto(board);
    }

    @Transactional
    public CreateBoardResponseDto save(CreateBoardRequestDto requestDto) {
        Board board = new Board(requestDto.getTitle(), requestDto.getContent());
        boardRepository.save(board);

        return new CreateBoardResponseDto().toDto(board);
    }

    @Transactional
    public EditResponseDto edit(Long id, EditRequestDto requestDto) {
        Board findItem = boardRepository.findById(id).orElseThrow(BoardNotFoundException::new);

        findItem.setTitle(requestDto.getTitle());
        findItem.setContent(requestDto.getContent());

        return new EditResponseDto().toDto(findItem);
    }

    @Transactional
    public void delete(Long id) {
        boardRepository.findById(id).orElseThrow(BoardNotFoundException::new);

        boardRepository.deleteById(id);
    }
}

Controller 부분은 평소와 다른 점이 없었지만, Service 부분은 게시글을 단일 조회할 경우 조회수가 증가하게끔 설정해주었습니다.

    @Transactional
    public BoardResponseDto getBoard(Long id) {
        Board board = boardRepository.findById(id).orElseThrow(BoardNotFoundException::new);

        board.setViewCount(board.getViewCount() + 1); // 조회수 증가

        return new BoardResponseDto().toDto(board);
    }

@Transactional 어노테이션을 활용해서 id값을 통하여 board Entity를 조회한 뒤에 수정한 사항을 바로 저장되게끔 설정해두었습니다.

일단 게시글을 생성한 뒤에 게시글을 전체 조회할 경우에는 조회수가 증가하지 않은 모습을 볼 수 있습니다.

하지만, 게시글 단일 조회 기능을 활용하여 특정 게시글을 반복적으로 조회한다면, 게시글의 조회수인 viewCount가 증가하는 것을 확인할 수 있습니다.

"제목1"이라는 게시글을 5번 조회한 뒤에 게시글을 전체조회 해보겠습니다.

그럼 다음과 같이 "제목1"이라는 게시글만 조회수가 5인 것을 확인할 수 있었습니다.

0개의 댓글