0Pricing
Frontend Academy · 강의

기능 기반 폴더 구조

타입이 아니라 기능 영역을 기준으로 코드를 구성하고, 테스트·스타일·컴포넌트를 함께 배치하며, eslint-plugin-boundaries로 경계를 강제합니다.

기능 기반 폴더 구조은(는) CoddyKit의 무료 Frontend Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Frontend Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Frontend Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

코드를 구성하는 두 가지 방법

코드를 유형별로(components/, hooks/, services/, types/) 그룹화하거나 기능별로(auth/, checkout/, dashboard/ — 각 폴더에 자체 components, hooks 등을 포함) 그룹화할 수 있습니다. 중간 규모 이상의 앱에서는 기능별 구성이 더 효과적입니다.

유형별 구성 — 흔한 기본 함정

전형적인 React 튜토리얼 구조는 모든 코드를 유형별로 그룹화합니다. 이 방식은 규모가 커질수록 관리하기 어렵습니다. 파일을 하나 변경할 때마다 서로 관련 없는 여러 폴더를 건드리게 되고, 'checkout 코드를 모두 찾아보기'도 전체 트리에서 검색해야 하기 때문입니다.

// Type-based (avoid for large apps):
src/
  components/
    Button.tsx
    LoginForm.tsx
    CartItem.tsx
  hooks/
    useAuth.ts
    useCart.ts
  services/
    auth.ts
    cart.ts
  types/
    User.ts
    CartItem.ts

기능별 구조

기능과 관련된 모든 것을 하나의 폴더에 그룹화합니다. 찾기 쉽고, 삭제하기 쉽고, 구조를 파악하기 쉽습니다.

src/
  features/
    auth/
      LoginForm.tsx
      SignupForm.tsx
      useAuth.ts
      auth.service.ts
      auth.types.ts
      auth.test.tsx
    cart/
      CartItem.tsx
      CartSummary.tsx
      useCart.ts
      cart.service.ts
      cart.types.ts
  shared/
    components/
      Button.tsx
    hooks/
      useDebounce.ts

기능 내부의 공동 배치

기능 폴더에는 해당 도메인에 필요한 모든 코드인 components, hooks, services, types, tests가 들어갑니다. 새로운 개발자가 auth를 이해하려면 auth/를 열면 됩니다. auth를 삭제하려면 해당 폴더를 삭제하면 됩니다.

공유 코드와 기능별 코드

2개 이상의 기능에서 사용하는 코드는 shared/(또는 lib/)로 옮깁니다. 한 기능에서만 사용하는 코드는 해당 기능 안에 둡니다. '나중에 재사용할 수도 있다'는 생각에 섣불리 추출하지 마십시오. 두 번째 사용처가 생길 때까지 기다리십시오.

기능 경계 규칙

기능끼리는 서로 직접 가져와 사용하지 않아야 합니다. 두 기능이 코드를 공유해야 한다면 공유 코드를 shared/로 옮깁니다. 서로 조율해야 한다면 앱 수준의 이벤트나 공유 저장소를 사용합니다.

ESLint로 경계 적용하기

eslint-plugin-boundaries 또는 eslint-plugin-import를 사용하여 기능은 shared에서 가져올 수 있지만 서로 다른 기능에서는 가져올 수 없도록 강제합니다.

// .eslintrc.json
{
  "plugins": ["boundaries"],
  "settings": {
    "boundaries/elements": [
      { "type": "feature", "pattern": "src/features/*" },
      { "type": "shared",  "pattern": "src/shared/*" }
    ]
  },
  "rules": {
    "boundaries/element-types": ["error", {
      "default": "disallow",
      "rules": [
        { "from": "feature", "allow": ["shared"] },
        { "from": "shared",  "allow": ["shared"] }
      ]
    }]
  }
}

기능별 공개 API

각 기능은 features/auth/index.ts를 통해 공개 API를 내보냅니다. 다른 코드는 깊은 경로가 아니라 '@/features/auth'에서 가져옵니다. 이렇게 하면 사용하는 쪽을 변경하지 않고 내부 구현을 리팩터링할 수 있습니다.

// features/auth/index.ts
export { LoginForm } from './LoginForm';
export { useAuth } from './useAuth';
export type { User, AuthState } from './auth.types';

// Consumers:
import { LoginForm, useAuth } from '@/features/auth';
// NOT: import { LoginForm } from '@/features/auth/LoginForm';

하위 기능 중첩하기

규모가 큰 기능에는 하위 폴더를 둘 수 있습니다. 예를 들어 dashboard/widgets/, dashboard/charts/와 같이 구성합니다. 검색이 불편해지므로 2~3단계보다 깊게 중첩하지 마십시오.

경로가 위치하는 곳

페이지와 경로는 최상위 pages/ 또는 routes/ 폴더에 둘 수 있습니다. 이들은 얇은 계층으로, 기능에서 components와 hooks를 가져와 조합합니다.

src/
  pages/
    Dashboard.page.tsx   // composes Dashboard widgets from features/dashboard/
    Cart.page.tsx        // composes from features/cart/
  features/
  shared/

기존 앱 마이그레이션하기

새 기능부터 시작하여 새 코드를 features/에 넣으십시오. 모든 것을 한 번에 리팩터링하지 마십시오. 기존 파일을 수정할 일이 생길 때마다 점진적으로 옮기십시오. ESLint 경계 규칙을 사용하면 새 구조가 다시 무너지는 것을 막을 수 있습니다.

유형별 구성이 여전히 적합한 경우

매우 작은 앱(components가 30개 미만)이나 라이브러리에서는 유형별 구성이 적합합니다. auth, checkout, billing, settings처럼 서로 구분되는 비즈니스 도메인이 생기면 기능별 구성을 사용하십시오.

빠른 확인

파일 유형별 구성이 아니라 기능별로 코드를 그룹화할 때 얻는 가장 큰 조직상의 이점은 무엇입니까?

복습: 기능별 구조

features/에는 도메인별 코드가 들어가고, shared/에는 여러 기능에서 사용하는 유틸리티가 들어갑니다. 각 기능은 공개 index.ts를 내보냅니다. 기능은 서로 가져오지 않고 shared에서만 가져옵니다. eslint-plugin-boundaries로 이를 강제합니다. 페이지와 경로는 기능을 조합합니다. 점진적으로 마이그레이션하십시오. 작은 앱에서는 유형별 구성도 적합합니다.

자주 묻는 질문

“기능 기반 폴더 구조” 강의는 무료인가요?

네 — “기능 기반 폴더 구조” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Frontend Academy 강의 전체를 잠금 해제할 수 있습니다. Frontend Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“기능 기반 폴더 구조”에서 뭘 배우나요?

타입이 아니라 기능 영역을 기준으로 코드를 구성하고, 테스트·스타일·컴포넌트를 함께 배치하며, eslint-plugin-boundaries로 경계를 강제합니다. 브라우저에서 직접 실행하는 실습 코드로 Frontend Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Frontend Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Frontend Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“기능 기반 폴더 구조” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Frontend Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Frontend Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. Atomic Design: 원자, 분자, 유기체
  2. Turborepo를 사용한 모노레포 설정
  3. 마이크로 프런트엔드: Module Federation
  4. 기능 기반 폴더 구조
← Frontend Academy(으)로 돌아가기