Skip to content

코딩 컨벤션

dictionary-app이 실제로 지키는 코딩 컨벤션이다. Prettier/oxlint가 자동으로 강제하는 규칙과, 코드 작성·리뷰 시 직접 신경 써야 하는 규칙을 구분한다.

.prettierrc.cjs
module.exports = {
bracketSpacing: false,
singleQuote: true,
trailingComma: 'all',
arrowParens: 'always',
semi: false,
printWidth: 90,
tabWidth: 2,
useTabs: false,
endOfLine: 'lf',
}

세미콜론 없음, 싱글쿼트, trailing comma, printWidth 90 — pre-commit 훅의 lint-staged가 스테이징된 파일에 자동 적용한다(자세한 내용은 깃훅 가이드 참고).

.oxlintrc.json
{
"rules": {
"no-debugger": "error",
"no-var": "error",
"eqeqeq": "error",
"dot-notation": "error",
"react/rules-of-hooks": "error",
"react/exhaustive-deps": "error",
"react/only-export-components": "warn",
"typescript/no-unused-expressions": ["error", {"allowShortCircuit": true}]
}
}
  1. no-var/eqeqeq/dot-notation처럼 흔한 JS 실수를 막는 규칙과, react/rules-of-hooks/ react/exhaustive-deps처럼 훅 오용을 막는 React 전용 규칙을 함께 쓴다.
  2. pnpm lint로 직접 실행하거나, pre-commit 훅의 lint-staged(oxlint --fix)가 스테이징된 .ts/.tsx 파일에 자동 적용한다.

컴포넌트/함수 작성 규칙 (도구가 강제하지 않음, 직접 신경 써야 함)

Section titled “컴포넌트/함수 작성 규칙 (도구가 강제하지 않음, 직접 신경 써야 함)”
  1. function 대신 화살표 연산자를 사용한다.
  2. 이름 붙여 정의하는 함수(export const/const)는 한 줄로 표현 가능해도 암묵적 반환(=> expr) 대신 중괄호 + return을 쓴다.
    // ❌
    export const isNull = <T,>(value: T) => value === null
    // ✅
    export const isNull = <T,>(value: T) => {
    return value === null
    }
    나중에 조건 분기나 로그 한 줄이 추가돼도 화살표 스타일을 바꿀 필요가 없다. 배열 메소드 등에 즉석으로 넘기는 짧은 인라인 콜백(.map((i) => i))에는 적용하지 않는다 — 이름 붙여 정의하는 함수에 한정된 규칙이다.
  3. use client 구문은 사용하지 않는다.
  4. 모델을 알 수 있거나 제너릭을 쓸 수 있는 경우 제너릭을 적극 활용한다.
  5. 컴포넌트 이름은 파스칼 케이스, 확장자는 .tsx(HTML을 반환하지 않으면 .ts 허용)로 하고, 파일명은 컴포넌트 이름과 동일하게 짓는다.
  6. export default를 쓰지 않는다 — 컴포넌트/함수 정의 시 이름 왼쪽에 export를 붙여, 임포트할 때 뭉쳐서 쓸 수 있게 한다.
  7. 프롭으로 주입하는 이벤트 핸들러 이름은 handle 접두사를 쓴다 — onClick이 아니라 handleClick.
  8. 이벤트 핸들러는 JSX에 인라인 화살표 함수(onClick={() => ...})로 쓰지 않고, 컴포넌트 함수 바디에 handleClick 같은 이름의 함수로 분리한 뒤 참조한다. 리스트 렌더링처럼 인자를 즉시 바인딩해야 하는 경우에도 로직 자체는 이름 붙은 핸들러에 두고, JSX에서는 onClick={() => handleSelect(item.id)}처럼 인자만 넘기는 최소한의 래핑만 허용한다.