본문으로 건너뛰기

코드 표준

Elftia는 점진적 적용 전략과 함께 엄격한 ESLint 구성(typescript-eslint/strict)을 사용합니다.


도구 체인

도구목적구성 파일
ESLint코드 품질 검사(strict 모드)eslint.config.js
Prettier코드 형식 지정.prettierrc
HuskyGit Hooks 관리.husky/pre-commit
lint-staged스테이징된 파일 검사package.json

일반 명령

# Run ESLint checks
npm run lint:eslint

# Check Prettier formatting
npm run lint:prettier

# Auto-format code
npm run format

# Complete lint check (ESLint + TypeScript)
npm run lint

# Check a single file
npx eslint path/to/file.ts

# Auto-fix a single file
npx eslint path/to/file.ts --fix

Pre-Commit 자동 검사

코드를 커밋할 때 Husky는 스테이징된 .ts/.tsx 파일에 대해 eslint --fixlint-staged를 자동 실행합니다.

  • error 수준: 커밋을 차단하며 반드시 수정해야 합니다
  • warn 수준: 경고를 표시하지만 커밋은 허용합니다
  • auto-fix: import 정렬처럼 자동 수정 가능한 문제를 자동으로 수정합니다

ESLint 규칙 빠른 참조

심각도 수준

수준의미커밋 동작
error반드시 수정커밋 차단
warn수정 권장커밋 허용
off비활성화-

Error 수준 규칙(커밋 차단)

// simple-import-sort/imports — Auto-fixable
// Imports must be ordered as specified, eslint --fix will auto-fix

// prefer-const
let value = 1; // Never reassigned, should use const

// no-var
var x = 1; // var usage is prohibited

// eqeqeq
if (a == b) { } // Use == instead of === (except for null checks)

// react-hooks/rules-of-hooks
if (condition) { useState(); } // Hooks can only be called at top level

Warn 수준 규칙(커밋 허용)

TypeScript 규칙

규칙설명수정 방법
@typescript-eslint/no-unused-vars사용하지 않는 변수삭제하거나 _ 접두사를 붙입니다
@typescript-eslint/no-explicit-anyany 타입 사용구체적인 타입이나 unknown으로 변경합니다
@typescript-eslint/consistent-type-imports타입 전용이 아닌 importsimport { type Foo }로 변경합니다
@typescript-eslint/no-non-null-assertionNon-null assertion !Optional chaining ?. 또는 type guard를 사용합니다

React 규칙

규칙설명수정 방법
react-hooks/exhaustive-deps불완전한 Hook 의존성의존성 배열을 완성합니다
react/jsx-no-leaked-render누출된 렌더링(count && <X />)count > 0 && <X />로 변경합니다
react/self-closing-comp빈 태그가 self-close되지 않음<Comp></Comp><Comp />
react/jsx-curly-brace-presence불필요한 중괄호prop={"val"}prop="val"
react/jsx-boolean-value중복된 boolean 값disabled={true}disabled
react/hook-use-stateState 이름이 camelCase가 아님[Value, setV][value, setV]

기타 규칙

규칙설명수정 방법
no-consoleRenderer 프로세스에서 console.log 사용console.warn/error/info/debug로 변경합니다
jsx-a11y/*접근성 문제Design System을 참조하세요

Import 정렬 규칙

Imports는 다음 순서로 정렬해야 합니다(eslint --fix로 자동 수정 가능).

// 1. Node.js built-in modules
import path from 'node:path';
import fs from 'node:fs';

// 2. External packages
import React, { useState } from 'react';
import { useQuery } from '@tanstack/react-query';

// 3. Internal alias @/
import { Button } from '@/components/ui/button';
import { useAppState } from '@/shared/hooks/useAppState';

// 4. @shared/ alias
import type { Message } from '@shared/contracts';

// 5. @main/ alias
import { AppPaths } from '@main/services/infra/paths/paths';

// 6. Parent directory imports
import { utils } from '../utils';

// 7. Same directory imports
import { helper } from './helper';

// 8. Style imports
import './styles.css';

Prettier 구성

옵션설명
semitrue세미콜론 사용
singleQuotetrue작은따옴표 사용
tabWidth2들여쓰기 너비
trailingComma'es5'후행 쉼표
printWidth100줄 너비 제한

파일 크기 제한

황금 규칙: 단일 파일은 코드 600줄을 초과하지 않아야 합니다.

파일 유형권장 제한경고 줄 수하드 제한
React 컴포넌트400줄600줄800줄
Custom Hook300줄400줄600줄
유틸리티/헬퍼 함수150줄200줄300줄
타입 정의100줄150줄200줄
Service/API300줄400줄600줄

결과:

  • 경고 줄 수 초과 → 현재 작업에서 반드시 분리하고 미루지 마세요
  • 하드 제한 초과 → 즉시 중단하고 먼저 리팩터링한 뒤 계속하세요

명명 규칙

파일 명명

유형규칙예시
React 컴포넌트PascalCase.tsxUserMessage.tsx
Hooksuse + PascalCase.tsuseChatActions.ts
유틸리티 함수camelCase.tsmessageHelpers.ts
타입 정의camelCase.ts 또는 types.tschatTypes.ts
상수UPPER_CASE.tsAPI_CONSTANTS.ts
ServicesPascalCase + Service.tsChatService.ts
디렉터리kebab-casechat-messages/

컴포넌트 명명

// Good: Clear and descriptive
export function UserMessage() { }
export function EditTool() { }
export function ChatComposer() { }

// Bad: Too generic
export function Message() { }
export function Tool() { }
export function Input() { }

Hook 명명

// Good: use + feature description
export function useChatActions() { }
export function useMessageEffects() { }

// Bad: Does not follow React Hook naming convention
export function chatActions() { }
export function messageHook() { }

디렉터리 구조 표준

컴포넌트 디렉터리

components/
├── ComponentName/
│ ├── index.ts # Unified export
│ ├── ComponentName.tsx # Main component
│ ├── types.ts # Type definitions
│ ├── utils.ts # Utility functions
│ ├── SubComponent.tsx # Sub-component
│ └── __tests__/
│ └── ComponentName.test.tsx

Hooks 디렉터리

hooks/
├── domain/
│ ├── index.ts # Unified export
│ ├── useDomainState.ts # State
│ ├── useDomainActions.ts # Actions
│ └── useDomainEffects.ts # Side effects

Services 디렉터리

services/
├── ServiceName/
│ ├── index.ts # Unified export
│ ├── ServiceName.ts # Main service
│ ├── types.ts # Type definitions
│ └── subdomain/ # Sub-domain

TypeScript 모범 사례

타입 Imports

// Use type-only imports
import { type SomeType } from './types';
import type { AnotherType } from '@shared/contracts';

any 피하기

// Bad
function handle(data: any) { }

// Good: Use specific types
function handle(data: Message) { }

// Good: Use generics
function handle<T extends BaseMessage>(data: T) { }

// Good: Use unknown + type guard
function handle(data: unknown) {
if (isMessage(data)) { /* data: Message */ }
}

Barrel Export

// components/chat/messages/index.ts
export { MessageItem } from './MessageItem';
export { MessageList } from './MessageList';
export type { MessageItemProps } from './MessageItem';

코드 구성 순서

React 컴포넌트 구조

// 1. Imports
// 2. Type definitions
// 3. Constants
// 4. Helper functions
// 5. Main component
// 5.1 Hooks
// 5.2 Derived state (useMemo)
// 5.3 Event handlers (useCallback)
// 5.4 Effects (useEffect)
// 5.5 Render (return)
// 6. Sub-components (if simple)

단일 책임 원칙

각 파일은 변경되어야 할 이유가 하나뿐이어야 합니다. 컴포넌트는 다음과 같은 경우 분리해야 합니다.

  1. 코드가 300줄을 초과합니다
  2. 독립적인 로직 블록이 3개 이상 포함되어 있습니다
  3. 재사용 가능한 부분이 있습니다
  4. 서로 다른 부분의 변경 빈도가 다릅니다
  5. 테스트가 어려워집니다

분리 전략:

전략사용 시점예시
기능별 분리UI 블록이 독립적일 때Toolbar / Message list / Input box → 별도 컴포넌트
데이터 흐름별 분리복잡한 상태 로직State / Actions / Side effects → 별도 Hooks
도메인별 분리유사한 항목이 여러 개일 때EditTool / WriteTool / BashTool → 별도 파일

Git 워크플로

커밋 규칙

Conventional Commits 형식을 사용하세요.

feat: New feature description
fix: Bug fix description
refactor: Refactoring description
docs: Documentation update
style: Code formatting changes (no logic changes)
test: Test-related changes
chore: Build tool or auxiliary tool changes

Pre-Commit 체크리스트

  1. npm run lint 실행 — 오류가 없는지 확인합니다
  2. 모든 error 수준 문제를 수정합니다
  3. 가능한 경우 warn 수준 문제를 수정합니다
  4. npm run format 실행 — 코드를 형식 지정합니다
  5. 새 파일은 warning이 0개여야 합니다
  6. 기존 파일을 수정할 때는 해당 파일의 warning도 함께 수정합니다