Pangea
⏎
자동 분석 · 1달 전
로그인
데모 · 1D1S 프로젝트를 읽기 전용으로 보고 있습니다. 편집·AI 실행은 할 수 없습니다.내 레포로 시작하기 →
1D1S
홈브리핑진전이슈8일정화면API지도 탐색플로우문서변경

문서
루트/AI 역문서/2. 핵심 기능

AI 초안 · 검토 전노근 · 1달 전 수정

2.5 채팅과 신고

AI 역문서 · 1D1S-client@ad5edf9 · 1D1S-server-v2@f69a4eb 기준 · 코드에서 거꾸로 만든 초안입니다. 근거 링크로 확인하세요.

관련 소스 파일

  • 1D1S-client/src/app/chat/page.tsx
  • 1D1S-client/src/app/chat/rooms/[roomId]/page.tsx
  • 1D1S-client/src/app.feature/chat/socket/chatSocket.ts
  • 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/config/ChatConnectionRegistry.java
  • 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/config/ChatPushAsyncConfig.java
  • 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/config/ChatSessionTerminator.java
  • 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/config/ChatStompAuthInterceptor.java
  • 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/config/ChatWebSocketConfig.java
  • 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/AdminChatController.java
  • 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/ChatApiExamples.java
  • 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/ChatController.java
  • 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/ChatSocketController.java
  • 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/service/ChatBroadcaster.java
  • 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/service/ChatImageService.java
  • 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/service/ChatLinkPreviewDispatcher.java
  • 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/service/ChatLinkPreviewService.java
  • 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/service/ChatMessageCreatedEvent.java
  • 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/service/ChatMessageService.java
목적과 범위

이 페이지는 사용자가 채팅방 목록에서 방을 선택하고, REST API로 기존 메시지를 조회한 뒤, STOMP 구독을 통해 새 메시지·이미지·읽음 상태를 실시간으로 받는 흐름을 설명합니다. 메시지 전송은 STOMP SEND가 아니라 REST POST /chat/rooms/{roomId}/messages를 기본 경로로 사용하며, STOMP는 방 토픽 구독과 실시간 브로드캐스트 수신에 사용합니다.

이미지 전송에서는 ChatImageService가 발급한 S3 presigned URL로 파일을 업로드하고, 반환된 업로드 식별자를 메시지 요청에 포함하는 서버 측 검증 흐름을 다룹니다. 메시지 신고에서는 사용자 신고 요청의 실제 컨트롤러가 원문에 포함되어 있지 않으므로, 확인 가능한 관리자 처리 흐름과 ChatReportStatus를 중심으로 설명합니다.

다음 페이지와 함께 읽으면 전체 구조를 파악할 수 있습니다.

  • 1.3 시스템 아키텍처
  • 3.1 인증과 세션
  • 3.2 API와 응답 구조
  • 3.4 이미지 업로드
  • 3.5 알림과 푸시
  • 4.1 클라이언트 화면 구조
  • 4.2 관리자 콘솔

이 페이지는 채팅 화면의 실제 말풍선 컴포넌트 구현, 사용자 신고 작성 화면, 데이터베이스 마이그레이션 정의는 다루지 않습니다.

출처: 1D1S-client/src/app/chat/page.tsx:1-6, 1D1S-client/src/app/chat/rooms/[roomId]/page.tsx:1-17, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/ChatController.java:22-34

구성 요소와 역할
프론트엔드 라우트

1D1S-client/src/app/chat/page.tsx의 ChatPage는 /chat 경로에서 ChatRoomListScreen을 호출합니다. 방 목록 화면의 구체적인 API 호출 코드는 원문에 없지만, 서버에는 현재 회원의 방 목록을 반환하는 GET /chat/rooms가 있습니다.

1D1S-client/src/app/chat/rooms/[roomId]/page.tsx의 ChatRoomPage는 URL의 roomId를 숫자로 변환합니다. 값이 정수가 아니거나 0 이하이면 notFound()를 호출하고, 유효하면 ChatRoomScreen roomId={parsed}를 반환합니다. 따라서 채팅방 화면 진입 전에 클라이언트 라우트 단계에서 기본적인 방 번호 형식 검사가 수행됩니다.

REST 처리 계층

서버의 ChatController는 방 목록, 메시지 내역, 메시지 전송, 읽음 처리 같은 HTTP API를 제공합니다. 실제 저장과 권한 검사는 ChatRoomService, ChatMessageService, ChatImageService, ChatModerationService로 분리되어 있습니다.

