API 명세서 - 100-hours-a-week/5-yeosa-wiki GitHub Wiki
주요 변경사항
25.04.17. 피드백 반영 25.04.19. API 명세서문서화 25.05.28. API 수정(
GET /api/album/{albumId}
,PATCH /api/album/{albumId}/cluster/{clusterId}
,POST /api/album
)
📦 공통 Error Response
❗️401 Unauthorized – Access Token 만료
{
"code": "ACCESS_TOKEN_EXPIRED",
"message": "access token이 만료되었습니다.",
"data": null
}
❗️401 Unauthorized – Refresh Token 만료
{
"code": "REFRESH_TOKEN_EXPIRED",
"message": "refresh token이 만료되었습니다.",
"data": null
}
❗️500 Internal Server Error – 서버 오류
{
"code": "INTERNAL_SERVER_ERROR",
"message": "서버 오류가 발생했습니다.",
"data": null
}
공용 API
✅ Presigned URL 발급
- Endpoint:
/api/presigned-url
- HTTP Method:
POST
📥 Request
-
Request Header
Authorization: Bearer <access_token>
(필수)
-
Request Body
{ "pictures": [ { "pictureName": "photo1.png", "pictureType": "image/png" }, { "pictureName": "photo2.jpeg", "pictureType": "image/jpeg" }, { "pictureName": "photo3.webp", "pictureType": "image/webp" } ] }
✅ Success Response
-
200 OK – Presigned URL 발급 성공 (
PRESIGNED_URL_ISSUED
){ "presignedFiles": [ { "pictureName": "photo1.png", "presignedUrl": "https://bucket.s3.amazonaws.com/photo1.png?...", "pictureURL": "https://bucket.s3.amazonaws.com/photo1.png" }, { "pictureName": "photo2.jpeg", "presignedUrl": "https://bucket.s3.amazonaws.com/photo2.jpeg?...", "pictureURL": "https://bucket.s3.amazonaws.com/photo2.jpeg" }, { "pictureName": "photo3.webp", "presignedUrl": "https://bucket.s3.amazonaws.com/photo3.webp?...", "pictureURL": "https://bucket.s3.amazonaws.com/photo3.webp" } ] }
⚠️ Error Response
-
403 Forbidden – 앨범 멤버 아님
{ "code": "NOT_ALBUM_MEMBER", "message": "앨범 멤버가 아닙니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 프론트엔드에서 S3에 직접 이미지를 업로드할 수 있도록 Presigned URL을 발급합니다.
- 클라이언트는 해당 URL로 이미지를 업로드하고, 응답으로 받은
pictureURL
을 앨범 생성, 앨범에 사진 추가, 프로필 이미지 업로드 등의 API에 활용합니다. - 이 API는 앨범 생성 전, 또는 앨범에 사진을 추가하기 전에 실행되는 API입니다.
- 클라이언트는 해당 URL로 이미지를 업로드하고, 응답으로 받은
- 요청자는 해당 앨범의 멤버여야 하며, 그렇지 않으면 403 응답이 반환됩니다.
- 이 구조는 대용량 이미지 처리 시 백엔드 서버의 부담을 줄이고, 업로드 속도를 최적화하는 데 유리합니다.
- Presigned URL은 이미지 업로드만을 위해 사용되어야 하므로 짧은 수명을 가집니다.(5분 / 개발 중 실험을 통해 수명 확정 예정)
유저 관련
✅ 로그인 요청
- Endpoint:
/api/auth
- HTTP Method:
GET
📥 Request
- Request Params: 없음
- Request Body: 없음
📤 Response
-
302 Found
사용자를 카카오 로그인 페이지로 리디렉션
Location: https://kauth.kakao.com/oauth/authorize?response_type=code&client_id={REST_API_KEY}&redirect_uri={REDIRECT_URI}
⚠️ Error Response
- 에러 발생 없음 (리디렉션 전용 API)
🧩 설계 근거 및 시나리오
- 이 API는 온기 서비스에서 카카오 로그인 페이지로 이동시키기 위한 리디렉션용 API입니다.
- 클라이언트는 이 URL에 접근하면 카카오의 인증 페이지로 이동하고, 사용자는 카카오 로그인을 수행한 후
authorization code
를 포함한 응답을 받게 됩니다. - 그 후 클라이언트는
/api/auth/callback
으로 백엔드 서버에 해당 코드를 넘겨 토큰 발급 절차를 진행합니다.
✅ 로그인 (토큰 발급)
- Endpoint:
/api/auth/callback?code={authorization_code}
- HTTP Method:
POST
📥 Request
-
Request Params
authorization_code
(String): 카카오에서 발급한 authorization code
-
Request Body
- 없음
📤 Response
✅ Success Response
-
200 OK – 이미 등록된 사용자 (
USER_ALREADY_REGISTERED
){ "code": "USER_ALREADY_REGISTERED", "accessToken": "access_token_value", "refreshTokenExpiresIn": 1209600, "refreshToken": "refresh_token_value", "user": { "userId": 1, "nickname": "gray_123!", "profileImageURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/1.jpg", "cacheTtl": 300 } }
-
200 OK – 신규 사용자 (
USER_NOT_REGISTERED
){ "code": "USER_NOT_REGISTERED", "accessToken": "access_token_value", "refreshTokenExpiresIn": 1209600, "refreshToken": "refresh_token_value", "user": { "userId": 1, "nickname": "gray_123!", "profileImageURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/1.jpg", "cacheTtl": 300 } }
⚠️ Error Response
-
400 Bad Request
{ "code": "INVALID_REQUEST", "message": "인가 코드가 유효하지 않습니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 카카오 로그인 후 프론트로 전달한
authorization code
를 바탕으로 온기 서비스 전용 access token과 refresh token을 발급합니다. - 전달된 인가 코드를 기반으로
POST https://kauth.kakao.com/oauth/token
로 kakao api 사용 목적의 access token과 refresh token을 발급받습니다.- 전달받은 access token을 사용하여
GET https://kapi.kakao.com/v2/user/me
로 유저 정보를 요청합니다. - 제공받은 id를 user 테이블의 provider_id와 비교하여 가입 여부를 확인하여 로그인 처리하고, 미가입 유저 시 회원가입 처리시킵니다.
- 온기 서비스를 위한 별도의 access_token과 refresh_token을 생성하여 응답 body에 포함합니다.
- 전달받은 access token을 사용하여
- 사용자가 이미 가입된 경우와 처음 로그인하는 경우를 구분해 응답의
code
필드에 상태를 명시합니다. - 응답에는 인증 토큰과 함께 유저 정보가 포함되며, 이후 서비스 이용 시 이 토큰이 인증 수단으로 사용됩니다.
✅ 토큰 재발급
- Endpoint:
/api/auth/refresh
- HTTP Method:
POST
📥 Request
-
Request Params: 없음
-
Request Body
{ "refreshToken": "refresh_token_value" }
📤 Response
✅ Success Response
-
200 OK – 토큰 재발급 성공 (
TOKEN_REFRESH_SUCCESS
){ "code": "TOKEN_REFRESH_SUCCESS", "message": "토큰이 재발급되었습니다.", "accessToken": "access_token_value" }
🧩 설계 근거 및 시나리오
- 이 API는 클라이언트가 보유하고 있는 Refresh Token을 이용해 Access Token을 재발급받기 위해 사용됩니다.
- 사용자는 로그인 후 일정 시간이 지나면 Access Token이 만료되기 때문에, 별도로 저장해둔 Refresh Token으로
/api/auth/reissue
API를 호출하여 새로운 Access Token을 받게 됩니다. - Refresh Token 자체가 만료되었거나 잘못된 경우에는 401 또는 400 오류가 발생합니다.
✅ 로그아웃
- Endpoint:
/api/auth
- HTTP Method:
POST
📥 Request
-
Request Header
Authorization: Bearer <access_token>
(필수)
-
Request Params: 없음
-
Request Body
{ "refreshToken": "refresh_token_value" }
✅ Success Response
-
200 OK – 로그아웃 성공 (
LOGOUT_SUCCESS
){ "code": "LOGOUT_SUCCESS", "message": "로그아웃이 완료되었습니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 사용자가 서비스에서 로그아웃할 때 호출됩니다.
- Access Token은 헤더로 전달되며, Refresh Token은 본문에 포함되어야 합니다.
- 로그아웃 시 서버는 해당 Refresh Token을 무효화하고, 클라이언트는 보유 중인 인증 정보를 삭제하게 됩니다.
- 토큰이 누락되었거나 유효하지 않은 경우 해당 상황에 따른 공통 에러 응답이 반환됩니다.
✅ 유저 정보 확인
- Endpoint:
/api/user/{userId}
- HTTP Method:
GET
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Request Params: 없음
- Request Body: 없음
✅ Success Response
-
200 OK – 유저 정보 조회 성공 (
USER_INFO_SUCCESS
){ "code": "USER_INFO_SUCCESS", "message": "유저 조회 완료했습니다.", "user": { "userId": 1, "nickname": "gray_123!", "profileImageURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/1.jpg", "cacheTtl": 300 } }
🧩 설계 근거 및 시나리오
- 이 API는 클라이언트가 보유한 Access Token을 기반으로 현재 로그인된 유저의 정보를 조회합니다.
- 프로필, 닉네임 등 기본 정보와 함께
cacheTtl
등의 캐시 유효 시간도 포함되어 있으며, 인증된 사용자만 호출 가능하고Authorization
헤더가 반드시 포함되어야 합니다.
✅ 유저정보 수정
- Endpoint:
/api/user/{userId}
- HTTP Method:
PUT
📥 Request
-
Request Header
Authorization: Bearer <access_token>
(필수)
-
Request Params
userId
(Long, 필수): 수정할 유저의 ID
-
Request Body
{ "nickname": "gray_321!", "profileImageURL" : "https://ongi.s3.ap-northeast-2.amazonaws.com/1.jpg" }
✅ Success Response
-
200 OK – 유저 닉네임 변경 성공 (
USER_NICKNAME_UPDATE_SUCCESS
){ "code": "USER_NICKNAME_UPDATE_SUCCESS", "message": "유저 닉네임 변경 완료했습니다.", "user": { "userId": 1, "nickname": "gray_321!", "profileImageURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/1.jpg", "cacheTtl": 300 } }
⚠️ Error Response
-
400 Bad Request – 유효하지 않은 닉네임
{ "code": "INVALID_VALUE", "message": "유효한 닉네임이 아닙니다.", "data": null }
-
403 Frobidden – 타 유저정보 수정 시도
{ "code": "USER_UPDATE_DENIED", "message": "타인의 유저정보는 수정할 수 없습니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 인증된 사용자가 닉네임과 프로필 이미지를 수정하는 기능을 제공합니다.
- 닉네임은 유효성 검사를 거쳐야 하며, 기존 닉네임과 중복되거나 규칙에 어긋날 경우 400 오류가 반환됩니다.
- 요청이 성공하면 변경된 닉네임과 프로필 사진의 URL을 포함한 유저 정보를 반환합니다.
- 프론트는 기존 캐싱하고 있던 유저정보를 새 정보로 교체합니다.
✅ 유저 사진 일간 개수 월별 조회
- Endpoint:
/api/user/statistics/picture/?yearmonth={yearMonth}
- HTTP Method:
GET
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Request Params
yearMonth
(optional,yyyy-MM
형식): 조회할 연월- 미전달 시 전체 등록 사진 수만 반환
- 전달 시 해당 월의 사진 통계 기록 반환
- Request Body: 없음
✅ Success Response
-
200 OK – 유저 사진 총 개수 조회 성공 (
USER_PICTURE_TOTAL_STATISTICS_SUCCESS
){ "code": "USER_PICTURE_TOTAL_STATISTICS_SUCCESS", "message": "유저 등록 사진 수 조회 성공", "data": { "count": 10 } }
-
200 OK – 유저 사진 일간 통계 조회 성공 (
USER_PICTURE_MONTHLY_STATISTICS_SUCCESS
){ "code": "USER_PICTURE_MONTHLY_STATISTICS_SUCCESS", "message": "월단위 일간 사진 등록 수 조회 성공", "data": { "yearMonth": "2025-04", "dailyImageCount": { "2025-04-01": 3, "2025-04-02": 0, "2025-04-03": 7, ... "2025-04-30": 2 } } }
🧩 설계 근거 및 시나리오
- 이 API는 사용자가 해당 월(
yearMonth
)에 각 날짜별로 업로드한 사진 수를 조회할 수 있도록 합니다. - 이를 통해 클라이언트는 월별 업로드 추이를 시각화하거나 캘린더 형태의 통계 UI를 제공할 수 있습니다.
yearMonth
를 Query Parameter로 입력하며, 양식은yyyy-mm
입니다. 전체 등록 사진 개수를 조회하고 싶으면 입력하지 않을 수 있습니다.yyyy-mm
의 경우yyyy-MM-dd
와 일별 사진 수가 key-value 형식으로 구성됩니다.
- 입력하지 않을 경우
- 유저가 등록한 사진의 총 개수를
count
를 통해 나타냅니다.
- 유저가 등록한 사진의 총 개수를
✅ 유저가 방문한 장소 조회
- Endpoint:
/api/user/statistics/place?yearMonth={yearMonth}
- HTTP Method:
GET
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Request Params
yearMonth
(optional,yyyy-MM
형식): 조회할 연월- 미전달 시 전체 방문 장소 수만 반환
- 전달 시 해당 월의 상세 방문 기록 반환
- Request Body: 없음
✅ Success Response
-
200 OK – 유저 방문 모든 장소 숫자 성공 (
USER_ALL_PLACE_SUCCESS
){ "code": "USER_ALL_PLACE_SUCCESS", "message": "유저 방문 장소 조회 성공", "data": { "count": 23 } }
-
200 OK – 유저 방문 장소 조회 성공 (
USER_PLACE_SUCCESS
){ "code": "USER_PLACE_SUCCESS", "message": "유저 방문 장소 조회 성공", "data": [ { "city": "강원도", "district": "횡성군", "town": "횡성읍", "count": 10 } ] }
🧩 설계 근거 및 시나리오
- 이 API는 사용자가 특정 월에 방문했던 행정구역 단위 장소 목록을 조회하기 위한 기능입니다.
yearMonth
를 Query Parameter로 입력하며, 양식은yyyy-mm
입니다. 전체 방문 장소 개수를 조회하고 싶으면 입력하지 않을 수 있습니다.yyyy-mm
의 경우- 각 장소는 시(city), 군/구(district), 읍/면/동(town) 단위로 제공되며, 한달 기준으로 해당 지역에서 사진이 업로드된 횟수(
count
)를 기반으로 사용자의 방문량을 나타냅니다.
- 각 장소는 시(city), 군/구(district), 읍/면/동(town) 단위로 제공되며, 한달 기준으로 해당 지역에서 사진이 업로드된 횟수(
- 입력하지 않을 경우
- 유저가 방문한 도시의 총 개수를
count
를 통해 나타냅니다.
- 유저가 방문한 도시의 총 개수를
앨범 관련
✅ 전체 앨범 목록 월별 조회
- Endpoint:
/api/album/monthly?yearMonth={yearmonth}
- HTTP Method:
GET
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Request Params
yearMonth
(String): 조회하고 싶은 연월 (예:"2025-04"
)- 최초 요청 시
null
로 요청 - 이후 요청 시 응답으로 받은
nextYearMonth
사용
- Request Body: 없음
✅ Success Response
-
200 OK – 앨범 목록 조회 성공 (
MONTHLY_ALBUM_SUCCESS
){ "code": "MONTHLY_ALBUM_SUCCESS", "message": "앨범 목록 조회 성공", "data": { "albums": [ { "albumId": 1, "albumName": "봄 소풍", "thumbnailURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/IMG-0001.jpg", "createdAt": "2025-04-18T12:00:00", "memberProfileImageURL": [ "https://ongi.s3.ap-northeast-2.amazonaws.com/IMG-0314.jpg", "https://ongi.s3.ap-northeast-2.amazonaws.com/IMG-0978.jpg" ] }, ... ], "nextYearMonth": "2025-03" } }
🧩 설계 근거 및 시나리오
- 이 API는 사용자가 생성한 앨범을 월 단위로 조회하는 기능을 제공합니다.
- 전체 앨범 목록을 한 번에 불러오지 않고,
yearMonth
쿼리 파라미터를 기준으로 월별로 끊어서 데이터를 받아오는 방식입니다. - 이 방식은 다음과 같은 무한 스크롤 UI에 최적화되어 있습니다:
- 클라이언트는 현재 연월(
2025-04
) 기준으로 API를 호출해 한 달치 앨범 목록을 로드합니다. - 사용자가 아래로 스크롤할 때 다음 달(
2025-03
) 데이터를 추가로 요청하는 식의 월 단위 페이징 흐름을 구성할 수 있습니다. - 최대 로딩 사이즈는 24입니다.
- 클라이언트는 현재 연월(
✅ 앨범 요약 조회
- Endpoint:
/api/album/{albumId}/summary
- HTTP Method:
GET
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Request Params
albumId
(Long, 필수): 조회할 앨범의 ID
- Request Body: 없음
✅ Success Response
-
200 OK – 앨범 요약 조회 성공 (
ALBUM_SUMMARY_SUCCESS
){ "code": "ALBUM_SUMMARY_SUCCESS", "message": "앨범 요약 조회 성공", "data": [ { "pictureId": 501, "pictureURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/pic-501.jpg", "latitude": 37.5441, "longitude": 127.0372 }, { "pictureId": 502, "pictureURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/pic-502.jpg", "latitude": 35.1586, "longitude": 129.1604 } ] }
⚠️ Error Response
-
403 Forbidden – 앨범 멤버 아님
{ "code": "NOT_ALBUM_MEMBER", "message": "앨범 멤버가 아닙니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 특정 앨범의 대표 사진들을 요약하여 제공합니다. 각 사진은 위치 정보(위도, 경도)를 포함하며, 사용자가 앨범에 포함된 주요 사진들을 빠르게 확인할 수 있도록 합니다.
- 이 정보를 활용하여 앨범의 위치 기반 서비스를 제공하거나, 사진들에 대한 미리보기 기능을 제공할 수 있습니다.
✅ 앨범 상세 조회
- Endpoint:
/api/album/{albumId}
- HTTP Method:
GET
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Request Params
albumId
(Long, 필수): 조회할 앨범의 ID
- Request Body: 없음
✅ Success Response
- 200 OK – 앨범 조회 성공 (
ALBUM_ACCESS_SUCCESS
)
{
"code": "ALBUM_ACCESS_SUCCESS",
"message": "앨범 조회 성공",
"data": [
{
"title": "제주도 여행",
"picture": [
{
"pictureId": 501,
"pictureURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/pic-2.jpg",
"latitude": 35.1586,
"longitude": 129.1604,
"tag": "여행",
"isDullicated": false,
"isShaky": false,
"createdAt": "2025-05-04T12:12:12"
}
],
"cluster" : [
{
"clusterId" : 1,
"clusterName" : "사람-1",
"representativePicture" : "https://cdn.ongi.today/image1.jpg",
"bboxX1" : 00,
"bboxY1" : 00,
"bboxX2" : 00,
"bboxY2" : 00,
"clusterPicture" : ["https://cdn.ongi.today/image1.jpg", "https://cdn.ongi.today/image2.jpg"]
}
]
}
]
}
⚠️ Error Response
-
403 Forbidden – 앨범 멤버 아님
{ "code": "NOT_ALBUM_MEMBER", "message": "앨범 멤버가 아닙니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 특정 앨범의 상세 정보를 조회합니다.
- 앨범 제목과 함께, 해당 앨범에 포함된 모든 사진의 메타데이터를 포함하여 반환합니다.
- 사진은 위도/경도, 태그, 흔들림 여부, 중복 여부, 생성 시간 등의 정보를 담고 있습니다.
- 사진이 인물사진인 경우 클러스터에 포함됩니다. 인물사진은 여러 클러스터에 포함될 수 있습니다. 대표 인물사진은 사진을 확대하기 위한 bbox정보를 함께 반환합니다.
✅ 앨범 생성
- Endpoint:
/api/album
- HTTP Method:
POST
📥 Request
-
Request Header
Authorization: Bearer <access_token>
(필수)
-
Request Body
{ "albumName": "제주도 여행", "concepts" : ["산","바다"], "pictureURLs": [ "https://ongi.s3.ap-northeast-2.amazonaws.com/1.jpg", "https://ongi.s3.ap-northeast-2.amazonaws.com/2.jpg" ] }
✅ Success Response
-
200 OK – 앨범 생성 성공 (
ALBUM_CREATE_SUCCESS
){ "code": "ALBUM_CREATE_SUCCESS", "message": "앨범이 생성되었습니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 사용자가 새로운 앨범을 생성할 때 사용됩니다.
- 앨범 이름과 대표 이미지 URL, 앨범 컨셉들을 전달하며, 서버는 이를 기반으로 앨범을 생성하고 내부적으로 사진 메타데이터를 저장합니다.
- 성공 시 별도의 데이터 반환 없이 성공 메시지를 응답합니다.
✅ 앨범에 사진 추가
- Endpoint:
/api/album/{albumId}/picture
- HTTP Method:
POST
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Path Variable
albumId
(Long, 필수): 사진을 추가할 대상 앨범 ID
- Request Body
{
"pictureURLs": [
"https://ongi.s3.ap-northeast-2.amazonaws.com/1.jpg",
"https://ongi.s3.ap-northeast-2.amazonaws.com/2.jpg"
]
}
✅ Success Response
- 200 OK – 사진 추가 성공 (
PICTURE_ADD_SUCCESS
)
{
"code": "PICTURE_ADD_SUCCESS",
"message": "앨범에 사진을 추가했습니다.",
"data": null
}
⚠️ Error Response
-
403 Forbidden – 앨범 멤버 아님
{ "code": "NOT_ALBUM_MEMBER", "message": "앨범 멤버가 아닙니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 특정 앨범에 이미지 URL들을 추가하는 기능을 제공합니다.
- 사용자는 업로드된 이미지들의 URL을 배열로 전달하며, 서버는 이를 기존 앨범에 연결된 사진 목록에 추가합니다.
- 앨범 멤버가 아닌 사람이 사진을 추가하려고 할 때 403에러를 리턴합니다.
✅ 앨범 이름 수정
- Endpoint:
/api/album/{albumId}
- HTTP Method:
PUT
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Path Variable
albumId
(Long, 필수): 이름을 수정할 앨범의 ID
- Request Body
{
"albumName": "제주도 여행"
}
✅ Success Response
- 200 OK – 앨범 이름 수정 성공 (
ALBUMNAME_UPDATE_SUCCESS
)
{
"code": "ALBUMNAME_UPDATE_SUCCESS",
"message": "앨범 이름을 수정했습니다.",
"data": null
}
⚠️ Error Response
-
403 Forbidden – 앨범 소유자 아님
{ "code": "NOT_ALBUM_OWNER", "message": "앨범 멤버가 아닙니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 사용자가 기존 앨범의 이름을 수정할 수 있도록 제공됩니다.
- 수정 대상 앨범은
albumId
를 통해 식별하며, 요청 본문에 새 앨범명을 전달합니다. - 성공 시 변경 완료 메시지만 반환됩니다.
- 앨범 소유자가 아닌 경우 403 에러를 반환합니다.
✅ 클러스터 이름 변경
- Endpoint:
/api/album/{albumId}/cluster/{clusterId}
- HTTP Method:
PATCH
📥 Request
-
Request Header
- Authorization: Bearer <access_token> (필수)
-
Path Variables
- albumId (Long): 조회하고자 하는 앨범 아이디
- clusterId (Long): 변경하고자 하는 클러스터 아이디
-
Request Body
{
"clusterName": "사람-수정"
}
✅ 앨범 사진 삭제
- Endpoint:
/api/album/{albumId}/image
- HTTP Method:
DELETE
✅ Success Response
- 200 OK – 클러스터 이름 변경 성공 (
CLUSTER_RENAME_SUCCESS
)
{
"code": "CLUSTER_RENAME_SUCCESS",
"message": "클러스터 이름이 변경되었습니다.",
"data": null
}
🧩 설계 근거 및 시나리오
- 이 API는 특정 얼굴 클러스터의 이름을 사용자가 임의로 수정할 수 있도록 지원합니다.
- 클러스터는 AI 분석 결과로 분류된 사람 그룹을 의미하며, 사용자가 이를 “엄마”, “친구A”처럼 이해하기 쉽게 이름 지정 가능하게 합니다.
- 접근 권한은 해당 앨범의 멤버인 경우에만 부여됩니다.
- 변경 시 프론트엔드에서 실시간 반영 가능하도록 200 응답만 반환하며, 별도 데이터는 포함하지 않습니다.
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Path Variable
albumId
(Long, 필수): 사진을 삭제할 대상 앨범 ID
- Request Body
{
"pictureIds": [501, 502, 503]
}
✅ Success Response
- 200 OK – 앨범 내 사진 삭제 성공 (
PICTURE_DELETE_SUCCESS
)
{
"code": "PICTURE_DELETE_SUCCESS",
"message": "앨범 내 사진을 삭제했습니다.",
"data": null
}
⚠️ Error Response
-
403 Forbidden – 앨범 멤버 아님
{ "code": "NOT_ALBUM_MEMBER", "message": "앨범 멤버가 아닙니다.", "data": null }
-
404 Not Found – 앨범 또는 사진을 찾을 수 없음
{ "code": "ALBUM_NOT_FOUND", "message": "사진을 찾을 수 없습니다", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 특정 앨범 내에서 선택된 사진들을 삭제하는 기능을 합니다.
- 삭제할 사진들의 ID는 배열로 전달되며,
albumId
를 통해 앨범을 식별합니다. - 유효하지 않은 앨범이거나, 요청한 사진이 존재하지 않는 경우 404 에러를 반환합니다.
- 앨범 구성원이 아닐 경우 403 에러를 반환합니다.
✅ 앨범 삭제
- Endpoint:
/api/album/{albumId}
- HTTP Method:
DELETE
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Path Variable
albumId
(Long, 필수): 삭제할 앨범의 ID
- Request Body: 없음
✅ Success Response
- 200 OK – 앨범 삭제 성공 (
ALBUM_DELETE_SUCCESS
)
{
"code": "ALBUM_DELETE_SUCCESS",
"message": "앨범이 삭제되었습니다.",
"data": null
}
⚠️ Error Response
-
403 Forbidden – 앨범 소유자 아님
{ "code": "NOT_ALBUM_OWNER", "message": "앨범 소유자가 아닙니다.", "data": null }
-
404 Not Found – 앨범을 찾을 수 없음
{ "code": "ALBUM_NOT_FOUND", "message": "앨범을 찾을 수 없습니다", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 사용자가 특정 앨범을 완전히 삭제할 때 호출됩니다.
- 앨범 ID를 통해 삭제할 앨범을 지정하며, 인증된 사용자만 삭제를 요청할 수 있습니다.
- 앨범 소유자가 아닌 경우 403 에러를 반환합니다.
- 요청한 앨범이 존재하지 않는 경우에는 404 에러를 반환합니다.
✅ 공동작업자 목록 조회
- Endpoint:
/api/album/{albumId}/members
- HTTP Method:
GET
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Request Params
albumId
(Long, 필수): 대상 앨범 ID
✅ Success Response
- 200 OK – 공동작업자 목록 조회 성공 (
ALBUM_MEMBER_LIST_SUCCESS
)
{
"code": "ALBUM_MEMBER_LIST_SUCCESS",
"message": "공동작업자 목록 조회 성공",
"data": [
{
"userId": 1,
"nickname": "gray (Owner)",
"profileImageURL": "https://ongi.s3.amazonaws.com/profiles/gray.jpg"
},
{
"userId": 2,
"nickname": "noah",
"profileImageURL": "https://ongi.s3.amazonaws.com/profiles/noah.jpg"
}
]
}
⚠️ Error Response
-
403 Forbidden – 앨범 멤버 아님
{ "code": "NOT_ALBUM_MEMBER", "message": "앨범 멤버가 아닙니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 앨범에 초대된 모든 유저(본인 포함)를 조회합니다.
- 앨범 유저가 아닌데 조회하려 할 경우 403에러를 반환합니다.
✅ 초대 링크 생성
- Endpoint:
/api/album/{albumId}/invite/link
- HTTP Method:
POST
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Path Variable
albumId
(Long, 필수)
✅ Success Response
- 200 OK – 초대 링크 생성 성공 (
INVITE_LINK_CREATED
)
{
"code": "INVITE_LINK_CREATED",
"message": "초대 링크가 생성되었습니다.",
"data": {
"inviteLink": "https://ongi.com/invite?token=eyJhbGciOiJIUzI1NiIsInR5..."
}
}
⚠️ Error Response
-
403 Forbidden – 앨범 멤버 아님
{ "code": "NOT_ALBUM_MEMBER", "message": "앨범 멤버가 아닙니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 앨범 공동작업자 초대를 위한 JWT 기반 링크를 생성합니다.
- 생성된 링크는 클립보드 복사 등으로 사용자가 다른 사람에게 전달할 수 있습니다.
- 토큰은 유효기간과 앨범 ID를 포함하며 DB 저장 없이도 검증 가능하도록 설계됩니다.
- 앨범 멤버만 초대 링크를 만들 수 있으며, 앨범 멤버가 아닐 경우 403에러를 반환합니다.
✅ 초대 수락
- Endpoint:
/api/album/{albumId}/invite
- HTTP Method:
POST
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Path Variable
albumId
(Long, 필수)
- Request Body
{
"inviteToken": "eyJhbGciOiJIUzI1NiIsInR5..."
}
✅ Success Response
- 200 OK – 초대 수락 성공 (
ALBUM_INVITE_SUCCESS
)
{
"code": "ALBUM_INVITE_SUCCESS",
"message": "앨범에 초대되었습니다.",
"data": {
"albumId": 5,
"albumName": "제주 여행"
}
}
⚠️ Error Response
-
403 Forbidden – 초대 링크 만료
{ "code": "INVITE_LINK_EXPIRED", "message": "초대 링크가 만료되었습니다.", "data": null }
-
403 Forbidden – 초대 링크 인증 불가
{ "code": "INVALID_INVITE_LINK", "message": "초대 링크가 유효하지 않습니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 초대 링크를 받은 사용자가 앨범에 참여할 수 있도록 합니다.
- 토큰 내
albumId
와 URI 내albumId
의 일치 여부를 검증하여 보안을 강화합니다. - 초대 수락 시
UserAlbum
테이블에 새로운 데이터가 생성되고 Normal로 권한이 기본 설정됩니다. - 초대 링크가 만료되거나 유효하지 않을 경우 403에러를 반환합니다.
✅ 유저의 앨범 접근 권한 확인
- Endpoint:
/api/album/{albumId}/role
- HTTP Method:
GET
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Path Variable
albumId
(Long, 필수)
✅ Success Response
-
200 OK – 접근 권한 있음 (
ALBUM_AUTHORIZED
){ "code": "ALBUM_AUTHORIZED", "message": "앨범 접근 권한 있음", "data": { "role": "OWNER" // 또는 MEMBER } }
⚠️ Error Response
-
403 Forbidden – 앨범 접근 권한 없음
{ "code": "INVALID_ALBUM_ACCESS", "message": "앨범 접근 권한이 없습니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 사용자가 앨범 페이지 접근 전에 권한이 있는지 사전 확인하는 용도로 사용됩니다.
UserAlbum
테이블에서 매핑 여부를 조회하며, OWNER/MEMBER 여부도 함께 응답합니다.
✅ 공동작업자 삭제
- Endpoint:
/api/album/{albumId}/members/{userId}
- HTTP Method:
DELETE
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Path Variable
albumId
(Long, 필수)userId
(Long, 필수)
✅ Success Response
- 200 OK – 공동작업자 삭제 성공 (
ALBUM_MEMBER_DELETE_SUCCESS
)
{
"code": "ALBUM_MEMBER_DELETE_SUCCESS",
"message": "공동작업자를 삭제했습니다.",
"data": null
}
🧩 설계 근거 및 시나리오
- 이 API는 앨범의 OWNER가 공동작업자를 강제 제거할 수 있도록 제공합니다.
UserAlbum
에서 해당 유저-앨범 매핑을 삭제하며, 본인 자신은 제거할수 없습니다.
✅ 공동작업자 소유권 위임
- Endpoint:
/api/album/{albumId}/owner
- HTTP Method:
PUT
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수, 반드시 현재 OWNER의 토큰이어야 함)
- Path Variable
albumId
(Long, 필수): 소유권을 위임할 앨범 ID
- Request Body
{
"newOwnerId": 42
}
✅ Success Response
- 200 OK – 소유권 위임 성공 (
ALBUM_OWNERSHIP_TRANSFER_SUCCESS
)
{
"code": "ALBUM_OWNERSHIP_TRANSFER_SUCCESS",
"message": "앨범 소유권이 정상적으로 이전되었습니다.",
"data": {
"oldOwnerId": 1,
"newOwnerId": 42
}
}
⚠️ Error Response 예시
- 403 Forbidden – 요청자가 OWNER가 아님
{
"code": "FORBIDDEN",
"message": "앨범 소유자가 아닙니다.",
"data": null
}
- 404 Not Found – 대상 유저가 해당 앨범의 구성원이 아님
{
"code": "MEMBER_NOT_FOUND",
"message": "해당 앨범의 공동작업자가 아닙니다.",
"data": null
}
🧩 설계 근거 및 시나리오
- 이 API는 앨범의 소유권을 다른 유저에게 이전할 수 있는 기능을 제공합니다.
- 기존 OWNER가 요청을 보내면,
UserAlbum
테이블에서:- 본인의
role
을NORMAL
로 변경하고 newOwnerId
의role
을OWNER
로 변경합니다.
- 본인의
- 이를 통해 OWNER는 유연하게 권한을 넘기고, 새로운 관리자가 생길 수 있습니다.
피드 관련
✅ 피드 등록
- Endpoint:
/api/feed
- HTTP Method:
POST
📥 Request
-
Request Header
Authorization: Bearer <access_token>
(필수)
-
Request Body
{ "albumId": 1, "content": "판교 산책", "pictureIds": [101, 102, 103] }
✅ Success Response
-
200 OK – 피드 등록 성공 (
FEED_CREATE_SUCCESS
){ "code": "FEED_CREATE_SUCCESS", "message": "피드가 성공적으로 생성되었습니다.", "data": null }
⚠️ Error Response
-
400 Bad Request – 사진이 존재하나 같은 앨범에 존재하지 않음
{ "code": "PICTURE_NOT_IN_SAME_ALBUM", "message": "요청한 사진이 같은 앨범에 존재하지 않습니다.", "data": null }
-
404 Not Found – 사진이 존재하지 않음
{ "code": "PICTURE_NOT_FOUND", "message": "해당 사진을 조회할 수 없습니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 사용자가 앨범 내 사진을 선택해 피드를 생성하는 기능을 제공합니다.
- 본문에는 피드 내용과 함께 어떤 앨범을 기준으로 생성할 것인지(
albumId
), 어떤 사진들이 포함될 것인지(pictureIds
)를 명시합니다. - 피드 등록 시 선택한 사진이 실제 앨범에 포함되어 있어야 하며, 없는 사진이 포함될 경우 404 응답을 반환하고, 사진 리소스가 존재하나 같은 앨범에 포함되어있지 않으면 400 응답을 반환합니다.
✅ 피드 상세 조회
- Endpoint:
/api/feed/{feedId}
- HTTP Method:
GET
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Path Variable
feedId
(Long, 필수): 조회할 피드의 ID
- Request Body: 없음
✅ Success Response
-
200 OK – 피드 상세 조회 성공 (
FEED_DETAIL_SUCCESS
){ "code": "FEED_DETAIL_SUCCESS", "message": "피드 상세 조회 성공", "data": { "feedId": 55, "content": "제주도 여행하고 싶다.", "createdAt": "2025-04-17T15:30:00", "updatedAt": "2025-04-17T15:30:00", "writer": { "userId": 1, "nickname": "aaron", "profileImageURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/profiles/user1.jpg" }, "pictures": [ { "pictureId": 501, "pictureURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/pic-501.jpg", "tag": "바다", "latitude": 33.4567, "longitude": 126.5678, "place": { "city": "제주특별자치도", "district": "서귀포시", "town": "성산읍" } }, { "pictureId": 502, "pictureURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/pic-502.jpg", "tag": "쇼핑", "latitude": null, "longitude": null, "place": null} ], "likeCount": 12, "commentCount": 4, "isLiked": true} }
⚠️ Error Response
-
404 Not Found – 피드가 존재하지 않음
{ "code": "FEED_NOT_FOUND", "message": "존재하지 않는 피드입니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 클라이언트가 특정 피드의 전체 상세 내용을 조회할 수 있도록 제공됩니다.
- 작성자 정보, 포함된 사진, 위치 정보, 좋아요 수, 댓글 수, 로그인 사용자의 좋아요 여부(
isLiked
) 등이 포함되어 있습니다. - 사진마다 장소 정보가 있을 수도 있고 없을 수도 있으며, 위치 기반 콘텐츠 기능 구현에 활용됩니다.
✅ 피드 전체 조회
- Endpoint:
/api/feed?cursor={lastFeedId}
- HTTP Method:
GET
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Requset Params
lastFeedId
(Long): 마지막으로 받은 피드 ID- null이라면 최신 피드부터 조회 시작
- Request Body: 없음
✅ Success Response
-
200 OK – 피드 목록 조회 성공 (
FEED_LIST_SUCCESS
){ "code": "FEED_LIST_SUCCESS", "message": "피드 목록 조회 성공", "data": { "feeds": [ { "feedId": 101, "thumbnailURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/thumbnail-101.jpg", "createdAt": "2025-04-17T14:00:00", "likeCount": 12, "isLiked": true, "writer": { "nickname": "gray", "profileImageURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/profiles/gray.jpg" } }, { "feedId": 100, "thumbnailURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/thumbnail-100.jpg", "createdAt": "2025-04-17T13:20:00", "likeCount": 5, "isLiked": false, "writer": { "nickname": "noah", "profileImageURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/profiles/yeon.jpg" } } ], "hasNext": true, "lastFeedId": 100 } }
⚠️ Error Response
-
404 Not Found – 피드 목록 없음
{ "code": "FEED_NOT_FOUND", "message": "피드 목록을 조회할 수 없습니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 무한 스크롤 방식으로 피드 목록을 조회하기 위한 기능을 제공합니다.
- 클라이언트는
lastFeedId
를 기준으로 더 이전 피드를 요청하며, 응답에는 다음 페이지 여부(hasNext
)와 함께 마지막 피드 ID가 함께 제공됩니다. - 각 피드는 썸네일, 작성자 정보, 좋아요 수 및 로그인 사용자의 좋아요 여부(
isLiked
) 정보를 포함합니다. - 피드 로딩 사이즈 단위는 10입니다.
✅ 팔로우한 유저의 피드 조회
- Endpoint:
/api/feed/follow?cursor={lastFeedId}
- HTTP Method:
GET
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Requset Params
lastFeedId
(Long): 마지막으로 받은 피드 ID- null이라면 최신 피드부터 조회 시작
- Request Body: 없음
✅ Success Response
-
200 OK – 피드 목록 조회 성공 (
FEED_LIST_SUCCESS
){ "code": "FEED_LIST_SUCCESS", "message": "피드 목록 조회 성공", "data": { "feeds": [ { "feedId": 101, "thumbnailURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/thumbnail-101.jpg", "createdAt": "2025-04-17T14:00:00", "likeCount": 12, "isLiked": true, "writer": { "nickname": "gray", "profileImageURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/profiles/gray.jpg" } }, { "feedId": 100, "thumbnailURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/thumbnail-100.jpg", "createdAt": "2025-04-17T13:20:00", "likeCount": 5, "isLiked": false, "writer": { "nickname": "noah", "profileImageURL": "https://ongi.s3.ap-northeast-2.amazonaws.com/profiles/yeon.jpg" } } ], "hasNext": true, "lastFeedId": 100 } }
⚠️ Error Response
-
404 Not Found – 피드를 찾을 수 없음
{ "code": "FEED_NOT_FOUND", "message": "피드 목록을 조회할 수 없습니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 사용자가 팔로우한 유저들이 작성한 피드만을 최신순으로 페이징 조회하기 위해 사용됩니다.
- 기본적인 무한스크롤 구조를 따르며,
lastFeedId
를 기준으로 다음 피드 목록을 요청할 수 있습니다. hasNext
가 true일 경우 다음 요청이 가능하며, 클라이언트는 마지막feedId
를 기준으로 추가 로딩을 이어갑니다.- 전체 피드 조회와 구분되어 필터링된 피드만 노출됩니다.
✅ 피드 수정
- Endpoint:
/api/feed/{feedId}
- HTTP Method:
PUT
📥 Request
-
Request Header
Authorization: Bearer <access_token>
(필수)
-
Path Variable
feedId
(Long, 필수): 수정할 피드의 ID
-
Request Body
{ "albumId": 1, "content": "판교 산책 수정", "pictureIds": [101, 102, 103] }
✅ Success Response
-
200 OK – 피드 수정 성공 (
FEED_UPDATE_SUCCESS
){ "code": "FEED_UPDATE_SUCCESS", "message": "피드를 수정했습니다.", "data": null }
⚠️ Error Response
-
404 Not Found – 앨범을 찾을 수 없음
{ "code": "ALBUM_NOT_FOUND", "message": "앨범을 조회할 수 없습니다.", "data": null }
-
404 Not Found – 사진을 찾을 수 없음
{ "code": "PICTURE_NOT_FOUND", "message": "사진을 조회할 수 없습니다.", "data": null }
-
400 Bad Request – 사진이 존재하나 같은 앨범에 존재하지 않음
{ "code": "PICTURE_NOT_IN_SAME_ALBUM", "message": "요청한 사진이 같은 앨범에 존재하지 않습니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 사용자가 이미 등록한 피드의 앨범, 내용, 사진 목록을 수정할 수 있도록 제공됩니다.
- 피드 ID로 기존 피드를 지정하고, 수정할 내용과 연결할 사진 목록을 함께 전송합니다.
- 앨범이나 사진이 존재하지 않을 경우 404 응답이 반환됩니다.
✅ 피드 삭제
- Endpoint:
/api/feed/{feedId}
- HTTP Method:
DELETE
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Path Variable
feedId
(Long, 필수): 삭제할 피드의 ID
- Request Body: 없음
✅ Success Response
-
200 OK – 피드 삭제 성공 (
FEED_DELETE_SUCCESS
){ "code": "FEED_DELETE_SUCCESS", "message": "피드를 삭제했습니다.", "data": null }
⚠️ Error Response
-
404 Not Found – 피드가 존재하지 않음
{ "code": "FEED_NOT_FOUND", "message": "피드를 찾을 수 없습니다", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 사용자가 작성한 피드를 완전히 삭제하는 기능을 합니다.
feedId
를 기준으로 피드를 찾아 삭제하며, 인증된 사용자만 요청할 수 있습니다.
댓글 관련
✅ 전체 댓글 조회
- Endpoint:
/api/feed/{feedId}/comment?cursor={commentId}
- HTTP Method:
GET
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Request Params
feedId
(Long, 필수): 댓글을 조회할 피드 IDcommentId
(Long): 마지막으로 받은 댓글 IDnull
이면 가장 최신 댓글부터 조회 시작
- Request Body: 없음
✅ Success Response
-
200 OK – 댓글 목록 조회 성공 (
COMMENT_LIST_SUCCESS
){ "code": "COMMENT_LIST_SUCCESS", "message": "피드의 댓글 목록조회 성공했습니다.", "data": { "content": [ { "commentId": 1001, "userId": 501, "nickname": "gray", "profileImageURL": "https://.../gray.jpg", "content": "진짜 멋져요!", "createdAt": "2025-04-19T15:50:00", "isAuthor": true}, { "commentId": 1000, ... } ], "hasNext": true, "lastFeedId": 100 } }
⚠️ Error Response
-
404 Not Found – 댓글 목록 없음
{ "code": "COMMENT_LIST_NOT_FOUND", "message": "댓글 목록을 조회할 수 없습니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 특정 피드에 작성된 댓글들을 페이지네이션 방식으로 조회하는 기능을 합니다.
- 응답에는 총 댓글 수, 전체 페이지 수, 현재 페이지 여부를 포함하여 무한 스크롤 또는 페이지 UI 구성에 활용할 수 있습니다.
- 각 댓글 항목은 작성자 정보, 댓글 내용, 작성 시각 및 로그인 유저가 작성자인지 여부(
isAuthor
)까지 포함합니다.
✅ 특정 댓글 조회
- Endpoint:
/api/feed/{feedId}/comment/{commentId}
- HTTP Method:
GET
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Path Variables
feedId
(Long, 필수): 피드 IDcommentId
(Long, 필수): 조회할 댓글 ID
- Request Body: 없음
✅ Success Response
-
200 OK – 특정 댓글 조회 성공 (
COMMENT_DETAIL_SUCCESS
){ "code": "COMMENT_DETAIL_SUCCESS", "message": "댓글 상세 조회에 성공했습니다.", "data": { "comment": { "commentId": 1001, "userId": 501, "nickname": "gray", "profileImageURL": "https://.../gray.jpg", "content": "진짜 멋져요!", "createdAt": "2025-04-19T15:50:00", "isAuthor": true } } }
⚠️ Error Response
-
404 Not Found – 댓글이 존재하지 않음
{ "code": "COMMENT_LIST_NOT_FOUND", "message": "댓글 목록을 조회할 수 없습니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 특정 피드에 작성된 댓글 중 하나를 ID 기준으로 단건 조회하는 기능을 제공합니다.
- 단일 댓글에는 작성자 정보, 댓글 내용, 작성 시간, 본인 여부(
isAuthor
)가 포함되어 있습니다.
✅ 댓글 작성
- Endpoint:
/api/feed/{feedId}/comment
- HTTP Method:
POST
📥 Request
-
Request Header
Authorization: Bearer <access_token>
(필수)
-
Path Variable
feedId
(Long, 필수): 댓글을 작성할 피드 ID
-
Request Body
{ "content": "진짜 멋져요!" }
✅ Success Response
-
200 OK – 댓글 작성 성공 (
COMMENT_CREATE_SUCCESS
){ "code": "COMMENT_CREATE_SUCCESS", "message": "댓글이 생성되었습니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 사용자가 특정 피드에 댓글을 작성할 때 사용됩니다.
- 요청 본문에는 댓글의 내용만 전달하면 되고, 성공 시 서버는 댓글을 저장한 뒤 성공 메시지를 응답합니다.
✅ 댓글 수정
- Endpoint:
/api/feed/{feedId}/comment/{commentId}
- HTTP Method:
PUT
📥 Request
-
Request Header
Authorization: Bearer <access_token>
(필수)
-
Path Variable
feedId
(Long, 필수): 피드 IDcommentId
(Long, 필수): 수정할 댓글 ID
-
Request Body
{ "content": "진짜 안멋져요!" }
✅ Success Response
-
200 OK – 댓글 수정 성공 (
COMMENT_UPDATE_SUCCESS
){ "code": "COMMENT_UPDATE_SUCCESS", "message": "댓글이 수정되었습니다.", "data": null }
⚠️ Error Response
-
403 Forbidden – 댓글 작성자가 아님
{ "code": "NOT_COMMENT_AUTHOR", "message": "댓글 작성자가 아닙니다.", "data": null }
-
404 Not Found – 댓글이 존재하지 않음
{ "code": "COMMENT_LIST_NOT_FOUND", "message": "댓글 목록을 조회할 수 없습니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 사용자가 작성한 댓글의 내용을 수정할 수 있도록 합니다.
- 댓글 ID와 피드 ID를 통해 대상을 특정하고, 작성자 본인인지 검증 후 수정이 수행됩니다.
- 수정 내용은 본문으로 전달되며, 성공 시 확인 메시지를 응답합니다.
✅ 댓글 삭제
- Endpoint:
/api/feed/{feedId}/comment/{commentId}
- HTTP Method:
DELETE
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Path Variable
feedId
(Long, 필수): 피드 IDcommentId
(Long, 필수): 삭제할 댓글 ID
✅ Success Response
-
200 OK – 댓글 삭제 성공 (
COMMENT_DELETE_SUCCESS
){ "code": "COMMENT_DELETE_SUCCESS", "message": "댓글이 삭제되었습니다.", "data": null }
⚠️ Error Response
-
403 Forbidden – 댓글 작성자가 아님
{ "code": "NOT_COMMENT_AUTHOR", "message": "댓글 작성자가 아닙니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 사용자가 작성한 댓글을 삭제할 때 사용됩니다.
- 요청자는 해당 댓글의 작성자여야 하며, 피드 ID와 댓글 ID를 통해 삭제할 댓글을 정확히 식별합니다.
- 삭제가 정상적으로 완료되면 성공 메시지를 반환하며, 이후 해당 댓글은 더 이상 조회되지 않습니다.
팔로우 관련
✅ 팔로우
- Endpoint:
/api/follow/{userId}
- HTTP Method:
POST
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Request Params
userId
(Long, 필수): 팔로우할 대상 유저 ID
✅ Success Response
-
201 Created – 팔로우 성공 (
FOLLOW_SUCCESS
)json 복사편집 { "code": "FOLLOW_SUCCESS", "message": "팔로우가 완료되었습니다.", "data": { "followerId": 1001, "followingId": 2002, "createdAt": "2025-04-24T02:30:12" } }
⚠️ Error Response
-
400 Bad Request – 이미 팔로우한 경우
{ "code": "FOLLOW_ALREADY_EXISTS", "message": "이미 팔로우한 유저입니다.", "data": null }
-
404 Not Found – 대상 유저 없음
{ "code": "FOLLOW_TARGET_NOT_FOUND", "message": "해당 유저를 찾을 수 없습니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 로그인한 사용자가 다른 유저를 팔로우할 때 사용됩니다.
- 요청자는
access token
을 통해 인증되며, 대상 유저 ID는Path Variable
로 전달됩니다. - 중복 팔로우는 허용하지 않으며, 이미 팔로우한 유저에게 요청하면
400
오류를 반환합니다. - 팔로우 요청이 성공하면 팔로우 관계가 저장되고, 생성 시각을 함께 응답합니다.
✅ 언팔로우
- Endpoint:
/api/follow/{userId}
- HTTP Method:
DELETE
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Path Variable
userId
(Long, 필수): 언팔로우할 대상 유저 ID
✅ Success Response
-
200 OK – 언팔로우 성공 (
UNFOLLOW_SUCCESS
){ "code": "UNFOLLOW_SUCCESS", "message": "팔로우가 완료되었습니다.", "data": null }
⚠️ Error Response
-
400 Bad Request – 이미 언팔로우 상태
{ "code": "ALREADY_UNFOLLOW", "message": "이미 언팔로우 되어있습니다", "data": null }
-
404 Not Found – 대상 유저 없음
{ "code": "FOLLOW_TARGET_NOT_FOUND", "message": "해당 유저를 찾을 수 없습니다.", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 로그인한 사용자가 기존에 팔로우하고 있던 유저를 언팔로우할 때 사용됩니다.
- 이미 언팔로우 상태인 경우 400 에러를 반환하여 중복 제거를 방지합니다.
- 삭제 성공 시 클라이언트는 팔로우 버튼을 다시 활성화할 수 있도록 처리합니다.
✅ 내 팔로잉 리스트 조회
- Endpoint:
/api/follow/following?cursor={followerId}
- HTTP Method:
GET
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Query Parameter
-
cursor
(Long, optional): 마지막으로 받은userId
.페이징 처리를 위한 커서 값.
null
또는 생략 시 최신부터 조회
-
✅ Success Response
-
200 OK – 팔로잉 목록 조회 성공 (
FOLLOWING_LIST_SUCCESS
){ "code": "FOLLOWING_LIST_SUCCESS", "message": "팔로잉 목록 조회에 성공했습니다.", "data": { "followings": [ { "userId": 2002, "nickname": "친구1", "profileImageUrl": "https://s3.amazonaws.com/.../profile1.png", "createdAt": "2025-04-20T01:10:00" }, { "userId": 2003, "nickname": "친구2", "profileImageUrl": "https://s3.amazonaws.com/.../profile2.png", "createdAt": "2025-04-18T14:22:11" } ], "hasNext": true, "nextCursor": 2003 } }
🧩 설계 근거 및 시나리오
- 이 API는 로그인한 사용자가 현재 팔로우하고 있는 팔로잉 리스트를 무한스크롤 방식으로 조회하는 기능입니다.
cursor
를 기준으로 다음 목록을 요청할 수 있으며, 응답에는hasNext
와nextCursor
가 함께 제공됩니다. 로딩 기본사이즈는 20입니다.- 닉네임, 프로필 이미지, 팔로우한 시간(
createdAt
) 등 기본 사용자 정보가 포함됩니다.
✅ 내 팔로워 리스트 조회
- Endpoint:
/api/follow/follower?cursor={followerId}
- HTTP Method:
GET
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Query Parameter
-
cursor
(Long, optional): 마지막으로 받은userId
.페이징 처리를 위한 커서 값. 생략 또는 null이면 첫 페이지 조회
-
✅ Success Response
-
200 OK – 팔로워 목록 조회 성공 (
FOLLOWERS_LIST_SUCCESS
){ "code": "FOLLOWERS_LIST_SUCCESS", "message": "팔로워 목록 조회에 성공했습니다.", "data": { "followers": [ { "userId": 2002, "nickname": "친구1", "profileImageUrl": "https://s3.amazonaws.com/.../profile1.png", "createdAt": "2025-04-20T01:10:00" }, { "userId": 2003, "nickname": "친구2", "profileImageUrl": "https://s3.amazonaws.com/.../profile2.png", "createdAt": "2025-04-18T14:22:11" } ], "hasNext": true, "nextCursor": 2003 } }
🧩 설계 근거 및 시나리오
- 이 API는 로그인한 사용자를 팔로우한 팔로워 목록을 커서 기반 무한스크롤로 조회합니다.
cursor
는 마지막으로 조회된userId
기준이며,hasNext
와nextCursor
로 프론트가 다음 페이지 요청 가능 여부를 판단할 수 있습니다. 기본 로딩 사이즈는 20입니다.- 팔로워의 기본 정보(닉네임, 프로필, 팔로우 시점 등)가 함께 제공됩니다.
알림 관련
✅ 알림 목록 조회
- Endpoint:
/api/notification?cursor={lastNotificationId}
- HTTP Method:
GET
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Query Parameter
lastNotificationId
(Long): 마지막으로 받은 알림 IDnull
이면 가장 최신 알림부터 조회 시작
✅ Success Response
-
200 OK – 알림 목록 조회 성공 (
NOTIFICATION_LIST_SUCCESS
){ "code": "NOTIFICATION_LIST_SUCCESS", "message": "알림 목록을 불러왔습니다.", "data": { "content": [ { "notificationId": 101, "type": "FEED_COMMENT", "resourceId": 555, "message": "gray님이 댓글을 남겼습니다.", "createdAt": "2025-04-19T15:56:00" } ], "page": 0, "size": 10, "totalElements": 25, "totalPages": 3, "last": false} }
🧩 설계 근거 및 시나리오
- 이 API는 사용자의 알림 목록을 최신순으로 조회하는 기능을 제공합니다.
lastNotificationId
를 기준으로 이전 알림들을 불러오는 무한스크롤 방식에 적합하게 설계되어 있습니다.- 각 알림에는 알림 유형(
type
), 관련 리소스 ID(resourceId
), 메시지, 생성 일시 등이 포함되어 있습니다.
✅ 알림 읽음 처리
- Endpoint:
/api/notification/{notificationId}/status
- HTTP Method:
POST
📥 Request
- Request Header
Authorization: Bearer <access_token>
(필수)
- Path Variable
notificationId
(Long, 필수): 읽음 처리할 알림 ID
✅ Success Response
-
200 OK – 알림 읽음 처리 성공 (
NOTIFICATION_READ_SUCCESS
){ "code": "NOTIFICATION_READ_SUCCESS", "message": "알림을 읽었습니다", "data": null }
🧩 설계 근거 및 시나리오
- 이 API는 사용자가 받은 특정 알림을 읽음 처리하기 위한 기능입니다.
- 읽음 처리된 알림은 UI 상에서 읽은 표시(예: bold 제거, 뱃지 감소 등)로 반영할 수 있으며, 서버에서도 상태 관리가 가능합니다.