행사방 위치별 영상 탐색 및 아카이브¶
티켓: MSG-436(상위) · 세부 MSG-438~443 (2026-08-20 발행) · 원본: Codex 세션 2026-08-19 작성 상태: 확정 (2026-08-20 팀원 K 승인) — 행사방 정본. 기존 event-room.md의 제보·참여 모델을 대체한다. 뷰포트 기준 행사 칩 노출과 시 칩 묶음(구 PRD FR-1), 수동 시드 등재, 미션 축 연계 비목표 결정은 그대로 승계된다. 2026-09-09 개정(MSG-586): 상태 표에 지도 칩 노출 열을 추가하고 업로드 유예 회차를 칩에 노출하기로 확정했다. FR-23~25 신설.
1. 개요¶
행사방은 초대형 행사와 행사에서 파생된 여러 장소를 지도 격자 위에서 탐색하고, 장소별 현장 영상을 촬영하거나 갤러리에서 업로드하는 기능이다. 등재 대상은 정말 큰 행사만이다(눈높이 기준은 BTS 부산 콘서트급, 2026-08-20 팀원 K 확정). 도시 하나가 들썩이는 규모라야 파생 장소와 현장 영상 수요가 성립하기 때문이다.
사용자는 지역 → 행사 → 행사 위치 → 위치별 영상 순서로 탐색한다. 영상은 행사 영역 전체에 복제하지 않고 대표 격자 하나에만 저장한다. 다만 행사 위치에 연결된 어느 격자를 눌러도 같은 위치별 영상 피드를 조회할 수 있다.
행사가 끝난 뒤에도 기록은 유지한다. 종료 후 30일까지는 지난 영상을 추가로 올릴 수 있고 댓글과 도움돼요도 그대로 남길 수 있다. 30일이 지나면 영상 업로드와 댓글·도움돼요 변경이 함께 차단되고 완전한 읽기 전용 아카이브로 전환한다.
관련 디자인¶
- Figma 파일:
Fill Map - 행사방 섹션:
행사방 시안 - 포켓몬 메가페스타 부산 - 기준 화면: 행사 개요, 알림 상태, 위치별 영상, 빈 위치, 업로드, 영상 상세, 종료 아카이브
- Figma URL: https://www.figma.com/design/CpqOlgayviFOG0WXTBUfpp/Fill-Map?node-id=14599-10560
2. 목표¶
- 사용자가 행사에 포함된 팝업, 체험존, 퍼레이드, 포토존을 위치 단위로 탐색할 수 있게 한다.
- 현장에 있지 않아도 촬영 또는 갤러리 선택으로 행사 영상을 올릴 수 있게 한다.
- 영상 파일과 DB 레코드를 중복 생성하지 않고 대표 격자 한 곳에만 저장한다.
- 행사 위치 영역의 어느 격자를 눌러도 위치별 영상 기록에 접근할 수 있게 한다.
- 행사 종료 후 30일간 누락된 영상을 보완할 수 있게 한다.
- 아카이브로 넘어간 행사의 영상, 댓글, 도움돼요 수를 변경 불가능한 기록으로 보존한다.
- 현재 행사방 열람 인원을 heartbeat와 캐시로 근실시간 표시한다.
- 같은 행사가 다시 열릴 때 이전 회차 기록과 새 회차 데이터를 분리한다.
3. 핵심 용어와 데이터 관계¶
EventSeries (행사 시리즈)
└─ EventOccurrence (행사 회차)
├─ EventLocation (행사 위치)
│ ├─ EventLocationGrid[] (영역을 구성하는 격자)
│ └─ representativeGridId (영상 저장 대표 격자)
└─ EventVideo[]
├─ eventOccurrenceId
├─ eventLocationId
└─ gridId = representativeGridId
EventSeries: 포켓몬 메가페스타처럼 반복 개최될 수 있는 행사의 공통 단위EventOccurrence: 특정 기간에 열린 행사 회차EventLocation: 부산역 팝업, 광안리 퍼레이드처럼 회차에 속한 실제 장소EventLocationGrid: 행사 위치가 지도에서 차지하는 전체 격자 영역representativeGridId: 영상 레코드가 실제로 연결되는 격자 하나EventVideo: 영상 파일과 행사 회차·위치·대표 격자 연결 정보
4. 확정 정책¶
4.1 대표 격자 지정¶
- 행사 위치 영역이 9×9처럼 홀수 행·열의 직사각형이면 정중앙 격자를 대표 격자로 지정한다.
- 영역이 직사각형이 아니거나 중앙 격자를 계산할 수 없으면 운영자가 지정한
representativeGridId를 사용한다. - 운영자가 대표 격자를 지정하지 않은 예외 상황에서는 영역 중심점과 가장 가까운 포함 격자를 선택하고 그 결과를 저장한다.
- 한 행사 위치의 모든 영상은 해당 위치의 대표 격자 하나에만 연결한다.
- 영상 파일이나 영상 레코드를 9×9 전체 격자에 복제하지 않는다.
- 행사 영역의 다른 격자를 클릭하면
EventLocationGrid연결을 통해 같은 위치별 영상 피드를 조회한다.
4.2 행사 상태¶
| 상태 | 기간 | 영상 조회 | 영상 업로드 | 댓글 작성·수정 | 도움돼요 변경 | 알림 | 지도 칩 노출 |
|---|---|---|---|---|---|---|---|
| 예정 | 시작 전 | 가능 | 불가 (2026-08-21 확정) | 가능 | 가능 | 사용자 선택 | 시작 2주 전부터 |
| 진행 중 | 시작~종료 | 가능 | 가능 | 가능 | 가능 | 사용자 선택 | 노출 |
| 업로드 유예 | 종료 후 30일 | 가능 | 가능 | 가능 | 가능 | 자동 OFF | 노출 (2026-09-09 확정) |
| 아카이브 | 종료 30일 이후 | 가능 | 불가 | 불가 | 불가 | OFF | 미노출 |
- 아카이브 전환(종료 + 30일) 시 댓글 입력창과 도움돼요 버튼을 비활성화한다.
- 기존 댓글과 도움돼요 수는 아카이브에서도 계속 표시한다.
- 종료 후 30일 동안 업로드한 영상에도 댓글과 도움돼요를 남길 수 있다.
- 2026-08-21 확정(번복): 댓글·도움돼요 잠금 시점을 행사 종료에서 아카이브 전환(종료 + 30일)으로 옮겼다.
유예 기간을 둔 목적이 "행사 다녀와서 나중에 올리기"인데 그 영상이 처음부터 아무도 반응할 수 없는 상태로
올라가면 유예의 목적과 결과가 서로 깎이기 때문이다. 기존 근거였던 "종료 = 기록 확정"은 "아카이브 전환 =
기록 확정"으로 옮겨갔고, 이로써 업로드 창과 반응 창이
시작 ~ 종료 + 30일로 정렬된다. - 2026-09-09 확정(번복): 업로드 유예 상태의 회차도 지도 칩에 노출한다. 기존에는 종료 정각에 칩에서 빠져 사용자가 그 행사로 들어갈 입구가 사라졌고, 그 상태로 업로드와 댓글과 도움돼요만 열려 있었다. 2026-08-21에 반응 잠금 시점을 옮길 때 쓴 근거가 그대로 적용된다. 유예 기간을 둔 목적이 "행사 다녀와서 나중에 올리기"인데 들어갈 경로가 없으면 유예의 목적과 결과가 서로 깎인다. 아카이브 회차는 계속 칩에서 빼는데, 읽기 전용 기록이라 지난 행사 아카이브 화면이 그 접근을 맡기 때문이다.
- 칩 목록의 순서 기준은 이번 변경으로 바뀌지 않는다. 시 이름을 1차 기준으로 유지해 화면이 시 단위로 칩을 묶는 구조를 그대로 쓴다. 진행 중인 행사를 끝난 행사보다 앞으로 당기는 별도 정렬은 도입하지 않는다.
- 업로드 마감 시각은
eventEndAt + 30일이다. - 마감 시각 비교는 서버 시간을 기준으로 한다.
- 2026-08-21 확정: 행사 경유 업로드는 행사 시작부터 개방한다(구 표기 "정책상 허용 시 가능" 미결의 해소). 시작 전 시도는
EVENT_UPLOAD_NOT_STARTED로 거부하고(FE는 버튼 비활성화), 일반 격자 업로드는 행사와 무관하게 언제나 자유다.
4.3 업로드 방식¶
- 사용자는 현재 행사 위치에 있지 않아도 업로드할 수 있다.
- 업로드 화면은
촬영하기와영상 선택을 같은 단계에서 제공한다. - 제목과 영상 설명은 입력받지 않는다.
- 사용자가 행사 위치 화면에서 업로드하면 행사 회차와 행사 위치를 자동 지정한다.
gridId는 서버가 행사 위치의 대표 격자로 결정한다.- 기기의 현재 위치나 영상 GPS 메타데이터는 필수 조건으로 사용하지 않는다.
- 업로드 완료 후 해당 행사 위치의 최신 영상 피드로 돌아간다.
4.4 현재 열람 인원¶
- 프론트엔드는 행사방을 보고 있는 동안 주기적으로 heartbeat를 전송한다.
- 기본 전송 주기는 30초다.
- 서버는 마지막 heartbeat가 90초 이내인 고유 세션을 현재 열람자로 집계한다.
- 로그인 사용자는 사용자 ID, 비로그인 사용자는 익명 세션 ID로 중복 제거한다.
- 활성 세션은 Redis 등 TTL을 지원하는 캐시에 저장한다.
- UI 문구는
120명 보는 중형식으로 행사명 인접 영역에 표시한다. - 행사 알림 영역 아래에는 열람 인원을 중복 표시하지 않는다.
5. 사용자 스토리¶
US-001: 지역 행사 칩 탐색¶
Description: 사용자는 지역 칩을 펼쳐 현재 지역의 대표 행사를 선택하고 싶다.
Acceptance Criteria:
- [ ] 접힌 상태에는 부산 ›만 표시된다.
- [ ] 펼친 상태에는 📍 부산, 활성 행사, 추천 행사가 한 행에 표시된다.
- [ ] 활성 행사 칩 포켓몬 부산 D-7은 파란색으로 표시된다.
- [ ] 지역축제 기본 칩은 제거되지 않는다.
- [ ] 칩이 서로 겹치거나 중복 표시되지 않는다.
- [ ] 종료 뒤에도 종료 시각 + 30일 정각 전까지는 칩에 계속 표시된다(2026-09-09 확정).
- [ ] 종료 시각 + 30일 정각부터는 칩에서 사라진다(그 순간이 아카이브 전환 시각이다).
- [ ] Typecheck와 lint가 통과한다.
- [ ] 브라우저에서 실제 화면을 검증한다.
US-002: 행사 개요와 위치 목록 조회¶
Description: 사용자는 행사에 들어간 뒤 관련 장소와 영상 현황을 먼저 보고 싶다.
Acceptance Criteria: - [ ] 행사 이미지, 행사명, 기간, D-day, 열람 인원, 작은 알림 토글이 표시된다. - [ ] 행사 위치 목록에 위치명, 유형, 운영 시간, 영상 수가 표시된다. - [ ] 지도에서 각 행사 위치 영역이 서로 떨어진 실제 위치에 표시된다. - [ ] 각 격자 색상은 셀 경계 전체를 정확히 채운다. - [ ] 위치 카드 선택 시 해당 위치별 영상 피드로 이동한다. - [ ] Typecheck와 lint가 통과한다. - [ ] 브라우저에서 실제 화면을 검증한다.
US-003: 행사 위치 격자 조회¶
Description: 사용자는 지도에서 행사 위치에 속한 격자를 눌러 그 위치의 영상을 보고 싶다.
Acceptance Criteria:
- [ ] 행사 위치의 모든 격자는 EventLocationGrid로 연결된다.
- [ ] 영역 내 어느 격자를 선택해도 동일한 eventLocationId가 해석된다.
- [ ] 선택 위치는 진한 파란색, 다른 행사 위치는 낮은 강도의 행사색으로 표시된다.
- [ ] 선택된 색상 영역은 실제 지도 격자의 X/Y 및 크기와 일치한다.
- [ ] 영상 데이터를 다른 격자에 복제하지 않는다.
- [ ] Typecheck와 lint가 통과한다.
- [ ] 브라우저에서 실제 화면을 검증한다.
US-004: 위치별 영상 피드 조회¶
Description: 사용자는 선택한 행사 위치에 올라온 영상을 한 행에 하나씩 보고 싶다.
Acceptance Criteria:
- [ ] 위치별 영상 API는 eventOccurrenceId와 eventLocationId로 조회한다.
- [ ] 각 카드는 전체 너비 16:9 썸네일, 재생 버튼, 길이를 표시한다.
- [ ] 카드 하단에는 하트 수, 댓글 수, 업로드 시간이 표시된다.
- [ ] 카드 목록에는 사용자가 입력하지 않은 제목이나 설명을 표시하지 않는다.
- [ ] 업로드 시간은 가장 오른쪽에 표시된다.
- [ ] 결과가 없으면 아직 이 위치에 올라온 영상이 없어요와 업로드 CTA를 표시한다.
- [ ] Typecheck와 lint가 통과한다.
- [ ] 브라우저에서 실제 화면을 검증한다.
US-005: 영상 촬영 및 갤러리 업로드¶
Description: 사용자는 현장에서 바로 촬영하거나 나중에 갤러리 영상을 선택해 올리고 싶다.
Acceptance Criteria:
- [ ] 업로드 카드에 촬영하기와 영상 선택 버튼이 함께 표시된다.
- [ ] 업로드는 사용자의 현재 위치와 무관하게 가능하다.
- [ ] 업로드 요청에 eventOccurrenceId와 eventLocationId가 포함된다.
- [ ] 서버가 eventLocationId의 대표 격자를 조회해 gridId를 지정한다.
- [ ] 제목과 설명 입력 필드가 존재하지 않는다.
- [ ] 성공 시 위치별 피드 최상단에 새 영상이 표시된다.
- [ ] 마감 이후 요청은 명확한 마감 오류로 거절된다.
- [ ] Typecheck와 lint가 통과한다.
- [ ] 브라우저에서 촬영·갤러리 두 흐름을 검증한다.
US-006: 영상 상세와 댓글¶
Description: 사용자는 영상을 재생하고 반응 및 댓글 기록을 확인하고 싶다.
Acceptance Criteria: - [ ] 상세에는 영상, 대표 격자, 업로드 시각, 작성자 정보가 표시된다. - [ ] 진행 중인 행사에서는 도움돼요와 댓글 작성이 가능하다. - [ ] 댓글마다 작성자, 내용, 작성 시간이 표시된다. - [ ] 아카이브된 행사에서는 기존 댓글과 도움돼요 수가 표시된다. - [ ] 아카이브된 행사에서는 댓글 입력과 도움돼요 변경이 서버와 UI 모두에서 차단된다. - [ ] 유예 기간(종료 후 30일)에는 댓글 입력과 도움돼요 변경이 계속 가능하다. - [ ] 목록의 하트 표기와 상세의 도움돼요 수는 동일한 반응 데이터를 사용한다. - [ ] Typecheck와 lint가 통과한다. - [ ] 브라우저에서 진행 중·유예·아카이브 상태를 각각 검증한다.
US-007: 행사 알림¶
Description: 사용자는 행사 시작과 일정 변경 알림을 작게 켜거나 끄고 싶다.
Acceptance Criteria: - [ ] 행사명 인접 영역에 작은 알림 토글이 표시된다. - [ ] 알림은 행사 시작과 일정 변경에 사용된다. - [ ] 행사 종료 시 서버가 알림 구독을 자동 비활성화한다. - [ ] 별도의 행사 참여하기나 행사방 나가기 과정이 없다. - [ ] Typecheck와 lint가 통과한다. - [ ] 브라우저에서 ON/OFF/자동 종료 상태를 검증한다.
US-008: 현재 열람 인원 표시¶
Description: 사용자는 현재 같은 행사방을 보고 있는 사람 수를 확인하고 싶다.
Acceptance Criteria:
- [ ] 행사방 진입 시 익명 또는 로그인 세션 ID로 heartbeat를 시작한다.
- [ ] 화면 이탈 또는 탭 비활성화 시 불필요한 heartbeat를 중단하거나 낮춘다.
- [ ] 마지막 신호가 90초를 넘긴 세션은 집계에서 제외된다.
- [ ] 동일 세션의 중복 탭 처리 정책에 따라 중복 집계되지 않는다.
- [ ] UI는 행사명 옆에 N명 보는 중을 표시한다.
- [ ] 캐시 장애 시 숫자를 숨기고 핵심 행사방 기능은 계속 동작한다.
- [ ] Typecheck와 lint가 통과한다.
- [ ] 브라우저에서 진입·이탈·만료 상황을 검증한다.
US-009: 종료 후 30일 업로드 유예¶
Description: 사용자는 행사 당일 놓친 영상을 다음 날 또는 종료 후 일정 기간 안에 올리고 싶다.
Acceptance Criteria:
- [ ] 종료 후 30일까지 지난 영상 올리기를 제공한다.
- [ ] 유예 기간 업로드에도 대표 격자 지정 규칙을 동일하게 적용한다.
- [ ] 유예 기간에 생성된 영상에도 댓글·도움돼요 변경이 가능하다(2026-08-21 번복).
- [ ] 종료 30일 이후 업로드 CTA가 사라진다.
- [ ] 경계 시각의 허용 여부는 서버 시간으로 일관되게 판정한다.
- [ ] Typecheck와 lint가 통과한다.
- [ ] 브라우저에서 종료 직전, 종료 후, 마감 직전, 마감 후 상태를 검증한다.
US-010: 지난 행사 회차 아카이브¶
Description: 사용자는 같은 행사가 다시 열려도 이전 회차의 장소와 영상을 구분해 보고 싶다.
Acceptance Criteria:
- [ ] 새 개최 기간에는 새 EventOccurrence를 생성한다.
- [ ] 기본 화면은 현재 회차를 표시한다.
- [ ] 지난 행사 영상에서 이전 회차를 선택할 수 있다.
- [ ] 이전 회차의 위치, 영상, 댓글, 도움돼요 수를 그대로 조회할 수 있다.
- [ ] 서로 다른 회차의 영상 수와 열람 인원이 섞이지 않는다.
- [ ] Typecheck와 lint가 통과한다.
- [ ] 브라우저에서 현재·이전 회차 전환을 검증한다.
6. 기능 요구사항¶
- FR-1: 시스템은 행사 시리즈와 행사 회차를 분리해 저장해야 한다.
- FR-2: 행사 위치는 행사 회차에 속해야 하며 하나 이상의 격자와 연결되어야 한다.
- FR-3: 행사 위치는 반드시 유효한 대표 격자 하나를 가져야 한다.
- FR-4: 9×9 영역의 대표 격자는 5번째 행·5번째 열의 중앙 격자여야 한다.
- FR-5: 중앙 계산 실패 시 설정된 대표 격자를 사용해야 한다.
- FR-6: 대표 격자 설정도 없으면 영역 중심에 가장 가까운 포함 격자를 계산하고 저장해야 한다.
- FR-7: 영상은 행사 회차, 행사 위치, 대표 격자에 각각 한 번만 연결되어야 한다.
- FR-8: 행사 영역의 어느 격자에서 진입해도 위치별 피드를 조회할 수 있어야 한다.
- FR-9: 업로드는 현재 위치 권한 없이도 동작해야 한다.
- FR-10: 업로드는 촬영과 갤러리 선택을 모두 지원해야 한다.
- FR-11: 업로드는 영상 제목과 설명을 요구하지 않아야 한다.
- FR-12: 종료 후 30일까지 영상 업로드를 허용해야 한다.
- FR-13: 아카이브 전환(종료 + 30일) 시 댓글 생성·수정·삭제와 도움돼요 추가·취소를 차단해야 한다(2026-08-21 번복 — 유예 기간은 허용).
- FR-14: 아카이브 후에도 댓글과 도움돼요 집계는 조회할 수 있어야 한다.
- FR-15: 종료 30일 이후 모든 영상 업로드를 차단해야 한다.
- FR-16: 종료 시 알림 구독을 자동으로 비활성화해야 한다.
- FR-17: 행사방 열람자는 heartbeat 기반으로 중복 제거해 집계해야 한다.
- FR-18: 캐시에서 90초 이상 갱신되지 않은 세션은 자동 제외해야 한다.
- FR-19: 열람자 집계 장애는 영상 조회·업로드 API에 영향을 주지 않아야 한다.
- FR-20: 영상 목록은 최신 업로드 순으로 정렬해야 한다.
- FR-21: 댓글 목록은 댓글 작성 시간을 제공해야 한다.
- FR-22: 종료 상태와 업로드 마감은 클라이언트 값이 아니라 서버 시각으로 판정해야 한다.
- FR-23: 지도 뷰포트 행사 칩 목록에는 노출 기간에 든 예정 회차, 진행 중 회차, 업로드 유예 회차를 담아야 한다(2026-09-09 확정, SRS FR-EVENT-01 개정).
- FR-24: 지도 뷰포트 행사 칩 목록에서 아카이브 회차(종료 시각 + 30일 정각 이후)는 제외해야 한다(SRS FR-EVENT-01).
- FR-25: 칩 목록은 시 이름을 1차 정렬 기준으로 유지해, 화면이 시 단위로 칩을 묶는 구조가 깨지지 않아야 한다(SRS FR-EVENT-01의 시 칩 묶음 계약).
7. 제안 API¶
조회¶
GET /event-occurrences/{occurrenceId}: 행사 헤더, 상태, 기간, 알림 상태GET /event-occurrences/{occurrenceId}/locations: 위치 목록, 영역 격자, 대표 격자, 영상 수GET /event-occurrences/{occurrenceId}/locations/{locationId}/videos?cursor=: 위치별 영상 피드GET /grids/{gridId}/event-locations: 선택 격자가 속한 현재·지난 행사 위치GET /event-videos/{videoId}: 영상 상세, 댓글, 도움돼요 수, 읽기 전용 여부GET /event-videos/{videoId}/comments?cursor=: 댓글 목록 둘째 페이지부터 (커서 기반. 첫 페이지는 위 영상 상세 응답에 실려 온다. US-006·FR-21의 댓글 목록을 전달하는 API이며 2026-08-21 MSG-441 스펙 작성 중 등재했다)GET /event-occurrences/{occurrenceId}/viewer-count: 현재 열람 인원
변경¶
POST /event-occurrences/{occurrenceId}/heartbeat: 열람 세션 갱신POST /event-occurrences/{occurrenceId}/locations/{locationId}/videos: 영상 업로드 생성POST /event-videos/{videoId}/comments: 아카이브 전 행사 댓글 작성PATCH /event-videos/{videoId}/comments/{commentId}: 아카이브 전 행사 댓글 수정DELETE /event-videos/{videoId}/comments/{commentId}: 아카이브 전 행사 댓글 삭제PUT /event-videos/{videoId}/helpful: 아카이브 전 행사 도움돼요 추가DELETE /event-videos/{videoId}/helpful: 아카이브 전 행사 도움돼요 취소PUT /event-occurrences/{occurrenceId}/notification: 사용자 알림 ON/OFF
공통 오류 코드¶
EVENT_NOT_FOUND: 행사 회차가 없음EVENT_LOCATION_NOT_FOUND: 행사 위치가 없음EVENT_UPLOAD_CLOSED: 종료 후 30일 업로드 마감EVENT_INTERACTION_LOCKED: 아카이브된 행사 댓글·도움돼요 변경 시도REPRESENTATIVE_GRID_MISSING: 대표 격자 결정 실패INVALID_VIDEO: 지원하지 않는 영상 또는 업로드 제한 위반
8. 데이터 필드 제안¶
EventOccurrence¶
ideventSeriesIdtitlestartsAtendsAtuploadClosesAt=endsAt + 30일status:UPCOMING | LIVE | UPLOAD_GRACE | ARCHIVED
EventLocation¶
ideventOccurrenceIdnametypeoperatingHoursrepresentativeGridId
EventLocationGrid¶
eventLocationIdgridIdrowIndex와columnIndex또는 공간 좌표
EventVideo¶
ideventOccurrenceIdeventLocationIdgridIduploaderIdvideoUrlthumbnailUrldurationSecondscapturedAt(선택)createdAtinteractionLocked
ViewerPresence¶
- 캐시 키: 행사 회차 ID
- 멤버: 사용자 ID 또는 익명 세션 ID
- 값: 마지막 heartbeat 시각
- 활성 기준: 현재 시각 기준 90초 이내
9. UI·UX 요구사항¶
- 배경은 밝은 회청색, 카드는 흰색, 주요 행동과 선택 상태는 파란색을 사용한다.
- 행사 칩은 부산 불꽃축제 시안과 같은 구성으로 통일한다.
📍 부산: 연한 파란색포켓몬 부산 D-7: 파란색 활성🎬 부산국제영화제: 흰색 추천- 행사 위치는 지도에 실제로 떨어진 위치로 분산해 표시한다.
- 행사 위치가 차지하는 셀은 일부 도형이 아니라 완전한 격자 단위로 채운다.
- 위치별 영상은 한 행에 하나씩 표시한다.
- 업로드 카드에는
촬영하기와영상 선택을 나란히 표시한다. - 상세 댓글에는 상대 작성 시간을 오른쪽에 표시한다.
- 아카이브 상태에서는 댓글 입력창을 숨기거나 비활성 상태와 사유를 명확히 표시한다.
- 아카이브 상태의 도움돼요 버튼은 현재 수만 표시하고 클릭할 수 없어야 한다.
10. 비기능 요구사항¶
- 위치별 영상 첫 페이지 응답 목표는 p95 1.5초 이하다.
- 영상 목록은 커서 기반 페이지네이션을 사용한다. 댓글 목록도 같은 규칙을 따른다(상세 응답이 첫 페이지를 담고, 그다음은 커서로 이어 받는다).
- 동일 영상 업로드 요청의 재시도는 중복 레코드를 만들지 않도록 멱등 키를 지원한다. 보장 범위는 해당 영상이 교체되거나 삭제되기 전까지다(2026-08-21 확정 — 교체와 삭제는 확정 응답을 받은 클라이언트만 할 수 있어, 이 보장이 겨누는 응답 유실 재시도와 실행 순서가 겹치지 않는다).
- 대표 격자 연결과 영상 생성은 하나의 트랜잭션으로 처리한다.
- 댓글·도움돼요 잠금은 UI뿐 아니라 변경 API에서 반드시 검증한다.
- 업로드 마감 시각과 행사 상태 전환 작업은 재실행해도 안전해야 한다.
- heartbeat 캐시 장애 시 열람 인원만 숨기고 행사 핵심 기능은 정상 제공한다.
- 영상 접근 권한, 신고, 삭제 등 기존 공통 영상 정책을 그대로 적용한다.
- 영상 파일의 최대 길이(30초)·용량·지원 코덱도 기존 공통 업로드 정책을 재사용한다(2026-08-21 확정 — 행사 전용 파일 규격을 두지 않는다).
11. 비목표¶
- 별도 행사 참여하기 및 행사방 나가기
- 참여 인원 수 집계
- 제보 작성·목록·상세 기능
- 영상 제목 및 설명 입력
- 영상 레코드를 행사 위치의 모든 격자에 복제 저장
- 현재 위치와 업로드 위치의 강제 일치
- 아카이브된 행사에서 댓글이나 도움돼요 변경
- 행사 전용 채팅방 또는 영상 외 질문 창구
12. 성공 지표¶
- 위치 카드 선택 후 영상 재생까지의 중앙값이 3단계 이내다.
- 영상 업로드 시작 사용자의 70% 이상이 업로드를 완료한다.
- 행사 종료 후 업로드된 영상 비율을 측정해 유예 기간 사용성을 확인한다.
- 대표 격자 누락으로 실패하는 업로드 비율이 0.1% 미만이다.
- 하나의 영상 ID가 여러 격자에 중복 생성되는 사례가 0건이다.
- heartbeat 만료 후 90초 이내에 열람 인원에서 제거된다.
- 아카이브된 행사에서 댓글·도움돼요 변경 성공 사례가 0건이다.
13. 테스트 시나리오¶
- 9×9 행사 위치를 생성하면 중앙 격자가 대표로 결정된다.
- 불규칙 영역에서 설정된 대표 격자가 사용된다.
- 대표 격자 설정이 없으면 중심점에서 가장 가까운 포함 격자가 저장된다.
- 행사 영역의 서로 다른 두 격자를 눌러도 같은 위치별 피드가 반환된다.
- 영상 업로드 후 대표 격자 한 곳에만 영상 관계가 생성된다.
- 현재 행사 지역 밖에서도 촬영 및 갤러리 업로드가 성공한다.
- 행사 진행 중 댓글과 도움돼요 변경이 성공한다.
- 종료 직후 영상 업로드와 댓글·도움돼요 변경이 모두 성공하고, 아카이브 전환 후에는 둘 다 거절된다.
- 종료 후 30일 마감 직전 업로드는 성공한다.
- 마감 이후 업로드는
EVENT_UPLOAD_CLOSED로 실패한다. - 같은 행사의 새 회차를 생성해도 이전 영상이 현재 회차에 섞이지 않는다.
- heartbeat 전송 중인 세션만 집계되고 90초가 지나면 제거된다.
- 댓글 작성 시간이 목록과 상세에 올바르게 표시된다.
- 캐시 장애 시 열람 인원은 숨겨지지만 영상 조회와 업로드는 동작한다.
14. 구현 순서 제안¶
- 행사 시리즈·회차·위치·위치 격자·대표 격자 데이터 모델
- 대표 격자 계산 및 운영자 대체값 검증
- 행사 위치 및 격자 역조회 API
- 위치별 영상 조회 API와 커서 페이지네이션
- 촬영·갤러리 공통 업로드 API 및 멱등 처리
- 행사 상태와 종료 후 30일 업로드 유예 정책
- 아카이브된 행사 댓글·도움돼요 변경 잠금
- heartbeat와 열람 인원 캐시 집계
- 지역·행사 칩과 행사 개요 UI
- 위치별 영상·빈 상태·업로드·상세 UI
- 종료 아카이브와 이전 회차 전환 UI
- 브라우저 E2E 및 서버 경계 시각 테스트
15. 남은 확인 사항¶
- 운영자가 행사 위치 영역과 대표 격자를 등록하는 어드민 화면의 범위를 별도로 정해야 한다.
- 예정 상태 영상 업로드 허용 여부: 2026-08-21 차단으로 확정돼 종결(§4.2 확정 기록 참조).
- 영상 신고 및 운영자 삭제 시 아카이브 카운트 처리 정책을 기존 영상 정책과 맞춰야 한다.
- 비로그인 사용자의 영상 업로드·댓글·도움돼요 허용 여부: 조회는 GET 한정으로 비로그인 허용, 업로드·댓글·도움돼요 변경은 로그인 필수로 MSG-439·440에서 확정돼 종결(MSG-441이 댓글·도움돼요 변경에 같은 정책을 승계한다). 익명 세션 ID는 §4.4 열람 인원 집계 전용이라 쓰기 주체가 아니다.