-
Notifications
You must be signed in to change notification settings - Fork 0
Group V2 Requirements
핵심 내용 정리
- 모임 이미지는 “사전 업로드 → imageKey로 등록” 방식입니다.
- 업로드는 최대 3장, 변형은 440x240 / 100x100 WEBP 2종입니다.
- pre-upload imageKey는 2시간 유효하며, 업로더만 사용할 수 있고, 사용 시 1회 소비됩니다.
- 수정의 imageKeys는 “최종 상태”이며,
null=변경 없음,[]=전체 삭제,[..]=그대로 최종 반영(0번째 대표)입니다. - 모임 삭제는 DB 삭제 확정 후(커밋 후) 이미지 파일을 삭제합니다.
모임을 생성하거나 수정할 때 이미지를 바로 저장하지 않고, 먼저 이미지를 업로드해서 서버가 imageKey와 URL 세트를 발급합니다.
그 다음 모임 생성/수정 API에서는 imageKey 목록을 전달해서 해당 이미지를 모임에 연결합니다.
- 사용자는 이미지 업로드 요청을 먼저 수행한다.
- 서버는 업로드된 이미지마다 imageKey(고유 키) 를 발급한다.
- 모임 생성/수정에서는 업로드 결과로 받은 imageKey를 사용해 이미지를 확정 등록한다.
해당 정책의 목적은 “이미지 파일 업로드”와 “모임 데이터 저장”을 분리해서, 모임 생성/수정 시 데이터 정합성을 유지하고, 이미지 URL 규격을 서버가 보증하도록 하기 위함이에요.
사전 업로드 API(/api/v2/groups/images/upload)는 한 번 요청에 최대 3개 파일만 받습니다.
- 0장: 허용(이미지 없이 업로드 요청을 보내면 실질적으로 결과는 빈 배열이에요.)
- 1~3장: 정상 처리
- 4장 이상: 오류
사용자가 올린 이미지 1장은 서버에서 다음 2개 변형(Variant)으로 만들어 저장합니다. 올린 이미지 형식은 모두 .webp로 변환되고, 원본 이미지에 대한 정보를 보관하지 않습니다.
- 카드용 이미지: 440 x 240 (WEBP)
- 썸네일 이미지: 100 x 100 (WEBP)
따라서 “모임 이미지 1장”은 내부적으로는 아래 2개의 URL을 갖고 있습니다.
- url440x240
- url100x100
이 URL은 클라이언트가 임의로 만들거나 조합하는 값이 아니라, 서버가 업로드 처리 과정에서 생성하고 보증하는 결과물입니다.
사전 업로드로 발급된 imageKey는 2시간(TTL) 동안만 유효합니다.
2시간이 지나면 해당 imageKey로 모임 생성/수정에 사용할 수 없습니다(서버에서 찾을 수 없게 돼요.)
- 유효기간 내에 모임 생성/수정 요청에서 사용해야 합니다.
- 유효기간이 지나면 다시 업로드를 해야 합니다.
사전 업로드로 발급된 imageKey는 업로더(uploaderId) 가 함께 저장됩니다.
만약 모임 생성/수정에서 imageKey를 사용하려고 할 때, 요청한 사용자와 업로더가 다르면 오류 처리됩니다.
따라서 다른 사람이 올린 imageKey를 가져다가 내 모임에 붙일 수 없습니다.
모임 생성/수정에서 imageKey를 사용할 때 서버는 Redis에서 그 값을 consume(가져오고 삭제해서 consume이에요!) 합니다.
- 같은 imageKey를 두 번 재사용할 수 없습니다.
- 모임 생성 요청에서 한 번 사용되면, 같은 imageKey로 또 다른 모임에 붙일 수 없습니다.
- 수정에서도 마찬가지로, “새로 추가되는 이미지”는 반드시 “아직 소비되지 않은 pre-upload imageKey”여야 합니다.
📥모임 생성 요청(POST /api/v2/groups/create)에서 images가 있을 경우
- 각 이미지 항목은 imageKey가 반드시 필요합니다.
- sortOrder는 선택으로 프론트가 보내면 그 값을 사용합니다. 만약, 안 보내면 서버가 요청 순서대로 0(대표이미지)부터 부여합니다.
- 또한 생성 시 이미지도 최대 3장까지 등록 가능합니다.
모임 수정에서 이미지 필드는 imageKeys: List 형태로 받습니다. 해당 리스트는 “부분 수정용”이 아니라 최종 상태(final state)를 의미합니다.
수정 요청의 imageKeys가 의미하는 바는 다음과 같습니다.
- 이 리스트에 포함된 imageKey들만 모임에 포함됩니다.
- 리스트에 없는 기존 이미지는 삭제됩니다.
- 리스트에 있고 기존에 없던 imageKey는 신규 이미지로 추가됩니다.(사전 업로드가 필요합니다.)
- 리스트의 순서가 최종 표시 순서가 됩니다.(0번이 대표 이미지)
8-1) 수정 요청에서 imageKeys가 null이면?
- 이미지 변경 없음: 기존 이미지 상태를 유지합니다.
8-2) 수정 요청에서 imageKeys가 빈 리스트([])이면?
- 이미지 전체 삭제: 모임에 연결된 이미지가 모두 제거됩니다.
8-3) 수정 요청에서 imageKeys가 1~3개이면?
- 해당 키 목록이 곧 “최종 이미지 목록 + 최종 순서”가 됩니다.(0번째가 대표 이미지에요.)
8-4) 수정에서 중복 imageKey는 금지
- imageKeys 안에 동일한 key가 중복되면 오류 처리합니다.
8-5) 수정에서 최대 3장 제한
- imageKeys는 최대 3개까지만 허용됩니다.
모임 이미지의 대표(썸네일/대표 노출)는 항상 sortOrder = 0 을 의미합니다.
- 이미지가 3장이면 sortOrder는 0,1,2로 관리됩니다.
- 수정에서 넘어온 imageKeys의 리스트 순서대로 0.. 재부여 됩니다.
모임을 “하드 삭제”하면 DB 데이터 삭제 후, 트랜잭션 커밋이 끝난 다음 S3 파일(URL 기반) 을 삭제합니다.
- DB가 먼저 삭제 확정
- 그 다음 이미지 파일 삭제 수행
- 만약 파일 삭제가 실패하더라도 DB는 이미 삭제된 상태일 수 있습니다. → (추후 재시도(outbox) 확장 포인트 고려 중)
핵심 내용 정리
- 모임은 RECRUITING / FULL / CLOSED / CANCELLED / FINISHED 5가지 상태를 가집니다.
- 참가 가능 여부는 모집중(RECRUITING) + 남은 자리 있음 조건으로 판단합니다.
- HOST는 참가·탈퇴가 불가능하며, 수정·삭제 권한을 가집니다.
- 참가자 수는 ATTEND 상태만 집계합니다.
- FULL 상태는 자동 전환/복귀되며, CANCELLED·FINISHED는 최종 상태입니다.
| 모임 상태 | 설명 |
|---|---|
| RECRUITING | 모집 중 상태이며, 기본 상태입니다. 참가가 가능합니다. |
| FULL | 최대 인원에 도달한 상태입니다. 참가자는 더 받을 수 없지만, 탈퇴가 발생하면 다시 RECRUITING으로 돌아갈 수 있습니다. |
| CLOSED | 모집이 종료된 상태입니다. 참가 및 재참가는 모두 불가능합니다 |
| CANCELLED | 모임이 취소된 상태입니다. 더 이상 수정·참가·재개가 불가능합니다. |
| FINISHED | 모임이 종료된 상태입니다. 더 이상 수정·참가가 불가능합니다. |
모임 생성 직후 상태는 항상 RECRUITING 입니다.
모임 상태는 정해진 방향으로만 변경할 수 있습니다.
| 모임 상태 | 변경 가능한 상태 |
|---|---|
| RECRUITING | FULL, CLOSED, CANCELLED, FINISHED |
| FULL | RECRUITING, CLOSED, CANCELLED, FINISHED |
| CLOSED | CANCELLED, FINISHED |
| CANCELLED | 모임 상태 변경 불가 |
| FINISHED | 모임 상태 변경 불가 |
위 규칙을 벗어난 상태 변경 요청은 모두 오류 처리됩니다.
모임에 참가 버튼이 활성화되는 조건은 다음 두 가지를 모두 만족해야 합니다.
- 모임 상태가 RECRUITING
- 현재 참가 인원 < 최대 인원
아래 모임 상태에서는 참가가 불가능합니다.
- FULL
- CLOSED
- CANCELLED
- FINISHED
반드시 “모집중 + 남은 자리 있음” 상태에서만 참가가 가능합니다.
모임 참가자는 다음 역할 중 하나를 가집니다.
| 모임 참가자 역할 | 설명 |
|---|---|
| HOST | 모임 생성자 모임 수정 및 삭제 권한 보유 참가(ATTEND) 및 탈퇴(LEFT) 불가 |
| MEMBER | 일반 참가자 |
| MANAGER | (현재는 확장 예정 역할) |
HOST는 모임 생성 시 자동으로 부여됩니다.
모임 참가자는 아래 상태 중 하나를 가집니다.
- ATTEND: 현재 참가 중
- LEFT: 자발적 탈퇴
- KICKED: 강제 퇴장
- BANNED: 영구 차단
참가자 수 집계에는 ATTEND 상태만 포함됩니다.
📌 참가 기본 조건
- 로그인 사용자만 가능
- HOST는 참가 불가
- 모임 상태는 반드시 RECRUITING이어야 합니다.
📌 기존 참가 이력에 따른 처리
- ATTEND → 오류 (이미 참가 중)
- LEFT / KICKED → 재참가 허용
- BANNED → 참가 불가 (오류)
- 기존 이력 없음 → 신규 참가자로 생성
📌재참여하는 경우
- 상태는 ATTEND로 변경(joinedAt은 새로 기록됩니다.)
참가 또는 재참가 처리 후, ATTEND 상태 참가자 수를 기준으로 정원을 체크합니다.
참가자 수가 최대 인원을 초과하면 전체 요청은 오류 처리되며 롤백됩니다.
📌 자동 상태 변경
- 참가자 수 == 최대 인원 → FULL로 자동 전환
- FULL 상태에서 탈퇴 발생 → RECRUITING으로 자동 복귀
HOST는 탈퇴할 수 없습니다.
ATTEND 상태일 때만 탈퇴가 가능합니다.
탈퇴 처리 결과
- 상태는 LEFT로 변경(leftAt(탈퇴 시각)이 기록됩니다.)
참가자 수(participantCount)는 항상 ATTEND 상태만 기준으로 계산합니다.
LEFT, KICKED, BANNED 상태는 참가자 수에 포함되지 않습니다.
HOST가 조회할 경우
- 모든 참가자 상태(ATTEND / LEFT / KICKED / BANNED) 확인 가능
- 탈퇴 시각(leftAt) 포함
일반 사용자 또는 비로그인
- ATTEND 상태 참가자만 노출
- 탈퇴·강퇴 정보는 노출되지 않음
모임 삭제는 HOST만 가능합니다. 삭제 순서는 다음과 같습니다.
- 참가자 정보 삭제
- 태그 연결 삭제
- 이미지 삭제 (variants → images)
- 모임 엔티티 삭제
- 트랜잭션 커밋 이후 이미지 파일(S3) 삭제
핵심 내용 정리
- 모임 생성은 로그인한 사용자만 가능하며, 생성자는 자동으로 HOST가 됩니다.
- 모임 생성에는 5초 쿨다운이 적용됩니다.
- 제목·설명·위치·시간·정원은 필수 또는 조건부 필수입니다.
- 태그는 최대 10개까지 가능하며, 중복은 허용되지 않습니다.
- 이미지는 사전 업로드된 imageKey를 통해 최대 3장까지 등록할 수 있습니다.
- 모임 생성은 다음 조건을 만족해야 가능합니다.
- 로그인한 사용자만 모임을 생성할 수 있습니다.
- 비로그인 사용자는 모임 생성이 불가능합니다.
- 모임 생성 요청 시, 요청 사용자는 자동으로 해당 모임의 HOST가 됩니다.
- HOST는 생성과 동시에 모임에 참가자로 등록됩니다.
- 모임 생성에는 연속 생성 방지를 위한 쿨다운 정책이 적용됩니다.
- 동일 사용자는 5초에 1번만 모임을 생성할 수 있습니다.
- 쿨다운 시간 내에 다시 생성 요청을 하면 오류가 발생합니다.
- 쿨다운 남은 시간(초 단위)이 함께 전달됩니다.
📌 예시
- A 사용자가 12:00:00에 모임 생성
- 12:00:05 이전에 다시 생성 요청 → 실패
- 12:00:05 이후 요청 → 성공
📌 보장 정책 모임 생성 트랜잭션이 실패(롤백) 되면, 쿨다운도 함께 해제됩니다.
모임 생성 시 다음 항목은 반드시 입력되어야 합니다.
- 제목(title)
- 위치(location)
- 시작 시간(startTime)
- 설명(description)
- 최대 인원(maxParticipants)
위 항목 중 하나라도 누락되면 모임 생성은 실패합니다.
제목(title)
- 필수 입력 값입니다.
- 공백만 입력하는 것은 허용되지 않습니다.
- 최대 길이는 50자입니다.
- 앞뒤 공백은 제거(trim) 후 저장됩니다.
설명(description)
- 필수 입력 값입니다.
- 공백만 입력하는 것은 허용되지 않습니다.
- 최대 길이는 300자입니다.
- 앞뒤 공백은 제거(trim) 후 저장됩니다.
위치(location / locationDetail)
- location(기본 위치)은 필수 입력입니다.
- locationDetail(상세 위치)는 선택 입력입니다.
- location은 공백이거나 비어 있을 수 없습니다.
📌 예시
- location: “서울 강남구”
- locationDetail: “강남역 3번 출구 앞”
시간(startTime / endTime)
- startTime은 필수 입력입니다.
- startTime은 현재 시각 이후(또는 현재) 여야 합니다.
- endTime은 선택 입력입니다.
📌 시간 검증 규칙
- endTime이 존재하는 경우: 반드시 startTime < endTime 이어야 합니다.
- endTime이 없는 경우: 단일 시점 모임으로 처리됩니다. 시간 조건을 만족하지 않으면 모임 생성은 실패합니다.
최대 인원(maxParticipants)
- 필수 입력 값입니다.
- 최소 인원: 2명
- 최대 인원: 12명 2명 미만 또는 12명 초과일 경우 오류 처리됩니다.
태그(tags) 정책
- 태그는 선택 입력입니다.
- 최대 10개까지 등록할 수 있습니다.
- 공백이거나 빈 문자열 태그는 무시됩니다.
- 동일한 태그가 중복되면 오류 처리됩니다.
📌 태그 처리 방식
- 기존에 존재하는 태그는 재사용됩니다.
- 존재하지 않는 태그는 새로 생성됩니다.
모임 생성 시 이미지 처리 정책
- 이미지는 선택 입력입니다.
- 최대 3장까지 등록 가능합니다.
- 이미지는 반드시 사전 업로드된 imageKey를 통해 등록해야 합니다.
- imageKey가 유효하지 않거나, 업로더가 다르면 오류 처리됩니다.
- 이미지 정책의 상세 내용은 「🖼️ 이미지 정책(사전 업로드 방식)」을 따릅니다.
모임이 정상적으로 생성되면 다음 상태가 됩니다.
- 모임 상태: RECRUITING
- 생성자(HOST): 자동 참가 상태(ATTEND)
- 생성 시각(createdAt), 수정 시각(updatedAt) 기록
핵심 내용 정리
- 모임 목록 조회는 커서 기반 페이징 방식입니다.
- 기본 필터는 ACTIVE이며, 상태 기준으로 노출 범위가 결정됩니다.
- 키워드 검색은 제목·위치·설명을 대상으로 합니다.
- 목록에서는 대표 이미지 최대 3장과 태그만 요약 노출합니다.
- 참가 가능 여부(joinable)와 남은 자리(remainingSeats)는 서버에서 계산합니다.
모임 목록 조회 API는 다음 목적을 가집니다.
- 전체 모임 목록 조회
- 키워드 기반 검색
- 상태 기반 필터링
- 무한 스크롤을 위한 커서 기반 페이징 지원
기본적으로 삭제된 모임은 목록에 노출되지 않습니다.
모임 목록 조회는 페이지 번호 방식이 아닌 커서 기반 페이징을 사용합니다.
- cursor는 마지막으로 조회한 모임의 groupId 입니다.
- 최신 모임이 먼저 노출되며, groupId 내림차순 기준입니다.
- 다음 페이지가 있는 경우에만 nextCursor가 내려옵니다.
📌 동작 방식
- 첫 요청: cursor 없이 요청
- 서버는 size + 1 만큼 조회
- size 초과 여부로 다음 페이지 존재 여부 판단
- 다음 페이지가 있으면 마지막 요소의 groupId를 nextCursor로 반환
모임 목록 조회에는 filter 파라미터가 존재합니다.
| 필터 | 설명 |
|---|---|
| ACTIVE | 현재 사용자에게 노출되는 모임 포함 상태: RECRUITING, FULL, CLOSED
|
| ARCHIVED | 종료된 모임 목록 포함 상태: CANCELLED, FINISHED
|
| ALL | 상태 제한 없이 전체 모임 조회 |
filter가 명시되지 않으면 기본값은 ACTIVE입니다.
목록 조회 시 상태 필터를 직접 지정할 수 있습니다.
- includeStatuses가 있으면 filter의 기본 include 규칙을 무시하고 includeStatuses만 사용합니다.
- excludeStatuses가 있으면 해당 상태는 조회 결과에서 제외됩니다.
📌 충돌 처리 규칙
- include와 exclude에 동일한 상태가 있을 경우 exclude가 우선되며, 해당 상태는 제외됩니다.
📌 주의
- filter=ALL 인 경우에는 기본 상태 강제가 적용되지 않습니다.('기본 노출 규칙'을 무시하고 전체를 다 보여줘요.)
키워드 검색은 선택 조건입니다.
검색 대상 필드
- 모임 제목(title)
- 모임 위치(location)
- 모임 상세 위치(locationDetail)
- 모임 설명(description)
검색 방식
- 대소문자 구분 없음
- 부분 일치 검색
키워드가 공백이거나 비어 있으면 검색 조건은 적용되지 않습니다.
모임 목록에서는 이미지 전체 정보를 내려주지 않습니다.
- 대표 이미지 기준으로 최대 3장까지만 노출됩니다.
- 이미지 규격은 CARD_440_240 만 사용됩니다.
- 이미지가 없는 경우 빈 배열이 내려옵니다.
이미지의 정렬 순서는 모임 이미지의 sortOrder 기준입니다.
목록에서 사용되는 값들은 서버에서 계산됩니다.
- participantCount: ATTEND 상태 참가자 수
- remainingSeats: maxParticipants - participantCount (0 미만이면 0)
- joinable
- 아래 조건을 만족하면 true
- 모임 상태가 RECRUITING
- remainingSeats > 0
- 아래 조건을 만족하면 true
프론트에서는 별도의 계산을 하지 않아도 됩니다.
핵심 내용 정리
- 모임 수정은 HOST만 가능합니다.
- 수정 요청은 “부분 수정”이지만, 각 필드는 최종 상태 기준으로 반영됩니다.
- CANCELLED·FINISHED 상태의 모임은 수정할 수 없습니다.
- 태그·이미지는 null과 []의 의미가 명확히 다릅니다.
- 이미지 수정은 최종 imageKeys 리스트 기준으로 동작합니다.
모임 수정은 다음 조건을 만족해야 가능합니다.
- 로그인한 사용자만 수정 요청 가능합니다.
- 요청 사용자는 반드시 해당 모임의 HOST여야 합니다.
- 모임이 삭제되지 않은 상태여야 합니다.
- 모임 상태가 CANCELLED 또는 FINISHED가 아니어야 합니다.
위 조건 중 하나라도 만족하지 않으면 수정 요청은 실패합니다.
모임 수정 요청은 모든 필드를 한 번에 보내지 않아도 됩니다.
- 요청에 포함된 필드만 수정됩니다.
- 요청에 포함되지 않은 필드는 기존 값이 유지됩니다.
📌 단, 각 필드는 최종 상태로 반영되며, 서버가 유효성 검사를 수행합니다.
아래 조건에 해당하면 모임 수정은 불가능합니다.
- 모임이 이미 삭제된 경우
- 모임 상태가 CANCELLED
- 모임 상태가 FINISHED
이 경우 모든 수정 요청은 오류 처리됩니다.
- 요청에 title이 포함된 경우에만 수정됩니다.
- 공백만 있는 값은 허용되지 않습니다.
- 최대 길이는 50자입니다.
- 앞뒤 공백은 제거(trim) 후 저장됩니다.
요청에 description이 포함된 경우에만 수정됩니다.
- 공백만 있는 값은 허용되지 않습니다.
- 최대 길이는 300자입니다.
- 앞뒤 공백은 제거(trim) 후 저장됩니다.
위치 정보는 부분 수정이 가능합니다.
- location 또는 locationDetail 중 하나라도 요청에 포함되면
- 서버는 최종 주소 객체를 새로 구성합니다.
📌 동작 방식
- location이 없고 locationDetail만 요청된 경우: 기존 location 유지 + locationDetail 변경
- location만 요청된 경우: location 변경 + 기존 locationDetail 유지
location은 반드시 값이 있어야 하며, 공백은 허용되지 않습니다.
시간 정보는 단일 수정 또는 동시 수정이 가능합니다.
- startTime만 수정 가능
- endTime만 수정 가능
- startTime + endTime 동시 수정 가능
📌 공통 검증 규칙
- startTime은 null이 될 수 없습니다.
- endTime이 존재하는 경우 반드시 startTime < endTime 조건을 만족해야 합니다.
조건을 만족하지 않으면 수정 요청은 실패합니다.
- maxParticipants가 요청에 포함된 경우에만 수정됩니다.
- 현재 ATTEND 상태 참가자 수보다 작아질 수 없습니다.
📌 예시
- 현재 참가자 5명
- maxParticipants를 4로 수정 요청 → 오류
- maxParticipants를 6 이상으로 수정 → 정상
status는 요청에 포함된 경우에만 변경됩니다.
- 상태 변경은 정해진 상태 전이 규칙을 따릅니다.
- 허용되지 않은 상태 전이는 오류 처리됩니다.
(상태 전이 규칙은 「👥 모임 상태 · 참가 · 정원 · 역할 정책」을 따릅니다.)
태그 수정은 최종 상태 기준 교체 방식입니다.
tags = null: 태그 변경 없음
tags = []: 모든 태그 삭제
tags = ["A", "B"]: 기존 태그 전체 제거 후 A, B로 재구성
📌 태그 검증 규칙
- 최대 10개까지 허용
- 중복 태그는 허용되지 않음
- 공백 또는 빈 문자열 태그는 무시됨
이미지 수정은 최종 상태 리스트 방식으로 처리됩니다.
- imageKeys =
null: 이미지 변경 없음 - imageKeys =
[]: 이미지 전체 삭제 - imageKeys =
["k1", "k2"]: k1, k2만 남기고 순서대로 정렬 (0번 대표)
📌 이미지 정책 요약
- 최대 3장까지 허용
- 중복 imageKey 허용 안 됨
- 신규 imageKey는 반드시 사전 업로드된 값이어야 함
- 기존 이미지 중 리스트에 없는 것은 삭제됨
(상세 규칙은 「🖼️ 이미지 정책」을 따릅니다.)
핵심 내용 정리
- 모든 실패는 명확한 원인과 메시지를 가진 에러로 응답됩니다.
- 인증·권한·상태·입력값·정합성 오류를 구분합니다.
- 서버 오류가 아닌 경우, 대부분은 사용자 행동에 따른 예측 가능한 실패입니다.
- 실패한 요청은 부분 반영 없이 전체 롤백됩니다.
모임 서비스의 에러 처리는 다음 원칙을 따릅니다.
- 유효성 검증 실패는 즉시 요청을 중단합니다.
- 하나의 요청에서 오류가 발생하면 아무 변경도 반영되지 않습니다.
- 클라이언트는 에러 메시지를 기준으로 사용자에게 안내합니다.
- 서버 내부 오류(500)는 예외적인 경우에만 발생해야 합니다.
다음 경우 요청은 실패합니다.
로그인하지 않은 사용자가 다음 요청 시도를 하는 경우 해당 요청은 거부됩니다.
- 모임 생성
- 모임 수정
- 모임 삭제
- 모임 참가 / 탈퇴
사용자는 “로그인이 필요합니다”와 유사한 메시지를 받습니다.
다음 경우 요청은 실패합니다.
HOST가 아닌 사용자인 경우
- 모임 수정 요청
- 모임 삭제 요청
HOST 사용자인 경우
- 자기 모임에 참가(attend)하려는 경우
- 자기 모임에서 탈퇴(left)하려는 경우
📌 결과
요청은 거부됩니다.
“권한이 없습니다” 또는 “허용되지 않은 요청”와 유사한 메시지가 반환됩니다.
다음 상태에서는 특정 요청이 실패합니다.
📌 참가 실패 케이스
- 모임 상태가 RECRUITING이 아닌 경우
- FULL
- CLOSED
- CANCELLED
- FINISHED
📌 수정 실패 케이스
- 모임 상태가 CANCELLED 또는 FINISHED인 경우
📌 상태 변경 실패 케이스
- 허용되지 않은 상태 전이 요청
다음 경우 모임 참가 요청은 실패합니다.
- 이미 ATTEND 상태인 경우
- BANNED 상태인 경우
- 정원이 초과된 경우
- HOST가 참가하려는 경우
📌 결과
- 참가 처리되지 않음
- 참가자 수 증가 없음
- 상태 변경 없음
다음 경우 모임 탈퇴 요청은 실패합니다.
- HOST가 탈퇴하려는 경우
- ATTEND 상태가 아닌 경우
- LEFT
- KICKED
- BANNED
📌 결과
- 탈퇴 처리되지 않음
- 상태 변경 없음
다음 경우 요청은 실패합니다.
모임 생성 시
- 2명 미만
- 12명 초과
모임 수정 시
- 현재 ATTEND 참가자 수보다 작은 값으로 수정 요청한 경우
📌 결과
요청은 전체 실패 처리됩니다.
다음 경우 이미지 처리 요청은 실패합니다.
- imageKey가 존재하지 않는 경우
- imageKey가 이미 소비(consumed)된 경우
- imageKey 업로더와 요청 사용자가 다른 경우
- 이미지 개수가 3장을 초과한 경우
- 수정 요청에서 중복 imageKey가 포함된 경우
📌 결과
- 이미지 등록/수정 전체 실패
- 기존 이미지 상태 유지
다음 경우 태그 요청은 실패합니다.
- 태그 개수가 10개를 초과한 경우
- 중복된 태그가 포함된 경우
📌 결과
- 태그 변경 전체 실패
- 기존 태그 상태 유지
다음 경우 요청은 실패합니다.
- startTime이 null인 경우
- startTime이 현재 시각 이전인 경우
- endTime이 startTime보다 같거나 빠른 경우
📌 결과
- 모임 생성 또는 수정 실패
다음 경우 모임 생성 요청은 실패합니다.
- 동일 사용자가 쿨다운 시간(5초) 이내에 다시 생성 요청한 경우
📌 결과
- 생성 실패
- 남은 쿨다운 시간이 함께 전달됨
하나의 요청에서 여러 변경이 발생하더라도, 중간에 오류가 발생하면 모든 변경은 롤백됩니다.
📌 예시
- 이미지 등록 중 오류 발생: 태그, 모임 정보, 이미지 모두 저장되지 않음
핵심 내용 정리
- 모든 모임 관련 행동은 사용자 역할(HOST / MEMBER / 비로그인) 기준으로 제한됩니다.
- 인증(Authentication)과 권한(Authorization)은 명확히 구분됩니다.
- 서버는 항상 권한을 우선 검증하며, 프론트 요청을 전적으로 신뢰하지 않습니다.
- “보여줄 수 있음”과 “행동할 수 있음”은 별개의 개념입니다.
모임 서비스는 다음 인증 원칙을 따릅니다.
- 로그인 여부는 서버 기준으로 판단합니다.
- 로그인하지 않은 사용자는 조회만 가능하며, 변경을 수반하는 모든 요청은 제한됩니다.
- 인증 정보가 없거나 만료된 경우 요청은 즉시 거부됩니다.
📌 인증이 필요한 기능
- 모임 생성
- 모임 수정
- 모임 삭제
- 모임 참가 / 탈퇴
- 내 모임 목록 조회
모임 서비스에서 사용자는 다음 3가지 유형으로 구분됩니다.
- 비로그인 사용자
- 일반 로그인 사용자
- HOST (모임 생성자)
HOST는 “로그인 사용자”의 특수한 역할이며,특정 모임에 대해서만 HOST 권한을 가집니다.
비로그인 사용자는 다음 행동만 가능합니다.
✅가능한 행동
- 모임 목록 조회
- 모임 상세 조회
❌ 불가능한 행동
- 모임 생성
- 모임 수정
- 모임 삭제
- 모임 참가
- 모임 탈퇴
- 내 모임 목록 조회
📌 비로그인 사용자는 읽기 전용(Read-only) 사용자입니다.
일반 로그인 사용자는 다음 행동이 가능합니다.
✅ 가능한 행동
- 모임 목록 조회
- 모임 상세 조회
- 모임 참가 (조건 충족 시)
- 모임 탈퇴 (ATTEND 상태일 때)
- 내 모임 목록 조회
❌ 불가능한 행동
- 타인의 모임 수정
- 타인의 모임 삭제
- HOST 권한이 필요한 관리 기능
📌 로그인 사용자라도, HOST가 아닌 모임에 대해서는 관리 권한이 없습니다.
HOST는 자신이 생성한 모임에 대해 다음 권한을 가집니다.
✅ 가능한 행동
- 모임 수정
- 모임 삭제
- 모임 상태 변경
- 참가자 전체 조회
❌ 불가능한 행동
- 자기 모임에 참가
- 자기 모임에서 탈퇴
📌 HOST는 “관리자”이며, 참가자 개념과 분리됩니다.
| 행동 | 비로그인 | 로그인 | HOST |
|---|---|---|---|
| 모임 목록 조회 | ✅ | ✅ | ✅ |
| 모임 상세 조회 | ✅ | ✅ | ✅ |
| 모임 생성 | ❌ | ✅ | ✅ |
| 모임 참가 | ❌ | ✅ | ❌ |
| 모임 탈퇴 | ❌ | ✅ | ❌ |
| 모임 수정 | ❌ | ❌ | ✅ |
| 모임 삭제 | ❌ | ❌ | ✅ |
| 참가자 전체 조회 | ❌ | ❌ | ✅ |
| 내 모임 목록 조회 | ❌ | ✅ | ✅ |
서버는 요청 처리 시 다음 순서로 검증합니다.
- 인증 여부 확인
- 요청 대상 모임 존재 여부 확인
- 삭제 여부 확인
- 권한(HOST / MEMBER) 확인
- 상태(Status) 검증
- 비즈니스 로직 수행
📌 권한이 없는 요청은 비즈니스 로직 실행 전 즉시 차단됩니다.
- 클라이언트에서 전달하는 role 정보는 신뢰하지 않습니다.
- 모든 권한 판단은 서버의 데이터 기준으로 수행합니다.
- URL 조작, ID 추측 등을 통한 접근은 모두 차단됩니다.
- 모임 ID는 내부 식별자이며, 권한 검증 없이 정보가 노출되지 않습니다.