diff --git a/src/main/java/study/goorm/domain/cloth/domain/repository/ClothRepository.java b/src/main/java/study/goorm/domain/cloth/domain/repository/ClothRepository.java index dc3eeb7..02ec98f 100644 --- a/src/main/java/study/goorm/domain/cloth/domain/repository/ClothRepository.java +++ b/src/main/java/study/goorm/domain/cloth/domain/repository/ClothRepository.java @@ -3,6 +3,8 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import study.goorm.domain.cloth.domain.entity.Cloth; import study.goorm.domain.member.domain.entity.Member; @@ -24,4 +26,8 @@ public interface ClothRepository extends JpaRepository { Page findByMemberOrderByCreatedAtDesc(Member member, Pageable pageable); List findByMemberId(Long memberId); + + @Query("SELECT c FROM Cloth c WHERE c.id IN :ids AND c.member.id = :memberId") + List findAllByIdsAndMemberId(@Param("ids") List ids, @Param("memberId") Long memberId); + } diff --git a/src/main/java/study/goorm/domain/history/api/HistoryRestController.java b/src/main/java/study/goorm/domain/history/api/HistoryRestController.java index 7928130..69b1d22 100644 --- a/src/main/java/study/goorm/domain/history/api/HistoryRestController.java +++ b/src/main/java/study/goorm/domain/history/api/HistoryRestController.java @@ -89,6 +89,7 @@ public BaseResponse updateHistory( return BaseResponse.onSuccess(SuccessStatus.HISTORY_UPDATED, result); } + // 기록 삭제 @DeleteMapping("{history-id}") @Operation(summary = "유저의 날짜별 옷 기록을 삭제하는 API", description = "path variable로 history-id를 넘겨주세요.") @ApiResponses({ @@ -104,4 +105,31 @@ public BaseResponse deleteHistory( return BaseResponse.onSuccess(SuccessStatus.HISTORY_DELETED, null); } + + // 좋아요 추가 / 삭제 + @PostMapping("/like") + @Operation(summary = "기록의 좋아요를 추가하고 삭제하는 API", description = "request body에 좋아요 상태와 history-id를 넘겨주세요.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "HISTORY_LIKE_201", description = "CREATED, 좋아요 상태가 성공적으로 변경되었습니다..") + }) + public BaseResponse like( + @RequestBody @Valid HistoryRequestDTO.HistoryLikeRequest historyLikeRequest) { + + HistoryResponseDTO.HistoryLikeResult result = historyService.likeHistory(historyLikeRequest.getHistoryId(), historyLikeRequest.isLiked()); + + return BaseResponse.onSuccess(SuccessStatus.HISTORY_LIKE_CREATED, result); + } + + // 댓글 작성 + @PostMapping("/{historyId}/comments") + @Operation(summary = "댓글을 작성하는 API", description = "path variable에 history-id를 넘겨주시고, request body에 commentId와 content를 넘겨주세요.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "HISTORY_COMMENT_201", description = "CREATED, 댓글이 성공적으로 생성되었습니다.") + }) + public BaseResponse writeComment( + @PathVariable @Valid Long historyId, + @RequestBody @Valid HistoryRequestDTO.CommentWriteRequest commentWriteRequest) { + + return BaseResponse.onSuccess(SuccessStatus.HISTORY_COMMENT_CREATED, historyService.writeComment(historyId, commentWriteRequest.getCommentId(), commentWriteRequest.getContent())); + } } diff --git a/src/main/java/study/goorm/domain/history/application/HistoryService.java b/src/main/java/study/goorm/domain/history/application/HistoryService.java index b1077ba..8c9c392 100644 --- a/src/main/java/study/goorm/domain/history/application/HistoryService.java +++ b/src/main/java/study/goorm/domain/history/application/HistoryService.java @@ -9,6 +9,7 @@ public interface HistoryService { + // 기록 HistoryResponseDTO.MonthlyHistoryPreview getMonthlyPreview(String clokeyId, String date); HistoryResponseDTO.DailyHistoryPreview getDailyPreview(Long historyId); @@ -18,4 +19,10 @@ public interface HistoryService { HistoryResponseDTO.HistoryUpdateResult updateHistory(HistoryRequestDTO.HistoryUpdateRequest historyUpdateRequest, List imageFile, Long historyId); void deleteHistory(Long historyId); + + // 좋아요 + HistoryResponseDTO.HistoryLikeResult likeHistory(Long historyId, boolean liked); + + // 댓글 작성 + HistoryResponseDTO.CommentWriteResult writeComment(Long historyId, Long parentCommentId, String content); } diff --git a/src/main/java/study/goorm/domain/history/application/HistoryServiceImpl.java b/src/main/java/study/goorm/domain/history/application/HistoryServiceImpl.java index 646eae6..574e97c 100644 --- a/src/main/java/study/goorm/domain/history/application/HistoryServiceImpl.java +++ b/src/main/java/study/goorm/domain/history/application/HistoryServiceImpl.java @@ -34,8 +34,11 @@ public class HistoryServiceImpl implements HistoryService { private final ClothRepository clothRepository; private final HistoryClothRepository historyClothRepository; private final HashtagRepository hashtagRepository; + private final MemberLikeRepository memberLikeRepository; private final MinioClient minioClient; + public static final int IMAGE_LIMIT = 10; + // 월별 기록 조회 @Transactional(readOnly = true) @Override @@ -58,13 +61,12 @@ public HistoryResponseDTO.MonthlyHistoryPreview getMonthlyPreview(String clokeyI .orElseThrow(() -> new HistoryException(ErrorStatus.NO_SUCH_MEMBER)); } - // 기록 조회 + // 기록 조회, 리스트가 비어있다면 빈 리스트 반환 List histories = historyRepository.findHistoriesByMemberIdAndYearMonth(member.getId(), date); if (histories.isEmpty()) { - throw new HistoryException(ErrorStatus.NO_SUCH_HISTORY); + return HistoryConverter.toMonthlyHistoryPreview(member, Collections.emptyList(), Collections.emptyMap()); } - List historyIds = histories.stream() .map(History::getId) .collect(Collectors.toList()); @@ -72,7 +74,6 @@ public HistoryResponseDTO.MonthlyHistoryPreview getMonthlyPreview(String clokeyI // 사진 조회 List historyImages = historyImageRepository.findAllByHistoryIdIn(historyIds); - // historyId → 첫 번째 이미지 URL Map firstImagesOfHistory = historyImages.stream() .collect(Collectors.groupingBy( img -> img.getHistory().getId(), @@ -82,15 +83,7 @@ public HistoryResponseDTO.MonthlyHistoryPreview getMonthlyPreview(String clokeyI )) )); - List resultList = histories.stream() - .map(history -> HistoryResponseDTO.MonthlyHistoryItemResult.builder() - .historyId(history.getId()) - .date(history.getHistoryDate().toString()) - .imageUrl(firstImagesOfHistory.getOrDefault(history.getId(), "비공개입니다")) - .build()) - .collect(Collectors.toList()); - - return HistoryConverter.toMonthlyHistoryPreview(member, resultList); + return HistoryConverter.toMonthlyHistoryPreview(member, histories, firstImagesOfHistory); } // 일별 기록 조회 @@ -126,16 +119,7 @@ public HistoryResponseDTO.DailyHistoryPreview getDailyPreview(Long historyId) { List cloths = clothRepository.findByMemberId(member.getId()); - List clothPreviews = cloths.stream() - .map(cloth -> HistoryResponseDTO.DailyHistoryClothesPreview.builder() - .clothId(cloth.getId()) - .clothImageUrl(cloth.getClothUrl()) // 이미지 필드 맞게 수정 - .clothName(cloth.getName()) - .build()) - .toList(); - - - return HistoryConverter.toDailyHistoryPreview(member, history, images, hashtagNameList, commentCount, clothPreviews); + return HistoryConverter.toDailyHistoryPreview(member, history, images, hashtagNameList, commentCount, cloths); } // 날짜별 옷 기록 추가 @@ -144,7 +128,7 @@ public HistoryResponseDTO.DailyHistoryPreview getDailyPreview(Long historyId) { public HistoryResponseDTO.HistoryCreateResult createHistory(HistoryRequestDTO.HistoryCreateRequest historyCreateRequest, List image) { // 이미지 업로드 개수 제한 - if (image.size() >= 10) { + if (image.size() >= IMAGE_LIMIT) { throw new HistoryException(ErrorStatus.TOO_MANY_IMAGES); } @@ -164,15 +148,12 @@ public HistoryResponseDTO.HistoryCreateResult createHistory(HistoryRequestDTO.Hi // clothId 검증 List requestedIds = historyCreateRequest.getClothes(); - for (Long id : requestedIds) { - boolean exists = clothRepository.existsById(id); - if (!exists) { - throw new HistoryException(ErrorStatus.NO_SUCH_CLOTH); - } - } + // DB에서 요청된 clothId 전부 가져옴 + List clothes = clothRepository.findAllByIdsAndMemberId(requestedIds, member.getId()); - // ClothId 기록 - List clothes = clothRepository.findAllById(requestedIds); + if (clothes.size() != requestedIds.size()) { + throw new HistoryException(ErrorStatus.NO_SUCH_CLOTH); + } List historyClothes = clothes.stream() .map(cloth -> HistoryCloth.builder() @@ -261,7 +242,7 @@ public HistoryResponseDTO.HistoryCreateResult createHistory(HistoryRequestDTO.Hi @Override public HistoryResponseDTO.HistoryUpdateResult updateHistory(HistoryRequestDTO.HistoryUpdateRequest request, List images, Long historyId) { - if (images.size() >= 10) { + if (images.size() >= IMAGE_LIMIT) { throw new HistoryException(ErrorStatus.TOO_MANY_IMAGES); } @@ -281,7 +262,12 @@ public HistoryResponseDTO.HistoryUpdateResult updateHistory(HistoryRequestDTO.Hi // 새로운 clothes 저장 List clothIds = request.getClothes(); - List clothes = clothRepository.findAllById(clothIds); + + List clothes = clothRepository.findAllByIdsAndMemberId(clothIds, member.getId()); + + if (clothes.size() != clothIds.size()) { + throw new HistoryException(ErrorStatus.NO_SUCH_CLOTH); + } List historyClothes = clothes.stream() .map(cloth -> HistoryCloth.builder() @@ -332,13 +318,13 @@ public HistoryResponseDTO.HistoryUpdateResult updateHistory(HistoryRequestDTO.Hi try { objectName = url.substring(url.lastIndexOf("/") + 1); } catch (Exception ex) { - System.err.println("❌ URL에서 objectName 추출 실패: " + url); + System.err.println("URL에서 objectName 추출 실패: " + url); continue; } // MinIO에서 삭제 시도 try { - System.out.println("🗑️ MinIO 삭제 시도: " + objectName); + System.out.println("MinIO 삭제 시도: " + objectName); minioClient.removeObject( RemoveObjectArgs.builder() @@ -347,9 +333,9 @@ public HistoryResponseDTO.HistoryUpdateResult updateHistory(HistoryRequestDTO.Hi .build() ); - System.out.println("✅ 삭제 성공: " + objectName); + System.out.println("삭제 성공: " + objectName); } catch (Exception e) { - System.err.println("❌ 삭제 실패: " + objectName + ", 이유: " + e.getMessage()); + System.err.println("삭제 실패: " + objectName + ", 이유: " + e.getMessage()); throw new HistoryException(ErrorStatus.MINIO_DELETE_FAILED); // 정의 필요 } } @@ -358,6 +344,7 @@ public HistoryResponseDTO.HistoryUpdateResult updateHistory(HistoryRequestDTO.Hi // DB에서 HistoryImage 삭제 historyImageRepository.deleteAllByHistory(history); + // 중복 // 새 이미지 업로드 및 저장 for (MultipartFile file : images) { String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename(); @@ -430,4 +417,74 @@ public void deleteHistory(Long historyId) { // 해당 기록 삭제 historyRepository.delete(history); } -} + + // 좋아요 추가 및 삭제 + @Transactional + @Override + public HistoryResponseDTO.HistoryLikeResult likeHistory(Long historyId, boolean isLiked) { + + // 로그인 된 계정 + Member member = memberRepository.findById(1L) + .orElseThrow(() -> new HistoryException(ErrorStatus.NO_SUCH_MEMBER)); + + History history = historyRepository.findById(historyId) + .orElseThrow(() -> new HistoryException(ErrorStatus.NO_SUCH_HISTORY)); + + if (isLiked) { + history.decreaseLikes(); + memberLikeRepository.deleteByMemberIdAndHistoryId(member.getId(), historyId); + } else { + history.increaseLikes(); + + MemberLike memberLike = MemberLike.builder() + .member(member) + .history(history) + .build(); + + memberLikeRepository.save(memberLike); + } + + return HistoryConverter.toHistoryLikeResult(history, isLiked); + } + + @Transactional + @Override + public HistoryResponseDTO.CommentWriteResult writeComment(Long historyId, Long parentCommentId, String content) { + + Member member = memberRepository.findById(1L) + .orElseThrow(() -> new HistoryException(ErrorStatus.NO_SUCH_MEMBER)); + + History history = historyRepository.findById(historyId) + .orElseThrow(() -> new HistoryException(ErrorStatus.NO_SUCH_HISTORY)); + + Comment parentComment = null; + + // 상위 댓글이 존재하는지 확인 + if (parentCommentId != null) { + parentComment = commentRepository.findById(parentCommentId) + .orElseThrow(() -> new HistoryException(ErrorStatus.NO_SUCH_COMMENT)); + + // 대댓글까지만 가능하도록 처리 + if (parentComment.getComment() != null) { + throw new HistoryException(ErrorStatus.TOO_DEEP_REPLY); + } + + // 같은 히스토리인지 확인 + if (!parentComment.getHistory().getId().equals(historyId)) { + throw new HistoryException(ErrorStatus.PARENT_COMMENT_HISTORY); + } + } + + // 댓글 엔티티 생성 + Comment comment = Comment.builder() + .content(content) + .comment(parentComment) // null이면 일반 댓글, 아니면 대댓글 + .history(history) + .member(member) + .build(); + + Comment result = commentRepository.save(comment); + + return HistoryConverter.toCommentWriteResult(result); + } +} \ No newline at end of file diff --git a/src/main/java/study/goorm/domain/history/converter/HistoryConverter.java b/src/main/java/study/goorm/domain/history/converter/HistoryConverter.java index 63b0f75..d89407c 100644 --- a/src/main/java/study/goorm/domain/history/converter/HistoryConverter.java +++ b/src/main/java/study/goorm/domain/history/converter/HistoryConverter.java @@ -1,6 +1,7 @@ package study.goorm.domain.history.converter; import study.goorm.domain.cloth.domain.entity.Cloth; +import study.goorm.domain.history.domain.entity.Comment; import study.goorm.domain.history.domain.entity.Hashtag; import study.goorm.domain.history.domain.entity.History; import study.goorm.domain.history.domain.entity.HistoryImage; @@ -9,15 +10,28 @@ import java.util.List; import java.util.Map; +import java.util.stream.Collectors; public class HistoryConverter { - public static HistoryResponseDTO.MonthlyHistoryPreview toMonthlyHistoryPreview(Member member, List result) { + // 기록 + public static HistoryResponseDTO.MonthlyHistoryPreview toMonthlyHistoryPreview ( + Member member, + List histories, + Map firstImagesOfHistory) { return HistoryResponseDTO.MonthlyHistoryPreview.builder() .memberId(member.getId()) .nickName(member.getNickname()) - .histories(result) + .histories( + histories.stream() + .map(history -> HistoryResponseDTO.MonthlyHistoryItemResult.builder() + .historyId(history.getId()) + .date(history.getHistoryDate().toString()) + .imageUrl(firstImagesOfHistory.getOrDefault(history.getId(), "비공개입니다")) + .build()) + .collect(Collectors.toList()) + ) .build(); } @@ -27,7 +41,7 @@ public static HistoryResponseDTO.DailyHistoryPreview toDailyHistoryPreview( List images, List hashtags, long commentCount, - List cloths + List cloths ) { return HistoryResponseDTO.DailyHistoryPreview.builder() @@ -42,7 +56,15 @@ public static HistoryResponseDTO.DailyHistoryPreview toDailyHistoryPreview( .likeCount(history.getLikes()) .commentCount(commentCount) .date(history.getHistoryDate()) - .cloths(cloths) + .cloths( + cloths.stream() + .map(cloth -> HistoryResponseDTO.DailyHistoryClothesPreview.builder() + .clothId(cloth.getId()) + .clothImageUrl(cloth.getClothUrl()) + .clothName(cloth.getName()) + .build()) + .collect(Collectors.toList()) + ) .build(); } @@ -57,4 +79,20 @@ public static HistoryResponseDTO.HistoryUpdateResult toHistoryUpdateResult(Histo .historyId(history.getId()) .build(); } + + // 좋아요 추가 / 삭제 + public static HistoryResponseDTO.HistoryLikeResult toHistoryLikeResult(History history, boolean isLiked) { + return HistoryResponseDTO.HistoryLikeResult.builder() + .historyId(history.getId()) + .isLiked(isLiked) + .likeCount(history.getLikes()) + .build(); + } + + // 댓글 작성 + public static HistoryResponseDTO.CommentWriteResult toCommentWriteResult(Comment comment) { + return HistoryResponseDTO.CommentWriteResult.builder() + .commentId(comment.getId()) + .build(); + } } diff --git a/src/main/java/study/goorm/domain/history/domain/entity/History.java b/src/main/java/study/goorm/domain/history/domain/entity/History.java index fdf455c..dac9903 100644 --- a/src/main/java/study/goorm/domain/history/domain/entity/History.java +++ b/src/main/java/study/goorm/domain/history/domain/entity/History.java @@ -33,12 +33,22 @@ public class History extends BaseEntity { @Column(length = 200) private String content; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", nullable = false) + private Member member; + // update 메서드 추가 + public void update(String content) { this.content = content; } + public void increaseLikes() { + this.likes++; + } - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "member_id", nullable = false) - private Member member; + public void decreaseLikes() { + if (this.likes > 0) { + this.likes--; + } + } } \ No newline at end of file diff --git a/src/main/java/study/goorm/domain/history/domain/repository/HashtagHistoryRepository.java b/src/main/java/study/goorm/domain/history/domain/repository/HashtagHistoryRepository.java index f1f0ccc..b27e270 100644 --- a/src/main/java/study/goorm/domain/history/domain/repository/HashtagHistoryRepository.java +++ b/src/main/java/study/goorm/domain/history/domain/repository/HashtagHistoryRepository.java @@ -1,6 +1,8 @@ package study.goorm.domain.history.domain.repository; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import study.goorm.domain.history.domain.entity.HashtagHistory; import study.goorm.domain.history.domain.entity.History; @@ -8,8 +10,8 @@ public interface HashtagHistoryRepository extends JpaRepository { - // History - List findByHistoryId(Long historyId); + @Query("SELECT hh FROM HashtagHistory hh JOIN FETCH hh.hashtag WHERE hh.history.id = :historyId") + List findByHistoryId(@Param("historyId") Long historyId); void deleteByHistory(History history); void deleteAllByHistory(History history); } diff --git a/src/main/java/study/goorm/domain/history/domain/repository/MemberLikeRepository.java b/src/main/java/study/goorm/domain/history/domain/repository/MemberLikeRepository.java index d870309..efdc82b 100644 --- a/src/main/java/study/goorm/domain/history/domain/repository/MemberLikeRepository.java +++ b/src/main/java/study/goorm/domain/history/domain/repository/MemberLikeRepository.java @@ -1,7 +1,11 @@ package study.goorm.domain.history.domain.repository; import org.springframework.data.jpa.repository.JpaRepository; +import study.goorm.domain.history.domain.entity.History; import study.goorm.domain.history.domain.entity.MemberLike; +import study.goorm.domain.member.domain.entity.Member; public interface MemberLikeRepository extends JpaRepository { + + void deleteByMemberIdAndHistoryId(Long memberId, Long historyId); } diff --git a/src/main/java/study/goorm/domain/history/dto/HistoryRequestDTO.java b/src/main/java/study/goorm/domain/history/dto/HistoryRequestDTO.java index 6679f2c..69b17ac 100644 --- a/src/main/java/study/goorm/domain/history/dto/HistoryRequestDTO.java +++ b/src/main/java/study/goorm/domain/history/dto/HistoryRequestDTO.java @@ -43,4 +43,28 @@ public static class HistoryUpdateRequest { private Visibility visibility; } + + // 좋아요 + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class HistoryLikeRequest { + + private Long historyId; + + private boolean liked; + } + + // 댓글 작성 + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class CommentWriteRequest { + + private Long commentId; + + private String content; + } } diff --git a/src/main/java/study/goorm/domain/history/dto/HistoryResponseDTO.java b/src/main/java/study/goorm/domain/history/dto/HistoryResponseDTO.java index 3b2b371..4667d35 100644 --- a/src/main/java/study/goorm/domain/history/dto/HistoryResponseDTO.java +++ b/src/main/java/study/goorm/domain/history/dto/HistoryResponseDTO.java @@ -77,4 +77,28 @@ public static class HistoryUpdateResult { private Long historyId; } + + // 좋아요 + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class HistoryLikeResult { + + private Long historyId; + + private boolean isLiked; + + private int likeCount; + } + + // 댓글 작성 + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class CommentWriteResult { + + private Long commentId; + } } diff --git a/src/main/java/study/goorm/global/error/code/status/ErrorStatus.java b/src/main/java/study/goorm/global/error/code/status/ErrorStatus.java index 3b89301..c3cb798 100644 --- a/src/main/java/study/goorm/global/error/code/status/ErrorStatus.java +++ b/src/main/java/study/goorm/global/error/code/status/ErrorStatus.java @@ -31,6 +31,10 @@ public enum ErrorStatus implements BaseErrorCode{ NO_SUCH_HISTORY(HttpStatus.BAD_REQUEST, "HISTORY_4001", "기록이 존재하지 않습니다."), INVALID_DATE_FORMAT(HttpStatus.BAD_REQUEST, "HISTORY_4002", "날짜 형식이 맞지 않습니다."), NO_SUCH_HASHTAG(HttpStatus.BAD_REQUEST, "HISTORY_4003", "해당 해시태그가 존재하지 않습니다."), + NO_SUCH_COMMENT(HttpStatus.BAD_REQUEST, "HISTORY_4004", "해당 댓글이 존재하지 않습니다."), + PARENT_COMMENT_HISTORY(HttpStatus.BAD_REQUEST, "HISTORY_4005", "부모 댓글이 같은 히스토리에 속하지 않습니다."), + TOO_DEEP_REPLY(HttpStatus.BAD_REQUEST, "HISTORY_4006", "대댓글까지만 작성 가능합니다."), + // MINIO MINIO_UPLOAD_FAILED(HttpStatus.BAD_REQUEST, "MINIO_4001", "이미지 업로드에 실패했습니다."), diff --git a/src/main/java/study/goorm/global/error/code/status/SuccessStatus.java b/src/main/java/study/goorm/global/error/code/status/SuccessStatus.java index c3c3611..1439c02 100644 --- a/src/main/java/study/goorm/global/error/code/status/SuccessStatus.java +++ b/src/main/java/study/goorm/global/error/code/status/SuccessStatus.java @@ -20,7 +20,9 @@ public enum SuccessStatus implements BaseCode{ HISTORY_VIEW_SUCCESS(HttpStatus.OK, "HISTORY_200", "기록이 성공적으로 조회되었습니다."), HISTORY_CREATED(HttpStatus.CREATED, "HISTORY_201", "기록이 성공적으로 추가되었습니다."), HISTORY_UPDATED(HttpStatus.OK, "HISTORY_200", "기록이 성공적으로 수정되었습니다."), - HISTORY_DELETED(HttpStatus.NO_CONTENT, "HISTORY_202", "기록이 성공적으로 삭제되었습니다."); + HISTORY_DELETED(HttpStatus.NO_CONTENT, "HISTORY_202", "기록이 성공적으로 삭제되었습니다."), + HISTORY_LIKE_CREATED(HttpStatus.CREATED, "HISTORY_LIKE_201", "좋아요 상태가 성공적으로 변경되었습니다."), + HISTORY_COMMENT_CREATED(HttpStatus.CREATED, "HISTORY_COMMENT_201", "댓글이 성공적으로 생성되었습니다."); private final HttpStatus httpStatus; private final String code;