01. 프로젝트 폴더 구조

필요한 폴더 생성

필요한 폴더 생성 코드. 더 필요한게 있다면 mkdir 폴더명으로 추가할 것.

mkdir apis
mkdir assets
mkdir components
mkdir containers
mkdir pages
mkdir hooks
mkdir routes
mkdir store
mkdir utils

절대 경로 커스텀

폴더 path (tsconfig.json)

{
  "compilerOptions": {
    "baseUrl": "./",
    "paths": {
      "@/*": ["src/*"],
      "@apis/*": ["src/apis/*"],
      "@assets/*": ["src/assets/*"],
      "@components/*": ["src/components/*"],
      "@containers/*": ["src/containers/*"],
      "@pages/*": ["src/pages/*"],
      "@hooks/*": ["src/hooks/*"],
      "@routes/*": ["src/routes/*"],
      "@store/*": ["src/store/*"],
      "@utils/*": ["src/utils/*"]
    }
  }
}

vite일 경우, vite.config.ts에 아래 코드도 추가

resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
      '@apis': path.resolve(__dirname, 'src/apis'),
      '@assets': path.resolve(__dirname, 'src/assets'),
      '@components': path.resolve(__dirname, 'src/components'),
      '@containers': path.resolve(__dirname, 'src/containers'),
      '@pages': path.resolve(__dirname, 'src/pages'),
      '@hooks': path.resolve(__dirname, 'src/hooks'),
      '@routes': path.resolve(__dirname, 'src/routes'),
      '@store': path.resolve(__dirname, 'src/store'),
      '@utils': path.resolve(__dirname, 'src/utils')
    }
  }

Barrel

간결하고 짧은 import문을 위한 index문을 자동으로 생성해주는 코드.

  1. 루트 디렉토리에 generateBarrel.js 작성

    import fs from "fs"; // 파일 시스템 모듈 사용
    import path from "path"; // 경로 관련 모듈 사용
    import { fileURLToPath } from "url";
    
    const __filename = fileURLToPath(import.meta.url); // 현재 파일의 경로
    const __dirname = path.dirname(__filename); // 현재 디렉토리 경로
    
    // 소스 코드 디렉토리 경로 설정
    const srcFolderPath = path.join(__dirname, "src");
    let count = 0;
    
    // (수정 필요) index.js = true, index.ts = false
    const isJavaScript = false;
    const extension = isJavaScript ? "js" : "ts";
    
    // (수정 필요) 처리 대상 디렉토리 목록
    const targetFolderList = [
      "apis",
      "components",
      "containers",
      "hooks",
      "pages",
      "routes",
      "store",
      "utils",
    ];
    
    // (수정 필요) 예외 파일 목록
    const exceptionFileList = ["exception"];
    
    // 대상 폴더 리스트 처리
    targetFolderList.forEach((folder) => {
      const folderPath = path.join(srcFolderPath, folder); // 대상 폴더의 전체 경로 생성
      if (fs.existsSync(folderPath) && fs.statSync(folderPath).isDirectory()) {
        generateIndexFile(folderPath); // 대상 폴더에서 index.js(ts) 파일 생성 함수 호출
      }
    });
    
    // 지정된 디렉터리 내의 파일들을 기반으로 index.js(ts) 파일을 생성하는 함수
    function generateIndexFile(directoryPath) {
      // 현재 디렉터리 내의 index.js(ts) 파일 경로 생성
      const indexFilePath = path.join(directoryPath, `index.${extension}`);
    
      // 현재 스크립트 파일과의 상대 경로 계산
      const relativePath = path.relative(__dirname, indexFilePath);
    
      const files = fs.readdirSync(directoryPath); // 디렉터리 내의 파일 목록을 읽어옴
    
      const exportStatementList = []; // export 구문을 담을 배열
    
      files.forEach((file) => {
        // 파일의 전체 경로 생성
        const filePath = path.join(directoryPath, file);
    
        // 확장자를 제외한 파일 이름 추출
        const fileNameWithoutExtension = path.basename(file, path.extname(file));
    
        // 예외 파일 목록에 포함되는지 확인
        const isException = exceptionFileList.some((exceptionFileName) =>
          exceptionFileName
            .toLowerCase()
            .includes(fileNameWithoutExtension.toLowerCase())
        );
    
        if (isException) return; // 예외 파일인 경우, 다음 파일로 넘어감
    
        if (
          fs.statSync(filePath).isFile() &&
          (file.endsWith(`.${extension}`) || file.endsWith(`.${extension}x`)) &&
          file !== `index.${extension}`
        ) {
          // 파일이 존재하고 확장자가 .js(ts) 또는 .jsx(tsx)이며, 파일 이름이 index.js(ts)가 아닌 경우
          exportStatementList.push(
            `export * from './${fileNameWithoutExtension}';`
          );
        } else if (
          fs.statSync(filePath).isDirectory() &&
          file !== `index.${extension}`
        ) {
          // 디렉토리인 경우, 파일 이름이 index.js(ts)가 아닌 경우
          exportStatementList.push(
            `export * from './${fileNameWithoutExtension}';`
          );
          generateIndexFile(filePath); // 재귀적으로 하위 디렉터리 처리
        }
      });
    
      const content = exportStatementList.join("\\n"); // export 구문을 줄 바꿈으로 연결하여 내용 생성
      fs.writeFileSync(indexFilePath, content); // 생성된 내용을 index.js(ts) 파일에 쓰기
    
      console.log(`${++count} ${`\\t`} ${relativePath}`);
    }
    
  2. package.json 파일에 실행 스크립트 추가

    "barrel": "node generateBarrel.js"
    
  3. npm run barrel 명령어로 실행