-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
enhancementNew feature or requestNew feature or request
Description
๐ ์กฐํ API 3์ข ๊ตฌํ ์๋ฃ
๐ ์ด์ ๊ฐ์
ํ์ ๋ฆฌ๋ทฐ, ๊ฐ๊ฒ ๋ฏธ์ , ํ์ ๋ฏธ์ ์กฐํ๋ฅผ ์ํ REST API 3์ข ์ ๊ตฌํํ์์ต๋๋ค.
โ ๊ตฌํ ์๋ฃ API ๋ชฉ๋ก
1๏ธโฃ ๋ด๊ฐ ์์ฑํ ๋ฆฌ๋ทฐ ๋ชฉ๋ก ์กฐํ API
- API Path:
GET /api/members/{memberId}/reviews - ๊ธฐ๋ฅ: ํน์ ํ์์ด ์์ฑํ ๋ฆฌ๋ทฐ ๋ชฉ๋ก์ ํ์ด์งํ์ฌ ์กฐํ
- ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ:
page(๊ธฐ๋ณธ๊ฐ: 0) - ํ์ด์ง ๋ฒํธsize(๊ธฐ๋ณธ๊ฐ: 10) - ํ์ด์ง ํฌ๊ธฐ
- ์๋ต ์ฝ๋:
REVIEW200_4
2๏ธโฃ ํน์ ๊ฐ๊ฒ์ ๋ฏธ์ ๋ชฉ๋ก ์กฐํ API
- API Path:
GET /api/stores/{storeId}/missions - ๊ธฐ๋ฅ: ํน์ ๊ฐ๊ฒ์ ๋ฏธ์ ๋ชฉ๋ก์ ํ์ด์งํ์ฌ ์กฐํ
- ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ:
page(๊ธฐ๋ณธ๊ฐ: 0) - ํ์ด์ง ๋ฒํธsize(๊ธฐ๋ณธ๊ฐ: 10) - ํ์ด์ง ํฌ๊ธฐ
- ์๋ต ์ฝ๋:
MISSION200_7
3๏ธโฃ ๋ด๊ฐ ์งํ ์ค์ธ ๋ฏธ์ ๋ชฉ๋ก ์กฐํ API
- API Path:
GET /api/members/{memberId}/missions - ๊ธฐ๋ฅ: ํน์ ํ์์ด ์งํ ์ค์ธ ๋ฏธ์ ๋ชฉ๋ก์ ํ์ด์งํ์ฌ ์กฐํ
- ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ:
page(๊ธฐ๋ณธ๊ฐ: 0) - ํ์ด์ง ๋ฒํธsize(๊ธฐ๋ณธ๊ฐ: 10) - ํ์ด์ง ํฌ๊ธฐ
- ์๋ต ์ฝ๋:
MISSION200_8
๐ง ๊ตฌํ ์ธ๋ถ์ฌํญ
API 1: ๋ด๊ฐ ์์ฑํ ๋ฆฌ๋ทฐ ๋ชฉ๋ก ์กฐํ
์์ฑ/์์ ๋ ํ์ผ
- โ
ReviewController.java- GET ์๋ํฌ์ธํธ ์ถ๊ฐ - โ
ReviewQueryService.java- ์ธํฐํ์ด์ค ๋ฉ์๋ ์ถ๊ฐ - โ
ReviewQueryServiceImpl.java- ์กฐํ ๋ก์ง ๊ตฌํ - โ
ReviewResDTO.java-MyReviewPageDTO,MyReviewDTO์ถ๊ฐ - โ
ReviewConverter.java- DTO ๋ณํ ๋ฉ์๋ ์ถ๊ฐ - โ
ReviewRepository.java-findByMemberId()๋ฉ์๋ ์ถ๊ฐ - โ
ReviewSuccessCode.java-MY_REVIEW_LIST_RETRIEVED์ฝ๋ ์ถ๊ฐ
์ฃผ์ ๊ธฐ๋ฅ
- ํ์ ID๋ก ์์ฑํ ๋ฆฌ๋ทฐ ์กฐํ
- ์ต์ ์ ์ ๋ ฌ (createdAt DESC)
- ํ์ด์ง ์ฒ๋ฆฌ ์ง์
- ๊ฐ๊ฒ ์ ๋ณด ํฌํจ (Join Fetch ์ต์ ํ ๊ฐ๋ฅ)
์๋ต ์์
{
"isSuccess": true,
"code": "REVIEW200_4",
"message": "๋ด๊ฐ ์์ฑํ ๋ฆฌ๋ทฐ ๋ชฉ๋ก ์กฐํ์ ์ฑ๊ณตํ์ต๋๋ค.",
"result": {
"currentPage": 0,
"totalPages": 3,
"totalElements": 25,
"pageSize": 10,
"hasNext": true,
"hasPrevious": false,
"reviews": [
{
"reviewId": 15,
"storeId": 5,
"storeName": "๋ง์๋ ๋ก๋ณถ์ด",
"star": 5,
"content": "์ ๋ง ๋ง์์ด์!",
"createdAt": "2025-11-20T14:30:00"
}
]
}
}API 2: ํน์ ๊ฐ๊ฒ์ ๋ฏธ์ ๋ชฉ๋ก ์กฐํ
์์ฑ/์์ ๋ ํ์ผ
- โ
MissionController.java- GET ์๋ํฌ์ธํธ ์ถ๊ฐ - โ
MissionQueryService.java- ์ธํฐํ์ด์ค ๋ฉ์๋ ์ถ๊ฐ - โ
MissionQueryServiceImpl.java- ์กฐํ ๋ก์ง ๊ตฌํ - โ
MissionResDTO.java-MissionPageDTO,MissionDTO์ถ๊ฐ - โ
MissionConverter.java- DTO ๋ณํ ๋ฉ์๋ ์ถ๊ฐ - โ
MissionRepository.java-findByStoreId()๋ฉ์๋ ์ถ๊ฐ - โ
MissionSuccessCode.java-MISSION_LIST_RETRIEVED์ฝ๋ ์ถ๊ฐ
์ฃผ์ ๊ธฐ๋ฅ
- ๊ฐ๊ฒ ID๋ก ๋ฏธ์ ๋ชฉ๋ก ์กฐํ
- ๊ฐ๊ฒ ์กด์ฌ ์ฌ๋ถ ๊ฒ์ฆ
- ์ต์ ์ ์ ๋ ฌ (createdAt DESC)
- ํ์ด์ง ์ฒ๋ฆฌ ์ง์
- ์ฐธ์ฌ ์ธ์ ์ ํ์
์๋ต ์์
{
"isSuccess": true,
"code": "MISSION200_7",
"message": "ํน์ ๊ฐ๊ฒ์ ๋ฏธ์
๋ชฉ๋ก ์กฐํ์ ์ฑ๊ณตํ์ต๋๋ค.",
"result": {
"currentPage": 0,
"totalPages": 1,
"totalElements": 8,
"pageSize": 10,
"hasNext": false,
"hasPrevious": false,
"missions": [
{
"missionId": 3,
"conditional": "๋ก๋ณถ์ด 3ํ ๊ตฌ๋งค",
"point": 1000,
"deadline": "2025-12-31",
"createdAt": "2025-11-15T10:00:00",
"participantCount": 12
}
]
}
}API 3: ๋ด๊ฐ ์งํ ์ค์ธ ๋ฏธ์ ๋ชฉ๋ก ์กฐํ
์์ฑ/์์ ๋ ํ์ผ
- โ
MemberMissionRepository.java- ์ ๊ท ์์ฑ (member ํจํค์ง) - โ
MissionController.java- GET ์๋ํฌ์ธํธ ์ถ๊ฐ - โ
MissionQueryService.java- ์ธํฐํ์ด์ค ๋ฉ์๋ ์ถ๊ฐ - โ
MissionQueryServiceImpl.java- ์กฐํ ๋ก์ง ๊ตฌํ - โ
MissionResDTO.java-MyMissionPageDTO,MyMissionDTO์ถ๊ฐ - โ
MissionConverter.java- DTO ๋ณํ ๋ฉ์๋ ์ถ๊ฐ - โ
MissionSuccessCode.java-MY_MISSION_LIST_RETRIEVED์ฝ๋ ์ถ๊ฐ - โ
MissionCommandServiceImpl.java- import ์์
์ฃผ์ ๊ธฐ๋ฅ
- ํ์ ID๋ก ์งํ ์ค์ธ ๋ฏธ์ ์กฐํ
- ํ์ ์กด์ฌ ์ฌ๋ถ ๊ฒ์ฆ
- ์ต์ ์ ์ ๋ ฌ (createdAt DESC)
- ํ์ด์ง ์ฒ๋ฆฌ ์ง์
- ๋ฏธ์ ์๋ฃ ์ฌ๋ถ ํ์
- ๊ฐ๊ฒ ์ ๋ณด ํฌํจ
Repository ์ถ๊ฐ ๋ฉ์๋
// MemberMissionRepository
Page<MemberMission> findByMemberId(Long memberId, Pageable pageable);
boolean existsByMemberIdAndMissionId(Long memberId, Long missionId);
Page<MemberMission> findInProgress(@Param("memberId") Long memberId, Pageable pageable);
Page<MemberMission> findCompleted(@Param("memberId") Long memberId, Pageable pageable);์๋ต ์์
{
"isSuccess": true,
"code": "MISSION200_8",
"message": "๋ด๊ฐ ์งํ ์ค์ธ ๋ฏธ์
๋ชฉ๋ก ์กฐํ์ ์ฑ๊ณตํ์ต๋๋ค.",
"result": {
"currentPage": 0,
"totalPages": 2,
"totalElements": 15,
"pageSize": 10,
"hasNext": true,
"hasPrevious": false,
"missions": [
{
"memberMissionId": 1,
"missionId": 5,
"storeName": "๋ง์๋ ๋ก๋ณถ์ด",
"conditional": "๋ก๋ณถ์ด 3ํ ๊ตฌ๋งค",
"point": 1000,
"deadline": "2025-12-31",
"isComplete": false,
"startedAt": "2025-11-20T10:30:00"
}
]
}
}๐๏ธ ๊ณตํต ์ํคํ ์ฒ ํจํด
๋ชจ๋ ์กฐํ API๋ ๋์ผํ ๋ ์ด์ด๋ ์ํคํ ์ฒ๋ฅผ ๋ฐ๋ฆ ๋๋ค:
Controller โ QueryService โ Repository โ Entity
โ โ โ โ
์์ฒญ ์์ ๋น์ฆ๋์ค ๋ก์ง ๋ฐ์ดํฐ ์กฐํ DB ๋งคํ
โ โ
Converter โ DTO ๋ณํ
โ
Response ๋ฐํ
๊ณ์ธต๋ณ ์ญํ
-
Controller Layer
- HTTP ์์ฒญ ์์ ๋ฐ ๊ฒฝ๋ก ๋งคํ
- ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ ์ฒ๋ฆฌ (page, size)
- ์๋ต ํฌ๋งท ํต์ผ (
ApiResponse)
-
Service Layer
- ๋น์ฆ๋์ค ๋ก์ง ์คํ
- ์ํฐํฐ ์กด์ฌ ์ฌ๋ถ ๊ฒ์ฆ
- ํ์ด์ง ์ค์ (Pageable ์์ฑ)
-
Repository Layer
- JPA ๋ฉ์๋ ์ฟผ๋ฆฌ ๋๋ JPQL ์ฌ์ฉ
- ํ์ด์ง ์ง์ (
Page<T>๋ฐํ)
-
Converter Layer
- Entity โ DTO ๋ณํ
- Page ๊ฐ์ฒด ๋ฉํ๋ฐ์ดํฐ ์ถ์ถ
-
DTO Layer
- ์๋ต ๋ฐ์ดํฐ ๊ตฌ์กฐํ
- ํ์ด์ง ์ ๋ณด ํฌํจ
๐ฏ ๊ณตํต ๊ธฐ๋ฅ
ํ์ด์ง ์ฒ๋ฆฌ
- Spring Data JPA์
Pageableํ์ฉ - ๊ธฐ๋ณธ๊ฐ: page=0, size=10
- ์ ๋ ฌ: ์ต์ ์ (createdAt DESC)
์๋ฌ ์ฒ๋ฆฌ
- ์กด์ฌํ์ง ์๋ ํ์:
MemberException - ์กด์ฌํ์ง ์๋ ๊ฐ๊ฒ:
StoreException - ํต์ผ๋ ์๋ฌ ์๋ต ํฌ๋งท
์๋ต ๊ตฌ์กฐ
๋ชจ๋ API๋ ๋ค์ ์ ๋ณด๋ฅผ ํฌํจ:
currentPage: ํ์ฌ ํ์ด์ง ๋ฒํธtotalPages: ์ ์ฒด ํ์ด์ง ์totalElements: ์ ์ฒด ํญ๋ชฉ ์pageSize: ํ์ด์ง ํฌ๊ธฐhasNext: ๋ค์ ํ์ด์ง ์กด์ฌ ์ฌ๋ถhasPrevious: ์ด์ ํ์ด์ง ์กด์ฌ ์ฌ๋ถ[data]: ์ค์ ๋ฐ์ดํฐ ๋ฆฌ์คํธ
๐ ํด๊ฒฐํ ์ด์
MemberMissionRepository ์ค๋ณต ๋ฌธ์
- ๋ฌธ์ :
MemberMissionRepository๊ฐ member, mission ํจํค์ง์ ์ค๋ณต ์์ฑ - ์์ธ: Bean ์ด๋ฆ ์ถฉ๋ ๋ฐ์
- ํด๊ฒฐ:
- mission ํจํค์ง์ Repository ์ญ์
- member ํจํค์ง๋ก ํตํฉ
- ๋ชจ๋ ๋ฉ์๋ ๋ณํฉ
- import ๋ฌธ ์์
๐ ํ ์คํธ ๋ฐฉ๋ฒ
1. ๋ด๊ฐ ์์ฑํ ๋ฆฌ๋ทฐ ๋ชฉ๋ก ์กฐํ
GET http://localhost:8080/api/members/1/reviews?page=0&size=102. ํน์ ๊ฐ๊ฒ์ ๋ฏธ์ ๋ชฉ๋ก ์กฐํ
GET http://localhost:8080/api/stores/1/missions?page=0&size=103. ๋ด๊ฐ ์งํ ์ค์ธ ๋ฏธ์ ๋ชฉ๋ก ์กฐํ
GET http://localhost:8080/api/members/1/missions?page=0&size=10Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request