특히 ChatMessageService.send는 요청 형식, 중복 메시지, 방 쓰기 권한, 전송 빈도, 이미지 업로드 검증을 순서대로 처리한 뒤 메시지를 저장합니다. 저장이 끝나면 ChatBroadcaster.message가 방 토픽으로 같은 메시지를 전파합니다.

STOMP 처리 계층

chatSocket.ts는 모듈 스코프의 STOMP Client를 하나만 유지합니다. 여러 화면이 같은 연결을 공유하고, 화면별로 subscribeChatRoom을 호출해 방 구독만 추가하거나 제거합니다. 서버의 ChatWebSocketConfig는 /ws/chat 엔드포인트, /topic·/queue 브로커, /user 사용자 destination을 설정합니다.

출처: 1D1S-client/src/app/chat/page.tsx:1-6, 1D1S-client/src/app/chat/rooms/[roomId]/page.tsx:1-17, 1D1S-client/src/app.feature/chat/socket/chatSocket.ts:13-35, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/ChatController.java:22-34, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/service/ChatMessageService.java:24-77

채팅 데이터와 메시지 모델
방 목록 데이터

GET /chat/rooms의 예시 응답에는 다음 정보가 포함됩니다.

필드설명
roomId채팅방 식별자입니다.
challengeId연결된 챌린지 식별자입니다.
challengeTitle챌린지 제목입니다.
status방 상태 예시로 ACTIVE가 제시됩니다.
myRole현재 회원의 방 역할입니다.
myMembershipStatus현재 회원의 참여 상태입니다.
pushEnabled방 알림 활성화 여부입니다.
unreadCount방의 읽지 않은 메시지 수입니다.
notice방 공지입니다. 없으면 null입니다.
lastMessage현재 회원이 볼 수 있는 최신 메시지입니다.
challengeEnded챌린지 기간 종료 여부를 나타냅니다.

응답 최상위의 hiddenMemberIds는 내가 차단했거나 나를 차단한 회원의 ID 집합입니다. 서버는 목록과 과거 내역에서 차단 관계를 필터링하지만, 방 전체에 동일한 payload를 보내는 실시간 토픽에서는 클라이언트가 senderId를 이 목록과 비교해 필터링해야 합니다.

메시지 데이터

ChatMessageResponse 예시에는 다음 필드가 있습니다.

필드설명
id메시지 식별자입니다.
roomId메시지가 속한 방입니다.
senderId발신자 식별자입니다.
senderNickname발신자 닉네임입니다.
clientMessageId클라이언트가 생성하는 중복 제거 키입니다.
typeTEXT, IMAGE 등의 메시지 유형입니다.
content텍스트 또는 이미지 캡션입니다.
imageUrl이미지 메시지의 다운로드 URL입니다. 없으면 null입니다.
status예시로 ACTIVE가 제시됩니다.
createdAt생성 시각입니다.

메시지 내역은 Pagination<ChatMessageResponse>로 반환되며, pageInfo.limit, pageInfo.hasNextPage, pageInfo.nextCursor를 사용합니다. ChatMessageService.history는 cursor를 복호화해 이전 메시지를 조회하고, 한 페이지보다 하나 더 읽어 다음 페이지 존재 여부를 판단합니다. 차단된 발신자의 메시지는 메모리 필터가 아니라 저장소 조회 단계에서 제외합니다.

메시지 유형별 요청 조건은 다음과 같습니다.

유형필수 또는 금지 필드
TEXTcontent 필수, imageUploadId와 sharedTargetId 금지
IMAGEimageUploadId 필수, sharedTargetId 금지
공유 유형sharedTargetId 필수, 이미지 첨부 금지
STATS_SHAREsharedTargetId와 imageUploadId 금지
SYSTEM클라이언트가 직접 보낼 수 없음

content의 최대 길이는 2,000자입니다. 모든 전송 요청에는 clientMessageId와 type이 필요합니다.

출처: 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/ChatApiExamples.java:8-35, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/ChatController.java:36-68, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/service/ChatMessageService.java:27-77, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/service/ChatMessageService.java:79-118, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/service/ChatMessageService.java:144-190

