Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
e6f627f
test: 비즈니스 로직 단위 테스트 6개 추가 (Permission, me model, 폼 검증, PKCE)
LivingLikeKrillin Feb 22, 2026
a5a249a
test: 2단계 단위 테스트 6개 추가 (alert-message, dj, avatar-body, event-emitter…
LivingLikeKrillin Feb 22, 2026
dc4ab39
test: 3단계 단위 테스트 6개 추가 (Chat, i18n processors, delay, Singleton)
LivingLikeKrillin Feb 22, 2026
ba3f375
test: 4단계 단위 테스트 6개 추가 (preview-helpers, cn, repeatAnimationFrame, Mo…
LivingLikeKrillin Feb 22, 2026
08906b0
test: categorizeByGradeType 크루 등급 분류 테스트 추가
LivingLikeKrillin Feb 22, 2026
6975637
test: 모킹 테스트 6개 추가 (network-log, with-log, capture-dom, nft.model, pr…
LivingLikeKrillin Feb 22, 2026
693345b
test: 테스트 17개 추가 — API 에러, Zustand 스토어, 훅, 컴포넌트 (Phase A-E)
LivingLikeKrillin Feb 22, 2026
999a265
refactor: UI 컴포넌트 barrel export를 index.ui.ts로 분리 및 테스트 설정 개선
LivingLikeKrillin Feb 25, 2026
e7438f0
test: 고 ROI 모듈 테스트 8개 파일 76개 추가 (클래스, 어댑터, 소켓, 이벤트 핸들러)
LivingLikeKrillin Mar 1, 2026
25de6fb
test: subscription 콜백 11개 + 공유 훅 2개 + 인터셉터 1개 테스트 추가 (14파일 39케이스)
LivingLikeKrillin Mar 2, 2026
0fc8fed
test: 순수 유틸리티·도메인 모델 테스트 16개 추가 (5파일, 594→610)
LivingLikeKrillin Mar 2, 2026
0f18552
test: MSW 도입 + 통합 테스트 14개 추가 (3파일, 610→624)
LivingLikeKrillin Mar 2, 2026
4cf59ea
test: shared/ui 컴포넌트 테스트 18파일 ~110케이스 추가
LivingLikeKrillin Mar 2, 2026
1c7dc7b
test: shared 훅 테스트 6파일 16케이스 추가
LivingLikeKrillin Mar 2, 2026
14a1f1b
test: MSW 통합 테스트 확장 — 서비스·뮤테이션·쿼리 훅 10파일 ~44케이스 추가
LivingLikeKrillin Mar 2, 2026
92f81d6
test: entities/features 훅 테스트 14파일 48케이스 추가
LivingLikeKrillin Mar 2, 2026
e8c5800
test: widgets 컴포넌트 테스트 5파일 21케이스 추가
LivingLikeKrillin Mar 2, 2026
512e62f
docs: 테스트 가이드 신규 작성 및 기존 문서 갱신
LivingLikeKrillin Mar 2, 2026
1ec04ba
test: Phase 4-6 통합·훅·위젯 테스트 추가 및 ESLint 수정 (202 suites / 1003 tests)
LivingLikeKrillin Mar 2, 2026
41d5190
fix: chat-item 테스트에 누락된 receivedAt 프로퍼티 추가
LivingLikeKrillin Mar 2, 2026
33c7b47
docs: ADR 11건 및 기술 부채 문서 작성
LivingLikeKrillin Mar 3, 2026
9fc11d8
feat: 공유 링크 OG 메타태그 및 동적 OG 이미지 생성
LivingLikeKrillin Mar 8, 2026
b43bfe4
refactor: enterByLink API를 getPartyroomByLink로 분리하여 조회와 인증 관심사 분리
LivingLikeKrillin Mar 8, 2026
7200f5f
fix: OAuth 콜백 페이지에서 Strict Mode로 인한 중복 호출 방지
LivingLikeKrillin Mar 8, 2026
7d814b9
chore: Swagger 스펙 기준 프론트엔드 API 타입 정렬
LivingLikeKrillin Mar 8, 2026
217d86a
refactor: 에러 코드 enum을 백엔드 API 스펙에 맞게 정렬
LivingLikeKrillin Mar 9, 2026
75dc7ed
refactor: REST API URL 및 응답 타입을 백엔드 스펙에 맞게 정렬
LivingLikeKrillin Mar 9, 2026
83cb683
refactor: OAuth 인증 응답 타입을 단일 구조로 단순화
LivingLikeKrillin Mar 9, 2026
8bb4d45
refactor: WebSocket 이벤트 타입을 AsyncAPI 스펙에 맞게 전면 재구성
LivingLikeKrillin Mar 9, 2026
6bc3f64
refactor: DJ 큐 갱신 책임을 DJ_QUEUE_CHANGED 핸들러로 단일화
LivingLikeKrillin Mar 9, 2026
6cc2c01
refactor: 서버에서 불필요한 Me 데이터 prefetch 제거
LivingLikeKrillin Mar 9, 2026
9e37485
refactor: PartyroomConnectionProvider를 parties 레이아웃으로 이동
LivingLikeKrillin Mar 9, 2026
a57e1ee
fix: BoldProcessor의 class 속성을 className으로 수정
LivingLikeKrillin Mar 9, 2026
aa7281b
fix: YouTubePreviewPlayer에서 불필요한 ref prop 제거
LivingLikeKrillin Mar 9, 2026
32912d5
fix: PartyroomClient가 SSR에서 초기화되지 않도록 수정
LivingLikeKrillin Mar 9, 2026
7a30204
refactor: WalletProvider를 parties, settings 레이아웃으로 이동
LivingLikeKrillin Mar 9, 2026
489390f
refactor: WalletProvider를 RootLayout으로 복원하고 ssr: true 활성화
LivingLikeKrillin Mar 9, 2026
606b891
fix: 프로필 미설정 유저 parties 접근 차단 및 아바타 설정 무한루프 수정
LivingLikeKrillin Mar 9, 2026
5f9455d
fix: DialogProvider children 타입을 ReactNode로 변경
LivingLikeKrillin Mar 9, 2026
69f993e
chore: Jest에서 Vitest로 테스트 환경 전면 마이그레이션
LivingLikeKrillin Mar 9, 2026
9f39f80
fix: tsconfig에 vitest/globals 타입 추가 및 테스트 파일 제외 복원
LivingLikeKrillin Mar 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions .env.development
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
NEXT_PUBLIC_API_HOST_NAME="https://pfplay-api.app/api/"
NEXT_PUBLIC_API_WS_HOST_NAME="wss://pfplay-api.app/ws"
NEXT_PUBLIC_API_HOST_NAME="http://localhost:8080/api/"
NEXT_PUBLIC_API_WS_HOST_NAME="ws://localhost:8080/ws"
NEXT_PUBLIC_USE_MOCK="false"
7 changes: 5 additions & 2 deletions .swcrc
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"tsx": true,
"decorators": true,
"dynamicImport": true
},
"transform": {
"legacyDecorator": true,
"decoratorMetadata": true
"decoratorMetadata": true,
"react": {
"runtime": "automatic"
}
}
},
"module": {
Expand Down
21 changes: 21 additions & 0 deletions docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,27 @@ FSD(Frontend Structure Design) 아키텍쳐를 기반으로 작업합니다.
- ext - `png|jpg|jpeg|gif|...`
- `/public/images/` 디렉터리에 넣습니다.

## Testing

> Last Update (26.03.02)

```bash
# 전체 테스트
yarn test

# 커버리지 없이 빠르게 실행
npx jest --no-coverage

# 특정 경로만 실행
npx jest src/shared/ui --no-coverage
```

- 테스트 파일은 소스 파일과 **동일 디렉토리에 co-locate** 합니다.
- 네이밍: `{name}.test.ts`, `{name}.component.test.tsx`, `{name}.hook.test.ts`, `{name}.integration.test.ts`
- MSW 통합 테스트 작성 시 `import '@/shared/api/__test__/msw-server'`를 반드시 추가해야 합니다.

상세 가이드는 [TESTING.md](./TESTING.md)를 참고하세요.

## react-query

> Last Update (25.05.11)
Expand Down
11 changes: 9 additions & 2 deletions docs/DOCS_ENTRY.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
# 250519 기준 프로젝트 문서 목록
# 프로젝트 문서 목록

> Last Update (26.03.02)

## root

### docs

- [docs/REACT_QUERY.md](./REACT_QUERY.md) - 서버 상태 관리를 위한 React Query 라이브러리 사용 가이드. API 데이터 호출, 캐싱, 동기화 등을 효율적으로 처리하고 싶을 때 참고하세요.
- [docs/README.md](./README.md) - 프로젝트의 전반적인 개요, 설정 방법, 실행 방법 등을 안내합니다. 프로젝트를 처음 시작하거나 전체 구조를 파악하고 싶을 때 읽어보세요.
- [docs/CONTRIBUTING.md](./CONTRIBUTING.md) - 프로젝트에 기여하는 방법을 안내합니다. 코드 스타일, 브랜치 전략, PR 규칙 등을 확인할 수 있습니다.
- [docs/FLOW.md](./FLOW.md) - 프로젝트의 주요 기능 흐름 또는 개발 워크플로우를 설명합니다. 특정 기능의 동작 방식이나 전체적인 서비스 흐름을 이해하고 싶을 때 유용합니다.
- [docs/REACT_QUERY.md](./REACT_QUERY.md) - 서버 상태 관리를 위한 React Query 라이브러리 사용 가이드. API 데이터 호출, 캐싱, 동기화 등을 효율적으로 처리하고 싶을 때 참고하세요.
- [docs/TESTING.md](./TESTING.md) - 테스트 작성 가이드. 테스트 기법(유닛/통합), MSW 인프라, 파일 네이밍 컨벤션, 패턴별 코드 예시 등을 확인할 수 있습니다.

### 테스트

- [TEST_ROADMAP.md](../TEST_ROADMAP.md) - 테스트 커버리지 확장 로드맵. FSD 레이어별 현황, 6단계 Phase 진행 상태, 잔여 작업 목록을 관리합니다.

## src

Expand Down
33 changes: 23 additions & 10 deletions docs/REACT_QUERY.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# react-query 컨벤션

> Last Update (26.03.02)

### 개요

react-query-wrapper - react-query의 추상화 레이어
react-query-wrapper - react-query의 추상화 레이어 (TanStack Query v5)

### 1. react query wrapper는 react query와 백엔드 서비스의 연동 레이어라는 단일 책임만 가지게 하며, 실제 api를 활용한 로직은 application service 로직을 구현할 hook 혹은 컴포넌트에서 처리한다.

Expand All @@ -29,13 +31,16 @@ function SomeFeature() {

### 2. react-query-wrapper 파일 네이밍 규칙은 아래와 같이 한다.

- query - `use[Entity]Query.ts`
- `ex) usePostsQuery.ts`
- `ex) usePostsInfiniteQuery.ts`
- `ex) usePostsSuspenseQuery.ts`
- mutation - `use[Entity][Action]Mutation.ts`
- `ex) usePostCreateMutation.ts`
- `ex) usePostUpdateMutation.ts`
kebab-case 파일명에 `.query.ts` / `.mutation.ts` 접미사를 사용한다.

- query - `use-{동작}-{엔티티}.query.ts`
- `ex) use-fetch-playlists.query.ts`
- `ex) use-fetch-playlist-tracks.query.ts`
- `ex) use-search-musics.query.ts`
- mutation - `use-{동작}-{엔티티}.mutation.ts`
- `ex) use-create-playlist.mutation.ts`
- `ex) use-enter-partyroom.mutation.ts`
- `ex) use-block-crew.mutation.tsx`

### 3. query 의 옵션을 잘 활용한다.

Expand All @@ -47,9 +52,17 @@ staleTime과 gcTime을 몇으로 설정할지에 대한 명확한 기준은 없
- ⭐ _[공식문서의 설명](https://tanstack.com/query/latest/docs/react/guides/advanced-ssr)에 따라, 서버 측 렌더링 시에는 staleTime을 0이 아닌 값으로 설정해야 한다._
- etc..

#### 3-2. staleTime의 기본값이 5분이므로, refetchOnWindowFocus 옵션을 default true 로 놓되, 필요할 땐 적절히 활용한다.
#### 3-2. 프로젝트 기본 설정을 참고하여 옵션을 조정한다.

프로젝트의 `QueryClient` 기본값 (`src/app/_providers/react-query.provider.tsx`):

| 옵션 | 기본값 | 비고 |
| ---------------------- | ----------------------------- | ----------------------------------------- |
| `staleTime` | 5분 (`FIVE_MINUTES`) | `src/shared/config/time.ts` 상수 사용 |
| `refetchOnWindowFocus` | `false` | 필요 시 개별 쿼리에서 `true`로 오버라이드 |
| `retry` | dev: `false` / prod: 최대 3회 | 인증 에러(`isAuthError`)는 즉시 중단 |

외부의 요인, 사용자의 액션 등으로 계속해서 변경되어 캐시가 무의미한 데이터인 경우, refetchOnWindowFocus 옵션을 true 로 설정하여 적절한 시점에 데이터를 갱신할 수 있도록 한다.
외부의 요인, 사용자의 액션 등으로 계속해서 변경되어 캐시가 무의미한 데이터인 경우, 개별 쿼리에서 `refetchOnWindowFocus: true`를 설정하여 적절한 시점에 데이터를 갱신할 수 있도록 한다.

### 4. 제네릭을 활용한다.

Expand Down
4 changes: 4 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ yarn dev

And then, open `https://localhost:3000` in your browser.

## Testing

Please refer to [Testing Guide](./TESTING.md).

## Contributing

Please refer to [Contributing](./CONTRIBUTING.md).
113 changes: 113 additions & 0 deletions docs/TECH_DEBT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Technical Debt Registry

> 코드 품질·유지보수성 관점에서 개선이 필요한 항목을 추적한다.
> 각 항목은 방향이 명확하여 ADR 없이 바로 실행 가능한 것들이다.

---

## 우선순위 범례

| 등급 | 의미 |
| ------------- | ----------------------------------- |
| P0 — Critical | 프로덕션 안정성·보안에 직접 영향 |
| P1 — High | 개발 생산성·코드 품질에 상당한 영향 |
| P2 — Medium | 개선하면 좋지만 당장 문제는 아님 |

---

## P0 — Critical

### TD-001: WebSocket 재연결에 지수 백오프 없음

- **파일**: `src/shared/api/websocket/client.ts:55`
- **현상**: `reconnectDelay: 5000` 고정값 사용. 서버 장애 시 모든 클라이언트가 동시에 5초 간격으로 재연결을 시도하여 thundering herd 문제 발생 가능
- **개선 방향**: 지수 백오프 + jitter + 최대 재시도 횟수 적용
- **참고**: ADR-002

### TD-002: WebSocket 타입 백엔드 미검증

- **파일**: `src/shared/api/websocket/types/partyroom.ts`
- `:81` — `// TODO: 임의로 작성. 실제 타입 확인 필요` (PlaybackSkipEvent)
- `:143` — `// FIXME: 맘대로 작성함. api 측과 enum 일치할지 확인 필요` (PARTYROOM_CLOSE)
- **현상**: 프론트엔드가 임의로 정의한 타입이 백엔드와 불일치할 수 있음
- **개선 방향**: 백엔드 API 스펙과 대조 후 타입 확정

### TD-003: 에러 객체 직접 변이 (mutation)

- **파일**: `src/shared/api/http/client/interceptors/response.ts:53`
- **현상**: `e.response.data = e.response.data.data` — AxiosError 객체를 직접 변이
- **개선 방향**: WeakMap 등으로 원본 에러 객체를 보존하면서 unwrap된 데이터를 별도로 관리
- **참고**: ADR-005

---

## P1 — High

### TD-004: STOMP 하트비트 커스텀 구현 → 내장 기능 전환

- **파일**: `src/shared/api/websocket/client.ts:158-183`
- **현상**: GCP 60초 타임아웃 우회를 위해 4초 간격 커스텀 heartbeat(`/pub/heartbeat`)를 `setInterval`로 구현. STOMP 프로토콜 내장 heartbeat를 사용하지 않음
- **개선 방향**: STOMP built-in heartbeat로 마이그레이션 (Slack 논의 참조)
- **참고**: 코드 내 주석에 마이그레이션 계획 기재됨

### TD-005: TODO/FIXME 41개 미해결

- **현상**: `src/` 전체에 41개의 TODO/FIXME가 32개 파일에 분포
- **주요 파일**:
- `src/shared/api/websocket/types/partyroom.ts` — 타입 검증 2건
- `src/shared/api/http/types/@enums.ts` — enum 스크립트 2건
- `src/entities/partyroom-client/lib/subscription-callbacks/` — 구현 누락 1건
- `src/entities/current-partyroom/model/` — 상태 관리 1건
- **개선 방향**: 각 TODO를 GitHub Issue로 전환하여 추적하거나, 해결 후 제거

### TD-006: `@enums.ts` 자동 생성 스크립트 미작동

- **파일**: `src/shared/api/http/types/@enums.ts`
- `:45` — `// FIXME: enum auto generation 스크립트 수정 필요`
- `:55` — `// TODO: 현재 스크립트가 숫자 잡아내지 못해서 수동 수정. 스크립트 수정 필요`
- **현상**: enum 자동 생성 스크립트가 숫자형 enum을 처리하지 못하여 수동 관리 중
- **개선 방향**: 스크립트 수정 또는 OpenAPI codegen 도입

### TD-007: `usePlaybackSkipCallback` 빈 구현

- **파일**: `src/entities/partyroom-client/lib/subscription-callbacks/use-playback-skip-callback.hook.ts:3-6`
- **현상**: 콜백 함수가 `// TODO: implementation`만 있고 빈 상태
- **개선 방향**: 재생 스킵 이벤트 수신 시 UI 상태 반영 로직 구현

---

## P2 — Medium

### TD-008: Wallet Provider가 FCP를 차단

- **파일**: `src/app/_providers/wallet.provider.tsx:10-17`
- **현상**: SSR 하이드레이션 불일치 방지를 위해 `mounted` 상태가 `true`가 될 때까지 children을 렌더링하지 않음. 지갑 기능이 필요 없는 페이지까지 FCP가 지연됨
- **개선 방향**: 지갑 기능이 필요한 페이지에서만 Provider를 렌더링하거나, `dynamic(() => import(...), { ssr: false })` 적용
- **참고**: ADR-008

### TD-009: `useStores` 2단계 셀렉터 보일러플레이트

- **파일**: `src/entities/current-partyroom/lib/use-chat.hook.ts:11-12` 외 다수
- **현상**: 매번 `const { useX } = useStores(); const value = useX(state => state.field);` 두 단계 필요
- **개선 방향**: 커스텀 훅으로 1단계 접근 패턴 제공 (예: `useCurrentPartyroomField('chat')`)
- **참고**: ADR-001

### TD-010: `index.ui.ts` ESLint 경계 미강제

- **파일**: `src/shared/ui/index.ui.ts`, 각 feature/entity의 `index.ui.ts`
- **현상**: `index.ui.ts`에서만 `'use client'` 컴포넌트를 export하는 컨벤션이 있지만, ESLint 룰로 강제되지 않아 실수로 `index.ts`에서 CSR 컴포넌트를 export할 수 있음
- **개선 방향**: 커스텀 ESLint 룰 또는 `eslint-plugin-boundaries` 설정으로 강제
- **참고**: ADR-003, ADR-011

### TD-011: 이벤트 핸들러 매핑 타입 미강제

- **파일**: `src/entities/partyroom-client/lib/partyroom-client.ts`
- **현상**: WebSocket 구독 대상과 콜백 훅의 매핑이 수동으로 관리됨. 새 이벤트 추가 시 매핑 누락 가능
- **개선 방향**: 타입 레벨에서 모든 구독 대상에 대응하는 핸들러가 존재하는지 강제
- **참고**: ADR-002

### TD-012: API 버전 관리 부재

- **파일**: `src/shared/api/http/client/client.ts:12-17`
- **현상**: API 호출에 버전 정보 없음. `baseURL`이 호스트명만 포함하며 `/v1/` 등의 prefix가 없음
- **개선 방향**: 백엔드와 협의하여 URL prefix 또는 헤더 기반 버전 관리 도입
Loading
Loading