Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
2430ad8
[캠퍼스] SharedWorker + IndexedDB 적용 (#1142)
ff1451 Jan 21, 2026
5a5d5a2
[유저] 수강신청 연습페이지 UI 컴포넌트 구현 (#1136)
ff1451 Jan 21, 2026
c65318a
[유저] 모의 수강신청 로직 및 페이지 구현 (#1138)
ff1451 Jan 21, 2026
003a4c8
fix: lint error fix
ff1451 Jan 21, 2026
4763997
Merge branch 'feat/course-regist' into develop
ff1451 Jan 21, 2026
daa097b
[에러] 아이디 찾기 결과 UI 깨짐 현상 해결 (#1144)
dooohun Jan 23, 2026
7ade58a
[hotfix] 아이디 찾기 결과 UI 깨짐 현상 (#1145)
dooohun Jan 23, 2026
77b9804
[캠퍼스] 신규 공지사항 표시 hydration mismatch 수정 (#1105)
ff1451 Jan 26, 2026
c91a432
[캠퍼스] 분실물 스프린트 (#1154)
ff1451 Jan 26, 2026
adc5550
fix: 빌드 에러 임시 수정
ff1451 Jan 26, 2026
890d7fb
[공통] 리뷰어 목록 수정 (#1156)
JeongWon-CHO Jan 28, 2026
ec34334
[캠퍼스] 분실물 QA 수정 (#1159)
ff1451 Jan 30, 2026
0540e19
[유저] 모의수강신청 로깅 및 진입점 수정 (#1161)
ff1451 Jan 31, 2026
94fed1a
feat: 진입점 버튼 및 비로그인, 시간표 미존재 UI 추가
ff1451 Feb 1, 2026
5290f7b
hotfix: tanstack query cache 문제 수정 및 session storage로 새로고침 시 데이터 초기화 방지
ff1451 Feb 1, 2026
05b3c92
Merge remote-tracking branch 'origin/main' into develop
ff1451 Feb 1, 2026
1e58adb
[캠퍼스] 분실물 QA 수정 (#1166)
JeongWon-CHO Feb 2, 2026
7e078c2
[캠퍼스] 누락 로깅 추가 (#1168)
ff1451 Feb 2, 2026
669a9fd
[공통] 토큰 쿠키 도메인 수정 (#1172)
Gwak-Seungju Feb 6, 2026
2c55076
[공통] 로깅 코드 생성 파이프라인 추가 (#1170)
ff1451 Feb 9, 2026
0d2c9ae
[공통] 클로드 자동 코드 리뷰 추가 (#1175)
dooohun Feb 12, 2026
5e287fd
[공통] Barrel import 제거 (#1181)
ff1451 Feb 19, 2026
18fc707
[캠퍼스] 채팅 polling 마이그레이션 (#1178)
dooohun Feb 20, 2026
8f94369
[공통] codeRabbit PR 리뷰 설정 추가 (#1182)
dooohun Feb 24, 2026
2586de0
[캠퍼스] 콜밴팟 메인 페이지 추가 (#1184)
dooohun Mar 4, 2026
ff5810a
[공통] 쿠키 도메인 확장으로 인한 SSR 500 에러 수정 (#1186)
ff1451 Mar 5, 2026
1b06f86
[캠퍼스] 콜밴 알림 UI 추가 (#1187)
dooohun Mar 7, 2026
7b26db4
[캠퍼스] 콜밴 게시글 추가 UI 및 API 추가 (#1188)
dooohun Mar 8, 2026
25df6ac
[캠퍼스] 콜밴팟 게시글 작성화면 기능 추가 (#1189)
dooohun Mar 8, 2026
528a82c
[캠퍼스] 콜밴 게시글 목록 작성자 액션 UI 구현 (#1190)
dooohun Mar 8, 2026
8e75568
[캠퍼스] 콜밴팟 참여자 목록 페이지 구현 (#1191)
dooohun Mar 9, 2026
e2ab474
[캠퍼스] 콜밴팟 사용자 신고 기능 구현 (#1194)
dooohun Mar 9, 2026
f53284c
[캠퍼스] 콜밴 그룹 채팅 기능 구현 (#1195)
dooohun Mar 9, 2026
3680433
[캠퍼스] 콜밴팟 메인 홈 메뉴 등재 및 비로그인 접근 제어 기능 추가 (#1196)
dooohun Mar 10, 2026
e280aee
[공통] Sentry 연결 (#1199)
ff1451 Mar 12, 2026
5dac084
fix: sentry 의존성 연결
ff1451 Mar 12, 2026
4900dbf
fix: sentry 의존성 연결
ff1451 Mar 12, 2026
fcda6e8
fix: 업로드 파일 범위 수정
ff1451 Mar 12, 2026
ae0b030
[공통] jenkins -> github actions 마이그레이션 (#1208)
ff1451 Mar 12, 2026
6c8c380
chore: 슬랙 알림 기능 추가
ff1451 Mar 12, 2026
0cf8488
fix: 커밋 특수문자 처리
ff1451 Mar 12, 2026
16b1391
chore: 수동 배포 추가
ff1451 Mar 12, 2026
e882a1f
chore: 환경변수 오기입 수정
ff1451 Mar 13, 2026
47d8f4a
[캠퍼스] 콜밴팟 API 이미지 업로드 추가 (#1209)
dooohun Mar 17, 2026
fd763d1
[캠퍼스] 콜밴팟 로깅 추가 및 버그 수정 (#1211)
dooohun Mar 17, 2026
e5314bb
[공통] querykey options factory 적용 (#1210)
ff1451 Mar 20, 2026
04d4edb
[캠퍼스] 콜밴 QA 이슈 해결 (#1212)
dooohun Mar 24, 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
  •  
  •  
  •  
213 changes: 213 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

KOIN is a campus service web application for Korea University of Technology and Education (KOREATECH). It provides timetable management, bus schedules, cafeteria menus, store/shop listings, community articles, clubs, lost & found, and graduation calculators.

Built with **Next.js 15 (Pages Router)**, **React 19**, and **TypeScript** (strict mode).

- Package manager: **Yarn 4 (Berry)** with PnP. Never use `npm install`.
- Node version: **20.11.1**

## Commands

```bash
yarn start # Dev server (next dev)
yarn build # Type-check (tsc) then production build
yarn lint # ESLint + Stylelint
yarn lint:eslint # ESLint only (src/)
yarn lint:stylelint # Stylelint only (src/**/*.scss)
yarn log # Generate analytics logging hooks from Notion spec
```

## Architecture

### Routing (Pages Router)

File-based routing in `src/pages/`. Type-safe route builder in `src/static/routes.ts`:

```typescript
ROUTES.StoreDetail({ id: '123' }); // → '/store/123'
```

Pages can declare static properties:

```typescript
Page.getLayout = (page: React.ReactNode) => <SSRLayout>{page}</SSRLayout>;
Page.requireAuth = true;
Page.title = 'Page Title';
```

### API Layer

`src/api/` uses a class-based pattern with `APIClient` wrapper (`src/utils/ts/apiClient.ts`):

1. Define request class in `APIDetail.ts` implementing `APIRequest<ResponseType>`
2. Define request/response types in `entity.ts`
3. Export callable function via `APIClient.of(DetailClass)` in `index.ts`

```typescript
export class Login implements APIRequest<LoginResponse> {
path = '/user/login';
method = HTTP_METHOD.POST;
data: LoginRequest;
}
// index.ts
export const login = APIClient.of(Login);
```

The APIClient handles token refresh (401), maintenance mode (503), and user type verification (403) automatically.

### State Management

- **Server state**: TanStack React Query (`staleTime: 60000`, `retry: false`). SSR via `getServerSideProps` + `HydrationBoundary`.
- **Client state**: Zustand stores in `src/utils/zustand/`. Many stores separate `State` and `Actions` types — follow the existing pattern of each file.

Zustand stores export selectors:

```typescript
export const useStateSelector = () => useStore((state) => state.prop);
export const useActions = () => useStore((state) => state.action);
```

### Styling

SCSS with CSS Modules (`[Component].module.scss`) using BEM methodology. Desktop-first approach with mobile overrides via responsive mixins in `src/utils/scss/`:

```scss
@include media.media-breakpoint(mobile) {
/* breakpoint: 576px */
}
```

### Component Organization

Feature-based: `src/components/[Feature]/` with co-located hooks in `hooks/` subdirectory and styles. Split responsive views into `MobileView/` and `PCView/` directories when layouts differ. Shared UI in `src/components/ui/`, layouts in `src/components/layout/`, modals in `src/components/modal/`.

### Layout

Two layout components in `src/components/layout/`:

- **`SSRLayout`**: No Suspense wrapping. Used for SSR pages via `getLayout`.
- **`Layout`** (default): Wraps Header/children in Suspense boundaries. Hides Footer in native WebView.

Misusing these causes hydration errors.

### Custom Hooks

Located in `src/utils/hooks/`, organized by category:

- `auth/` — useAuth, useAutoLogin, useLoginRedirect, useLogout
- `ui/` — useBodyScrollLock, useOutsideClick, useEscapeKeyDown
- `state/` — useBooleanState, useLocalStorage, useWebStorage, useMount
- `layout/` — useMediaQuery, useModalPortal
- `analytics/` — useLogger, useScrollLogging

### Internal Packages

- **`@bcsdlab/koin`**: `isKoinError()` type guard, `sendClientError()` (sends errors to internal Slack).
- **`@bcsdlab/utils`**: `cn()` (className merger), `sha256()` (Web Crypto hashing).

These are internal BCSD Lab packages — do not suggest replacing them with external alternatives.

### Cookie Management

Cookie keys are environment-aware via `IS_STAGE` flag in `src/static/url.ts`. Stage and production use different cookie key names (e.g., `STAGE_AUTH_TOKEN_KEY` vs `AUTH_TOKEN_KEY`) and different domains (`.stage.koreatech.in` vs `.koreatech.in`). Always use `COOKIE_KEY` constants and `getCookieDomain()` — never hard-code cookie names or domains.

### iOS Native Bridge

WebKit message handlers for token sync between web and native app via `window.webkit.messageHandlers`. Bridge functions in `src/utils/ts/iosBridge.ts`.

### Analytics

Generated logging hooks in `src/generated/analytics/` from Notion spec via `yarn log`. Google Analytics + GTM + Sentry error tracking.

## Code Conventions

### Imports

Absolute imports via `*` → `src/*` path mapping. Use `import X from 'components/...'` not `'../../../components/...'`. Relative parent imports (`../*`) are forbidden by ESLint.

Import order (enforced): React/Next → builtins → external packages → internal (`@/**`) → parent/sibling → types → styles (`.scss`).

### Naming

- Components/directories: PascalCase (`ArticleList.tsx`)
- Utilities: camelCase (`apiClient.ts`)
- Hooks: `use[Name].ts`
- Styles: `[Component].module.scss`
- API types: `entity.ts`, API classes: `APIDetail.ts`

### Formatting

Prettier: 120 char width, single quotes, trailing commas, 2-space indent. Stylelint enforces `stylelint-config-standard-scss`.

## PR Review Rules (for claude-code-action)

Write all review comments in Korean.

Focus on correctness, regression risk, security, and performance before style.

Use this output format for every finding:

- Severity: `[P0]` (blocks merge), `[P1]` (should fix), `[P2]` (suggestion)
- Location: `file:line`
- Why it matters
- Minimal fix suggestion

### Error Handling

- Always use `isKoinError()` type guard before accessing error properties on API errors.
- In ErrorBoundary, use `isAxiosError()` type guard to branch handling.

```typescript
onError: (error) => {
if (isKoinError(error)) {
showToast('error', error.message || 'fallback message');
} else {
showToast('error', 'fallback message');
}
};
```

### React Query

- Query keys as arrays: `['resource', 'action', params]`.
- Prefer `useSuspenseQuery` when a Suspense boundary wraps the component for blocking UI. Use `useQuery` for conditional fetching (`enabled`), background refresh, or non-blocking patterns.
- Invalidate cache via `queryClient.invalidateQueries()` after mutations.
- Every mutation `onError` must follow the error handling pattern above.

### Analytics Logging

- All user interactions (click, swipe, page load) must include logging.
- Use the `useLogger()` hook with `team`, `event_label`, `value` structure.
- Define logging constants (`loggingTitle`, `loggingValue`) at the top of the component.

### General

- No `console.log` (ESLint warn). Only `console.warn` and `console.error` allowed.
- Import SVGs as React components via `@svgr/webpack`.
- Use `showToast(type, message)` utility instead of calling `toast()` directly. Type: `'success' | 'error' | 'info' | 'warning' | 'default'`.

### Project-Specific Must-Checks

- **SSR safety**: Guard `window`, `document`, `localStorage`, `sessionStorage` with browser checks. Verify correct layout usage (`SSRLayout` for SSR pages, `Layout` for client pages).
- **React Query SSR hydration**: Verify prefetch query keys and hydration state keys are consistent.
- **Auth/API stability**: Do not break token refresh lock, 401/403/503 handling, or retry flow.
- **Cookie safety**: Must use `COOKIE_KEY` constants and `getCookieDomain()` — never hard-code cookie names or domains. Verify stage/production separation is preserved.
- **iOS bridge stability**: Preserve `window.webkit` optional chaining and native callback contract.
- **Routing consistency**: Prefer `ROUTES` helpers over hard-coded path strings.
- **Next.js performance**: Flag async waterfalls, unnecessary heavy static imports, and missed dynamic imports.

### Validation Policy

- Primary check: `yarn lint`.
- `yarn build` may fail due to environment constraints (missing API access, sandbox limitations); treat as non-blocking unless the changed code directly caused the failure.

### Do Not Review

- Pure formatting/import-order noise already covered by lint.
- Generated artifacts only (`analytics.events.json`, `src/generated/**`) unless generation logic changed.
- `@bcsdlab/koin` and `@bcsdlab/utils` are internal packages — do not suggest external replacements.
82 changes: 82 additions & 0 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
language: ko
early_access: true
reviews:
profile: chill
request_changes_workflow: false
high_level_summary: true
high_level_summary_placeholder: '@coderabbitai summary'
changed_files_summary: true
sequence_diagrams: true
poem: false
review_status: true
collapse_walkthrough: false
path_filters:
- '**'
- '!.next/**'
- '!yarn.lock'
- '!.yarn/**'
- '!.pnp.cjs'
- '!.pnp.loader.mjs'
- '!public/**'
auto_review:
enabled: true
drafts: false
base_branches:
- develop
- main
tools:
shellcheck:
enabled: false
ruff:
enabled: false
biome:
enabled: false
github-checks:
enabled: true
timeout_ms: 120000
path_instructions:
- path: src/pages/**
instructions: |
이 디렉토리는 Next.js Pages Router의 페이지 컴포넌트입니다.
1. 페이지 컴포넌트에서 비즈니스 로직이 과도하게 포함되어 있지 않은지 확인해주세요.
2. SEO 관련 메타 태그(Head 컴포넌트)가 적절히 설정되어 있는지 확인해주세요.
3. getServerSideProps/getStaticProps 사용 시 에러 핸들링이 적절한지 확인해주세요.
- path: src/components/**
instructions: |
1. 컴포넌트의 단일 책임 원칙(SRP)을 준수하고 있는지 확인해주세요.
2. Props 타입이 명확하게 정의되어 있는지(interface 사용 권장) 확인해주세요.
3. 불필요한 리렌더링을 유발하는 패턴(인라인 함수, 객체 리터럴 등)이 있는지 확인해주세요.
4. 접근성(a11y) 관련 속성이 적절히 사용되고 있는지 확인해주세요.
- path: src/api/**
instructions: |
1. API 호출 시 적절한 에러 핸들링이 되어 있는지 확인해주세요.
2. 요청/응답 타입이 명확하게 정의되어 있는지 확인해주세요.
3. API 엔드포인트 URL에 하드코딩된 값이 없는지 확인해주세요.
4. 인증 토큰 등 민감 정보 처리가 안전한지 확인해주세요.
- path: src/hooks/**
instructions: |
1. 커스텀 훅의 네이밍이 use 접두사를 따르고 있는지 확인해주세요.
2. 의존성 배열이 정확하게 설정되어 있는지 확인해주세요.
3. 메모리 누수 가능성이 있는 패턴(cleanup 미처리)이 없는지 확인해주세요.
- path: src/utils/**
instructions: |
1. 유틸 함수가 순수 함수로 작성되어 있는지 확인해주세요.
2. 엣지 케이스(null, undefined, 빈 배열 등) 처리가 되어 있는지 확인해주세요.
- path: src/**
instructions: |
1. Next.js, React, TypeScript 팀 코드 컨벤션 및 공식 스타일 가이드(React/TS best practices)를 우선적으로 반영하여, 가독성·안정성(Null/에러 처리)·테스트/유지보수 용이성·브라우저/접근성 이슈 등을 검토해주세요.
2. 최신 React/TypeScript 트렌드, 팀 스타일 통일성, 성능 최적화, 보안 취약점 등도 함께 고려해주세요.
3. 각 리뷰 포인트별로 문제점과 대안, 장단점을 논리적으로 제시하고, 필요한 경우 예시 코드도 추가해주세요.
4. 리뷰가 너무 많아서 피로감을 줄 수 있으니, 꼭 필요한 부분에 집중해주고, 나머지는 캡션으로 설명해주세요.
5. 리뷰 남겨주는 부분은 해당 라인 범위의 코멘트에 작성해주세요.
6. zustand 스토어 사용 시 selector 패턴을 권장해주세요.
7. @tanstack/react-query 사용 시 queryKey 컨벤션과 에러/로딩 상태 처리를 확인해주세요.

chat:
auto_reply: true

knowledge_base:
web_search:
enabled: true
learnings:
scope: local
9 changes: 3 additions & 6 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
- Close #ISSUE_NUMBER

## What is this PR? 🔍

- 기능 :
- 기능 :
- issue : #

## Changes 📝

<!-- 이번 PR에서의 변경점 -->



## ScreenShot 📷

<!-- 개발 기능을 보여줄 수 있는 이미지, GIF -->

## Test CheckList ✅

<!--
<!--
- [ ] 카테고리 설정이 null 로 들어가지 않는지 체크
-->

Expand All @@ -27,7 +25,6 @@

## Precaution


## ✔️ Please check if the PR fulfills these requirements

- [ ] It's submitted to the correct branch, not the `develop` branch unconditionally?
Expand Down
Loading
Loading