일반 메시지와 이미지 전송 흐름
방 진입과 기존 내역 조회
  1. 사용자가 /chat에 진입하면 ChatPage가 ChatRoomListScreen을 렌더링합니다.
  2. 사용자가 방을 선택하면 /chat/rooms/:roomId 경로의 ChatRoomPage가 실행됩니다.
  3. ChatRoomPage가 roomId를 숫자로 검증한 뒤 ChatRoomScreen에 전달합니다.
  4. 채팅 화면은 GET /chat/rooms/{roomId}/messages를 호출해 기존 내역을 가져옵니다. 첫 요청에서는 cursor를 생략하고, 이후에는 이전 응답의 pageInfo.nextCursor를 그대로 전달합니다.
  5. 서버의 ChatMessageService.history가 roomService.requireReadable로 접근 권한을 확인한 뒤 메시지, 공유 카드, 링크 프리뷰, 발신자 레벨을 조합합니다.
텍스트 또는 이미지 메시지 전송
  1. 사용자가 텍스트를 입력하거나 이미지 파일을 선택합니다.
  2. 이미지인 경우 서버의 이미지 presign 처리에 필요한 파일명, MIME 타입, 크기를 전달합니다. 이 요청을 받는 ChatController의 구체적인 매핑은 제공된 원문에 포함되어 있지 않습니다.
  3. ChatImageService.issue가 확장자와 MIME 타입을 비교하고 파일 크기를 검사합니다. 허용 확장자는 jpg, jpeg, png, heic, heif이며 최대 크기는 10MB입니다.
  4. 검사를 통과하면 ChatImageService가 chat/quarantine/... 형식의 S3 object key와 5분 유효한 presigned PUT URL을 만들고 ChatMediaUpload를 ISSUED 상태로 저장합니다.
  5. 클라이언트가 presigned URL로 S3에 파일을 업로드합니다.
  6. 클라이언트가 POST /chat/rooms/{roomId}/messages를 호출합니다. 이미지 메시지라면 요청의 imageUploadId를 포함합니다.
  7. ChatMessageService.send가 ChatImageService.verify를 호출해 S3의 실제 크기와 MIME 타입을 발급 당시 값과 비교합니다.
  8. 검증된 메시지는 저장되고, ChatController.send가 ChatBroadcaster.message를 호출합니다.
  9. 방 토픽 /topic/chat/rooms/{roomId}에 메시지가 브로드캐스트됩니다. 발신자도 토픽을 구독 중이면 HTTP 응답과 브로드캐스트를 모두 받을 수 있으므로 clientMessageId로 중복 표시를 제거해야 합니다.

출처: 1D1S-client/src/app/chat/rooms/[roomId]/page.tsx:7-17, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/ChatController.java:70-101, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/ChatController.java:103-168, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/service/ChatImageService.java:37-121, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/service/ChatImageService.java:124-169, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/service/ChatMessageService.java:44-76

REST API와 STOMP 계약
REST 엔드포인트
메서드와 경로역할서버 처리
GET /chat/rooms내 채팅방 목록 조회ChatRoomService.getMyRooms
GET /chat/rooms/{roomId}/messages과거 메시지 cursor 조회ChatMessageService.history
POST /chat/rooms/{roomId}/messages메시지 저장 및 전송ChatMessageService.send 후 ChatBroadcaster.message
POST /chat/shares/resolveURL 공유 가능 여부 확인ChatShareService.resolveLink
PUT /chat/rooms/{roomId}/read마지막 읽은 메시지 저장ChatMessageService.markRead 후 필요 시 읽음 브로드캐스트
GET /chat/rooms/{roomId}/read-states방 멤버별 읽음 위치 조회ChatRoomService.getReadStates
PUT /chat/rooms/{roomId}/notifications방 알림 설정 변경ChatController의 후반부 매핑으로 보이나 구현 본문은 일부만 제공됨
GET /admin/chat/reports관리자 채팅 신고 목록 조회ChatModerationService.reports
PATCH /admin/chat/reports/{reportId}신고를 ACCEPTED 또는 REJECTED로 처리ChatModerationService.resolve
PATCH /admin/chat/messages/{messageId}숨김 메시지 차단 해제ChatModerationService.updateMessageStatus

GET /chat/rooms/{roomId}/messages의 기본 size는 30이고, 서버는 1~50으로 보정합니다. 방 목록의 archived query parameter는 생략, true, false로 보관 여부를 구분합니다.

STOMP destination
destination방향역할
/ws/chat연결STOMP WebSocket 엔드포인트입니다.
/topic/chat/rooms/:roomId서버에서 클라이언트새 메시지 본문을 전달합니다.
/topic/chat/rooms/:roomId/notice서버에서 클라이언트공지 설정·해제 변화를 전달합니다.
/topic/chat/rooms/:roomId/updates서버에서 클라이언트링크 프리뷰 지연 갱신을 전달합니다.
/topic/chat/rooms/:roomId/read서버에서 클라이언트읽음 위치 갱신을 전달합니다.
/user/queue/chat-errors서버에서 해당 사용자구독 거절과 STOMP 처리 오류를 전달합니다.
/app/chat/rooms/:roomId/messages클라이언트에서 서버소켓 메시지 전송 매핑입니다. 다만 현재 클라이언트 주석은 REST 전송을 사용한다고 설명합니다.

클라이언트의 ChatRoomHandlers는 onMessage, onNotice, onUpdate, onRead, onError, onReconnect 콜백으로 채널별 이벤트를 전달받습니다. 연결이 끊겼다가 다시 붙으면 토픽은 과거 메시지를 재전송하지 않으므로 onReconnect에서 최신 REST 페이지를 다시 받아 누락 구간을 보완합니다.

출처: 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/ChatController.java:58-101, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/ChatController.java:161-169, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/ChatController.java:241-290, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/AdminChatController.java:24-64, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/AdminChatController.java:66-105, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/AdminChatController.java:108-157, 1D1S-client/src/app.feature/chat/socket/chatSocket.ts:26-58

STOMP 연결, 인증과 재연결
연결과 구독
  1. subscribeChatRoom(roomId, handlers)가 방별 리스너를 등록합니다.
  2. ensureClient가 아직 클라이언트가 없으면 STOMP Client를 생성하고 socketUrl()로 API_BASE_URL의 프로토콜을 ws 또는 wss로 바꾼 뒤 경로를 /ws/chat으로 설정합니다.
  3. 연결이 성공하면 /user/queue/chat-errors를 먼저 구독합니다.
  4. 이후 방마다 본문, /notice, /updates, /read 네 채널을 구독합니다.
  5. 마지막 화면 리스너가 제거되면 해당 방의 네 채널만 unsubscribe하며, 전체 WebSocket 연결은 유지합니다.
  6. 로그아웃 등으로 전체 연결을 닫을 때는 closeChatSocket이 리스너·구독 상태를 비우고 Client.deactivate()를 호출합니다.

브라우저 채팅 연결은 HTTP 핸드셰이크에 실린 쿠키로 인증됩니다. ChatStompAuthInterceptor는 핸드셰이크에서 만들어진 principal을 사용하고, 별도 principal이 없으면 STOMP CONNECT의 Authorization 헤더에서 토큰을 추출합니다. CONNECT 성공 시 ChatConnectionRegistry.reserve가 전역 및 회원별 연결 수를 예약합니다.

구독 권한과 오류 전달

SUBSCRIBE 요청에서 destination이 /topic/chat/rooms/으로 시작하지 않으면 CHAT_ROOM_NOT_ACCESS가 됩니다. 방 번호를 추출한 뒤 ChatRoomService.canRead가 현재 회원의 읽기 권한을 확인합니다. 권한이 없는 구독은 세션 전체를 끊지 않고 /user/queue/chat-errors로만 오류를 전송합니다.

클라이언트는 오류의 code, message, retryAfterSeconds, x-failed-destination를 파싱합니다. CHAT-015이면 서버가 알려준 재시도 시간 또는 기본 5초 동안 연결을 보류합니다. 방별 구독 오류는 failedRoomId로 방을 식별하고 해당 방 리스너에만 전달합니다.

서버와 클라이언트의 하트비트 주기는 모두 10초입니다. 클라이언트 재접속 지연은 3초이며, 첫 연결이 성공하지 못한 상황에서는 refreshAccessTokenOnce를 한 번 호출한 뒤 다음 핸드셰이크에 갱신된 쿠키를 사용합니다.

출처: 1D1S-client/src/app.feature/chat/socket/chatSocket.ts:63-77, 1D1S-client/src/app.feature/chat/socket/chatSocket.ts:209-257, 1D1S-client/src/app.feature/chat/socket/chatSocket.ts:259-302, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/config/ChatStompAuthInterceptor.java:79-107, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/config/ChatStompAuthInterceptor.java:116-166, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/config/ChatStompAuthInterceptor.java:209-241

메시지 상태, 읽음과 부가 갱신

