diff --git a/.gemini/styleguide.md b/.gemini/styleguide.md new file mode 100644 index 0000000..d89d32c --- /dev/null +++ b/.gemini/styleguide.md @@ -0,0 +1,3 @@ +# 스타일 가이드 + +작업 정책과 코드 스타일의 정본은 [AGENTS.md](../AGENTS.md)입니다. 상세 관례는 [코드 관례](../docs/guides/code-conventions.md)를 확인합니다. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..461c19a --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,26 @@ +# Stology Frontend 작업 안내 + +이 문서는 AI 작업 정책의 정본입니다. 상세 기술·환경·기능 사실은 여기서 복제하지 않고 [문서 인덱스](docs/README.md)에 둡니다. + +## 작업 전 읽기 순서 + +1. [문서 인덱스](docs/README.md)와 변경 대상의 온보딩/기능 문서를 읽습니다. +2. 변경 대상 소스와 설정을 다시 확인합니다. 문서보다 현재 코드·설정이 사실의 기준입니다. +3. 변경 범위에 맞는 [코드 관례](docs/guides/code-conventions.md)와 [PR 검토](docs/guides/pr-review.md)를 확인합니다. + +## 현재 구조 지도 + +- 애플리케이션 조립과 라우팅은 `src/app`, 화면은 `src/pages`, 공용 코드와 UI는 `src/shared`에 있습니다. +- 기능별 상세와 탐색 경로는 [기능 온보딩](docs/onboarding/domain/README.md)을 기준으로 합니다. +- React 함수 컴포넌트와 hooks를 사용하고, 스타일은 Tailwind CSS를 우선합니다. +- 서버 상태는 TanStack Query, 클라이언트/UI 상태는 Zustand, 검증이 필요한 폼은 React Hook Form과 Zod를 사용합니다. + +## 작업 규칙 + +- 화면·컴포넌트는 PascalCase, hook은 camelCase, 유틸리티와 기타 파일은 snake_case를 사용합니다. +- 일반 함수는 function 선언을, 컴포넌트는 화살표 함수를 사용하고 메인 컴포넌트를 파일 상단에 둡니다. Props interface를 명시합니다. +- 공용화 전 기능 로컬 컴포넌트를 우선하며, 합의 없이 CSS-in-JS를 도입하지 않습니다. +- 화면 변경 시 loading, empty, error, permission, disabled, 종료된 스터디의 읽기 전용 상태를 검토합니다. +- AI는 Concept 후보만 제안하며 팀 검토를 거쳐 활성화됩니다. 질문은 Q&A에서 별도로 관리하며 Concept로 자동 변환하지 않습니다. +- 코드·설정 변경 시 영향을 받는 온보딩·기능·가이드 문서도 함께 갱신합니다. +- 되돌리기 어려운 실제 결정만 [ADR](docs/adr/README.md)로 기록합니다. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..5b2d63d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,3 @@ +# Claude 안내 + +작업 정책의 정본은 [AGENTS.md](AGENTS.md)입니다. 시작점은 [문서 인덱스](docs/README.md)이며, 변경 대상은 [기능 지도](docs/onboarding/domain/README.md)와 [가이드](docs/guides/README.md)에서 찾아 확인합니다. diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 0000000..e56395b --- /dev/null +++ b/GEMINI.md @@ -0,0 +1,3 @@ +# Gemini 안내 + +작업 정책의 정본은 [AGENTS.md](AGENTS.md)입니다. 시작점은 [문서 인덱스](docs/README.md)이며, 변경 대상은 [기능 지도](docs/onboarding/domain/README.md)와 [가이드](docs/guides/README.md)에서 찾아 확인합니다. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..7896b40 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,27 @@ +# Stology Frontend 문서 + +현재 코드와 설정을 탐색하기 위한 인덱스입니다. 정책 정본은 루트의 [AGENTS.md](../AGENTS.md)이며, 상세 사실은 아래 소유 문서에서 관리합니다. + +## 권장 읽기 경로 + +1. 처음 참여하거나 실행 환경을 확인할 때: [온보딩](onboarding/README.md) +2. 기능 변경 전: [기능 지도](onboarding/domain/README.md)와 해당 문서 + - [인증·초대](onboarding/domain/auth.md) + - [홈](onboarding/domain/home.md) + - [스터디](onboarding/domain/study.md) + - [AI 후보 검토](onboarding/domain/review.md) +3. 구현·검토 시: [가이드](guides/README.md) +4. 되돌리기 어려운 결정을 기록할 때: [ADR 안내](adr/README.md) + +## 기존 참고 문서 + +- [백엔드 데이터베이스 스키마](backend-database-schema.md): 프론트엔드 더미데이터의 엔티티 관계 참고 +- [디자인 토큰](design-tokens.md) +- [Hermes 권한 확인](hermes-permission-check.md) + +## 문서 소유권 + +- 온보딩은 실행 환경과 현재 구조의 사실을 설명합니다. +- 기능 문서는 각 화면의 현재 모델과 탐색 경로를 설명합니다. +- 가이드는 코드·문서 갱신 및 검토 기준을 제공합니다. +- ADR은 미래의 실제 결정을 기록하는 형식만 제공합니다. 기존 구현의 의도를 소급해 확정하지 않습니다. diff --git a/docs/adr/README.md b/docs/adr/README.md new file mode 100644 index 0000000..6de54c4 --- /dev/null +++ b/docs/adr/README.md @@ -0,0 +1,23 @@ +# Architecture Decision Records + +ADR은 이미 코드에 존재하는 구조의 의도를 추측하는 문서가 아니라, 앞으로 내리는 되돌리기 어려운 기술 결정을 기록하는 문서입니다. + +## 기록 대상 + +- 여러 기능에 영향을 주는 상태 관리, 라우팅, API 계층의 변경 +- 기존 공개 동작이나 데이터 계약과 호환되지 않는 결정 +- 장기간 유지할 라이브러리 또는 아키텍처 선택 + +단순 리팩터링, 버그 수정, 현재 코드 설명은 ADR 대상이 아닙니다. + +## 파일 형식 + +확정된 결정은 `YYYY-MM-DD-short-title.md`로 추가하고 다음을 기록합니다. + +1. 상태와 결정일 +2. 문제와 제약 +3. 검토한 선택지 +4. 선택한 결정과 근거 +5. 영향과 후속 작업 + +결정 전 초안은 PR 또는 이슈에서 논의하며, 합의되지 않은 추정을 ADR로 확정하지 않습니다. diff --git a/docs/backend-database-schema.md b/docs/backend-database-schema.md new file mode 100644 index 0000000..ceaa2b6 --- /dev/null +++ b/docs/backend-database-schema.md @@ -0,0 +1,217 @@ +# 백엔드 데이터베이스 스키마 + +> 이 문서는 백엔드 저장 구조를 프론트엔드 더미데이터 설계에 활용하기 위한 동기화 사본입니다. 정본은 [Stology/BE의 데이터베이스 스키마](https://github.com/Stology/BE/blob/main/docs/onboarding/database-schema.md)이며 최초 반영은 [BE PR #39](https://github.com/Stology/BE/pull/39)에서 확인합니다. + +이 문서는 현재 JPA 엔티티와 애플리케이션 설정을 기준으로 관계형 데이터베이스 구조를 정리합니다. 별도 DDL 또는 Flyway/Liquibase 마이그레이션은 없으며, 기본 설정은 MySQL dialect와 `ddl-auto: create`, 프로덕션 설정은 MySQL dialect와 `ddl-auto: update`를 사용합니다. + +따라서 아래 내용은 **현재 코드에서 도출되는 Hibernate 매핑**입니다. 특히 프로덕션 데이터베이스에는 과거 `update` 실행으로 남은 컬럼·제약이 있을 수 있으므로 실제 운영 스키마의 완전한 사본으로 간주하지 않습니다. + +## 프론트엔드 더미데이터 활용 기준 + +- 엔티티 간 식별자와 참조 관계를 유지해 서로 연결되는 fixture를 구성할 때 이 문서를 사용합니다. +- 현재 `src/shared/mocks/studies.ts`처럼 화면에 맞춘 mock은 DB 행을 그대로 복제하지 않고, TypeScript 타입과 실제 API 응답 계약에 맞는 view model로 변환합니다. +- DB의 snake case 컬럼명은 저장 구조 설명이며 프론트엔드 객체의 필드명 규칙을 대체하지 않습니다. API DTO가 확정되면 해당 계약을 우선합니다. +- `created_at`, `updated_at`, `deleted_at` 같은 공통 컬럼은 화면 시나리오에 필요한 경우에만 ISO 8601 문자열 등 API 표현 형식으로 포함합니다. +- `@Builder.Default`로 표시된 값은 DB DEFAULT가 아니므로, 원시 엔티티 형태의 fixture를 만들 때 필요한 값은 명시적으로 채웁니다. + +## 이름과 타입 해석 기준 + +- `@Table`, `@Column(name = ...)`이 없는 엔티티·필드는 현재 Spring Boot/Hibernate naming strategy에 따라 snake case로 적었습니다. 예: `MemberStudy` → `member_study`, `socialUid` → `social_uid`. +- 모든 엔티티의 `id`는 `Long`이며 `IDENTITY` 방식의 기본 키입니다. +- 별도 길이 지정이 없는 `String`은 Hibernate의 기본 문자열 매핑을 사용합니다. `Report`의 일부 필드만 코드에서 `json` 또는 `text`로 명시합니다. +- 모든 엔티티는 `BaseEntity`를 상속하므로 `created_at`, `updated_at`, `deleted_at`을 공유합니다. +- `@JoinColumn`에 `nullable = false`가 없고 연관 필드도 `optional = false`가 아니므로 외래 키 컬럼의 NOT NULL 제약은 코드에 명시되어 있지 않습니다. +- `@Builder.Default`는 Lombok builder로 객체를 생성할 때의 Java 기본값이며 DB의 `DEFAULT` 제약이 아닙니다. + +## 관계 개요 + +```mermaid +erDiagram + MEMBER ||--o{ TEMPLATE : uploads + MEMBER ||--o{ MEMBER_STUDY : joins + TEMPLATE ||--o{ TEMPLATE_NODE : contains + TEMPLATE ||--o{ STUDY : bases + STUDY ||--o{ MEMBER_STUDY : has + STUDY ||--o{ QUESTION : has + QUESTION ||--o{ QUESTION_IMAGE : has + QUESTION ||--o{ ANSWER : has + ANSWER ||--o{ ANSWER_IMAGE : has + STUDY ||--o{ REPORT : has + STUDY ||--o{ STUDY_NODE : has + STUDY_NODE ||--o{ NODE_CANDIDATE : receives + STUDY_MATERIAL ||--o{ NODE_CANDIDATE : produces +``` + +코드의 모든 연관은 단방향 `@ManyToOne(fetch = LAZY)`입니다. 반대 방향 컬렉션, cascade, orphan removal은 선언되어 있지 않습니다. 다이어그램의 `||--o{`는 참조 방향과 다대일 구조를 읽기 쉽게 표현한 것이며, 코드가 외래 키 컬럼에 NOT NULL을 명시한다는 의미는 아닙니다. + +## 공통 컬럼 + +아래 컬럼은 13개 엔티티 테이블에 모두 포함됩니다. + +| 컬럼 | Java 타입 | 매핑 및 의미 | +| ------------ | --------------- | ---------------------------------------------- | +| `created_at` | `LocalDateTime` | `@CreatedDate`, 수정 불가(`updatable = false`) | +| `updated_at` | `LocalDateTime` | `@LastModifiedDate` | +| `deleted_at` | `LocalDateTime` | soft delete 시각, 코드상 nullable | + +## 회원 + +### `member` + +| 컬럼 | Java 타입 | 키/제약 및 매핑 | +| ------------- | ------------ | ----------------------------------------- | +| `id` | `Long` | PK, identity | +| `name` | `String` | Bean Validation `@NotBlank` | +| `social_type` | `SocialType` | 문자열 enum, `@NotNull`; 현재 값: `KAKAO` | +| `social_uid` | `String` | Bean Validation `@NotBlank` | +| `email` | `String` | Bean Validation `@Email`, `@NotBlank` | + +코드에는 `social_type`과 `social_uid` 조합을 조회하는 repository 메서드가 있지만, 해당 조합의 UNIQUE 제약이나 인덱스는 선언되어 있지 않습니다. + +## 노드와 템플릿 + +### `template` + +| 컬럼 | Java 타입 | 키/제약 및 매핑 | +| ------------- | --------- | ------------------- | +| `id` | `Long` | PK, identity | +| `uploader` | `Long` | FK → `member.id` | +| `name` | `String` | 별도 컬럼 제약 없음 | +| `description` | `String` | 별도 컬럼 제약 없음 | + +### `template_node` + +| 컬럼 | Java 타입 | 키/제약 및 매핑 | +| ------------- | --------- | ------------------ | +| `id` | `Long` | PK, identity | +| `template_id` | `Long` | FK → `template.id` | + +### `study_node` + +| 컬럼 | Java 타입 | 키/제약 및 매핑 | +| -------------- | --------- | --------------------------------------------------- | +| `id` | `Long` | PK, identity | +| `study_id` | `Long` | FK → `study.id` | +| `active_level` | `Integer` | builder 생성 기본값 `0`; DB DEFAULT는 선언되지 않음 | + +### `study_material` + +| 컬럼 | Java 타입 | 키/제약 및 매핑 | +| ---------- | --------- | ------------------- | +| `id` | `Long` | PK, identity | +| `file_url` | `String` | 별도 컬럼 제약 없음 | + +### `node_candidate` + +| 컬럼 | Java 타입 | 키/제약 및 매핑 | +| ------------------- | ---------------- | ------------------------------------------------------------------------------------ | +| `id` | `Long` | PK, identity | +| `study_material_id` | `Long` | FK → `study_material.id` | +| `study_node_id` | `Long` | FK → `study_node.id` | +| `state` | `CandidateState` | 문자열 enum; 현재 값: `ACCEPT`, `DECLINED`, `PENDING`; builder 생성 기본값 `PENDING` | +| `accept_count` | `Integer` | builder 생성 기본값 `0`; DB DEFAULT는 선언되지 않음 | + +## 스터디 + +### `study` + +| 컬럼 | Java 타입 | 키/제약 및 매핑 | +| ----------------- | --------- | ------------------------------------------------------ | +| `id` | `Long` | PK, identity | +| `template_id` | `Long` | FK → `template.id` | +| `name` | `String` | 별도 컬럼 제약 없음 | +| `description` | `String` | 별도 컬럼 제약 없음 | +| `invitation_link` | `String` | 별도 컬럼 제약 없음 | +| `reviewer_count` | `Integer` | 별도 컬럼 제약 없음 | +| `is_active` | `Boolean` | builder 생성 기본값 `true`; DB DEFAULT는 선언되지 않음 | +| `study_leader` | `String` | 별도 컬럼 제약 없음 | + +### `member_study` + +| 컬럼 | Java 타입 | 키/제약 및 매핑 | +| ----------- | --------- | ---------------- | +| `id` | `Long` | PK, identity | +| `member_id` | `Long` | FK → `member.id` | +| `study_id` | `Long` | FK → `study.id` | + +`member_id`와 `study_id` 조합의 UNIQUE 제약은 선언되어 있지 않습니다. + +### `question` + +| 컬럼 | Java 타입 | 키/제약 및 매핑 | +| -------------- | --------- | --------------------------------------------------- | +| `id` | `Long` | PK, identity | +| `study_id` | `Long` | FK → `study.id` | +| `title` | `String` | 별도 컬럼 제약 없음 | +| `content` | `String` | 별도 컬럼 제약 없음 | +| `member_name` | `String` | 별도 컬럼 제약 없음 | +| `answer_count` | `Integer` | builder 생성 기본값 `0`; DB DEFAULT는 선언되지 않음 | +| `is_attached` | `Boolean` | 별도 컬럼 제약 없음 | + +### `question_image` + +| 컬럼 | Java 타입 | 키/제약 및 매핑 | +| ------------- | --------- | ------------------- | +| `id` | `Long` | PK, identity | +| `question_id` | `Long` | FK → `question.id` | +| `image_url` | `String` | 별도 컬럼 제약 없음 | + +### `answer` + +| 컬럼 | Java 타입 | 키/제약 및 매핑 | +| ------------- | --------- | ------------------- | +| `id` | `Long` | PK, identity | +| `question_id` | `Long` | FK → `question.id` | +| `content` | `String` | 별도 컬럼 제약 없음 | +| `member_name` | `String` | 별도 컬럼 제약 없음 | + +### `answer_image` + +| 컬럼 | Java 타입 | 키/제약 및 매핑 | +| ----------- | --------- | ------------------- | +| `id` | `Long` | PK, identity | +| `answer_id` | `Long` | FK → `answer.id` | +| `image_url` | `String` | 별도 컬럼 제약 없음 | + +### `report` + +| 컬럼 | Java 타입 | 키/제약 및 매핑 | +| --------------------------------- | --------- | --------------------------------------------------- | +| `id` | `Long` | PK, identity | +| `study_id` | `Long` | FK → `study.id` | +| `total_node_count` | `Integer` | builder 생성 기본값 `0`; DB DEFAULT는 선언되지 않음 | +| `new_active_node_count` | `Integer` | builder 생성 기본값 `0`; DB DEFAULT는 선언되지 않음 | +| `reinforced_node_count` | `Integer` | builder 생성 기본값 `0`; DB DEFAULT는 선언되지 않음 | +| `weekly_core_node_list` | `String` | MySQL `json`으로 명시 | +| `ai_review_content` | `String` | MySQL `text`로 명시 | +| `recommended_node_list` | `String` | MySQL `json`으로 명시 | +| `follow_up_content` | `String` | MySQL `text`로 명시 | +| `member_activity_statistics_list` | `String` | MySQL `json`으로 명시 | + +JSON 컬럼의 Java 타입은 구조화된 객체가 아닌 `String`입니다. 코드에는 JSON 변환기나 구체적인 JSON 내부 스키마가 선언되어 있지 않습니다. + +## 명시적으로 선언되지 않은 제약 + +현재 엔티티에는 다음 데이터베이스 제약이 선언되어 있지 않습니다. + +- 기본 키 이외의 UNIQUE 제약 +- 명시적 보조 인덱스 +- 외래 키 컬럼의 NOT NULL +- 연관 삭제/갱신 cascade 규칙 +- 문자열 길이, 숫자 범위, CHECK 제약 +- DB 수준의 컬럼 기본값 + +Bean Validation의 `@NotBlank`, `@NotNull`, `@Email`은 `member` 엔티티 객체 검증에 사용되지만, 이 문서에서는 이를 명시적인 JPA `nullable = false`나 데이터베이스 CHECK 제약으로 간주하지 않습니다. + +## 관계형 DB 밖의 저장 데이터 + +refresh token은 RDB 테이블이 아니라 Redis에 `refresh:{uid}` 키로 저장되며 TTL을 가집니다. 따라서 위 스키마와 테이블 목록에는 포함하지 않습니다. + +## 백엔드 기준 소스 + +- [공통 필드](https://github.com/Stology/BE/blob/main/src/main/java/com/stology/be/global/entity/BaseEntity.java) +- [회원 엔티티](https://github.com/Stology/BE/blob/main/src/main/java/com/stology/be/domain/member/entity/Member.java) +- [노드·템플릿 엔티티](https://github.com/Stology/BE/tree/main/src/main/java/com/stology/be/domain/node/entity) +- [스터디 엔티티](https://github.com/Stology/BE/tree/main/src/main/java/com/stology/be/domain/study/entity) +- [기본 DB/JPA 설정](https://github.com/Stology/BE/blob/main/src/main/resources/application.yaml) +- [프로덕션 DB/JPA 설정](https://github.com/Stology/BE/blob/main/src/main/resources/application-prod.yaml) diff --git a/docs/guides/README.md b/docs/guides/README.md new file mode 100644 index 0000000..6fef69b --- /dev/null +++ b/docs/guides/README.md @@ -0,0 +1,6 @@ +# 구현·검토 가이드 + +- [코드 관례](code-conventions.md): 현재 배치와 구현 원칙 +- [PR 검토](pr-review.md): 자동 검사와 사람 검토 기준 + +작업 정책은 [AGENTS.md](../../AGENTS.md), 현재 구조는 [온보딩](../onboarding/README.md)에서 확인합니다. diff --git a/docs/guides/code-conventions.md b/docs/guides/code-conventions.md new file mode 100644 index 0000000..4daff22 --- /dev/null +++ b/docs/guides/code-conventions.md @@ -0,0 +1,18 @@ +# 코드 관례 + +아래는 현재 프로젝트의 규칙과 관찰된 배치입니다. 변경 전에는 대상 소스를 다시 확인합니다. 작업 정책은 [AGENTS.md](../../AGENTS.md), 기능 지도는 [기능 온보딩](../onboarding/domain/README.md)을 따릅니다. + +## 배치와 이름 + +- 애플리케이션 조립은 `src/app`, 기능 화면은 `src/pages`, 공용 코드는 `src/shared`에 둡니다. +- 페이지와 컴포넌트 파일은 PascalCase, hook은 camelCase, 유틸리티와 기타 파일은 snake_case를 사용합니다. +- 변수는 camelCase, 함수는 동사로 시작하는 camelCase, boolean은 `is`, `has`, `should` 접두사, 배열은 복수형이나 `List` 접미사를 사용합니다. +- 컴포넌트는 화살표 함수, 일반 함수는 function 선언을 사용하며 Props interface를 명시합니다. + +## 구현 원칙 + +- 기능 로컬 컴포넌트를 우선하고 실제 재사용 근거가 생긴 뒤 `shared/ui`로 옮깁니다. +- Tailwind CSS와 기존 `shared/ui` 조합을 우선하며 합의 없이 CSS-in-JS를 도입하지 않습니다. +- 서버 상태는 TanStack Query, 클라이언트/UI 상태는 Zustand, 검증 폼은 React Hook Form과 Zod를 사용합니다. +- API base URL과 공통 Axios 설정은 `src/shared/api/http_client.ts`에서 확인합니다. +- 화면에는 변경 범위에 맞는 loading, empty, error, permission, disabled, 읽기 전용 상태를 고려합니다. diff --git a/docs/guides/pr-review.md b/docs/guides/pr-review.md new file mode 100644 index 0000000..d667230 --- /dev/null +++ b/docs/guides/pr-review.md @@ -0,0 +1,22 @@ +# PR 검토 + +현재 코드 배치는 [코드 관례](code-conventions.md), 작업 정책은 [AGENTS.md](../../AGENTS.md), 문서 위치는 [문서 인덱스](../README.md)에서 확인합니다. + +## 자동으로 확인할 항목 + +코드·설정 변경은 범위에 맞게 `pnpm format:check`, `pnpm lint`, `pnpm build`를 실행합니다. 실패를 숨기거나 검사를 사람의 판단으로 대체하지 않습니다. Markdown 전용 변경은 링크와 포맷을 확인하고 제품 빌드가 필요하지 않은 이유를 PR에 명시할 수 있습니다. + +## 사람이 판단할 항목 + +### 문서 + +- 수정한 Markdown 링크와 heading anchor가 유효하고 문서 인덱스의 탐색 경로가 유지되는지 확인합니다. +- 현재 소스·설정과 API, 라우트, 환경 변수 설명이 동기화되었는지 확인합니다. +- 되돌리기 어려운 결정이면 [ADR](../adr/README.md) 조건을 검토합니다. + +### 화면·상태·제품 규칙 + +- 기능 코드가 `app`, `pages`, `shared`의 현재 책임을 흐리지 않는지 확인합니다. +- loading, empty, error, permission, disabled와 종료된 스터디의 읽기 전용 상태를 확인합니다. +- AI 후보가 검토 없이 활성 Concept가 되거나 질문이 Concept로 자동 변환되지 않는지 확인합니다. +- UI 변경 PR에는 feature ID, screen ID, priority, 테스트 결과와 필요한 스크린샷이 포함되는지 확인합니다. diff --git a/docs/onboarding/README.md b/docs/onboarding/README.md new file mode 100644 index 0000000..a58de82 --- /dev/null +++ b/docs/onboarding/README.md @@ -0,0 +1,21 @@ +# 온보딩 + +이 문서는 현재 빌드와 설정의 사실을 요약합니다. 환경 변수의 실제 비밀값은 문서나 저장소에 기록하지 않습니다. + +## 실행 기반 + +- React 19, TypeScript 5.7, Vite 6 기반이며 패키지 매니저는 `pnpm@9.15.9`입니다. +- `pnpm install` 후 `pnpm dev`로 개발 서버를 실행합니다. +- 주요 검증 명령은 `pnpm format:check`, `pnpm lint`, `pnpm build`입니다. +- 주요 런타임 의존성은 React Router, TanStack Query, Axios, Zustand, React Hook Form, Zod입니다. +- 스타일은 Tailwind CSS 3와 전역 `src/styles.css`를 사용합니다. + +## 설정과 환경 변수 + +- Vite 설정은 `vite.config.ts`, TypeScript 설정은 `tsconfig*.json`, Tailwind 설정은 `tailwind.config.ts`에서 확인합니다. +- 현재 `.env.example`에는 `VITE_API_BASE_URL`만 선언되어 있습니다. 실제 값은 커밋하지 않습니다. +- `@` 경로 별칭은 실제 Vite 및 TypeScript 설정을 함께 확인한 뒤 사용합니다. + +## 다음 읽기 + +화면과 공용 구성요소는 [기능 온보딩](domain/README.md)에서, 구현·검토 기준은 [가이드](../guides/README.md)에서 확인합니다. diff --git a/docs/onboarding/domain/README.md b/docs/onboarding/domain/README.md new file mode 100644 index 0000000..4c8c95d --- /dev/null +++ b/docs/onboarding/domain/README.md @@ -0,0 +1,29 @@ +# 기능 온보딩 + +`src`의 현재 탐색 지도입니다. 상세 동작은 문서보다 대상 소스를 우선해 확인합니다. + +## 애플리케이션 + +- `src/main.tsx`: React 진입점 +- `src/app/App.tsx`: 애플리케이션 루트 +- `src/app/providers/AppProvider.tsx`: 전역 provider 조립 +- `src/app/router/router.tsx`: 공개 라우트 정의 + +## 기능 화면 + +- [인증·초대](auth.md): `src/pages/login`, `src/pages/invite` +- [홈](home.md): `src/pages/home` +- [스터디](study.md): `src/pages/study` +- [AI 후보 검토](review.md): `src/pages/review` +- `src/pages/dev`: 공용 컴포넌트 확인용 개발 화면 + +## 공용 코드 + +- `src/shared/ui`: 공용 UI 컴포넌트와 barrel export +- `src/shared/api`: HTTP client +- `src/shared/types`: 공유 타입 +- `src/shared/mocks`: 개발용 mock 데이터 +- `src/shared/lib`: 공용 유틸리티 +- `src/shared/assets`: 정적 asset + +기능 코드는 먼저 해당 `pages` 경로에 두고, 여러 기능에서 실제로 재사용될 때 `shared` 이동을 검토합니다. diff --git a/docs/onboarding/domain/auth.md b/docs/onboarding/domain/auth.md new file mode 100644 index 0000000..4ce1cfb --- /dev/null +++ b/docs/onboarding/domain/auth.md @@ -0,0 +1,12 @@ +# 인증·초대 + +## 탐색 경로 + +- 로그인 화면: `src/pages/login/LoginPage.tsx` +- 초대 수락 화면: `src/pages/invite/InvitePage.tsx` +- 라우트: `/login`, `/invite/:token` +- HTTP 기반: `src/shared/api/http_client.ts` + +## 제품 경계 + +`AUTH`는 인증과 라우팅, `HOME`은 스터디 진입, 초대는 초대 토큰을 통한 스터디 참여 흐름을 담당합니다. 인증 여부 판정, redirect, token 저장 방식을 변경할 때는 현재 라우터·provider·HTTP client 구현을 함께 확인하며 문서만으로 계약을 추정하지 않습니다. diff --git a/docs/onboarding/domain/home.md b/docs/onboarding/domain/home.md new file mode 100644 index 0000000..92f3c98 --- /dev/null +++ b/docs/onboarding/domain/home.md @@ -0,0 +1,12 @@ +# 홈 + +## 탐색 경로 + +- 화면: `src/pages/home/HomePage.tsx` +- 라우트: `/` +- 현재 mock 스터디 데이터: `src/shared/mocks/studies.ts` +- 공유 모델: `src/shared/types/stology.ts` + +## 제품 경계 + +`HOME`은 스터디 카드, 생성, 선택과 초대 링크 진입 전후의 홈 경험을 담당합니다. 목록을 서버 상태로 연결할 때 TanStack Query를 사용하고 loading, empty, error 상태를 함께 다룹니다. 종료된 스터디는 수정 가능한 화면으로 취급하지 않습니다. diff --git a/docs/onboarding/domain/review.md b/docs/onboarding/domain/review.md new file mode 100644 index 0000000..739b040 --- /dev/null +++ b/docs/onboarding/domain/review.md @@ -0,0 +1,11 @@ +# AI 후보 검토 + +## 탐색 경로 + +- 화면: `src/pages/review/ReviewPage.tsx` +- 라우트: `/studies/:studyId/review/:materialId` +- 공유 모델: `src/shared/types/stology.ts` + +## 제품 경계 + +`REV`는 업로드 자료에서 AI가 제안한 Concept 후보의 팀 검토를 담당합니다. AI 제안 자체가 활성 Concept가 아니며, 팀의 승인 결과만 지식 구조에 반영됩니다. 후보 상태를 연결할 때 loading, empty, error, permission, disabled 상태와 종료된 스터디의 읽기 전용 동작을 함께 확인합니다. diff --git a/docs/onboarding/domain/study.md b/docs/onboarding/domain/study.md new file mode 100644 index 0000000..2739e45 --- /dev/null +++ b/docs/onboarding/domain/study.md @@ -0,0 +1,12 @@ +# 스터디 + +## 탐색 경로 + +- 화면: `src/pages/study/StudyPage.tsx` +- 기본 진입: `/studies/:studyId`에서 `knowledge` 탭으로 이동 +- 탭 라우트: `/studies/:studyId/:tab` +- 공유 모델: `src/shared/types/stology.ts` + +## 제품 경계 + +`STD-COM`, `STD-MGT`, `STD-END`는 컨테이너·관리·종료 상태를, `STD-KNW`는 온톨로지 지식 구조를, `STD-UP`은 자료 업로드와 AI 추출을 담당합니다. 질문은 `QNA`에서 별도로 관리하며 Concept 노드로 자동 변환하지 않습니다. 종료된 스터디는 읽기 전용이고, 탭 추가나 변경 시 라우터와 화면의 허용 탭 처리를 함께 확인합니다.