Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 25 additions & 18 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,13 @@ CI·개발·미리보기·생산·Storybook의 Node 설정은

## 4. 코드와 문서 컨벤션

| 문서 | 소유하는 규칙 |
| ---------------------------------------------------------- | ------------------------------------------------ |
| [문서 작성](conventions/docs.md) | Markdown 형식, 길이, 문체, 중복, 링크·갱신 |
| [TypeScript·구조](conventions/typescript-and-structure.md) | 이름·선언·타입·파일 배치·주석 |
| [React·UI](conventions/react-and-ui.md) | 컴포넌트·Props·훅·effect·스타일·국제화·접근성 |
| [데이터·실시간](conventions/data-and-realtime.md) | Query·Mutation·API·MSW·Repository·소켓 작성 형식 |
| 문서 | 소유하는 규칙 |
| ---------------------------------------------------------- | -------------------------------------------------------- |
| [문서 작성](conventions/docs.md) | Markdown 형식, 길이, 문체, 중복, 링크·갱신 |
| [TypeScript·구조](conventions/typescript-and-structure.md) | 이름·선언·타입·파일 배치·주석 |
| [React·UI](conventions/react-and-ui.md) | 컴포넌트·Props·훅·effect·스타일·국제화·접근성 |
| [공통 디자인](conventions/design.md) | 시각 방향·색상·타이포그래피·형태·공간 대응·움직임 |
| [데이터·실시간](conventions/data-and-realtime.md) | Query·Mutation·API·MSW·Repository·소켓 작성 형식 |
| [테스트·Storybook](conventions/testing-and-storybook.md) | TDD, 테스트·모킹·Story 작성, Storybook 10 설정·수동 검증 |

## 5. 스킬 워크플로
Expand All @@ -90,18 +91,19 @@ CI·개발·미리보기·생산·Storybook의 Node 설정은
모든 코드 변경 전에 [헌법](CONSTITUTION.md)과 이 문서를 읽고, 아래에서 해당하는
상세 문서를 함께 읽음. 여러 행에 해당하면 모두 적용함.

| 작업 | 읽을 상세 문서 | 계약 변경 시 갱신할 문서 |
| ---------------------------------- | --------------------------------------------- | --------------------------------------- |
| 페이지·공용 UI·상태 훅 | 구조와 UI, React·UI, TypeScript·구조 | 구조와 UI 또는 React·UI |
| 라우트·인증·언어 | 앱·라우팅·국제화, React·UI | 앱·라우팅·국제화 |
| HTTP·Query·Mutation·Repository·MSW | 데이터 접근, 데이터·실시간, 테스트·Storybook | 데이터 접근 또는 데이터·실시간 |
| 소켓·타이머 공유 상태 | 실시간 통신, 데이터·실시간, 테스트·Storybook | 실시간 통신 또는 데이터·실시간 |
| 오류 UI·Sentry | 오류와 관측, React·UI, 테스트·Storybook | 오류와 관측 |
| 테스트·Story | 테스트·Storybook, 대상 기능의 아키텍처·컨벤션 | 테스트·Storybook 또는 대상 문서 |
| 문서·템플릿 | 문서 작성, 이 문서, 관련 상세 문서 | 원칙 변경은 헌법, 계약 변경은 소유 문서 |
| 실행 환경·의존성·workflow | 실행 환경 설정, 테스트·Storybook, 문서 작성 | 실행 환경 설정 |
| 코드 리뷰·리뷰 보고서 | 코드 리뷰, 변경 영역의 상세 문서 | 코드 리뷰 또는 해당 상세 문서 |
| 일반 PR 준비·생성 | 일반 PR 생성, 코드 리뷰, 문서 작성 | 일반 PR 생성 또는 코드 리뷰 |
| 작업 | 읽을 상세 문서 | 계약 변경 시 갱신할 문서 |
| ---------------------------------- | ------------------------------------------------- | --------------------------------------- |
| 페이지·공용 UI·상태 훅 | 구조와 UI, React·UI, TypeScript·구조, 공통 디자인 | 구조와 UI, React·UI 또는 공통 디자인 |
| 디자인·타이포그래피 | 공통 디자인, React·UI, 문서 작성 | 공통 디자인 |
| 라우트·인증·언어 | 앱·라우팅·국제화, React·UI | 앱·라우팅·국제화 |
| HTTP·Query·Mutation·Repository·MSW | 데이터 접근, 데이터·실시간, 테스트·Storybook | 데이터 접근 또는 데이터·실시간 |
| 소켓·타이머 공유 상태 | 실시간 통신, 데이터·실시간, 테스트·Storybook | 실시간 통신 또는 데이터·실시간 |
| 오류 UI·Sentry | 오류와 관측, React·UI, 테스트·Storybook | 오류와 관측 |
| 테스트·Story | 테스트·Storybook, 대상 기능의 아키텍처·컨벤션 | 테스트·Storybook 또는 대상 문서 |
| 문서·템플릿 | 문서 작성, 이 문서, 관련 상세 문서 | 원칙 변경은 헌법, 계약 변경은 소유 문서 |
| 실행 환경·의존성·workflow | 실행 환경 설정, 테스트·Storybook, 문서 작성 | 실행 환경 설정 |
| 코드 리뷰·리뷰 보고서 | 코드 리뷰, 변경 영역의 상세 문서 | 코드 리뷰 또는 해당 상세 문서 |
| 일반 PR 준비·생성 | 일반 PR 생성, 코드 리뷰, 문서 작성 | 일반 PR 생성 또는 코드 리뷰 |