채팅방의 종료와 보관은 같은 상태 축이 아닙니다. challengeEnded는 챌린지 기간 종료를 표시하지만 종료 뒤에도 방과 전송이 유지될 수 있습니다. 삭제된 챌린지에 연결된 방은 READ_ONLY가 될 수 있고, 챌린지 종료 후 7일이 지나 보관된 방은 archived=true로 조회할 수 있지만 메시지 전송은 CHAT-017로 거절됩니다. 입력창 잠금 판단에는 canSend와 chatClosesAt이 사용된다고 서버 설명에 명시되어 있습니다.

상태 또는 값의미
ACTIVE방 또는 메시지의 기본 활성 상태 예시입니다.
READ_ONLY삭제된 챌린지로 인해 방이 잠긴 상태입니다.
archived=true보관된 방입니다. 읽기만 가능하고 전송할 수 없습니다.
challengeEnded=true챌린지 기간이 끝났다는 표시입니다. 이것만으로 방이 잠기지는 않습니다.
PENDING신고가 아직 처리되지 않은 상태입니다.
ACCEPTED관리자 신고 처리 결과이며, 신고 메시지를 숨김 처리합니다.
REJECTED신고를 기각한 상태입니다.

읽음 처리는 PUT /chat/rooms/{roomId}/read에 lastReadMessageId를 전달하는 방식입니다. ChatMessageService.markRead는 기존 위치보다 뒤로 이동하지 않도록 처리하고, 실제로 위치가 전진한 경우에만 ChatReadReceipt를 /read 토픽으로 브로드캐스트합니다. 응답에는 notificationCount, chatCount, totalCount, 구버전 호환 필드인 unreadCount가 포함됩니다.

링크가 메시지 본문에 있으면 ChatLinkPreviewDispatcher가 커밋 이후 비동기로 링크를 확인합니다. 메시지 저장 응답의 linkPreview는 처음에 null일 수 있으며, 결과가 준비되면 /updates 토픽으로 메시지 ID를 포함한 갱신을 보냅니다. 링크 프리뷰 실패는 메시지 전송 실패로 전환되지 않습니다.

출처: 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/ChatController.java:36-48, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/ChatController.java:202-255, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/service/ChatMessageService.java:121-142, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/service/ChatLinkPreviewDispatcher.java:12-56

신고와 관리자 조치

확인 가능한 관리자 신고 흐름은 다음과 같습니다.

  1. 관리자가 GET /admin/chat/reports를 호출합니다.
  2. AdminChatController.reports가 page, size, status를 받아 ChatModerationService.reports를 호출합니다.
  3. status를 지정하면 해당 ChatReportStatus만 조회하고, 생략하면 처리된 신고를 포함한 전체 신고를 조회합니다.
  4. 결과는 OffsetPagination<ChatReportResponse>로 반환되며, size는 1~100으로 보정됩니다.
  5. 관리자가 PATCH /admin/chat/reports/{reportId}에 ChatReportResolveRequest를 보내 신고를 처리합니다.
  6. 처리 결과는 ACCEPTED 또는 REJECTED여야 합니다. ACCEPTED이면 신고된 메시지가 숨김 처리됩니다.
  7. 숨김 메시지를 다시 표시하려면 PATCH /admin/chat/messages/{messageId}를 호출하고 ChatMessageStatusUpdateRequest.status를 ACTIVE로 지정합니다.
  8. 차단 해제 시 메시지를 숨기게 만든 ACCEPTED 신고는 REJECTED로 바뀌고 처리자와 처리 시각이 갱신됩니다. 처리되지 않은 PENDING 신고는 그대로 유지됩니다.

관리자 조회 응답은 메시지가 HIDDEN이 된 뒤에도 content와 imageUrl 원문을 그대로 포함합니다. 따라서 신고 처리 후에도 관리자가 판단 근거와 번복에 필요한 내용을 확인할 수 있습니다.

다만 제공된 원문에는 사용자가 채팅 메시지를 신고하는 클라이언트 컴포넌트, 사용자용 신고 요청 DTO, 사용자용 신고 POST 엔드포인트가 없습니다. 따라서 “사용자가 신고 버튼을 누른 뒤 어떤 API를 호출하는가”와 신고 사유 필드의 이름은 이 코드만으로 확정할 수 없습니다.

출처: 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/AdminChatController.java:24-64, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/AdminChatController.java:66-105, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/AdminChatController.java:108-157, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/ChatApiExamples.java:33-35

오류와 운영 제한
오류 코드 또는 조건발생 지점클라이언트가 확인할 내용
CHAT-002방 조회 권한 없음REST 응답 오류로 처리합니다.
CHAT-003메시지 전송 권한 없음방이 쓰기 가능한지 확인합니다.
CHAT-004메시지 없음읽음 처리 대상이 유효한지 확인합니다.
CHAT-005메시지 형식 또는 중복 키 오류type, content, imageUploadId, clientMessageId 조합을 확인합니다.
CHAT-013메시지 전송 빈도 초과즉시 반복 전송하지 않습니다.
CHAT-015동시 WebSocket 연결 제한retryAfterSeconds만큼 재연결을 늦춥니다.
CHAT-017보관된 방에 전송내역 조회만 허용되는 상태로 처리합니다.
CHAT-012신고 처리 결과가 잘못됨ACCEPTED 또는 REJECTED만 사용합니다.
CHAT-016메시지 상태 변경 불가숨김은 신고 처리 경로로만 수행합니다.

ChatConnectionRegistry는 전체 연결을 600개, 회원별 연결을 8개로 제한합니다. 오래된 세션 기록은 30분 기준으로 정리하며, 정상적인 끊김은 SessionDisconnectEvent에서 회원별 수를 감소시킵니다. 서버와 클라이언트 하트비트는 10초입니다.

WebSocket transport의 메시지 크기 제한은 16KB, 송신 버퍼 제한은 256KB, 송신 시간 제한은 10초입니다. 단, 현재 클라이언트의 공식 메시지 전송 경로는 REST이므로 이미지 파일 자체를 STOMP 프레임에 넣지 않고 S3 업로드 후 메시지 요청에 업로드 식별자를 전달합니다.

출처: 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/config/ChatConnectionRegistry.java:31-71, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/config/ChatConnectionRegistry.java:74-110, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/config/ChatWebSocketConfig.java:27-28, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/config/ChatWebSocketConfig.java:104-109, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/ChatController.java:119-159

확인 필요
  • 사용자 메시지 신고를 생성하는 실제 REST 엔드포인트는 무엇입니까? 제공된 원문에는 AdminChatController의 관리자 조회·처리 API만 있고, 사용자용 신고 생성 API가 없습니다.
  • 사용자 신고 요청의 DTO와 필드 이름, 신고 사유 enum은 무엇입니까?
  • ChatImageService.issue를 호출하는 이미지 presign 컨트롤러의 HTTP 경로와 요청·응답 형식은 무엇입니까?
  • ChatRoomScreen, ChatRoomListScreen이 어떤 훅을 통해 GET /chat/rooms, GET /chat/rooms/:roomId/messages, PUT /chat/rooms/:roomId/read를 호출하는지 확인이 필요합니다.
  • ChatMediaUploadStatus의 전체 상태 전이와 업로드 완료 후 ISSUED 상태를 변경하는 코드는 제공된 원문에 없습니다. 업로드 성공 시 상태를 별도로 갱신하는지 확인이 필요합니다.
  • 사용자 신고가 접수될 때 메시지 발신자·신고자·신고 사유·중복 신고를 어떻게 저장하고 검증하는지 확인이 필요합니다.

출처: 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/controller/AdminChatController.java:24-157, 1D1S-server-v2/src/main/java/com/odos/odos_server_v2/domain/chat/service/ChatImageService.java:67-122, 1D1S-client/src/app/chat/page.tsx:1-6, 1D1S-client/src/app/chat/rooms/[roomId]/page.tsx:1-17

속성
분류스펙
폴더AI 역문서 / 2. 핵심 기능
#AI 역문서
연결된 화면·API16
POST/chat/rooms/{roomId}/messages
DELETE/chat/rooms/{roomId}/notice
POST/chat/shares/resolve
GET/chat/rooms/{roomId}/read-states
GET/chat/rooms/{roomId}/messages
GET/chat/rooms
POST/chat/messages/{messageId}/reports
PUT/chat/rooms/{roomId}/notice
PUT/chat/rooms/{roomId}/notifications
GET/admin/chat/reports
POST/chat/rooms/{roomId}/images/presign
화면chat/chat
PUT/chat/rooms/{roomId}/read
PATCH/admin/chat/messages/{messageId}
화면roomId/chat/rooms/[roomId]
PATCH/admin/chat/reports/{reportId}
이 문서를 언급한 문서3
0 목차스펙1.3 시스템 아키텍처스펙1.1 서비스와 레포 개요스펙
#AI 역문서
연결된 일정1
10/23검토채팅 신고 처리 정책 리뷰