Skip to content

Feat/week 2#21

Open
junyi04 wants to merge 18 commits intoApptiveDev:강준이from
junyi04:feat/week-2
Open

Feat/week 2#21
junyi04 wants to merge 18 commits intoApptiveDev:강준이from
junyi04:feat/week-2

Conversation

@junyi04
Copy link
Copy Markdown

@junyi04 junyi04 commented Nov 13, 2025

변경점 👍

Entity로 바로 연결했던 코드는 DTO를 통해 넘겨받을 수 있도록 수정
1주차에 임시로 연결했던 H2를 MySQL로 변경

버그 해결 💊

이전에 테이블에 likes 속성을 넣어뒀는데 default 값을 주지 않아 오류
likes 값을 지정하지 않아도 default 값을 0으로 설정

Copy link
Copy Markdown
Contributor

@sinsehwan sinsehwan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다! 2주차 과제 잘 작성해주셨네요! 피드백 내용 중 어려운 내용들이 조금 있습니다.. 알면 매우 좋은 내용들이라 일단 넣어뒀는데, 천천히 반영해보시면 좋을 것 같습니다!

Comment on lines +28 to +29
@OneToMany(mappedBy = "postEntity", cascade = CascadeType.ALL, orphanRemoval = true)
private List<CommentEntity> comments = new ArrayList<>();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OneToMany까지 적용해서 양방향으로 구현해주셨네요! 그런데 사실 단방향으로 @ManyToOne만 사용하더라도 DB 테이블에서 FK가 추가됩니다. 그래서 저는 양방향 연관관계가 꼭 필요한 게 아니면 보통 단방향만 사용하는 걸 추천드립니다. 양방향 연관관계 지정 시 객체 생성 시 서로 참조하는 형태라 순환참조 발생할 위험도 있고 cascade가 설정돼 있으면 삭제 시 의도치 않은 요소가 삭제될 수 있어서 관리하기가 어렵더라고요

Comment on lines +23 to +25
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "post_id")
private PostEntity postEntity;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재 로직상 Comment는 Post가 존재할 때만 만들어 질 수 있으니 @ManyToOne, @JoinColumn에 제약조건을 더 걸어도 될 것 같습니다!

@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "post_id", nullable = false)

Comment on lines +5 to +12
@Getter
public class CommentResponse {
private final Long id;
private final String username;
private final String content;
private final String createdAt;

public CommentResponse(Long id, String username, String content, String createdAt) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DTO 적용 좋습니다! 현재 @Getter를 통해 값을 조회하네요! 그런데 이런 경우에 class 대신 record를 쓴다면 코드를 아주 간결하게 작성할 수 있습니다. 불변객체라서 안정적이라는 장점도 있습니다. 저는 개인적으로 DTO는 항상 record로 작성하는 편입니다

참고 : https://wikidocs.net/287476


// 특정 게시글 댓글 조회
public List<CommentResponse> getCommentsByPost(Long postId) {
PostEntity postEntity = postRepository.findById(postId).orElseThrow();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

값이 없는 상황에서 예외처리의 경우 상황에 맞는 예외 클래스를 던지고, 전역 예외 핸들러를 통해서 예외처리하는 방식으로 작성할 수 있습니다! 나중에 프로젝트 하실 때 같이 고려하시면 될 것 같습니다!

//예시
@Transactional(readOnly = true)
    public DiaryEntity findDiaryById(Long diaryId) {
        return diaryRepository.findById(diaryId)
                .orElseThrow(() -> new NotFoundEntityException(ExceptionCode.NOT_FOUND_DIARY.getDescription()));
    }

Comment on lines +33 to +39
@Transactional
public PostEntity updatePost(Long id, PostEntity updated) {
PostEntity postEntity = postRepository.findById(id).orElseThrow();
postEntity.setTitle(updated.getTitle());
postEntity.setContent(updated.getContent());
return postRepository.save(postEntity);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

postEntity에 update()함수를 구현해서 해당 함수를 호출해서 값을 업데이트하는 형식으로 사용한다면 postEntity에게 update 책임을 위임할 수 있습니다! 이렇게 구성하면 setter도 제거할 수 있어요

// 예시
public void update(
            String musicTitle,
            String artist,
            String albumImageUrl
    ) {
        updateMusicTitle(musicTitle);
        updateArtist(artist);
        updateAlbumImageUrl(albumImageUrl);
    }

    private void updateMusicTitle(String musicTitle) {
        if (musicTitle != null && !musicTitle.isBlank()) {
            this.musicTitle = musicTitle;
        }
    }
// ...

Comment on lines +2 to +3
<html xmlns:th="http://www.thymeleaf.org">
<body>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거는 백엔드에서 꼭 알아야 하는 사항은 아닌데 Thymeleaf 사용하실 때 Thymeleaf Layout을 적용하면 시멘틱 태그 단위로 재사용할 수 있습니다! 나중에 시간이 되면 알아보시면 좋을 것 같아요

Comment on lines +50 to +54
return new CommentResponse(
comment.getId(),
comment.getUsername(),
comment.getContent(),
comment.getCreatedAt().toString()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분은 취향이긴 한데 DTO가 Entity보다 상대적으로 상위 계층이라서 DTO에 Entity를 받는 생성자를 만들어서 간결하게 넘겨주는 방식도 있습니다! 의존성 생기는 게 부담스럽다면 DTO Mapper를 따로 정의해서 사용할 수도 있습니다!

private PostEntity postEntity;

// JPA 기본 생성자
protected CommentEntity() {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

잘 작성해주셨네요! JPA의 지연로딩 때문에 빈 프록시 객체를 만들기 위한 protected 레벨의 기본 생성자가 필요합니다! 이 부분을 다음과 같은 어노테이션 추가해서 생략할 수도 있습니다

@NoArgsConstructor(access = AccessLevel.PROTECTED)

@sinsehwan
Copy link
Copy Markdown
Contributor

그리고 승인된 PR은 머지해주시면 됩니다! 병합 후 git pull 후 변경사항 추가 PR 날리는 형식으로 진행하면 지속적으로 브랜치를 업데이트할 수 있습니다. PR이 여러 개 열려 있으면 나중에 병합 시 충돌이 생길 가능성이 높아져서 승인된 변경사항은 바로 병합하시는 걸 추천드립니다!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants