Skip to content

Commit 4fd0240

Browse files
MEOHINdevnneth
andauthored
[feat/refactor] 나만의 bar API 분리 및 추가 #258 (#264)
* feat: MyBarIdResponseDto 추가 및 필드 정의 * feat: 마이바(MyBar) 목록 전체 조회 메서드 추가 (페이징 X) * refactor: MyBar 목록 조회를 ID 목록과 상세 목록으로 분리 * feat: MyBar Controller에 경량 ID 목록 조회 API 추가 및 상세 목록 분리 * test: MyBar 목록 조회 API 분리 및 테스트 코드 업데이트 --------- Co-authored-by: develosopher <[email protected]>
1 parent 983ac03 commit 4fd0240

File tree

5 files changed

+123
-123
lines changed

5 files changed

+123
-123
lines changed

src/main/java/com/back/domain/mybar/controller/MyBarController.java

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
package com.back.domain.mybar.controller;
22

3+
import com.back.domain.mybar.dto.MyBarIdResponseDto;
34
import com.back.domain.mybar.dto.MyBarListResponseDto;
45
import com.back.domain.mybar.service.MyBarService;
56
import com.back.global.rsData.RsData;
67
import com.back.global.security.SecurityUser;
78
import io.swagger.v3.oas.annotations.Operation;
89
import jakarta.validation.constraints.Max;
910
import jakarta.validation.constraints.Min;
11+
import java.time.LocalDateTime;
12+
import java.util.List;
1013
import lombok.RequiredArgsConstructor;
1114
import org.springframework.format.annotation.DateTimeFormat;
1215
import org.springframework.security.access.prepost.PreAuthorize;
1316
import org.springframework.security.core.annotation.AuthenticationPrincipal;
1417
import org.springframework.validation.annotation.Validated;
15-
import org.springframework.web.bind.annotation.*;
16-
17-
import java.time.LocalDateTime;
18+
import org.springframework.web.bind.annotation.DeleteMapping;
19+
import org.springframework.web.bind.annotation.GetMapping;
20+
import org.springframework.web.bind.annotation.PathVariable;
21+
import org.springframework.web.bind.annotation.PostMapping;
22+
import org.springframework.web.bind.annotation.RequestMapping;
23+
import org.springframework.web.bind.annotation.RequestParam;
24+
import org.springframework.web.bind.annotation.RestController;
1825

1926
@RestController
2027
@RequestMapping("/me/bar")
@@ -23,41 +30,32 @@
2330
@PreAuthorize("isAuthenticated()")
2431
public class MyBarController {
2532

26-
/**
27-
* 내 바(킵) API 컨트롤러.
28-
* 내가 킵한 칵테일 목록 조회, 킵 추가/복원, 킵 해제를 제공합니다.
29-
*/
30-
3133
private final MyBarService myBarService;
3234

33-
/**
34-
* 내 바 목록 조회(무한스크롤)
35-
* @param userId 인증된 사용자 ID
36-
* @param lastKeptAt 이전 페이지 마지막 keptAt (옵션)
37-
* @param lastId 이전 페이지 마지막 id (옵션)
38-
* @param limit 페이지 크기(1~100)
39-
* @return 킵 아이템 목록과 다음 페이지 커서
40-
*/
4135
@GetMapping
42-
@Operation(summary = "내 바 목록", description = "내가 킵한 칵테일 목록 조회. 무한 스크롤 커서 지원")
43-
public RsData<MyBarListResponseDto> getMyBarList(
36+
@Operation(summary = "내 바 경량 목록", description = "찜 ID 목록을 반환합니다.")
37+
public RsData<List<MyBarIdResponseDto>> getMyBarIds(
38+
@AuthenticationPrincipal SecurityUser principal
39+
) {
40+
Long userId = principal.getId();
41+
List<MyBarIdResponseDto> body = myBarService.getMyBarIds(userId);
42+
return RsData.successOf(body);
43+
}
44+
45+
@GetMapping("/detail")
46+
@Operation(summary = "내 바 상세 목록", description = "커서 기반으로 상세 찜 정보를 반환합니다.")
47+
public RsData<MyBarListResponseDto> getMyBarDetail(
4448
@AuthenticationPrincipal SecurityUser principal,
4549
@RequestParam(required = false)
4650
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime lastKeptAt,
4751
@RequestParam(required = false) Long lastId,
48-
@RequestParam(defaultValue = "20") @Min(1) @Max(100) int limit
52+
@RequestParam(defaultValue = "50") @Min(1) @Max(100) int limit
4953
) {
5054
Long userId = principal.getId();
51-
MyBarListResponseDto body = myBarService.getMyBar(userId, lastKeptAt, lastId, limit);
55+
MyBarListResponseDto body = myBarService.getMyBarDetail(userId, lastKeptAt, lastId, limit);
5256
return RsData.successOf(body);
5357
}
5458

55-
/**
56-
* 킵 추가(생성/복원/재킵)
57-
* @param userId 인증된 사용자 ID
58-
* @param cocktailId 칵테일 ID
59-
* @return 201 kept
60-
*/
6159
@PostMapping("/{cocktailId}/keep")
6260
@Operation(summary = "킵 추가/복원", description = "해당 칵테일을 내 바에 킵합니다. 이미 삭제 상태면 복원")
6361
public RsData<Void> keep(
@@ -66,15 +64,9 @@ public RsData<Void> keep(
6664
) {
6765
Long userId = principal.getId();
6866
myBarService.keep(userId, cocktailId);
69-
return RsData.of(201, "kept"); // Aspect가 HTTP 201로 설정
67+
return RsData.of(201, "kept");
7068
}
7169

72-
/**
73-
* 킵 해제(소프트 삭제) — 멱등
74-
* @param userId 인증된 사용자 ID
75-
* @param cocktailId 칵테일 ID
76-
* @return 200 deleted
77-
*/
7870
@DeleteMapping("/{cocktailId}/keep")
7971
@Operation(summary = "킵 해제", description = "내 바에서 해당 칵테일을 삭제(소프트 삭제, 멱등)")
8072
public RsData<Void> unkeep(
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.back.domain.mybar.dto;
2+
3+
import com.back.domain.mybar.entity.MyBar;
4+
import java.time.LocalDateTime;
5+
import lombok.Builder;
6+
import lombok.Getter;
7+
8+
@Getter
9+
@Builder
10+
public class MyBarIdResponseDto {
11+
private Long id;
12+
private Long cocktailId;
13+
private LocalDateTime keptAt;
14+
15+
public static MyBarIdResponseDto from(MyBar myBar) {
16+
return MyBarIdResponseDto.builder()
17+
.id(myBar.getId())
18+
.cocktailId(myBar.getCocktail().getId())
19+
.keptAt(myBar.getKeptAt())
20+
.build();
21+
}
22+
}

src/main/java/com/back/domain/mybar/repository/MyBarRepository.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515

1616
@Repository
1717
public interface MyBarRepository extends JpaRepository<MyBar, Long> {
18-
/** 나만의 bar(킵) 목록: ACTIVE만, id desc */
18+
/** 나만의 bar(킵) 목록: ACTIVE만, keptAt desc + id desc */
1919
Page<MyBar> findByUser_IdAndStatusOrderByKeptAtDescIdDesc(Long userId, KeepStatus status, Pageable pageable);
2020

21+
List<MyBar> findByUser_IdAndStatusOrderByKeptAtDescIdDesc(Long userId, KeepStatus status);
22+
2123
@Query("""
2224
select m from MyBar m
2325
where m.user.id = :userId

src/main/java/com/back/domain/mybar/service/MyBarService.java

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
package com.back.domain.mybar.service;
22

33
import com.back.domain.cocktail.repository.CocktailRepository;
4+
import com.back.domain.mybar.dto.MyBarIdResponseDto;
45
import com.back.domain.mybar.dto.MyBarItemResponseDto;
56
import com.back.domain.mybar.dto.MyBarListResponseDto;
67
import com.back.domain.mybar.entity.MyBar;
78
import com.back.domain.mybar.enums.KeepStatus;
89
import com.back.domain.mybar.repository.MyBarRepository;
910
import com.back.domain.user.repository.UserRepository;
1011
import com.back.domain.user.service.AbvScoreService;
12+
import java.time.LocalDateTime;
13+
import java.util.List;
14+
import java.util.Optional;
15+
import java.util.stream.Collectors;
1116
import lombok.RequiredArgsConstructor;
1217
import org.springframework.data.domain.Page;
1318
import org.springframework.data.domain.PageRequest;
1419
import org.springframework.data.domain.Pageable;
1520
import org.springframework.stereotype.Service;
1621
import org.springframework.transaction.annotation.Transactional;
1722

18-
import java.time.LocalDateTime;
19-
import java.util.ArrayList;
20-
import java.util.List;
21-
import java.util.Optional;
22-
2323
@Service
2424
@RequiredArgsConstructor
2525
public class MyBarService {
@@ -33,7 +33,15 @@ public class MyBarService {
3333
// - 커서: lastKeptAt + lastId 조합으로 안정적인 정렬/페이지네이션
3434
// - 첫 페이지: 가장 최근 keptAt 기준으로 최신순
3535
@Transactional(readOnly = true)
36-
public MyBarListResponseDto getMyBar(Long userId, LocalDateTime lastKeptAt, Long lastId, int limit) {
36+
public List<MyBarIdResponseDto> getMyBarIds(Long userId) {
37+
List<MyBar> rows = myBarRepository.findByUser_IdAndStatusOrderByKeptAtDescIdDesc(userId, KeepStatus.ACTIVE);
38+
return rows.stream()
39+
.map(MyBarIdResponseDto::from)
40+
.collect(Collectors.toList());
41+
}
42+
43+
@Transactional(readOnly = true)
44+
public MyBarListResponseDto getMyBarDetail(Long userId, LocalDateTime lastKeptAt, Long lastId, int limit) {
3745
int safeLimit = Math.max(1, Math.min(limit, 100));
3846
int fetchSize = safeLimit + 1; // 다음 페이지 여부 판단용으로 1개 더 조회
3947

@@ -50,10 +58,13 @@ public MyBarListResponseDto getMyBar(Long userId, LocalDateTime lastKeptAt, Long
5058

5159
// +1 로우가 있으면 다음 페이지가 존재
5260
boolean hasNext = rows.size() > safeLimit;
53-
if (hasNext) rows = rows.subList(0, safeLimit);
61+
if (hasNext) {
62+
rows = rows.subList(0, safeLimit);
63+
}
5464

55-
List<MyBarItemResponseDto> items = new ArrayList<>();
56-
for (MyBar myBar : rows) items.add(MyBarItemResponseDto.from(myBar));
65+
List<MyBarItemResponseDto> items = rows.stream()
66+
.map(MyBarItemResponseDto::from)
67+
.collect(Collectors.toList());
5768

5869
LocalDateTime nextKeptAt = null;
5970
Long nextId = null;

0 commit comments

Comments
 (0)