-
Notifications
You must be signed in to change notification settings - Fork 6
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
[BE] feature/#264 토픽에 대한 즐겨찾기 API #275
Changes from 16 commits
46e5107
0ea8213
a3d8629
47a52e7
f101ed3
4421edb
e3530d6
19b3f0c
81dffcb
a4d8897
5c9bfcb
9793347
e3684a2
4db58a9
3e8bb0b
d788f43
fe6691d
dbc8b12
a345b43
f97d032
f414e40
61b1ae4
770ab50
398f1e4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
== 즐겨찾기 | ||
|
||
=== 토픽을 유저의 즐겨찾기에 추가 | ||
|
||
operation::bookmark-controller-test/add-topic-in-bookmark[snippets='http-request,http-response'] | ||
|
||
=== 유저의 토픽 즐겨찾기 목록 조회 | ||
|
||
operation::bookmark-controller-test/find-topics-in-bookmark[snippets='http-request,http-response'] | ||
|
||
=== 유저의 토픽 즐겨찾기 단일 삭제 | ||
operation::bookmark-controller-test/delete-topic-in-bookmark[snippets='http-request,http-response'] | ||
|
||
=== 유저의 토픽 즐겨찾기 전 삭제 | ||
operation::bookmark-controller-test/delete-all-topics-in-bookmark[snippets='http-request,http-response'] |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,3 +11,4 @@ toc::[] | |
include::topic.adoc[] | ||
include::pin.adoc[] | ||
include::member.adoc[] | ||
include::bookmark.adoc[] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package com.mapbefine.mapbefine.bookmark.application; | ||
|
||
import com.mapbefine.mapbefine.auth.domain.AuthMember; | ||
import com.mapbefine.mapbefine.bookmark.domain.Bookmark; | ||
import com.mapbefine.mapbefine.bookmark.domain.BookmarkRepository; | ||
import com.mapbefine.mapbefine.member.domain.Member; | ||
import com.mapbefine.mapbefine.member.domain.MemberRepository; | ||
import com.mapbefine.mapbefine.topic.domain.Topic; | ||
import com.mapbefine.mapbefine.topic.domain.TopicRepository; | ||
import java.util.NoSuchElementException; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
@Transactional(readOnly = true) | ||
public class BookmarkCommandService { | ||
|
||
private final BookmarkRepository bookmarkRepository; | ||
|
||
private final MemberRepository memberRepository; | ||
|
||
private final TopicRepository topicRepository; | ||
|
||
public BookmarkCommandService( | ||
BookmarkRepository bookmarkRepository, | ||
MemberRepository memberRepository, | ||
TopicRepository topicRepository | ||
) { | ||
this.bookmarkRepository = bookmarkRepository; | ||
this.memberRepository = memberRepository; | ||
this.topicRepository = topicRepository; | ||
} | ||
|
||
public Long addTopicInBookmark(AuthMember authMember, Long topicId) { | ||
Topic topic = getTopicById(topicId); | ||
validateBookmarkingPermission(authMember, topic); | ||
Member member = getMemberById(authMember); | ||
|
||
Bookmark bookmark = Bookmark.createWithAssociatedTopicAndMember(topic, member); | ||
bookmarkRepository.save(bookmark); | ||
|
||
return bookmark.getId(); | ||
} | ||
|
||
private Topic getTopicById(Long topicId) { | ||
return topicRepository.findById(topicId) | ||
.orElseThrow(() -> new NoSuchElementException("존재하지 않는 토픽입니다.")); | ||
} | ||
|
||
private void validateBookmarkingPermission(AuthMember authMember, Topic topic) { | ||
if (authMember.canRead(topic)) { | ||
return; | ||
} | ||
|
||
throw new IllegalArgumentException("토픽에 대한 권한이 없어서 즐겨찾기에 추가할 수 없습니다."); | ||
} | ||
|
||
private Member getMemberById(AuthMember authMember) { | ||
return memberRepository.findById(authMember.getMemberId()) | ||
.orElseThrow(() -> new NoSuchElementException("존재하지 않는 멤버입니다.")); | ||
} | ||
|
||
public void deleteTopicInBookmark(AuthMember authMember, Long bookmarkId) { | ||
validateBookmarkDeletingPermission(authMember, bookmarkId); | ||
|
||
bookmarkRepository.deleteById(bookmarkId); | ||
} | ||
|
||
private void validateBookmarkDeletingPermission(AuthMember authMember, Long bookmarkId) { | ||
boolean canDelete = bookmarkRepository.existsByIdAndMemberId( | ||
bookmarkId, | ||
authMember.getMemberId() | ||
); | ||
|
||
if (canDelete) { | ||
return; | ||
} | ||
|
||
throw new IllegalArgumentException("즐겨찾기 삭제에 대한 권한이 없습니다."); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3. canDelete boolean을 반환하는 부분을 canDelete() 메서드로 분리해줘도 좋겠네요! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 해당 사항 반영했습니다 ㅏ! |
||
|
||
public void deleteAllBookmarks(AuthMember authMember) { | ||
bookmarkRepository.deleteAllByMemberId(authMember.getMemberId()); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package com.mapbefine.mapbefine.bookmark.application; | ||
|
||
import com.mapbefine.mapbefine.auth.domain.AuthMember; | ||
import com.mapbefine.mapbefine.bookmark.domain.Bookmark; | ||
import com.mapbefine.mapbefine.bookmark.domain.BookmarkRepository; | ||
import com.mapbefine.mapbefine.bookmark.dto.response.BookmarkResponse; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
@Transactional(readOnly = true) | ||
public class BookmarkQueryService { | ||
|
||
private final BookmarkRepository bookmarkRepository; | ||
|
||
public BookmarkQueryService(BookmarkRepository bookmarkRepository) { | ||
this.bookmarkRepository = bookmarkRepository; | ||
} | ||
|
||
public List<BookmarkResponse> findAllTopicsInBookmark(AuthMember authMember) { | ||
validateNonExistsMember(authMember); | ||
List<Bookmark> bookmark = bookmarkRepository.findAllByMemberId(authMember.getMemberId()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2. 변수명에 s가 붙으면 좋겠네용~~ |
||
|
||
return bookmark.stream() | ||
.map(BookmarkResponse::from) | ||
.toList(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P4. 당장 중요한 부분은 아니고, 반영하지 않아도 좋은데 원분들의 의견이 궁금해져서 코멘트 답니다!! public static List<BookmarkResponse> from(List<Bookmark> bookmarks) {
return bookmarks.stream()
.map(BookmarkResponse::from)
.toList();
}
// 서비스에서는 아래와 같이 간략화할 수 있음
return BookmarkResponse.from(bookmarks); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 대부분의 변환 로직이 굉장히 간략화 될 것 같아서 좋을 것 같습니다! 킹치만, 아주 조금 우려가 되는 부분은 public Bookmark toBookmark(Topic topic) {
...
}
return topic.stream()
.map(this::toBookmark)
.map(BookmarkResponse::from)
.toList();
->
List<Bookmark> bookmarks = topic.stream()
.map(this::toBookmark)
.toList();
return BookmarkResponse.from(bookmarks) (toBookmark 는 예시를 들기 위해서 사용한 임의의 변환 메서드입니다.) 위와 같은 경우 원래 한번의 스트림으로 해결할 수 있었지만, 해당 정팩매를 둠으로써 중간에 toList() 를 통해 추출해내야 한다는 단점도 생길 수 있을 것 같아요. 이런 경우에서만 정팩메를 사용하지 않는다는 저희만의 컨벤션을 만들거나, 혹은 더 나아가 이런 경우는 발생하지 않을 것 같다고 판단되면 추가해도 너무 좋을 것 같습니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저도 개인적으로 List 자체를 넘겨주는 것 좋습니다 ㅎㅎ 매튜가 착각한 것 같은데, List로 추출하지 않고 stream에서 한 번에 처리할 수 있지 않나요 !? |
||
} | ||
|
||
public void validateNonExistsMember(AuthMember authMember) { | ||
if (Objects.isNull(authMember.getMemberId())) { | ||
throw new IllegalArgumentException("존재하지 않는 유저입니다."); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package com.mapbefine.mapbefine.bookmark.domain; | ||
|
||
import com.mapbefine.mapbefine.member.domain.Member; | ||
import com.mapbefine.mapbefine.topic.domain.Topic; | ||
import jakarta.persistence.Entity; | ||
import jakarta.persistence.GeneratedValue; | ||
import jakarta.persistence.GenerationType; | ||
import jakarta.persistence.Id; | ||
import jakarta.persistence.JoinColumn; | ||
import jakarta.persistence.ManyToOne; | ||
import lombok.AccessLevel; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Entity | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@Getter | ||
public class Bookmark { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P4. Bookmark가 id를 가지도록 하신 이유가 궁금합니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 복합키를 기본키로 사용하는 구현 방식이 복잡하여 (Serializable, equals&hashCode 재정의 등) 기본키 자동 생성 전략을 택했는데요 ! 즐겨찾기를 삭제할 때, 각 id 값을 통해 삭제를 요청해야 올바른 흐름이라고 생각했어요. 하지만 이럴 경우, 토픽의 데이터를 내려줄 때 즐겨찾기 목록인지 아닌지에 따라 response body가 달라진다는 점에서 프론트에서 관리해야하는 포인트들이 더 생기는 것 같네요. 준팍과 도이의 의견을 일부 반영하여, 내부적으로는 기본키를 유지하되, 비즈니스 로직(즐겿자기 삭제 등)에서는 복합키로 처리하도록 하겠습니다. |
||
|
||
@ManyToOne | ||
@JoinColumn(name = "topic_id", nullable = false) | ||
private Topic topic; | ||
|
||
@ManyToOne | ||
@JoinColumn(name = "member_id", nullable = false) | ||
private Member member; | ||
|
||
private Bookmark(Topic topic, Member member) { | ||
this.topic = topic; | ||
this.member = member; | ||
} | ||
|
||
// TODO: 2023/08/11 필요한 검증이 무엇이 있을까.. 현재로썬 외부에서 검증하는 방법 밖에 ? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 쥬니짱 제가 위에서 코멘트 드렸던 부분
을 여기서 해결할 수 있지 않을까? 싶어요!
중복으로 저장되는 경우도 쉽게 막을 수 있을 것 같긴한데 쥬니짱짱 생각은 어떠세요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 물론 위 방식을 기용하면 equals, hashcode 를 추가해줘야 할 것 같긴하네요 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 좋은 방법인 것 같아요 ㅎㅎ 즐겨찾기는 매우 가벼운 비즈니스 로직인데, 매번 모든 정보를 가져와야 한다는 점이 걱정되네요 ㅎㅎ 이에따라, Service 계층에서 아래와 같이 검증 로직을 추가하였습니다 ! private void validateBookmarkDuplication(AuthMember authMember, Long topicId) {
if (isExistBookmark(authMember, topicId)) {
throw new IllegalArgumentException("이미 즐겨찾기로 등록된 토픽입니다.");
}
}
private boolean isExistBookmark(AuthMember authMember, Long topicId) {
return bookmarkRepository.existsByMemberIdAndTopicId(authMember.getMemberId(), topicId);
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네네 제 생각에도 Repository 에서 확인하는 것이 성능상 이점이 있을 것 같지만, 뭔가 조금 더 객체지향적으로 해결하려면 위와 같은 방법을 채택하는 것이 어떨까 해서 말씀드렸었습니당 홍홍홍 |
||
public static Bookmark createWithAssociatedTopicAndMember(Topic topic, Member member) { | ||
Bookmark bookmark = new Bookmark(topic, member); | ||
|
||
topic.addBookmark(bookmark); | ||
member.addBookmark(bookmark); | ||
|
||
return bookmark; | ||
} | ||
Comment on lines
+38
to
+45
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 연관관계를 꼭 맺어줘야할까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 생각해보니 Members엔 넣어주는게 더편할 수 있겠네요 ㅎㅎ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 다시 생각해보니 topic이 북마크된 숫자도 반환해야하니 필요하겠군요 |
||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.mapbefine.mapbefine.bookmark.domain; | ||
|
||
import java.util.List; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface BookmarkRepository extends JpaRepository<Bookmark, Long> { | ||
|
||
List<Bookmark> findAllByMemberId(Long memberId); | ||
|
||
void deleteAllByMemberId(Long memberId); | ||
|
||
boolean existsByIdAndMemberId(Long id, Long memberId); | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.mapbefine.mapbefine.bookmark.dto.response; | ||
|
||
import com.mapbefine.mapbefine.bookmark.domain.Bookmark; | ||
import com.mapbefine.mapbefine.topic.domain.Topic; | ||
import com.mapbefine.mapbefine.topic.domain.TopicInfo; | ||
import java.time.LocalDateTime; | ||
|
||
public record BookmarkResponse( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BookMarkResponse 따로 만들어주기보다는 TopicResponse로 통합해서 처리 가능하지 않을까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저도 동의합니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저는 현재 topicResponse 에 isBookmarked 가 포함되어 있어, 현재 방식도 괜찮아보이긴합니다. 만일 topicResponse 로 반환하게 된다면, TopicResponse.from(Topic topic) 을 호출해야할테고, 그렇다면 무조건 isBookmarked 가 false 로 설정되게 될테니까요. |
||
Long id, | ||
Long topicId, | ||
String name, | ||
String image, | ||
Integer pinCount, | ||
LocalDateTime updatedAt | ||
) { | ||
|
||
public static BookmarkResponse from(Bookmark bookmark) { | ||
Topic topic = bookmark.getTopic(); | ||
TopicInfo topicInfo = topic.getTopicInfo(); | ||
|
||
return new BookmarkResponse( | ||
bookmark.getId(), | ||
topic.getId(), | ||
topicInfo.getName(), | ||
topicInfo.getImageUrl(), | ||
topic.countPins(), | ||
topic.getUpdatedAt() | ||
); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package com.mapbefine.mapbefine.bookmark.presentation; | ||
|
||
import com.mapbefine.mapbefine.auth.domain.AuthMember; | ||
import com.mapbefine.mapbefine.bookmark.application.BookmarkCommandService; | ||
import com.mapbefine.mapbefine.bookmark.application.BookmarkQueryService; | ||
import com.mapbefine.mapbefine.bookmark.dto.response.BookmarkResponse; | ||
import com.mapbefine.mapbefine.common.interceptor.LoginRequired; | ||
import java.net.URI; | ||
import java.util.List; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.DeleteMapping; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@RequestMapping("/members/bookmarks") | ||
public class BookmarkController { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 즐겨찾기라는게 아무래도, 유저와 관련된 내용이다 보니 위와 같이 URI를 작성하였습니다. MemberController와 별도의 컨트롤러라는 점에서, 위 URI가 잘못된 구조인 것 같기도 합니다. 의견 부탁드립니다 ! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저는 members 빼는 게 더 좋을 것 같습니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저도 members 빼는 것에 동의합니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 젇후영~~~~~! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 반영했습니다 ~ |
||
|
||
private final BookmarkCommandService bookmarkCommandService; | ||
|
||
private final BookmarkQueryService bookmarkQueryService; | ||
|
||
public BookmarkController( | ||
BookmarkCommandService bookmarkCommandService, | ||
BookmarkQueryService bookmarkQueryService | ||
) { | ||
this.bookmarkCommandService = bookmarkCommandService; | ||
this.bookmarkQueryService = bookmarkQueryService; | ||
} | ||
|
||
@LoginRequired | ||
@PostMapping | ||
public ResponseEntity<Void> addTopicInBookmark( | ||
AuthMember authMember, | ||
@RequestParam Long topicId | ||
) { | ||
Long bookmarkId = bookmarkCommandService.addTopicInBookmark(authMember, topicId); | ||
|
||
return ResponseEntity.created(URI.create("/members/bookmarks/" + bookmarkId)).build(); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 즐겨찾기에 대한 Id를 반환해주어야 하는가 ? 라는 질문을 준팍이 하셨던 것 같아서 코멘트 남깁니다. 사용자가 자신의 즐겨찾기 목록에 존재하는 토픽을 삭제하려면, 해당 토픽의 id보다는 해당 즐겨찾기의 id를 요청하는 것이 맞다고 판단했습니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 즐겨찾기에 같은 토픽이 여러개 들어갈 수 없으니, TopicId와 MemberId로 충분히 탐색할 수 있지 않을까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. topicId, memberId로 식별하고, 그렇게 되면 아예 id 대신 두가지를 복합키로 하는 방식도 괜찮아보입니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 유연성 제한: id 컬럼 없이 memberId와 topicId만 사용하면 테이블 내에서 각 행을 고유하게 식별할 수 있습니다. 하지만 id를 사용하는 경우, 나중에 유연하게 스키마를 변경하거나 다른 관련 정보를 추가하는 데 더 유리할 수 있습니다. 성능 이슈: 복합키로 인덱스를 생성할 경우, 검색 성능이 향상될 수 있지만, 조건에 따라 성능이 저하될 수도 있습니다. 특히 대량의 데이터에서 복합키를 사용하면 인덱스 크기가 커져서 일부 검색 작업에서 더 많은 리소스를 필요로 할 수 있습니다. 복잡성 증가: 복합키를 사용하면 데이터베이스 쿼리 및 조인 작업이 복잡해질 수 있습니다. 특히 다른 테이블과의 조인 작업에서 조금 더 복잡한 SQL문이 필요할 수 있습니다. 데이터 무결성 유지: 복합키를 사용하는 경우, 데이터 무결성을 유지하기 위해 추가적인 제약 조건이나 처리 로직이 필요할 수 있습니다. 이를 관리하는 것도 고려해야 합니다. 확장성 제한: 나중에 테이블에 다른 컬럼을 추가하거나 변경할 때, 복합키가 있는 경우 일부 작업이 더 복잡해질 수 있습니다. gpt가 복합키를 사용했을 때의 단점은 이렇다고 하네용. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. id를 제거하는 방식이 아닌, 삭제 등의 요청에 대해 복합키를 사용하는 방식으로 결정하겠습니다 ! |
||
|
||
@LoginRequired | ||
@GetMapping | ||
public ResponseEntity<List<BookmarkResponse>> findAllTopicsInBookmark(AuthMember authMember) { | ||
List<BookmarkResponse> responses = bookmarkQueryService.findAllTopicsInBookmark(authMember); | ||
|
||
return ResponseEntity.ok(responses); | ||
} | ||
|
||
@LoginRequired | ||
@DeleteMapping("{bookmarkId}") | ||
public ResponseEntity<Void> deleteTopicInBookmark( | ||
AuthMember authMember, | ||
@PathVariable Long bookmarkId | ||
) { | ||
bookmarkCommandService.deleteTopicInBookmark(authMember, bookmarkId); | ||
|
||
return ResponseEntity.noContent().build(); | ||
} | ||
|
||
@LoginRequired | ||
@DeleteMapping | ||
public ResponseEntity<Void> deleteAllTopicsInBookmark(AuthMember authMember) { | ||
bookmarkCommandService.deleteAllBookmarks(authMember); | ||
|
||
return ResponseEntity.noContent().build(); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이전 코드들과의 일관성을 위해서 bookmark 를 저장하신건가용?
저는 쥬니짱이 말씀하셨던 것처럼 member 혹은 topic 을 저장하여 cascade 로 bookmark 를 저장하는 것도 좋아보여서요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
음 그리고 사용자가 즐겨찾기를 중복으로 실행하는 경우도 고려할 수 있을 것 같아요 쥬니짱.
물론 화면딴에서는 쥬니짱이 추가해주신 isBookmarked 로 인해 중복으로 즐겨찾기 하는 경우는 막을 수 있겠지만, 악의적인 유저가 Postman 을 이용하여 중복으로 즐겨찾기 요청을 계속 보내게되면 동일한 정보들이 DB 에 저장될 수도 있지 않을까? 하는 우려가 들기도 하네요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아앗.. 포스트맨이 있었군요.
저는 프론트 크루들을 전적으로 신뢰하고 있었기 떄문에, 별다른 검증을 하지 않았는데 ㅎㅎ
해당 사항 반영하였습니다 !