표의 항목은 2~5절의 설정 설명과 문서 링크를 가리킴. 정확히 일치하는 행이 없으면
변경 대상과 소비자를 기준으로 관련 문서를 선택함. 경로·기술·작업 분류가 바뀌면 이 문서의
Expand All @@ -114,3 +116,8 @@ CI·개발·미리보기·생산·Storybook의 Node 설정은
확정 규칙과 다를 수 있음. 기존 예외를 새 규칙으로 해석하지 않음. 공용 도메인
타입의 `src/types/` 이동은 이 개편에서 함께 수행함. 규칙과 코드 경로가
달라졌다면 현재 상태와 목표를 구분해 해당 상세 문서를 수정함.

[공통 디자인](conventions/design.md)의 브랜드·진영색, 기본 팔레트 사용과 역할별
타이포그래피 utility는 전역 CSS에 반영했음. 기존 사용자 정의 색상의 의미별
전환과 기존 화면의 글자 역할 적용은 아직 목표 상태임. 현재 구현과의 차이와
적용 경계는 해당 문서에서 확인함.
145 changes: 145 additions & 0 deletions docs/conventions/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# 공통 디자인 컨벤션

## 적용 범위와 현재 구현

페이지·공용 UI·기능 전용 UI의 시각 기준을 소유함. 신규 UI와 실질적으로 변경하는
UI는 이 기준에 맞춰 설계함. 같은 역할은 같은 기준을 사용하고, 사용 목적이
다르면 필요한 변형을 허용함. 변형은 기본 기준과 다른 이유·적용 범위를 간단히
기록하며, 화면마다 독립적인 시안을 만들지 않음.

**현재 상태와 목표**: 브랜드·진영색, Tailwind CSS 4 기본 팔레트 사용과 아래
타이포그래피의 공용 utility를 전역 CSS에 반영했음. 기존 사용자 정의 색상의
의미별 전환과 기존 화면의 글자 역할 적용은 아직 UI 전체에 반영되지 않은 목표임.
후속 UI 구현에서 실제 CSS 정의와 사용처를 함께 확인해 반영함. 기존 구현의
차이를 새로운 디자인의 예외로 해석하지 않음.

UI 책임과 재사용 범위는 [구조와 UI](../architecture/structure-and-ui.md),
스타일 구현·접근성·사용자 문구는 [React·UI](react-and-ui.md), 테스트와 시각
검증 절차는 [테스트·Storybook](testing-and-storybook.md)이 소유함.

## 기본 방향과 변형

흰 바탕·어두운 글자·노랑 강조를 기본으로 밝고 명확한 화면을 구성함. 현재의
[시간표 편집](../../src/page/TableComposition/TableCompositionPage.tsx)·
[개요](../../src/page/TableOverviewPage/TableOverviewPage.tsx)가 기본 인상의
근거임. 해당 화면의 모든 치수·배치·상태 표현을 규칙으로 채택하는 것은 아님.

일반 UI는 여유 있는 간격과 충분한 조작 영역을 기본으로 함. 정보량이 많은 곳은
조밀한 변형을 허용하되, 글자와 조작 영역을 무리하게 줄여 밀도를 높이지 않음.
원거리에서 확인하는 숫자, 긴 글을 읽는 영역, 소개용 큰 문구처럼 목적이 다른
표현은 그 목적에 맞게 조정함. 변형을 위한 크기 종류를 미리 늘리지 않음.

## 색상과 강조

### 유지하는 브랜드·진영색

[index.css](../../src/index.css)에 정의된 다음 색상을 유지함.

| 역할 | 이름 | 값 |
| ----------- | ------------- | --------- |
| 브랜드 강조 | `brand` | `#FECD4C` |
| 브랜드 호버 | `brand-hover` | `#DBA822` |
| 찬성 진영 | `stance-blue` | `#1E91D6` |
| 반대 진영 | `stance-red` | `#E14666` |

### 중립·오류색의 목표

중립색은 Tailwind CSS 4의 `neutral`, 오류색은 `red` 기본 팔레트를 사용함.
기존 v3 호환 재정의값을 목표 색상으로 고정하지 않음. 배경·본문·보조 설명·
경계·비활성 등 의미에 맞는 단계를 사용하고, 모든 단계의 사용처를 미리 정하지
않음. 흰색은 기본 면으로 사용하며 회색 계열을 화면마다 따로 선택하지 않음.

일반적인 주요 행동과 선택 강조는 브랜드 노랑을 중심으로 구성함. 컴포넌트마다
보라·파랑 등 별도의 일반 선택색을 만들지 않음. 진영과 오류처럼 별도 의미가
있는 색은 해당 역할에 사용하며, 색만으로 상태를 전달하지 않음. 비활성·미선택·
호버는 서로 다른 상태로 구분함.

색상 단계는 실제 배경과 글자·아이콘의 조합에서 읽기 쉬운지 확인해 선택함.
현재 `default-*`·`semantic-*` 색상이나 기본 팔레트 이름을 사용하는 것만으로
새 기준을 충족했다고 간주하지 않음. 기본 팔레트의 v3 호환 재정의는 제거했으나
기존 UI가 소비하는 사용자 정의 색상은 남아 있으므로 이름과 실제 값을 함께
확인해야 함.

## 타이포그래피

### 역할별 기본 스타일

글꼴은 현재 전역 Pretendard 계열과 대체 글꼴 순서를 상속함. 자간은 기본값을
사용함. 글자 크기·굵기·행간을 하나의 역할별 스타일로 다루고, 색상은 강조·
오류 등 문맥에 따라 별도로 선택함.

| 역할 | 용도 | 클래스 | 크기 | 굵기 | 행간 |
| -------- | --------------------- | ------------------ | ---- | ---- | ---- |
| Headline | 화면의 대표 제목 | `text-ui-headline` | 28px | 700 | 36px |
| Title | 구역·내용 묶음의 제목 | `text-ui-title` | 24px | 600 | 32px |
| Body | 본문 | `text-ui-body` | 16px | 400 | 24px |
| Label | 짧은 조작·항목 이름 | `text-ui-label` | 16px | 600 | 24px |
| Caption | 보조 설명 | `text-ui-caption` | 14px | 400 | 20px |

현재 전역 글자 크기를 출발점으로 삼고 보조 설명에 필요한 크기를 보완했음.
제목은 크기와 굵기로 분명히 드러내며, 본문과 보조 설명은 읽기 편한 차이를 둠.
역할마다 기본 스타일 하나로 시작하고 실제 필요가 있을 때만 변형을 추가함.
모든 역할에 작은·중간·큰 단계를 만들지 않음.

### 역할 선택과 기존 선택자의 차이

화면 대표 제목에는 Headline, 그 아래 구역 제목에는 Title을 선택함. 본문은
Body, 버튼·항목의 짧은 이름은 Label, 부가 설명은 Caption을 기본으로 함.
색이나 크기만 보고 역할을 선택하지 않음.

시각 역할을 HTML 요소와 일대일로 연결하지 않음. 예를 들어 Title 스타일의
HTML 제목 수준은 문서 구조에 따라 결정하며, Label 스타일이 HTML `label`
요소만을 뜻하지 않음. 의미 구조는 [React·UI](react-and-ui.md)의 계약을 따름.

현재 `.text-title`은 28px 크기만 선언하며 위 Title 역할의 전체 스타일과 다름.
기존 `.text-body` 등도 굵기·행간을 포함하는 새 역할의 구현으로 간주하지 않음.
새 역할에는 위 표의 `text-ui-*`를 사용함. 타이머 수치나 홍보 문구의 변형도
일반 역할의 기본값을 바꾸는 근거로 삼지 않음.

### 사용과 사양 동기화

[index.css](../../src/index.css)의 `@theme`에 `--text-ui-{역할}`과 이에 대응하는
`--line-height`·`--font-weight` 속성을 정의함. Tailwind가 이를 묶어 위 클래스와
`md:text-ui-title` 같은 화면 조건 조합을 생성함. 글꼴·색·자간은 역할에 고정하지
않으며, 선택한 역할의 크기·굵기·행간을 개별 utility로 임의 덮어쓰지 않음.
변형이 필요하면 이 문서의 공통 변형 원칙을 적용함.

```tsx
<h1 className="text-ui-headline">{t('토론 기록')}</h1>
<p className="text-ui-body text-neutral-700">{description}</p>
```

**타이포그래피 사양을 변경할 때는 이 문서의 표와 `src/index.css`의 대응
`@theme` 정의를 반드시 같은 변경에서 갱신함.** 역할·클래스명을 추가·변경·삭제하면
사용처와 [디자인 샘플 Story](../../src/components/DesignSystemSample/DesignSystemSample.stories.tsx)도
함께 갱신함. 값만 바뀌는 경우 Story는 같은 클래스를 통해 변경값을 반영함.
문서의 사양과 실제 생성 CSS의 크기·굵기·행간을 대조하고 lint·build로 검증함.

## 형태·영역 구분·행동의 위계

둥근 인상을 유지하되 작은 요소와 큰 면의 모서리를 소수 단계로 구분함.
완전히 둥근 형태는 강조·조작 등 역할이 분명한 곳에 사용함. 컴포넌트마다
독립적인 곡률을 만들거나 모든 요소를 같은 곡률로 맞추지 않음.

버튼은 공통 글자·형태·상태 표현 체계 안에서 행동의 중요도와 의미에 따라
강조 수준을 구분함. 주요 행동은 브랜드 강조, 보조 행동은 약한 면·테두리 등으로
위계를 만듦. CTA와 확인·취소라는 이름만으로 서로 독립적인 시안을 만들지 않음.
확인 동작도 해당 맥락의 주요 행동이면 같은 주요 강조 원칙을 사용함.

영역 구분과 상호작용 강조는 배경·테두리 변화를 우선함. 그림자는 떠 있는 면 등
깊이가 필요한 경우에 사용함. 확대·색 발광은 일반 강조 수단으로 널리 사용하지
않고 목적이 분명한 경우에 제한함. 각 컴포넌트의 치수·곡률·그림자 수치를 모두
공통 지침으로 고정하지 않음.

## 공간 제약과 움직임

화면이 좁거나 문구가 길면 정보와 조작의 가독성을 우선함. 줄바꿈·재배치·영역
확장·필요한 스크롤로 대응하고 한 화면에 넣기 위해 글자·조작 영역을 무리하게
축소하지 않음. 요약 영역에서 말줄임을 사용하면 펼침·상세 이동 등 전체 내용을
확인할 경로를 둠. 한국어·영어의 길이 차이와 좁거나 낮은 화면도 함께 확인함.
화면 조건의 정의는 [React·UI](react-and-ui.md#스타일과-접근성)를 따름.

움직임은 상태 변화와 동작 결과를 이해시키는 짧은 전환을 기본으로 함. 장식적·
반복적 움직임은 제한하고, 필요한 진행 표시에는 움직임 감소 설정에서 의미를
유지하는 대체 표현을 제공함. 모든 컴포넌트의 전환 시간을 하나의 수치로
고정하지 않음.
16 changes: 14 additions & 2 deletions docs/conventions/react-and-ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ effect 밖에서도 호출해야 하는 콜백은 기존 함수·`useCallback`·

## 스타일과 접근성

새 UI는 기존 UI의 재사용 가능성을 먼저 확인하고,
[공통 디자인](design.md)에서 시각 역할·필요한 변형을 선택함. 구현 시 실제 CSS
정의와 사용처를 대조하고, 관련 상태·긴 번역 문구·화면 조건에서 결과를 확인함.
UI 책임과 재사용 범위는 [구조와 UI](../architecture/structure-and-ui.md),
검증 절차는 [테스트·Storybook](testing-and-storybook.md)을 따름.

Tailwind utility와 제한된 공통 CSS를 사용함. `className` 문자열이 100자를
초과하면 `UPPER_SNAKE_CASE` 상수로 분리함. `DT*` 아이콘은 해당 아이콘 컴포넌트
파일에서 직접 import함. 다른 아이콘의 export 방식은 규정하지 않음.
Expand All @@ -55,8 +61,14 @@ utility를 사용하며 일반 CSS 선택자를 참조하지 않음. 기존 `.bu
화면 조건은 `md` 768px 이상, `lg` 1280px 이상임. `xl`은 너비 1600px 이상이면서
높이 1024px 이상, `short`는 높이 500px 이하인 사용자 정의 variant임. 기본
breakpoint는 초기화하며 `sm` 등 다른 화면 조건을 자동으로 추가하지 않음.
프로젝트 색상과 사용 중인 기본 팔레트 색상은 v3 값을 유지함. 색상 추가 시
기존 디자인과의 호환 여부를 확인함.
기본 팔레트는 v3 호환 재정의 없이 Tailwind CSS 4의 내장값을 사용함. 브랜드·
진영색과 기존 UI가 소비하는 `default-*`·`semantic-*` 사용자 정의 색상은
`src/index.css`에 남아 있음. 색상의 의미별 사용 기준은
[공통 디자인](design.md#색상과-강조)이 소유하며, 기존 사용자 정의 색상을
전환할 때는 사용처를 함께 확인함. 새 글자 역할은
[역할별 타이포그래피](design.md#타이포그래피)의 `text-ui-*`를 사용하며, 기존의
크기 전용 글자 스타일 선택자와 구분함. 사양과 소스의 동기화는
[사용과 사양 동기화](design.md#사용과-사양-동기화)를 따름.

클래스 정렬은 `.prettierrc`의 `prettier-plugin-tailwindcss`가 담당함.
`tailwindStylesheet`는 `./src/index.css`, `tailwindFunctions`는 `['clsx']`임.
Expand Down
14 changes: 7 additions & 7 deletions src/components/DesignSystemSample/DesignSystemSample.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@ const ColorItem = ({ className, title }: ColorItemProps) => {
const DesignSystemSample = () => (
<div className="flex w-fit flex-col space-y-4 p-4">
<section className="flex flex-col items-start space-y-4 p-4">
<h1 className="text-title rounded-xl bg-brand p-4">Typography</h1>
<h1 className="rounded-xl bg-brand p-4 text-ui-title">Typography</h1>

<p className="text-display">대제목</p>
<p className="text-title">제목</p>
<p className="text-subtitle">부제목</p>
<p className="text-detail">세부사항</p>
<p className="text-body">내용</p>
<p className="text-ui-headline">Headline · 화면의 대표 제목</p>
<p className="text-ui-title">Title · 구역·내용 묶음의 제목</p>
<p className="text-ui-body">Body · 본문</p>
<p className="text-ui-label">Label · 짧은 조작·항목 이름</p>
<p className="text-ui-caption">Caption · 보조 설명</p>
</section>

<section className="flex flex-col items-start space-y-4 p-4">
<h1 className="text-title rounded-xl bg-brand p-4">Colors</h1>
<h1 className="rounded-xl bg-brand p-4 text-ui-title">Colors</h1>
<ColorItem className={'bg-team-blue'} title="찬성" />
<ColorItem className={'bg-team-red'} title="반대" />
<ColorItem className={'bg-brand'} title="브랜드" />
Expand Down
Loading
Loading