StackUp νλ‘ νΈμλμ TypeScript νμ κ·μ½. νμ μ μ¬μ©λλ λ μ΄μ΄μ μ°λ€. μ΄λ¦μ μ λ―Έμ¬κ° μ± μ κ²½κ³λ₯Ό μ μΈνλ€.
μμ 컨ν μ€νΈ β coding-conventions.md (μΈμ΄ κ³΅ν΅ κ·μ½),
frontend/CLAUDE.md(FSD ꡬ쑰) μ μ© λ²μ βfrontend/src/
- μμΉ
- μ λ―Έμ¬ β λ μ΄μ΄ λ§€νΈλ¦μ€
- λ μ΄μ΄λ³ νμ νλ¦
typevsinterface- μ μ μμΉ
- shared μΉκ²© μκ³
- μν°ν¨ν΄
- PascalCase + μλ―Έ μλ μ λ―Έμ¬. μ λ―Έμ¬κ° νμ μ μ± μΒ·λ μ΄μ΄λ₯Ό μ κ³ νλ€.
I/THungarian prefix κΈμ§ β TypeScript μ»΄νμΌλ¬κ°type/interfaceλ₯Ό μΆ©λΆν ꡬλΆνλ€.- λ¨λ°©ν₯ νλ¦:
Dto β Entity β Model β Props. μλ°©ν₯ import κΈμ§. - μ μ
types/ν΄λ κΈμ§. μ¬λΌμ΄μ€ λ΄λΆμμ μμ, μ§μ§ 곡μ λ λλ§ λμ΄μ¬λ¦°λ€.
| μ λ―Έμ¬ | λ μ΄μ΄ | μ± μ | μ |
|---|---|---|---|
XxxDto |
shared/api/ (OpenAPI μλ μμ±) |
λ°±μλ wire format μ€λ μ·. μμ κΈμ§ | SessionDto, UserDto |
XxxRequest / XxxPayload |
API νΈμΆλΆ, μ΄λ²€νΈ publisher | HTTP μμ² body, RabbitMQ λ©μμ§ payload | CreateSessionRequest, ResumeAnalyzedPayload |
XxxResponse |
API νΈμΆλΆ | HTTP μλ΅ raw shape (μλ μ μ μ) β ν¨μ λ°νμ μ¬μ© β | LoginResponse |
Xxx (μ λ―Έμ¬ μμ) |
domain/{slice}/model/ |
λΉμ¦λμ€ μν°ν°. Dtoμμ λ§€νλ¨ | User, Session, Resume |
XxxResult |
λλ©μΈ / μ μ¦μΌμ΄μ€ ν¨μ λ°ν | λΉμ¦λμ€ λ‘μ§ μΆλ ₯ (HTTP λΉμ’ μ) | AnalysisResult, ValidationResult |
XxxModel |
features/*/ui/, widgets/*/ui/ |
UI νμ μ μ© κ°κ³΅ λ°μ΄ν° | SessionListItemModel, ServiceCardModel |
XxxProps |
μ»΄ν¬λνΈ μ | React props | ButtonProps, HomeHeroProps |
XxxState |
store / state machine | λͺ
μμ μν λͺ¨λΈ. λ¨λ° useState shape μ μ¬μ© β |
AuthState, SessionMachineState |
XxxOptions |
ν¨μΒ·ν μ€μ | μ΅μ λ μΈμ λ¬Άμ | UseTypewriterOptions |
XxxId |
μ΄λλ | branded identifier | type SessionId = number & { readonly __brand: 'SessionId' } |
[Backend OpenAPI]
β openapi-typescript μλ μμ±
βΌ
shared/api/generated.ts ββ XxxDto
β λ§€νΌ ν¨μ (toUser, toSession)
βΌ
domain/{slice}/model/ ββ Xxx (Entity)
β feature / widget μμ UI κ°κ³΅
βΌ
features|widgets/*/ui/ ββ XxxModel
β props λ‘ μ£Όμ
βΌ
React Component ββ XxxProps
κ²½κ³ κ·μΉ:
XxxDtoλshared/api/λ°μΌλ‘ μμ§ μλλ€. UI Β· λλ©μΈμ΄ Dto λ₯Ό μ§μ import νλ©΄ anti-corruption layer κ° λ¬΄λμ§λ€.Xxx(Entity) λdomain/μ΄ μμ . features / widgets λ read-only λ‘ μ°Έμ‘°νλ€.XxxModelμ μ¬λΌμ΄μ€ λ΄λΆμ λ¨Έλ¬Έλ€. λ€λ₯Έ μ¬λΌμ΄μ€λ‘ export νμ§ μλλ€ β UI νμ ννκ° λμλλ©΄ λ³κ²½ λΉμ©μ΄ νμ¦νλ€.
type κΈ°λ³Έκ°. interface λ λ κ²½μ°μλ§:
- ν΄λμ€κ°
implementsν λ (ErrorBoundaryλ±) - declaration merging νμ μ (μΈλΆ λΌμ΄λΈλ¬λ¦¬ augmentation)
// μ’μ
type SessionStatus = 'READY' | 'IN_PROGRESS' | 'COMPLETED';
type CreateSessionRequest = { userId: UserId; mode: SessionMode };
type AnalysisResult = { score: number; suggestions: string[] };
// μ’μ β implements κ° νμν μΌμ΄μ€
interface ErrorBoundaryProps { children: ReactNode; fallback: ReactNode }
class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> { ... }| 무μ | μ΄λ |
|---|---|
| μ»΄ν¬λνΈ props (λ¨μΌ μ¬μ©) | {Component}.tsx μλ¨, export μ ν¨ |
| μΈλΆμμλ import λλ props | {Component}.types.ts |
| λλ©μΈ μν°ν° | domain/{slice}/model/types.ts |
μ¬λΌμ΄μ€ λ΄ XxxModel |
features/{slice}/model/types.ts λλ ui/ λ΄λΆ |
API XxxDto |
shared/api/generated.ts (OpenAPI μ¬μμ±μΌλ‘λ§ κ°±μ ) |
μ μ src/types/ ν΄λλ λ§λ€μ§ μλλ€. μ¬λΌμ΄μ€ λ΄λΆμμ μμνκ³ , μ§μ§ 곡μ λ λλ§ λμ΄μ¬λ¦°λ€.
νμ
μ shared/ λ‘ μ¬λ¦¬λ μμ μ μλ‘ λ€λ₯Έ μ¬λΌμ΄μ€ 3κ³³ μ΄μμμ λμΌν shape μ΄ λ°λ³΅λ λ. κ·Έ μ μ μ¬λΌμ΄μ€ μμ μ°λ€.
"μΈμ κ° μΈμ§λ λͺ¨λ₯΄λ 미리 shared λ‘" λ νμ μλͺ»λ μΆμνλ‘ λλλ€.
- β
XxxResponseλ₯Ό ν¨μ λ°ν νμ μΌλ‘ μ¬μ© βXxxResultλ‘. - β UI μ»΄ν¬λνΈκ°
SessionDtoλ₯Ό props λ‘ λ°μ βSessionListItemModelλ‘ λ§€ν. - β λ‘컬
useState<{ ... }>shape μXxxStateμ΄λ¦ λΆμ΄κ³ export. - β
export type Props = { ... }κ°μ generic export β{Component}Propsλ‘. - β
src/types/λλsrc/shared/types/μ μ ν΄λ (junk drawer ν). - β
IXxx,TXxxHungarian prefix. - β
Dtoκ°features//widgets//domain/μμ import λλ κ²½μ° β boundary μλ°.