본문 바로가기
개발일지/일간회고 (TIL)

최종프로젝트 2, 3일차

by 윤승임 2023. 2. 9.

2일차에는 기능과 ERD, API명세서등을 마저 기획하였다.

 

3일차부터는 기능들을 구현하게 되었는데, 엔티티 기준으로 역할을 나누게 되었다.

댓글, 좋아요, 게시물, 쓰레드 등이 있었는데, 나는 그 중에서 게시물을 맡게 되었다.

 

게시물의 기능은 일단 CRUD랑.. 페이징 조회도 R에 해당하는건가.

다음과 같이 구현했다.

주석들은 생각해 볼 것들로, 블로그 작성하면서 덧붙인 것이다.

Entity

@Entity
@Getter
@NoArgsConstructor
public class Post extends BaseEntity {

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

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "account_id")
  private Account account;

  @Column(nullable = false)
  private String title;

  @Column
  private String image;
  // 이미지는 Multipart를 쓸 예정

  @Column(nullable = false)
  private String content;

  @Builder
  public Post(Account account, String title, String content) {
    this.account = account;
    this.title = title;
    this.content = content;
  }

  public void modifyPost(PostRequestDto postRequestDto) {
    this.title = postRequestDto.getTitle();
    this.content = postRequestDto.getContent();
  }
}

// Builder와 Constructor의 차이점

Controller

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

  private final PostService postService;

  @PostMapping
  public ResponseEntity<PostResponseDto> newPost(@RequestBody PostRequestDto postRequestDto,
      @AuthenticationPrincipal MemberDetails memberDetails) {
    return ResponseEntity.status(200).body(postService.newPost(postRequestDto, memberDetails));
  }

  @GetMapping("/page={pageChoice}")
  public List<PostResponseDto> getPosts(@PathVariable int pageChoice) {
    return postService.getPosts(pageChoice);
  }

  @GetMapping("/{postId}")
  public ResponseEntity<PostResponseDto> getPost(@PathVariable Long postId) {
    return ResponseEntity.status(200).body(postService.getPost(postId));
  }

  @PutMapping("/{postId}")
  public ResponseEntity<PostResponseDto> modifyPost(@PathVariable Long postId,
      @RequestBody PostRequestDto postRequestDto,
      @AuthenticationPrincipal MemberDetails memberDetails) {
    return ResponseEntity.status(200)
        .body(postService.modifyPost(postId, postRequestDto, memberDetails));
  }

  @DeleteMapping("/{postId}")
  public ResponseEntity<String> deletePost(@PathVariable Long postId,
      @AuthenticationPrincipal MemberDetails memberDetails) {
    postService.deletePost(postId, memberDetails);
    return ResponseEntity.status(200).body("삭제 완료");
  }
}

Service

public interface PostService {

  PostResponseDto getPost(Long postId);

  List<PostResponseDto> getPosts(int pageChoice);

  PostResponseDto newPost(PostRequestDto postRequestDto, MemberDetails memberDetails);

  PostResponseDto modifyPost(Long postId, PostRequestDto postRequestDto,
      MemberDetails memberDetails);

  void deletePost(Long postId, MemberDetails memberDetails);
}

// interface를 사용하는 이유
// 개발 표준화
// 다형성 지원
// 유연성
// 런타임 개선
// 객체 구조 개선
@Service
@RequiredArgsConstructor
public class PostServiceImpl implements PostService {

  private final PostRepository postRepository;

  @Override
  @Transactional
  public PostResponseDto newPost(PostRequestDto postRequestDto, MemberDetails memberDetails) {
    Post post = Post.builder()
        .account(memberDetails.getMember())
        .title(postRequestDto.getTitle())
        .content(postRequestDto.getContent())
        .build();
    postRepository.save(post);
    return new PostResponseDto(post);
  }

  @Override
  @Transactional
  public List<PostResponseDto> getPosts(int pageChoice) {
    Page<Post> posts = postRepository.findAll(pageableSetting(pageChoice));
    if (posts.isEmpty()) {
      throw new CustomException(ExceptionStatus.POST_IS_NOT_EXIST);
    }
    List<PostResponseDto> PostResponseDtoList = posts.stream().map(PostResponseDto::new).collect(
        Collectors.toList());
    return PostResponseDtoList;
  }

  private Pageable pageableSetting(int pageChoice) {
    Sort.Direction direction = Sort.Direction.DESC;
    Sort sort = Sort.by(direction, "id");
    Pageable pageable = PageRequest.of(pageChoice - 1, 4, sort);
    return pageable;
  }
 
  // 페이징을 하는 방법은 여러가지

  @Override
  @Transactional
  public PostResponseDto getPost(Long postId) {
    Post post = postRepository.findById(postId).orElseThrow(
        () -> new CustomException(ExceptionStatus.POST_IS_NOT_EXIST)
    );
    return new PostResponseDto(post);
  }

  @Override
  @Transactional
  public PostResponseDto modifyPost(Long postId, PostRequestDto postRequestDto,
      MemberDetails memberDetails) {
    Post post = postRepository.findById(postId).orElseThrow(
        () -> new CustomException(ExceptionStatus.POST_IS_NOT_EXIST)
    );
    post.modifyPost(postRequestDto);
    postRepository.save(post);
    return new PostResponseDto(post);
  }

  @Override
  @Transactional
  public void deletePost(Long postId, MemberDetails memberDetails) {
    Post post = postRepository.findById(postId).orElseThrow(
        () -> new CustomException(ExceptionStatus.POST_IS_NOT_EXIST)
    );
    postRepository.delete(post);
  }
}

Dto

@Getter
public class PostRequestDto {

  private final String title;
  private final String content;


  public PostRequestDto(String title, String content) {
    this.title = title;
    this.content = content;
  }
  // private final 필드는 객체가 생성된 후에도 값이 변경되지 않기 때문에
  // private final 필드를 갖는 경우, 해당 필드는 생성자에서 초기화하여야 한다.
}
@Getter
public class PostResponseDto {

  private final Long postId;

  private final String title;

  private final String nickname;

  private final String image;

  private final String content;

  private final LocalDateTime createDate;

  private final LocalDateTime modifiedDate;

  public PostResponseDto(Post post) {
    this.postId = post.getId();
    this.nickname = post.getAccount().getNickname();
    this.title = post.getTitle();
    this.image = post.getImage();
    this.content = post.getContent();
    this.createDate = post.getCreateDate();
    this.modifiedDate = post.getModDate();
  }
}

Repository

public interface PostRepository extends JpaRepository<Post, Long> {

  @Override
  Page<Post> findAll(Pageable pageable);
}

 

'개발일지 > 일간회고 (TIL)' 카테고리의 다른 글

CI / CD란  (0) 2023.02.27
20230220  (0) 2023.02.21
최종 프로젝트 시작 - 1일차  (0) 2023.02.06
devtools에 대해  (0) 2023.02.04
정적, 동적 메서드란?  (0) 2023.02.04