개발 노트/프론트엔드

리액트 시작하기

Roslyn 2026. 7. 5. 20:32
반응형

React / TypeScript 프로젝트 코딩 규칙 가이드
본 문서는 프로젝트의 일관된 아키텍처와 유지보수성 향상을 위한 작업 규칙 정의서입니다. 새로운 기능을 추가할 때는 아래 구조와 규칙을 반드시 준수하며, 기존 파일의 지역 관례를 최우선으로 적용합니다.

1. 프로젝트 구조 (Directory Architecture)
역할 중심의 디렉터리 분리를 통해 스파게티 코드를 방지하고, 특정 도메인 로직과 UI 컴포넌트의 결합도를 낮춥니다.

경로 (Path) 역할 및 준수 사항 src/main.tsx 애플리케이션의 진입점입니다. 전역 CSS, i18n, 인증 Provider, React Query Provider 등 시스템 전역에 영향을 주는 컨텍스트 및 환경 설정만 배치합니다. src/App.tsx 전체 라우터 구성을 담당합니다. 라우트 볼륨이 확장될 경우 public, admin, auth 등 도메인 단위 하위 라우트 파일로 분리하여 관리합니다. src/pages/ URL 라우팅 엔드포인트와 1:1로 대응되는 화면 컴포넌트 공간입니다. 영역별 식별을 위해 admin, writing, projects 같은 기능 단위 하위 디렉터리를 유지합니다. src/components/ 여러 화면에서 전역/공용으로 재사용되는 컴포넌트들의 집합입니다.

components/ui/: shadcn/Radix 기반의 원자형(Atomic) UI 요소. (Fast Refresh 독립성 유지 필수)

components/{admin, layout, common, brand}/: 성격과 쓰임새에 맞게 분류된 공용 컴포넌트.

src/hooks/ React Query 커스텀 훅, 전역 인증 상태, 화면 간 공유가 필요한 공통 상태 인터페이스를 격리합니다. 이 역시 admin, public 등으로 사용 경계를 명확히 분리합니다. src/services/ 순수 비동기 데이터 통신(API Request) 함수들만 선언합니다. React 훅, 상태(state), DOM 의존성 관련 코드가 절대 포함되어서는 안 됩니다. src/types/ 서버 스키마 기반의 API 데이터 모델 및 도메인 전역 타입을 집중 관리합니다. 특정 단일 페이지 내에서만 단발성으로 쓰이는 임시 타입은 예외적으로 해당 파일 내부에 정의할 수 있습니다. src/lib/ 도메인 비즈니스 데이터 가공, 상태별 텍스트 라벨 매핑, 복잡한 JSON 데이터 정규화처럼 React 렌더링 시스템 라이프사이클과 독립적인 코어를 구축합니다. src/utils/ 포맷팅, 안전한 JSON 파싱 등 프로젝트 도메인에 구애받지 않는 글로벌 범용 유틸리티 함수들을 정의합니다. src/config/ 환경 변수 접근자 관리, 고정된 인증 엔드포인트 경로 설정, OIDC 클라이언트 세팅 등 시스템 정적 데이터 구조를 배치합니다.

