| 기능 | URL | Method | Request | Success Response | Error Responses | Description | BE 담당자 | FE 담당자 |
|---|---|---|---|---|---|---|---|---|
| 회원가입 | /api/v1/users/signup | POST | body: { | |||||
| "email": "string", | ||||||||
| "password": "string", | ||||||||
| "nickname": "string", | ||||||||
| "phone": "string" | ||||||||
| } | 201 Created: { | |||||||
| "message": "입력하신 이메일로 인증 코드가 발송되었습니다." | ||||||||
| } |
| 400 Bad Request: { "message": "잘못된 요청입니다", "code": "VALIDATION_ERROR", "details": [ { "field": "${field}", "message": "${message}” } ] }
409 Conflict: { "message": "이미 사용 중인 ${field}입니다", "code": "DUPLICATE_ERROR", "field": "${field}" } | - ”${field}”: “email”, “nickname”, “phoneNumber” 중 하나를 값으로 가질 수 있고, 검증 과정에서 오류를 반환한 값입니다.
404 Not Found: { "message": "등록되지 않은 사용자입니다", "code": "USER_NOT_FOUND” }** | - 내부적으로 refreshToken을 생성하여 DB에 저장합니다.
쿠키를 생성하여 쿠키에도 refreshToken을 저장하여 “/api/v1/auth” 경로로 요청할 때마다 쿠키가 자동으로 전송되도록 합니다. | 한자랑 | 김지민 | | 소셜 로그인 콜백 (카카오) | /api/v1/oauth/kakao/callback | GET | Query Parameters: { code: string state: string (optional) error: string (optional) error_description: string (optional) } | 302 Found | | - 카카오에서 인증이 완료된 후 카카오가 우리 서버로 데이터를 전달하는 엔드포인트입니다.
OAuth 2.0 스펙에서는 authorization code를 Query Parameter로 전달하도록 정의하고 있습니다. | 한자랑 | | | 소셜 로그인 완료 (카카오) | /api/v1/oauth/kakao/callback | POST | body: { "code": "string” } | 200 OK: { "accessToken": "string", "refreshToken": "string", "userId": "number" } | 400 Bad Request: { "message": "잘못된 인증코드입니다", "code": "INVALID_VERIFICATION_CODE" } | - 내부적으로 refreshToken을 생성하여 DB에 저장합니다.
쿠키를 생성하여 쿠키에도 refreshToken을 저장하여 “/api/v1/auth” 경로로 요청할 때마다 쿠키가 자동으로 전송되도록 합니다. | 한자랑 | 김지민 | | 로그아웃 | /api/v1/users/logout | DELETE | headers: { ”Authorization”: “Baerer {accessToken} } | 200 OK: { "message": "로그아웃되었습니다" } | 401 Unauthorized: { ”message”: “인증에 실패했습니다.”, ”code”: “AUTH_ERROR” } | | 한자랑 | 김지민 | | 프로필 생성 | /api/v1/profiles | POST | headers: { ”Authorization”: “Baerer {accessToken} }
Content-Type: multipart/form-data request: { "gender": "string", "birth": "string”, ”introduction”: “string”(optional), ”mbti”: “string”(optional) ”profileImage”: “file” (optional) }, ”profileImage”: “file”(optional) | 201 Created: { "gender": “string”, "birth": "string", "profileImageUrl": “string”, "introduction": "string", "mbti": "string" } | 400 Bad Request: { ”message”: ${message} }
401 Unauthorized: { ”message”: “인증에 실패했습니다.” }
409 Conflict: { "message": “이미 프로필이 존재합니다." } | ${message}:
요청 형식이 잘못됐을 때 ex) 존재하지 않는 날짜 : ”잘못된 요청 형식입니다.”
성별 또는 생년월일이 null일 때: “성별(생년월일)을 입력해주세요.”
성별이 잘못 입력 됐을 때: "잘못된 Gender 값입니다: 'werwer'. 가능한 값: [MALE, FEMALE]”
생년월일을 미래로 입력했을 때: "생년월일은 미래일 수 없습니다.”
지원하는 이미지 형식이 아닐 때: "지원하지 않는 이미지 형식입니다.” | 강석진 | 김지민 | | 회원 탈퇴 | /api/v1/users | DELETE | headers: { ”Authorization”: “Baerer {accessToken} } | 200 OK: { "message": "회원 탈퇴가 완료되었습니다" } | 401 Unauthorized: { ”message”: “Expired JWT token” } | | 한자랑 | 김지민 | | 비밀번호 변경 링크 전송 | /api/v1/users/password/change/link-send | POST | body: { "email": "string", } | 200 OK: { "message": "비밀번호 변경 링크를 이메일로 전송하였습니다." } | 404 Not Found: { ”message": "사용자를 찾을 수 없습니다", "code": "USER_NOT_FOUND” } | - 이메일로 비밀번호를 변경할 수 있는 링크 전송 | 한자랑 | 김지민 | | 비밀번호 변경 | /api/v1/users/password/change | POST | body: { ”token”: “string”, ”newPassword”: “string” } | 200 OK: { "message": “비밀번호가 변경되었습니다." } | 400 Bad Request: { ”message”: “유효하지 않은 토큰입니다.”, ”code”: "INVALID_TOKEN" } | “token”: 이메일 링크에 포함된 토큰입니다. | 한자랑 | 김지민 | | 이메일 인증 | /api/v1/users/signup/verify | POST | Query Parameters: { code : {code} } | 200 OK: { "message": "이메일 인증이 완료되었습니다." } | 400 Bad Request: { "message": "유효하지않은 토큰입니다.", "code": "INVALID_TOKEN" } | | 한자랑 | 김지민 | | 액세스 토큰 갱신 | /token/reissue | POST | | 200 OK: { "accessToken": "string" } | 401 Unauthorized: { "message": "리프레시 토큰이 유효하지 않습니다", "code": "INVALID_REFRESH_TOKEN" } | - refreshToken은 쿠키에서 자동으로 전송되도록 한다. | | | | | | | | | | | | |
| 기능 | URL | Method | Request | Success Responses | Error Responses | description | BE 담당자 | FE 담당자 |
|---|---|---|---|---|---|---|---|---|
| 본인 프로필 조회 | /api/v1/users/me | GET | headers: { | |||||
| ”Authorization”: “Baerer {accessToken} | ||||||||
| } | 200 OK: { | |||||||
| ”userId”: “number”, | ||||||||
| ”nickname”: “string”, | ||||||||
| ”phoneNumber”: “string”, | ||||||||
| ”email”: “string”, | ||||||||
| ”gender”: “string”, | ||||||||
| ”birth”: “string”, | ||||||||
| ”profileImage”: “file”, | ||||||||
| ”introduction”: “stinrg”, | ||||||||
| ”mbti”: “string” | ||||||||
| } | 401 Unauthorized: { | |||||||
| ”message”: “Expired JWT token”, | ||||||||
| ”code”: “AUTH_ERROR” | ||||||||
| } |
| - “profileImage”: 저장소에 이미지를 저장할 때 생성한 URL을 반환합니다.
404 Not Found: { "message": "사용자를 찾을 수 없습니다", "code": "USER_NOT_FOUND” }30 | - “profileImage”: 저장소에 이미지를 저장할 때 생성한 URL을 반환합니다. | 한자랑 | | | 본인 정보 수정 | /api/v1/users/me | PUT | headers: { ”Authorization”: “Baerer {accessToken} }
Content-Type: multipart/form-data updateRequest: { "gender": "string", "birth": "string”, ”introduction”: “string”(optional), ”mbti”: “string”(optional) ”profileImage”: “file” (optional) }, ”profileImage”: “file”(optional) | 200 OK: { "message": "회원 정보가 수정되었습니다” } | 401 Unauthorized : { "message": "Invalid JWT token" } | - “details”: 에러 메세지에 필요한 파라미터를 전달합니다.
${field}: 검증 오류를 반환한 값입니다.
${code}: 상황에 맞는 오류 코드입니다. | 한자랑 | 김지민 | | 신청한 모임 목록 조회 | /api/v1/participations | GET | headers: { ”Authorization”: Bearer ${accessToken} }
Query Parameters: { ”lastId”: “number(default=0)”, ”pageSize”: “number(default=20)” } | 200 OK: { "appliedMeetings": [ { “id”: “number”, "meetingId": "number", “authorId”: “number”, “participationStatus”: “string”, "title": "string", "locationId": “number”, “latitude”: “number”, “longitude”: “number”, “address”: “string”, "meetingDateTime": "string", “maxCount”: “number”, “approvedCount”: “number”, "category": "string[]", ”content”: “string”, "thumbnail": "string" }, … ], "lastId": "number", ”hasNext”: “boolean” } | 401 Unauthorized: { ”message”: 인증에 실패했습니다.” } | - 요청 시에 마지막으로 조회됐던 모임의 id와 조회할 pageSIze를 받습니다.
401 Unauthorized: { ”message”: 인증에 실패했습니다.” }
403 Forbidden: { ”message”: “해당 참여 신청의 신청자가 아닙니다.” }
404 Not Found: { "message": "신청을 찾을 수 없습니다." }
404 Not Found: { ”message”: “해당 게시글을 찾을 수 없습니다.” } | 기획 문서 해당 부분입니다. 👍🏻 승인 거부, 모집 완료, 모집 취소 상태에는 삭제 버튼이 활성화 되어 해당 모집글을 목록에서 삭제할 수 있도록 한다. | 강석진 | | | 주최한 모임 목록 조회 | /api/v1/meetings/created | GET | header: { ”Authorization”: Bearer ${accessToken} }
Query Parameters: { ”lastId”: “number(default=0)”, ”pageSize”: “number(default=20)” } | 200 OK: { "createdMeetingDtos": [ { "userId": "number", “meetingId”: “number”, “meetingStatus”: “string”, "title": "string", "locationId": “number”, “latitude”: “number”, “longitude”: “number”, “address”: “string” "meetingDateTime": "string", "maxCount": "number", “approvedCount”: “number”,, "category": "string[]", “content”: “string” "thumbnail": "string", }, … ], ”lastId”: “number”, ”hasNext”: “boolean” } | 401 Unauthorized: { ”message”: 인증에 실패했습니다.” } | - 요청 시에 마지막으로 조회된 모임의 id와 조회할 pageSIze를 받습니다.
| 기능 | URL | Method | Request | Success Response | Error Responses | Description | BE 담당자 | FE 담당자 |
|---|---|---|---|---|---|---|---|---|
| 모임 작성 | /api/v1/meetings | POST | header: { | |||||
| ”Authorization”: Bearer ${accessToken} | ||||||||
| } |
Content-Type: multipart/form-data params: { "title": "string", ”locatinoId”: “number”, ”latitude”: “number”, ”longitude”: “number”, ”address”: “string”, ”meetingDateTime”: “string”, ”maxCount”: “number”, ”category”: “string[]” ”content”: “sring”, }, ”thumbnail”: “string”(optional) | 201 Created: { headers: { ”location” : “/api/meetins/{meetingId} }
body: { “id”: “number”, “title”: “string”, “locationId”: “number”, “latitude”: “number”, “longitude”: “number”, “address”: “string”, “meetingDateTime”: “string”, “maxCount”: “number”, “approvedCount”: “number”, “category”: string[], “content”: string, “thumbnail”: “string”, “meetingStatus”: “string” } | 400 Bad Request: { ”status”: 400, ”message”: “올바르지 않은 값이 있습니다.”, ”errors”: [ { “field”: ${filed}, “message”: ${message}, “rejectedValue”: ${rejectedValue} } ] }
401 Unauthorized: { ”message”: 인증에 실패했습니다.” }
429 Too Many Request: { "message": "하루 포스팅 개수 제한을 초과하였습니다.” } | ${field}: 검증에 실패한 필드입니다.
${message}: 해당 필드에 대한 오류 메세지입니다.
${ejectedValue}: 실패한 요청값입니다. | 강석진 | 이도현 | | 모임 수정 | /api/v1/meetings/{meetingId} | PUT | header: { ”Authorization”: “Bearer ${accessToken}” }
Content-Type: multipart/form-data request: { "title": "string", ”locatinoId”: “number”, ”latitude”: “number”, ”longitude”: “number”, ”address”: “string”, ”meetingDateTime”: “string”, ”maxCount”: “number”, ”category”: “string[]” ”content”: “sring”, ”thumbnail”: “string” }, ”newThumbnail”, “file”(optional) | 200 OK: { ”id”: “number”, ”title”: “string”, ”locationId”: “number”, “latitude”: “number”, “longitude”: “number”, “address”: “string”, “meetingDateTime”: “string”, “maxCount”: “number”, “approvedCount”: “number”, “category”: string[], “content”: string, “thumbnail”: “string”, “meetingStatus”: “string” } | 400 Bad Request: { ”status”: 400, ”message”: “올바르지 않은 값이 있습니다.”, ”errors”: [ { “field”: ${filed}, “message”: ${message}, “rejectedValue”: ${rejectedValue} } ] }
401 Unauthorized: { ”message”: 인증에 실패했습니다.”, }
403 Forbidden: { ”message”: “해당 모임의 작성자가 아닙니다.”, }
404 Not Found: { ”message”: “존재하지 않는 모임입니다.” } | ${field}: 검증에 실패한 필드입니다.
${message}: 해당 필드에 대한 오류 메세지입니다.
${ejectedValue}: 실패한 요청값입니다. | 강석진 | | | 모임 삭제 | /api/v1/meetings/{meetingId} | DELETE | header: { ”Authorization”: “Bearer ${accessToken}” } | 204 No Content | 401 Unauthorized: { ”message”: 인증에 실패했습니다.” }
403 Forbidden: { ”message”: “해당 모임의 작성자가 아닙니다.” }
404 Not Found: { ”message”: “존재하지 않는 모임입니다.” } | | 강석진 | | | 모임 목록 조회 | /api/v1/meetings | GET | Params: { ”latitude”: “number”, ”longitude”: “number”, ”lastId”: “number” ”lastDistance”: “number”, ”lastMeetingDateTime”: “string”, ”pageSize”: “number” } | 200 OK: { ”meetings”: [ { ”id”: “number”, “authorId”: “number”, ”title”: “string”, ”locationId”: “number”, “latitude”: “number”, ”longitude”: “number”, ”address”: “string”, ”meetingDateTime”: “string”, ”maxCount”: “number”, ”approvedCount”: “number’, “category”: “string[]”, ”content”: “string”, ”thumbnail”: “string” (optional), ”distance”: “number” (optional) }, … ], “hasNext”: “boolean” “cursor”: { id”: ${lastId}, “distance”: ${lastDistance}, “meetingDateTime”: ${lastMeetingDateTime} } } | 500 Internal Server Error: { ”message”: “내부 서버 오류”, ”code”: “INTERNAL_SERVER_ERROR” } | 사용자의 위치 정보가 없을 경우
사용자의 위치 정보가 있을 경우
두 경우 모두 초기 요청 시(가장 첫 페이지)에는 커서값이 null입니다. 이후 요청부터 이전 요청에서 반환된 커서값을 사용하여 요청하면 다음 페이지가 요청됩니다. | 강석진 | 이도현 | | 참여 신청자 목록 조회 | /api/v1/meetings/{meetingId}/participants | GET | headers: { ”Authorization”: “Bearer ${accessToken}” } | 200 OK: { "participants": [ { "userId": "number", “participationId”: “number”, "nickname": "string", "profileImage": "string", "participationStatus": "string" }, … ] } | 401 Unauthorized: { ”message”: 인증에 실패했습니다.” }
403 Forbidden: { ”message”: “해당 모임의 작성자가 아닙니다.” }
404 Not Found: { ”message”: “존재하지 않는 모임입니다.” } | | 강석진 | | | 모임 모집 완료 | /api/v1/meetings/{meetingID}/complete | PATCH | headers: { ”Authorization”: “Bearer ${accessToken}” } | 200 OK | 401 Unauthorized: { ”message”: 인증에 실패했습니다.” }
403 Forbidden: { ”message”: “작성자만 상태를 변경할 수 있습니다.” }
404 Not Found: { ”message”: “존재하지 않는 모임입니다.”, } | | 강석진 | |
| 기능 | URL | Method | Request | Success Response | Error Responses | Description | 담당자 | FE 담당자 |
|---|---|---|---|---|---|---|---|---|
| 모임 참여 신청 | /api/v1/participations/{meetingId} | POST | headers: { | |||||
| ”Authorization” “Bearer ${accessToken}” | ||||||||
| } | 201 Created | 400 Bad Request: { | ||||||
| "message": "신청할 수 없는 모임 상태입니다." | ||||||||
| } |
401 Unauthorized: { ”message”: 인증에 실패했습니다.” }
403 Forbidden: { ”message”: “본인이 개설한 모임에는 참여 신청을 할 수 없습니다.” }
404 Not Found: { ”message”: “존재하지 않는 모임입니다..” }
409 Conflict: { ”message”: “이미 참여 신청한 모임입니다.” } | | 강석진 | 김지민/이도현 | | 참여 신청한 모임 목록 조회 | /api/v1/participations | GET | headers: { ”Authorization”: Bearer {accessToken} }
Params: { ”lastId”: “number(default=0)”, ”pageSize”: “number(default=20)” } | 200 OK: { "appliedMeetings": [ { “participantId”: “number”, "meetingId": "number", “authorId”: “number”, “participationStatus”: “enum(’PENDING’, ‘APPROVED’, ‘REJECTED’, ‘CLOSED’, ‘CANCELED”), "title": "string", "locationId": “string”, “latitude”: “number”, “longitude”: “number”, “address”: “string”, "meetingDateTime": "strubg", “maxCount”: “number”, “approvedCount”: “number”, "category": "string[]", “content”: “string”, "thumbnail": "string", }, … ], ”lastId”: “number(optional)”, ”hasNext”: “boolean” } | 401 Unauthorized: { ”message”: 인증에 실패했습니다.” } | - 신청한 날짜 기준으로 오름차순 정렬하여 반환
lastId가 커서값입니다.
초기 요청 시(가장 첫 페이지)에는 커서값이 null입니다. 이후 요청부터 이전 요청에서 반환된 커서값을 사용하여 요청하면 다음 페이지가 요청됩니다. | 강석진 | | | 개최한 모임 목록 조회 | /api/v1/meetings/created | GET | header: { ”Authorization”: Bearer ${accessToken} }
Params: { ”lastId”: “number”, ”pageSize”: “number” } | 200 OK: { "createdMeetingDtos": [ { "userId": "number", “meetingId”: “number”, “meetingStatus”: “enum(’RECRUITING’, ‘CLOSED’)” "title": "string", "locationId": “number”, “latitude”: “number”, “longitude”: “number”, “address”: “string”, “meetingDateTime”: “string”, “maxCount”: “number”, “approvedCount”: “number”, “category”: “string[]”, “content”: “string”, “thumbnail”: “string” }, … ], ”lastId”: “number”, ”hasNext”: “boolean” } | 401 Unauthorized: { ”message”: 인증에 실패했습니다.” } | - 개최한 날짜 기준으로 오름차순 정렬하여 반환
lastId가 커서입니다.
초기 요청 시(가장 첫 페이지)에는 커서값이 null입니다. 이후 요청부터 이전 요청에서 반환된 커서값을 사용하여 요청하면 다음 페이지가 요청됩니다. | 강석진 | | | 참여 승인 | /api/v1/participations/{participationId}/approve | PATCH | headers: { ”Authorization” “Bearer ${accessToken}” } | 200 OK | 400 Bad Request: { ”message”: “유효하지 않은 참여 상태입니다.” }
401 Unauthorized: { ”message”: 인증에 실패했습니다.” }
403 Forbidden: { ”message”: “해당 모임의 작성자가 아닙니다.” }
404 Not Found: { ”message”: “신청을 찾을 수 없습니다.” }
409 Conflict: { ”message”: “모임 인원이 가득 찼습니다.” } | | 강석진 | | | 참여 거절 | /api/v1/participations/{participationId}/reject | PATCH | headers: { ”Authorization” “Bearer ${accessToken}” } | 200 OK | 400 Bad Request: { ”message”: “유효하지 않은 참여 상태입니다.” }
401 Unauthorized: { ”message”: 인증에 실패했습니다.” }
403 Forbidden: { ”message”: “해당 모임의 작성자가 아닙니다.” }
404 Not Found: { ”message”: “신청을 찾을 수 없습니다.” } | 참여가 승인되면 모임의 인원수가 1증가합니다. | 강석진 | | | 모임 참여 삭제 (참여한 모집글 목록에서 모집글 삭제 / 모임 참여 신청 취소) | /api/v1/participations/{participationId} | DELETE | headers: { ”Authorization”: Bearer {accessToken} } | 204 No Content | 400 Bad Request: { "message": "유효하지 않은 참여 상태입니다." }
403 Forbidden: { ”message”: “해당 참여 신청의 신청자가 아닙니다.” }
404 Not Found: { ”message”: “신청을 찾을 수 없습니다.”, } | 기획 문서 해당 부분입니다. 👍🏻 승인 거부, 모집 완료, 모집 취소 상태에는 삭제 버튼이 활성화 되어 해당 모집글을 목록에서 삭제할 수 있도록 한다. | 강석진 | |
| 기능 | URL | Method | Request | Success Responses | Error Responses | Description | 담당자 |
|---|---|---|---|---|---|---|---|
| 채팅방 생성 | /api/v1/chatrooms/{meetingId} | POST | headers: { | ||||
| ”Authorization”: “Baerer {accessToken} | |||||||
| } | 201 Created: { | ||||||
| "roomId": 1, | |||||||
| "meetingId": 1, | |||||||
| "meetingThumbnail": "thumbnailUrl", | |||||||
| "meetingTitle": "title", | |||||||
| "lastMessage": "", | |||||||
| "hostId": 1, | |||||||
| "readerId": [ | |||||||
| 1 | |||||||
| ], | |||||||
| "unreadMessagesCount": null | |||||||
| } | 400 Bad Request: { | ||||||
| ”message”: “유효하지 않은 요청” | |||||||
| } |
404 Not Found: { ”message”: “존재하지 않는 모임입니다.”, } | 모임생성시 자동생성됨. | BE: 정민균 | | 채팅방 목록 조회 | /api/v1/chatrooms | GET | headers: { ”Authorization”: “Baerer {accessToken} } | 200 OK: [ { "roomId": 1, "meetingId": 1, "meetingThumbnailUrl": "thumbnailUrl", "meetingTitle": "title", "lastMessage": "hi2", "hostId": 1, "readerId": [ 1, 2 ], "unreadMessagesCount": null } ] | 400 Bad Request: { ”message”: “유효하지 않은 요청” } | | BE: 정민균 | | 채팅방 정보 조회 | /api/v1/chatrooms/{roomId} | GET | headers: { ”Authorization”: “Baerer {accessToken} } | 200 OK: { "roomId": 1, "meetingId": 1, "meetingThumbnailUrl": "thumbnailUrl", "meetingTitle": "title", "lastMessage": "hi2", "hostId": 1, "readerId": [ 1, 2 ], "unreadMessagesCount": null } | 400 Bad Request: { ”message”: “유효하지 않은 요청” }
403 Forbidden: { ”message”: “해당 채팅방에 참여 중이 아닙니다.”, }
404 Not Found: { ”message”: “해당 채팅방이 없습니다.”, } | | BE: 정민균 | | 채팅방 삭제 (주최자) | /api/v1/chatrooms/{roomId} | DELETE | headers: { ”Authorization”: “Baerer {accessToken} } | 204 No Content | 400 Bad Request: { ”message”: “유효하지 않은 요청” }
401 Unauthorized: { ”message”: “호스트만 이 작업을 수행할 수 있습니다.” }
404 Not Found: { ”message”: “해당 채팅방이 없습니다.”, } | | BE: 정민균 | | 채팅 메시지 전송 | ws://localhost:8080/ws (WebSocket 연결) | WebSocket / STOMP | { "userId": 1, "roomId": 1, "message": "메시지 내용" } | { "roomId": 1, "message": "메시지 내용", "senderNickname": "nickname", ”senderId”: “userId”, ”userProfileImageUrl”: “ImageUrl” } | 400 Bad Request: { ”message”: “유효하지 않은 요청” }
404 Not Found: { ”message”: “해당 채팅방이 없습니다.”, } | STOMP Subscription Destination: /sub/chat/room/{roomId}
STOMP Send Destination: /pub/chat/message | BE: 정민균 | | 채팅방 입장 (모임입장) | /api/v1/chatrooms/{roomId}/join | POST | headers: { ”Authorization”: “Baerer {accessToken} } | 200 OK: { "roomId": 1, "meetingId": 1, "meetingThumbnailUrl": "thumbnailUrl", "meetingTitle": "title", "lastMessage": "", "hostId": 1, "readerId": [ 1, 2 ], "unreadMessagesCount": null } | 400 Bad Request: { ”message”: “유효하지 않은 요청” }
400 Bad Request: { ”message”: “이미 채팅방의 참여자입니다.” }
404 Not Found: { ”message”: “해당 채팅방이 없습니다.”, } | 모임 참가시 자동 입장됨. | BE: 정민균 | | 채팅방 퇴장 (모임 나가기 동일) | /api/v1/chatrooms/{roomId}/leave | POST | headers: { ”Authorization”: “Baerer {accessToken} } | 200 OK: { "roomId": 1, "meetingId": 1, "meetingThumbnailUrl": "thumbnailUrl", "meetingTitle": "title", "lastMessage": "", "hostId": 1, "readerId": [ 1, 2 ], "unreadMessagesCount": null } | 400 Bad Request: { ”message”: “유효하지 않은 요청” }
401 Unauthorized: { ”message”: “호스트는 이 작없을 수행할 수 없습니다.” }
404 Not Found: { ”message”: “해당 채팅방이 없습니다.”, } | | BE: 정민균 | | 채팅방 들어가기 (채팅 기록 조회) | /api/v1/chatrooms/{roomId}/in | POST | headers: { ”Authorization”: “Baerer {accessToken} } | 200 OK: [ { "userId": 1, "userNickname": "test1", "userProfileImageUrl": "", "message": "hi", "createdAt": "2025-01-06T04:40:02.140812", "updatedAt": "2025-01-06T04:40:02.140812" }, { "userId": 2, "userNickname": "test2", "userProfileImageUrl": "", "message": "hi2", "createdAt": "2025-01-06T04:40:25.073831", "updatedAt": "2025-01-06T04:40:25.073831" } ] | 400 Bad Request: { ”message”: “유효하지 않은 요청” }
403 Forbidden: { ”message”: “프로필 생성을 완료해 주세요.”, }
403 Forbidden: { ”message”: “해당 채팅방에 참여 중이 아닙니다.”, }
404 Not Found: { ”message”: “해당 채팅방이 없습니다.”, }
404 Not Found: { ”message”: “읽기 상태 정보가 없습니다.”, } | | BE: 정민균 | | 채팅방 나가기 (뒤로가기) | /api/v1/chatrooms/{roomId}/out | POST | headers: { ”Authorization”: “Baerer {accessToken} } | 200 OK: [ { "roomId": 1, "meetingId": 1, "meetingThumbnailUrl": "thumbnailUrl", "meetingTitle": "title", "lastMessage": "hi2", "hostId": 1, "readerId": [ 1, 2 ], "unreadMessagesCount": 0 } ] | 400 Bad Request: { ”message”: “유효하지 않은 요청” }
403 Forbidden: { ”message”: “해당 채팅방에 참여 중이 아닙니다.”, }
404 Not Found: { ”message”: “해당 채팅방이 없습니다.”, }
404 Not Found: { ”message”: “읽기 상태 정보가 없습니다.”, } | | | | 채팅방 참여자 조회 | /api/v1/chatrooms/{roomId}/participants | GET | headers: { ”Authorization”: “Baerer {accessToken} } | 200 OK: [ { "userId": 1, "nickname": "test1", "profileImageUrl": "" }, { "usdeId": 2, "nickname": "test2", "profileImageUrl": "" } ] | 400 Bad Request: { ”message”: “유효하지 않은 요청” }
403 Forbidden: { ”message”: “프로필 생성을 완료해 주세요.”, }
403 Forbidden: { ”message”: “해당 채팅방에 참여 중이 아닙니다.”, }
404 Not Found: { ”message”: “해당 채팅방이 없습니다.”, } | | BE: 정민균 | | 멤버 강퇴 | /api/v1/chatrooms/{roomId}/withdrawal/{userId} | POST | headers: { ”Authorization”: “Baerer {accessToken} } | 200 OK: { "roomId": 1, "meetingId": 1, "meetingThumbnailUrl": "thumbnailUrl", "meetingTitle": "title", "lastMessage": "hi2", "hostId": 1, "readerId": [ 1 ], "unreadMessagesCount": null } | 400 Bad Request: { ”message”: “유효하지 않은 요청” }
401 Unauthorized: { ”message”: “호스트만 이 작업을 수행할 수 있습니다.” }
404 Not Found: { ”message”: “사용자를 찾을 수 없습니다.”, }
404 Not Found: { ”message”: “해당 채팅방이 없습니다.”, } | | BE: 정민균 |
| 기능 | URL | Method | Request | Success Response | Error Responses | Description | BE 담당자 | FE 담당자 |
|---|---|---|---|---|---|---|---|---|
| SSE 구독 | /api/v1/notifications/subscribe | GET | headers: { | |||||
| ”Authorization”: “Baerer ${accessToken} | ||||||||
| } | 401 Unauthorized: { | |||||||
| ”message”: 인증에 실패했습니다.” | ||||||||
| } | 강석진 | |||||||
| 알림 목록 조회 | /api/v1/notifications | GET | headers: { | |||||
| ”Authorization”: “Baerer ${accessToken} | ||||||||
| } | 200 OK: | |||||||
| [ |
{
“id”: “number”,
“content”: “string”,
“notificationType”: “enum(’NEW_PARTICIPATION_REQUEST’,
’PARTICIPANT_LEFT’, ‘PARTICIPANT_APPROVED’, ‘PARTICIPANT_REJECTED’, ‘PARTICIPANT_KICKED’, ‘PARTICIPANT_MEETING_CLOSED’, ‘NEW_CHAT_MESSAGE’)” }, … ] | 401 Unauthorized: { ”message”: 인증에 실패했습니다.” } | | 강석진 | | | 특정 알림 삭제 | /api/v1/notifications/{notificationId} | DELETE | headers: { ”Authorization”: “Baerer ${accessToken} } | 204 No Content | 401 Unauthorized: { ”message”: 인증에 실패했습니다.” }
404 Not Found: { ”message”: “알림을 찾을 수 없습니다.” } | | 강석진 | | | 모든 알림 삭제 | /api/v1/notifications | DELETE | headers: { ”Authorization”: “Baerer ${accessToken} } | 204 No Content | | | 강석진 | |
| 기능 | URL | Method | Request | Success Response | Error Responses | Description | BE 담당자 | FE 담당자 |
|---|---|---|---|---|---|---|---|---|
| 검색 | /api/v1/meetings/search | GET | Params: { | |||||
| ”latitude”: “number”, | ||||||||
| ”longitude”: “number”, | ||||||||
| ”lastId”: “number” | ||||||||
| ”lastDistance”: “number”, | ||||||||
| ”lastMeetingDateTime”: “string”, | ||||||||
| ”pageSize”: “number”, | ||||||||
| ”searchType”: “enum(TITLE, ADDRESS, CONTENT)”, | ||||||||
| ”keyword”: “string”, | ||||||||
| ”foodCategory”: “string” | ||||||||
| } | 200 OK: { | |||||||
| ”meetings”: [ |
{
”id”: “number”,
“authorId”: “number”,
”title”: “string”,
”locationId”: “number”,
“latitude”: “number”,
”longitude”: “number”,
”address”: “string”,
”meetingDateTime”: “string”,
”maxCount”: “number”,
”approvedCount”: “number’,
“category”: “string[]”,
”content”: “string”,
”thumbnail”: “string” (optional),
”distance”: “number” (optional)
},
…
], “hasNext”: “boolean” “cursor”: { id”: ${lastId}, “distance”: ${lastDistance}, “meetingDateTime”: ${lastMeetingDateTime} } } | 500 Internal Server Error: { ”message”: “내부 서버 오류”, ”code”: “INTERNAL_SERVER_ERROR” } | - 검색 옵션 (TITLE, ADDRESS, 또는 CONTENT)