[Typescript] tsconfig 절대경로 설정하기

2022년 11월 16일

#Typescript#Tsconfig#Path-alias

서론

특정 컴포넌트나 파일을 import할 시 경로의 depth가 깊어지면 깊어질수록 import하려는 파일의 위치에 따라 상대경로가 상당히 길어질 수 있다.

// 극단적인 예
import deep from '../../../../../../../A/B/C/file.js';

// 이런게 수없이 많다면? 뎁스가 한없이 깊어진다면?
import deep1 from '../../../../../../../A/B/C/file1.js';
import deep2 from '../../../../../../../A/B/C/file2.js';
import deep3 from '../../../../../../../A/B/C/file3.js';
import deep4 from '../../../../../../../A/B/C/file4.js';
import deep5 from '../../../../../../../A/B/C/file5.js';
...
...
import deep999 from '../../../../../../../A/B/C/file5.js';

이런 식으로 상대경로가 길어지면 import할 파일을 찾기위한 수고가 커질 뿐더러 가독성 면에서도 좋지 않다.

tsconfig.json or jsconfig.json의 설정을 통해 절대경로를 설정할 수 있다.

tsconfig.json 이란?

typescript에 대한 설정을 할 수 있는 파일이며 javascript로 이루어진 레포지토리라면 jsconfig.json을 사용한다.

해당 레포지토리가 Typescript를 사용하고 있다면 루트 디렉토리에 tsconfig.json이 존재해야 하며 tsc 명령어를 통한 컴파일시 로드한다.

컴파일러에 대한 옵션 설정과 더불어 다양한 기능을 제공한다.

// tsconfig.json 의 예시
{
  "compilerOptions": {
    ...
  },
  "include": [...],
  "exclude": [...]
}

절대경로 설정하기

tsconifg.json에서 compilerOptions 옵션의 baseUrlpaths를 이용해서 절대경로를 설정한다.

baseUrl의 경우 paths를 설정하기 위해서는 반드시 설정해야하는 옵션이다.

paths의 경우 key-value쌍으로 이루어진 객체이며 절대경로를 정의하고자 하는 경로의 이름을 key에 입력하며 baseUrl을 기준으로 상대적인 경로를 value에 입력한다.

pathskey에는 주로 @으로 시작을 하며 바로 다음으로 /, _ 같은 특수문자를 넣는데 이유는 @로 시작하는 패키지가 종종 있기 때문이다.

// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".", // 이 경우는 tsconfig.json이 존재하는 루트 디렉토리를 기준으로 삼는다.
    "paths": {
      "@_components/*": ["src/components/*"],
      "@_apis/*": ["src/api/*"],
      "@_types/*": ["src/types/*"],
      "@_icons/*": ["public/assets/icons/*"],
      "@_images/*": ["public/assets/images/*"],
      "@_emojis/*": ["public/assets/emoji/*"]
    }
  }
}

위와 같은 paths를 지정한다면 실제로 루트 디렉토리를 기준으로한 구조는 다음과 같다.

Root ├─ public │ └─ assets │ ├─ icons │ ├─ images │ └─ emojis └─ src ├─ components ├─ api └─ types

실제 사용 예시

import path1 from "@_components/home/main.tsx";
import path2 from "@_icons/sample.png";
import path3 from "@_apis/member";

특정 파일뿐만 아니라 모듈도 절대경로로 지정이 가능하다.

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "jquery": ["node_modules/jquery/dist/jquery"]
    }
  }
}

프레임워크별 추가 설정

Next.js

Next.js에서는 tsconfig.json의 설정만으로도 바로 절대 경로가 동작합니다. 별도의 추가 설정이 필요하지 않습니다.

React (Create React App)

CRA에서는 tsconfig.json 설정과 함께 webpack 설정도 필요할 수 있습니다. 그러나 CRA 2.0 이상에서는 기본적으로 jsconfig.json이나 tsconfig.json의 paths를 지원합니다.

Vite

Vite를 사용하는 경우 추가로 vite.config.ts에 다음과 같은 설정이 필요합니다:

import { defineConfig } from "vite";
import path from "path";

export default defineConfig({
  resolve: {
    alias: {
      "@_components": path.resolve(__dirname, "./src/components"),
      "@_apis": path.resolve(__dirname, "./src/api"),
      // ... 나머지 alias들
    },
  },
});

설정 파일 분리하기

절대경로를 추가하는 paths가 늘어나면 tsconfig.jsonextends 옵션을 이용해서 따로 빼놓는 것도 가능하다.

기본 config 파일을 읽어온 후 extends에 지정한 파일에 의해 오버라이딩(overridden) 된다. includeexclude에 정의한 파일의 경우 기본 config 파일을 덮어쓴다.(overwrite)

extends 옵션은 스트링값으로만 받는다. 여러 설정 파일을 extend하고 싶다면 줄줄이 이어받는 구조를 만들어야한다.

// tsconfig.a.json
{
  "compilerOptions": {
    ...
  },
}

// tsconfig.b.json
{
  "compilerOptions": {
    ...
  },
  "extends": "./tsconfig.a.json"
}

// tsconfig.json
{
  "compilerOptions": {
    ...
  },
  "extends": "./tsconfig.b.json"
}

실제 설정 방법

  1. 먼저 경로 설정만을 위한 별도의 파일을 생성합니다.
// tsconfig.paths.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@_components/*": ["src/components/*"],
      "@_apis/*": ["src/api/*"],
      "@_types/*": ["src/types/*"],
      "@_icons/*": ["public/assets/icons/*"],
      "@_images/*": ["public/assets/images/*"],
      "@_emojis/*": ["public/assets/emoji/*"]
    }
  }
}
  1. 메인 tsconfig.json에서 extends로 해당 파일을 포함시킵니다.
// tsconifg.json
{
  "compilerOptions": {
    ...
  },
  "extends": "./tsconfig.paths.json"
}

주의사항

  • 경로 별칭(path alias)을 사용할 때는 IDE나 에디터의 지원이 필요할 수 있습니다. VSCode의 경우 기본적으로 지원하지만, 다른 에디터를 사용하는 경우 추가 설정이 필요할 수 있습니다.
  • Jest나 다른 테스트 도구를 사용하는 경우, 별도의 모듈 매핑 설정이 필요할 수 있습니다.
  • 빌드 도구(webpack, vite 등)에 따라 추가 설정이 필요할 수 있으니 해당 도구의 문서를 참고해야 합니다.

참조

피드백은 언제나 환영입니다.