2. 모듈 가져오기 (Import Rules)
▪ 경로 깊이에 상관없이 복잡한 상대 경로 연산을 방지하기 위해 @/* 경로 별칭(Alias)을 기본 참조합니다.

↳ 예시: import { fetchBoard } from '@/services/boardApi';

▪ 제한적 상대 경로: 동일 디렉터리 내에 물리적으로 인접해 있는 매우 긴밀한 파트너 파일(예: 가드 컴포넌트, 전용 아이콘 세트)에 한해서만 ./ 상대 경로 가독성을 인정합니다.

▪ 타입 컴파일 최적화 및 런타임 번들 크기 경량화를 위해 Type Definition 임포트 시 반드시 import type 구문을 활용합니다.

▪ 모듈의 일관성을 위해 상단 코드 정렬 시 1. 외부 Core 라이브러리 → 2. 프로젝트 에일리어스 모듈(@/*) → 3. 정적 타입 파일 계층 구조 순으로 일목요연하게 배치합니다.

3. 컴포넌트 선언 및 클린 코드 (Component Rules)
📌 렌더러 분리와 Fast Refresh 오류 방지
개발자 경험(DX) 향상을 위해 컴포넌트 파일 내에서 컴포넌트 본체 외에 다른 외부용 정적 상수나 스타일 배리언트 헬퍼 함수를 혼재하여 export 하는 구조를 전면 금지합니다.

핫 리로딩 도중 Fast Refresh 기능이 오작동하면, 지체 없이 관련 소스코드를 구조 분리하여 *-variants.ts, *.constants.ts, *.utils.ts 형태의 정적 모듈로 격리 배출하십시오.

📌 가독성이 확보된 JSX 환경 조성
마크업 가독성을 심각하게 훼손하는 복잡도가 높은 중첩 삼항 연산자, 거대한 인라인 맵 필터링 스크립트, 원시 데이터 포맷팅 정규식 구문을 JSX 식 내부에 직렬로 나열하는 행위를 절대 금지합니다. 렌더 블록 진입 직전, 명시적인 상단 지역 상수 변수(Memoized Variable)나 별도의 순수 헬퍼 함수로 결과물을 완전히 추출·선언한 후 컴포넌트 스코프 아래에는 정제된 기호 객체만 전달하십시오.

❌ BAD PRACTICE

return (
  

    {data?.items ? data.items
      .filter(i => i.status === 'ACTIVE')
      .map(i => {i.name.toUpperCase()})
      : '데이터가 존재하지 않습니다.'}
  

);
⭕ GOOD PRACTICE

const activeItems = useMemo(() => {
  if (!data?.items) return [];
  return data.items.filter(i => i.status === 'ACTIVE');
}, [data?.items]);

if (activeItems.length === 0) {
  return 
데이터가 존재하지 않습니다.
;
}

return (
  

    {activeItems.map(item => (
      {item.name.toUpperCase()}
    ))}
  

);
4. 데이터 상태 동기화 (Data Fetching & State)
외부 원격 서버 상태 제어는 예외 없이 전량 @tanstack/react-query의 생태계 기법에 전적으로 의존합니다.

데이터 가공 흐름 구조 준수: API 원시 비동기 통신 코드는 services/ 내부에 완전히 캡슐화 처리하고, 리액트 전용 라이프사이클 엔진에 편입시키는 React Query 어댑터 처리는 hooks/ 내의 단독 커스텀 훅으로 은닉 설계합니다.

Query Key 네임스페이스 규칙: 캐싱 무효화 범위를 명확화하기 위해 Query Key는 항상 데이터 레이어의 최상위 도메인 지칭 단어부터 유기적으로 시작되어야 합니다.
예시: ['admin', 'boards', masterCode] / ['public', 'boardContents', masterCode]

Mutation 후속 무효화 처리: 데이터의 생성, 수정, 삭제 작업을 수반하는 무테이션 행위 성공 완료 시에는, 사이드 이펙트에 연루되는 관계 관측 대상 대상 Query Key 목록 구조를 향해 명시적인 invalidateQueries 처리를 즉각 실행시켜 UI 불일치 현상을 원천적으로 차단합니다.

의존성 안정화 프로토콜: 렌더 레이어에서 무한 루프 렌더링 부작용 유발을 예방하기 위해, useMemo 혹은 useCallback의 디펜던시 어레이 내부에 data?.items ?? []처럼 매 평가 주기마다 메모리 힙 상에 새로운 원시 주소 배열을 인스턴스화하는 fallback 구문을 직접 대입하는 파괴적 행위를 엄금합니다. 반드시 아래의 가이드라인에 따라 전처리 단계를 분리하여 컴포넌트 객체의 참조 무결성을 영속화하십시오.

// ❌ BAD - 매 렌더링마다 생성된 빈 배열 주소가 들어가 불필요한 이펙트 폭발useEffect(() => { ... }, [data?.items ?? []]); // ⭕ GOOD - 상단에서 참조 메모리 포인터를 확고하게 계층 잠금 정형화const stableItems = useMemo(() => data?.items ?? [], [data?.items]);useEffect(() => { ... }, [stableItems]);

5. 엔드포인트 바인딩 및 타입 시스템 (API & Types)
▪ 모든 비동기 API 통신 서비스 함수는 결과값 추적성 확보 및 예기치 못한 에러 추적을 보조하기 위하여 Promise 형태로 명확한 시그니처 타입을 반환 설계하는 작업이 핵심 요건입니다.

▪ API 응답 스키마 정적 Normalization: 연동 레거시 백엔드 파트너 서버 간 데이터 필드 키 네이밍이 규칙성 없이 동적으로 변형 발생되는 경우에는, 컨트롤러 services/나 비즈니스 가공단 lib/ 계층에서 최초 진입 시 즉시 정규화 처리기를 관통시켜 변환 구조를 고정한 뒤 뷰 화면 내부에서는 철저하게 약속된 통합 가공 타입 규격으로만 데이터 처리를 전개하십시오.

▪ RESTful URL 스펙 라우팅 주소 연산 시 특수문자나 공백 문자로 인한 라우팅 세그먼트 폭파 결함을 예방하기 위하여, 변수가 매핑되는 경로 매개변수 오브젝트는 빠짐없이 encodeURIComponent() 래퍼 인코딩 처리를 거친 후 안전하게 연결합니다.

▪ 원천적인 any 타협 타파: 컴파일러의 실시간 모니터링 경고 추적 기능 무력화를 예방하기 위하여 코드 작성 시 어떠한 상황에서도 와일드카드 타입 any 선언을 허용하지 않습니다. 구조를 알 수 없는 유동적 데이터일 경우 차라리 unknown 타입을 배정하고, 비즈니스 판정 함수인 유틸 전용 Type Guard 메커니즘을 정의 및 분기 통과시켜 다루는 안정성을 실현하십시오.

6. 스타일링 통합 및 웹 인터페이스 준수 (Styling & A11y)
레거시 마이그레이션 도중 산입되어 남아있는 기존 특수 유효 클래스(rd-* 전역 선택자 무리)나 임시 인라인 스타일 시트 구문은 순차적으로 해체합니다. 신규 개발 컴포넌트는 오직 Tailwind CSS 프레임워크 표준 클래스 명세만을 응용해 통합 가속 스타일링 작업을 완성하는 편성을 수립합니다.

동일한 레이아웃 테두리 내부에서 시스템 간 미시적인 디자인 시각 언어가 훼손·분열되지 않도록 정형화된 공용 단추 폼, 인디케이터 배지, 컴보 셀렉트 박스, 토스트 레이어는 자의적인 하드코딩 작업을 원천 배제한 채, 사전에 기획 내장되어 설계된 components/ui 또는 components/admin 하위 에셋 컴포넌트를 무조건 최우선 수용 탐색하여 배치합니다.

♿ 시각 접근성 및 마킹 최소 표준 의무화

인터랙션이 부과되는 마크업 태그 파트에는 고유 속성 타입과 스크린 리더 음성 해설 마크를 누락 없이 바인딩 선언하십시오.

✨ 이번 릴리즈 주요 리팩터링 및 보완 내역
✓ components/ui/button.tsx 및 badge.tsx 내에 내장되어 있던 Tailwind CVA Variant 스타일 유틸 변수 선언 구조를 외부 독립 소스 코드 파일로 완벽하게 전격 격리 분리해 냄으로써 컴포넌트 본체의 순수한 뷰 렌더 결합성과 단독 모듈 진위성(Fast Refresh 안정성 보장)을 성취했습니다.

✓ 서버 원격 통신 데이터 수신 지점의 배열 fallback 핸들링 로직을 전량 고차 useMemo 스코프로 안전하게 가두어 계층 제어화함으로써, 매 리렌더링마다 예기치 않게 힙 주소가 재할당되며 React Hook Dependency 체인을 연쇄 폭발시키던 불필요한 퍼포먼스 결함 요소를 안정적으로 진압 완료했습니다.

✓ 게시글 모델 전산화 파싱 로직 구문 내에서 불필요하게 가독성을 저해하던 선행 초기 미사용 인스턴스 데이터 대입문 구조를 면밀하게 완전 소거 정형화함으로써 뷰 프레임워크 런타임 내의 불필요한 메모리 파편 상수를 극소화했습니다.

리액트
시작하기

반응형