diff --git a/src/main/java/project/flipnote/like/controller/LikeController.java b/src/main/java/project/flipnote/like/controller/LikeController.java index b08b3128..a980d56a 100644 --- a/src/main/java/project/flipnote/like/controller/LikeController.java +++ b/src/main/java/project/flipnote/like/controller/LikeController.java @@ -15,10 +15,10 @@ import project.flipnote.common.model.response.PagingResponse; import project.flipnote.common.security.dto.AuthPrinciple; import project.flipnote.like.controller.docs.LikeControllerDocs; -import project.flipnote.like.model.LikeResponse; -import project.flipnote.like.model.LikeSearchRequest; -import project.flipnote.like.model.LikeTargetResponse; -import project.flipnote.like.model.LikeTargetTypeRequest; +import project.flipnote.like.model.response.LikeResponse; +import project.flipnote.like.model.request.LikeSearchRequest; +import project.flipnote.like.model.response.LikeTargetResponse; +import project.flipnote.like.model.request.LikeTargetTypeRequest; import project.flipnote.like.service.LikeService; @RequiredArgsConstructor diff --git a/src/main/java/project/flipnote/like/controller/docs/LikeControllerDocs.java b/src/main/java/project/flipnote/like/controller/docs/LikeControllerDocs.java index 373ecaf0..86ef56ff 100644 --- a/src/main/java/project/flipnote/like/controller/docs/LikeControllerDocs.java +++ b/src/main/java/project/flipnote/like/controller/docs/LikeControllerDocs.java @@ -7,10 +7,10 @@ import io.swagger.v3.oas.annotations.tags.Tag; import project.flipnote.common.model.response.PagingResponse; import project.flipnote.common.security.dto.AuthPrinciple; -import project.flipnote.like.model.LikeResponse; -import project.flipnote.like.model.LikeSearchRequest; -import project.flipnote.like.model.LikeTargetResponse; -import project.flipnote.like.model.LikeTargetTypeRequest; +import project.flipnote.like.model.response.LikeResponse; +import project.flipnote.like.model.request.LikeSearchRequest; +import project.flipnote.like.model.response.LikeTargetResponse; +import project.flipnote.like.model.request.LikeTargetTypeRequest; @Tag(name = "Like", description = "Like API") public interface LikeControllerDocs { diff --git a/src/main/java/project/flipnote/like/model/LikeSearchRequest.java b/src/main/java/project/flipnote/like/model/request/LikeSearchRequest.java similarity index 90% rename from src/main/java/project/flipnote/like/model/LikeSearchRequest.java rename to src/main/java/project/flipnote/like/model/request/LikeSearchRequest.java index c6ef3b9b..a2ad436d 100644 --- a/src/main/java/project/flipnote/like/model/LikeSearchRequest.java +++ b/src/main/java/project/flipnote/like/model/request/LikeSearchRequest.java @@ -1,4 +1,4 @@ -package project.flipnote.like.model; +package project.flipnote.like.model.request; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; diff --git a/src/main/java/project/flipnote/like/model/LikeTargetTypeRequest.java b/src/main/java/project/flipnote/like/model/request/LikeTargetTypeRequest.java similarity index 83% rename from src/main/java/project/flipnote/like/model/LikeTargetTypeRequest.java rename to src/main/java/project/flipnote/like/model/request/LikeTargetTypeRequest.java index 8bc862b2..7f37bad8 100644 --- a/src/main/java/project/flipnote/like/model/LikeTargetTypeRequest.java +++ b/src/main/java/project/flipnote/like/model/request/LikeTargetTypeRequest.java @@ -1,4 +1,4 @@ -package project.flipnote.like.model; +package project.flipnote.like.model.request; import project.flipnote.like.entity.LikeTargetType; diff --git a/src/main/java/project/flipnote/like/model/CardSetLikeResponse.java b/src/main/java/project/flipnote/like/model/response/CardSetLikeResponse.java similarity index 90% rename from src/main/java/project/flipnote/like/model/CardSetLikeResponse.java rename to src/main/java/project/flipnote/like/model/response/CardSetLikeResponse.java index ece0dfac..9847bf6a 100644 --- a/src/main/java/project/flipnote/like/model/CardSetLikeResponse.java +++ b/src/main/java/project/flipnote/like/model/response/CardSetLikeResponse.java @@ -1,4 +1,4 @@ -package project.flipnote.like.model; +package project.flipnote.like.model.response; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/src/main/java/project/flipnote/like/model/LikeResponse.java b/src/main/java/project/flipnote/like/model/response/LikeResponse.java similarity index 87% rename from src/main/java/project/flipnote/like/model/LikeResponse.java rename to src/main/java/project/flipnote/like/model/response/LikeResponse.java index af287dc5..481d1f72 100644 --- a/src/main/java/project/flipnote/like/model/LikeResponse.java +++ b/src/main/java/project/flipnote/like/model/response/LikeResponse.java @@ -1,4 +1,4 @@ -package project.flipnote.like.model; +package project.flipnote.like.model.response; import java.time.LocalDateTime; diff --git a/src/main/java/project/flipnote/like/model/LikeTargetResponse.java b/src/main/java/project/flipnote/like/model/response/LikeTargetResponse.java similarity index 62% rename from src/main/java/project/flipnote/like/model/LikeTargetResponse.java rename to src/main/java/project/flipnote/like/model/response/LikeTargetResponse.java index 2f6b70ff..b050e9cb 100644 --- a/src/main/java/project/flipnote/like/model/LikeTargetResponse.java +++ b/src/main/java/project/flipnote/like/model/response/LikeTargetResponse.java @@ -1,4 +1,4 @@ -package project.flipnote.like.model; +package project.flipnote.like.model.response; public abstract class LikeTargetResponse { public abstract Long getId(); diff --git a/src/main/java/project/flipnote/like/service/LikePolicyService.java b/src/main/java/project/flipnote/like/service/LikePolicyService.java index ea3d8c1f..a15d983f 100644 --- a/src/main/java/project/flipnote/like/service/LikePolicyService.java +++ b/src/main/java/project/flipnote/like/service/LikePolicyService.java @@ -3,26 +3,21 @@ import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; -import project.flipnote.cardset.service.CardSetService; import project.flipnote.common.exception.BizException; import project.flipnote.like.entity.LikeTargetType; import project.flipnote.like.exception.LikeErrorCode; +import project.flipnote.like.model.response.LikeTargetResponse; import project.flipnote.like.repository.LikeRepository; @RequiredArgsConstructor @Service public class LikePolicyService { - private final CardSetService cardSetService; private final LikeRepository likeRepository; + private final LikeTargetFetchService likeTargetFetchService; - public void validateTargetExists(LikeTargetType targetType, Long targetId) { - boolean targetExists = false; - switch (targetType) { - case CARD_SET -> targetExists = cardSetService.existsById(targetId); - } - - if (!targetExists) { + public void validateTargetExists(LikeTargetType targetType, Long targetId, Long userId) { + if (!likeTargetFetchService.isTargetViewable(targetType, targetId, userId)) { throw new BizException(LikeErrorCode.LIKE_TARGET_NOT_FOUND); } } diff --git a/src/main/java/project/flipnote/like/service/LikeReader.java b/src/main/java/project/flipnote/like/service/LikeReader.java new file mode 100644 index 00000000..d0f50b02 --- /dev/null +++ b/src/main/java/project/flipnote/like/service/LikeReader.java @@ -0,0 +1,22 @@ +package project.flipnote.like.service; + +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; +import project.flipnote.common.exception.BizException; +import project.flipnote.like.entity.Like; +import project.flipnote.like.entity.LikeTargetType; +import project.flipnote.like.exception.LikeErrorCode; +import project.flipnote.like.repository.LikeRepository; + +@RequiredArgsConstructor +@Service +public class LikeReader { + + private final LikeRepository likeRepository; + + public Like findByTargetAndUserId(LikeTargetType targetType, Long targetId, Long userId) { + return likeRepository.findByTargetTypeAndTargetIdAndUserId(targetType, targetId, userId) + .orElseThrow(() -> new BizException(LikeErrorCode.LIKE_NOT_FOUND)); + } +} diff --git a/src/main/java/project/flipnote/like/service/LikeService.java b/src/main/java/project/flipnote/like/service/LikeService.java index d7bf9df4..9471389c 100644 --- a/src/main/java/project/flipnote/like/service/LikeService.java +++ b/src/main/java/project/flipnote/like/service/LikeService.java @@ -1,10 +1,8 @@ package project.flipnote.like.service; import java.time.LocalDateTime; -import java.util.List; import java.util.Map; import java.util.Set; -import java.util.function.Function; import java.util.stream.Collectors; import org.springframework.context.ApplicationEventPublisher; @@ -13,7 +11,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import project.flipnote.common.exception.BizException; @@ -23,11 +20,10 @@ import project.flipnote.like.entity.Like; import project.flipnote.like.entity.LikeTargetType; import project.flipnote.like.exception.LikeErrorCode; -import project.flipnote.like.model.LikeResponse; -import project.flipnote.like.model.LikeSearchRequest; -import project.flipnote.like.model.LikeTargetResponse; +import project.flipnote.like.model.response.LikeResponse; +import project.flipnote.like.model.request.LikeSearchRequest; +import project.flipnote.like.model.response.LikeTargetResponse; import project.flipnote.like.repository.LikeRepository; -import project.flipnote.like.service.fetcher.LikeTargetFetcher; @Slf4j @RequiredArgsConstructor @@ -38,15 +34,8 @@ public class LikeService { private final LikeRepository likeRepository; private final ApplicationEventPublisher eventPublisher; private final LikePolicyService likePolicyService; - private final List> fetchers; - - private Map> fetcherMap; - - @PostConstruct - public void init() { - this.fetcherMap = this.fetchers.stream() - .collect(Collectors.toMap(LikeTargetFetcher::getTargetType, Function.identity())); - } + private final LikeTargetFetchService likeTargetFetchService; + private final LikeReader likeReader; /** * 좋아요 추가 @@ -58,7 +47,7 @@ public void init() { */ @Transactional public void addLike(Long userId, LikeTargetType targetType, Long targetId) { - likePolicyService.validateTargetExists(targetType, targetId); + likePolicyService.validateTargetExists(targetType, targetId, userId); likePolicyService.validateNotAlreadyLiked(targetType, targetId, userId); Like like = Like.builder() @@ -86,8 +75,7 @@ public void addLike(Long userId, LikeTargetType targetType, Long targetId) { */ @Transactional public void removeLike(Long userId, LikeTargetType targetType, Long targetId) { - Like like = likeRepository.findByTargetTypeAndTargetIdAndUserId(targetType, targetId, userId) - .orElseThrow(() -> new BizException(LikeErrorCode.LIKE_NOT_FOUND)); + Like like = likeReader.findByTargetAndUserId(targetType, targetId, userId); likeRepository.delete(like); @@ -100,11 +88,10 @@ public void removeLike(Long userId, LikeTargetType targetType, Long targetId) { * @param userId 좋아요 누른 목록을 조회하는 회원의 ID * @param targetType 조회할 좋아요 대상 타입 * @param req 페이징 및 검색 조건이 포함된 요청 정보 - * @param 좋아요 대상의 상세 정보를 담은 DTO 타입 (LikeTargetResponse 하위 타입) * @return 페이징된 좋아요 누른 목록 * @author 윤정환 */ - public PagingResponse> getLikes( + public PagingResponse> getLikes( Long userId, LikeTargetType targetType, LikeSearchRequest req @@ -114,14 +101,9 @@ public PagingResponse> getLikes( .collect(Collectors.toMap(Like::getTargetId, Like::getCreatedAt)); Set targetIds = likedAtMap.keySet(); - // TODO: 제네릭이 아닌 타입 별로 엔드포인트를 따로 만드는게 좋으려나 고민중, 현재 방법을 유지하면서 더 나은 구조 알고싶음... - LikeTargetFetcher fetcher = (LikeTargetFetcher)fetcherMap.get(targetType); - if (fetcher == null) { - throw new BizException(LikeErrorCode.INVALID_LIKE_TYPE); - } - - Map targetMap = fetcher.fetchByIds(targetIds); - Page> content = likePage + Map targetMap + = likeTargetFetchService.fetchByTypeAndIds(targetType, targetIds, userId); + Page> content = likePage .map(like -> new LikeResponse<>(targetMap.get(like.getTargetId()), likedAtMap.get(like.getTargetId()))); return PagingResponse.from(content); diff --git a/src/main/java/project/flipnote/like/service/LikeTargetFetchService.java b/src/main/java/project/flipnote/like/service/LikeTargetFetchService.java new file mode 100644 index 00000000..20ad697d --- /dev/null +++ b/src/main/java/project/flipnote/like/service/LikeTargetFetchService.java @@ -0,0 +1,57 @@ +package project.flipnote.like.service; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; + +import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; +import project.flipnote.common.exception.BizException; +import project.flipnote.like.entity.LikeTargetType; +import project.flipnote.like.exception.LikeErrorCode; +import project.flipnote.like.model.response.LikeTargetResponse; +import project.flipnote.like.service.fetcher.LikeTargetFetcher; + +@RequiredArgsConstructor +@Service +public class LikeTargetFetchService { + + private final List> fetchers; + + private Map> fetcherMap; + + @PostConstruct + public void init() { + this.fetcherMap = this.fetchers.stream() + .collect(Collectors.toMap(LikeTargetFetcher::getTargetType, Function.identity())); + } + + public boolean isTargetViewable(LikeTargetType targetType, Long targetId, Long userId) { + LikeTargetFetcher targetFetcher = getFetcher(targetType); + + return targetFetcher.isTargetViewable(targetId, userId); + } + + public Map fetchByTypeAndIds( + LikeTargetType targetType, + Set targetIds, + Long userId + ) { + LikeTargetFetcher targetFetcher = getFetcher(targetType); + + return targetFetcher.fetchByIds(targetIds, userId); + } + + private LikeTargetFetcher getFetcher(LikeTargetType targetType) { + LikeTargetFetcher fetcher = fetcherMap.get(targetType); + if (fetcher == null) { + throw new BizException(LikeErrorCode.INVALID_LIKE_TYPE); + } + + return fetcher; + } +} diff --git a/src/main/java/project/flipnote/like/service/fetcher/LikeCardSetFetcher.java b/src/main/java/project/flipnote/like/service/fetcher/LikeCardSetFetcher.java index 2c45c2d1..c6acecd6 100644 --- a/src/main/java/project/flipnote/like/service/fetcher/LikeCardSetFetcher.java +++ b/src/main/java/project/flipnote/like/service/fetcher/LikeCardSetFetcher.java @@ -10,8 +10,8 @@ import lombok.RequiredArgsConstructor; import project.flipnote.cardset.service.CardSetService; import project.flipnote.like.entity.LikeTargetType; -import project.flipnote.like.model.CardSetLikeResponse; -import project.flipnote.like.model.LikeTargetResponse; +import project.flipnote.like.model.response.CardSetLikeResponse; +import project.flipnote.like.model.response.LikeTargetResponse; @RequiredArgsConstructor @Component @@ -25,7 +25,12 @@ public LikeTargetType getTargetType() { } @Override - public Map fetchByIds(Set ids) { + public boolean isTargetViewable(Long targetId, Long userId) { + return cardSetService.isCardSetViewable(targetId, userId); + } + + @Override + public Map fetchByIds(Set ids, Long userId) { return cardSetService.getCardSetsByIds(ids).stream() .map(CardSetLikeResponse::from) .collect(Collectors.toMap(LikeTargetResponse::getId, Function.identity())); diff --git a/src/main/java/project/flipnote/like/service/fetcher/LikeTargetFetcher.java b/src/main/java/project/flipnote/like/service/fetcher/LikeTargetFetcher.java index 73339084..a14865aa 100644 --- a/src/main/java/project/flipnote/like/service/fetcher/LikeTargetFetcher.java +++ b/src/main/java/project/flipnote/like/service/fetcher/LikeTargetFetcher.java @@ -4,10 +4,12 @@ import java.util.Set; import project.flipnote.like.entity.LikeTargetType; -import project.flipnote.like.model.LikeTargetResponse; +import project.flipnote.like.model.response.LikeTargetResponse; public interface LikeTargetFetcher { LikeTargetType getTargetType(); - Map fetchByIds(Set ids); + boolean isTargetViewable(Long targetId, Long userId); + + Map fetchByIds(Set targetIds, Long userId); }