Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

키워드별 추천 포스트 어드민 기능을 구현한다 #1470

Merged
merged 25 commits into from
Aug 16, 2023

Conversation

nuyh99
Copy link
Contributor

@nuyh99 nuyh99 commented Aug 2, 2023

#️⃣연관된 이슈

📝작업 내용

@nuyh99 nuyh99 added BE 로드맵 로드맵 스쿼드 관련 이슈 labels Aug 2, 2023
@nuyh99 nuyh99 added this to the 2023 레벨3 milestone Aug 2, 2023
@nuyh99 nuyh99 requested review from Cl8D and java-saeng August 2, 2023 07:23
Copy link
Contributor

@Cl8D Cl8D left a comment

Choose a reason for hiding this comment

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

고생하셨어요!!
간단하게 리뷰 달았는데 확인 부탁드립니다!

import org.springframework.data.jpa.repository.JpaRepository;
import wooteco.prolog.roadmap.domain.RecommendedPost;

public interface RecommendedRepository extends JpaRepository<RecommendedPost, Long> {
Copy link
Contributor

Choose a reason for hiding this comment

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

대상 엔티티가 RecommendedPost니까 repository의 네이밍을 RecommendedPostRespository라고 짓는 게 조금 더 명확할 것 같아요!

Comment on lines 25 to 26
return ResponseEntity.created(
URI.create("/keywords/" + keywordId + "/recommended-posts/" + id)).build();
Copy link
Contributor

Choose a reason for hiding this comment

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

URI에 해당하는 경로에 대한 API가 없어서 단순히 status만 CREATED 하거나, 혹은 GET으로 받아오는 API가 필요할 것 같아요!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

굿굿 쓰이지 않는 API 추가보다는 201만 리턴하도록 할게요!

@PathVariable("recommendedId") Long recommendedId,
@RequestBody RecommendedUpdateRequest request) {
recommendedService.update(recommendedId, request);
return ResponseEntity.ok().build();
Copy link
Contributor

Choose a reason for hiding this comment

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

update의 경우에도 no_content를 적용할 수 있지 않을까요?

@AllArgsConstructor
public class RecommendedUpdateRequest {

private String url;
Copy link
Contributor

Choose a reason for hiding this comment

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

@NotEmpty 같은 제약 조건이나 혹은 Url에 대한 패턴 매칭이 필요할 것 같아요!
현재는 null이 들어와도 그대로 db에 null이 들어갈 수 있어서...!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

도메인에 검증 메서드 추가했습니다!

@AllArgsConstructor
public class RecommendedRequest {

private String url;
Copy link
Contributor

Choose a reason for hiding this comment

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

여기도 마찬가지로 @NotEmpty 같은 제약 조건이 필요할 것 같습니다!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

도메인에 검증 메서드 추가했습니다!

Comment on lines 56 to 57
recommendedPost.remove();
recommendedRepository.delete(recommendedPost);
Copy link
Contributor

Choose a reason for hiding this comment

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

여기서 remove() 호출 후 delete를 하시는 이유가 따로 있을까요?!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

없습니다!
필요 없는 로직들을 많이 짜뒀네요...뇌 빼고 했던 것 같습니다.
모두 제거했어요!

Copy link
Contributor

@java-saeng java-saeng left a comment

Choose a reason for hiding this comment

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

고생하셨습니다 !!

코멘트에 대한 아마란스와 연어의 의견 남겨주시고 다시 재요청 주세요!

@CollectionTable(name = "keyword_reference")
@Column(name = "url")
private List<String> references;
@OneToMany(mappedBy = "keyword", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
Copy link
Contributor

Choose a reason for hiding this comment

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

EAGER로 하신 이유가 있으신가요??

Copy link
Contributor Author

@nuyh99 nuyh99 Aug 3, 2023

Choose a reason for hiding this comment

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

현재 Keyword 객체를 쓸 때는 항상 RecommendedPost들이 필요합니다!
따라서 조회할 때 한 번에 조회문을 다 날리려고 했습니다.

위와는 별개 내용으로,
처음에는 주체적으로 동작하는 상황이 생길 것 같아서 독립적인 비 식별 관계의 Entity로 만들었습니다.

사실 지금 생각해보면 Embedded로 해서 식별 객체로 만드는 것이 나았던 것 같습니다.
앞으로 바뀌는 로드맵에서 어떤 식으로 response를 주고 할 지를 보니 그럴 일이 없을 것 같다고 생각해요...

Copy link
Contributor

Choose a reason for hiding this comment

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

EAGER를 사용하게 되면 나중에 연관관계가 복잡해질 때, 알 수 없는 쿼리들이 많이 나가는 것으로 알고 있어요.
저도 옛날에 EAGER 쓰는데 막 UNION쓰고, 제가 원하지 않는 쿼리들이 막 나가서 지양하고 있습니다.

혹시 나가는 쿼리들을 확인해보신건지 궁금해요.

말 그대로 EAGER는 "Keyword를 조회할 때 한번에 가져온다" 라는건 맞지만, 이 안에서 쿼리들이 어떻게 나갈지 모르기 때문에
직접 쿼리를 명시해줘서 가져오는게 좋지 않나 생각이 들어요.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Lazy로 바꾸고 Fetch Join 하도록 변경했습니다.
다만 Bag 타입의 경우 여러 Fetch Join을 한 번에 할 수가 없기 때문에 Set를 가지도록해서 한 번에 모두 가져왔어요.

근데 Fetch Join이 많아지면서 Cartesian Product가 발생하는데, 앞으로 성능상의 이슈가 발생한다면 고도화를 해야할 것 같습니다.
지금 생각나는 방법은 Fetch Join을 한 번씩 해오면 더 빠를 수도 있을 것 같다고 생각해요.
Fetch Join을 한 번 해오고 나머지 Fetch Join은 In 절로 가져온다면 디비로 SQL을 플러시하는 횟수는 증가하지만 Cartesian Product는 발생하지 않으니까요!

final Keyword keyword = findKeywordOrThrow(keywordId);

final RecommendedPost post = new RecommendedPost(request.getUrl());
post.addKeyword(keyword);
Copy link
Contributor

Choose a reason for hiding this comment

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

RecommendedPost 를 생성할 때 keyword를 같이 넣어주고 save하면 될 것 같은데

Post에 add를 해주고나서 save하신 이유가 궁금해요

Copy link
Contributor Author

Choose a reason for hiding this comment

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

꼼꼼한 리뷰 감사합니다!
생성자를 왜 url로만 했을까요...?

}

@PostMapping
public ResponseEntity<Void> createRecommendedPost(@PathVariable("keywordId") Long keywordId,
Copy link
Contributor

Choose a reason for hiding this comment

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

컨벤션 때 final 붙이기로 한 것 같아요 ~

nuyh99 and others added 21 commits August 11, 2023 00:53
@nuyh99 nuyh99 force-pushed the feat/1397-recommended-posts branch from bf1d8ea to 7124da0 Compare August 10, 2023 15:55
@sonarqubecloud
Copy link

SonarCloud Quality Gate failed.    Quality Gate failed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 1 Code Smell

76.4% 76.4% Coverage
0.0% 0.0% Duplication

warning The version of Java (11.0.20) you have used to run this analysis is deprecated and we will stop accepting it soon. Please update to at least Java 17.
Read more here

idea Catch issues before they fail your Quality Gate with our IDE extension sonarlint SonarLint

@nuyh99 nuyh99 merged commit e3ff353 into roadmap-develop Aug 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
BE 로드맵 로드맵 스쿼드 관련 이슈
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants