[TYPESCRIPT] TypeScript 프로젝트에서 절대 경로 설정을 운영 기준으로 잡는 방법

 

프로젝트가 작을 때는 상대 경로로도 충분합니다. 하지만 디렉터리가 깊어지고 모듈 간 이동이 잦아지면, ../../.. 같은 경로가 빠르게 늘어납니다.

 

이 시점에서 대부분 절대 경로(alias)를 도입합니다. 문제는 “에디터에서는 되는데 실행에서 깨지는” 상황이 생각보다 자주 발생한다는 점입니다.

 

절대 경로 설정은 단순히 tsconfig에 paths를 추가하는 것으로 끝나지 않습니다. 실제로 유지되는 구성을 기준으로 정리합니다.

 

가장 기본: tsconfig paths 설정

절대 경로의 출발점은 tsconfig입니다.

 


// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@src/*": ["src/*"]
    }
  }
}

 

이 설정 이후에는 다음처럼 import가 가능합니다.

 


import { UserService } from '@src/user/user.service';

 

여기까지는 대부분 잘 동작합니다. 문제는 TypeScript 컴파일러 외의 도구들입니다.

 

왜 런타임에서 깨지는가

tsconfig paths는 TypeScript 컴파일러에게만 의미가 있습니다. Node.js 런타임은 이 별칭을 전혀 모릅니다.

 

그래서 tsc로 JS를 생성한 뒤 바로 실행하면, 다음과 같은 오류가 자주 발생합니다.

 


Error: Cannot find module '@src/...'

 

이 지점에서 많은 팀이 처음으로 “타입은 되는데 실행이 안 되는” 상황을 겪습니다.

 

Node 런타임에서의 해결 방법

Node 백엔드 기준으로는 보통 두 가지 방향 중 하나를 선택합니다.

 

  • 빌드 단계에서 경로를 상대 경로로 변환
  • 런타임에 alias 해석기를 추가

 

방법 1: tsconfig-paths 사용 (런타임 해석)

개발 환경에서 많이 쓰는 방식입니다.

 


npm i tsconfig-paths

 


// 실행 예시
node -r tsconfig-paths/register dist/main.js

 

이 방식은 빠르게 적용할 수 있습니다. 다만 런타임 훅에 의존하기 때문에, Docker/PM2/서버리스 환경에서는 실행 커맨드를 항상 맞춰줘야 합니다.

 

방법 2: 번들러(esbuild/swc)에서 경로 변환

최근에는 이 쪽을 선택하는 팀도 많습니다. 빌드 시점에 alias를 실제 경로로 치환합니다.

 


// esbuild 예시
esbuild src/main.ts \
  --bundle \
  --platform=node \
  --outdir=dist \
  --alias:@src=./src

 

이 방식은 런타임이 단순해집니다. 대신 빌드 파이프라인에 alias 규칙을 반드시 맞춰줘야 합니다.

 

테스트 환경(Jest/Vitest)에서의 추가 설정

절대 경로는 테스트 환경에서 한 번 더 설정이 필요합니다. 여기를 놓치면 “개발 서버는 되는데 테스트만 실패”하는 패턴이 나옵니다.

 

Jest 예시


// jest.config.cjs
module.exports = {
  moduleNameMapper: {
    '^@src/(.*)$': '<rootDir>/src/$1',
  },
};

 

Vitest/Vite 예시


// vite.config.ts
import path from 'node:path';

export default {
  resolve: {
    alias: {
      '@src': path.resolve(__dirname, './src'),
    },
  },
};

 

여기서 중요한 건 한 가지입니다. tsconfig paths와 테스트 alias가 반드시 동일해야 합니다.

 

모노레포에서 특히 자주 깨지는 지점

모노레포에서는 절대 경로 문제가 더 자주 드러납니다.

 

  • 패키지마다 baseUrl이 다름
  • root tsconfig와 package tsconfig의 paths가 어긋남
  • 빌드 도구와 테스트 도구가 서로 다른 alias를 사용

 

이 상태가 되면, 어느 환경에서는 되고 어느 환경에서는 깨지는 코드가 생깁니다. 절대 경로는 편의 기능이지만, 경로 규칙을 중앙에서 관리하지 않으면 유지 비용이 빠르게 올라갑니다.

 

현실적으로 오래 유지되는 기준

여러 프로젝트를 거치다 보면, 다음 정도의 기준으로 정리되는 경우가 많습니다.

 

  • alias는 최소 개수로 유지
  • tsconfig paths를 단일 소스로 관리
  • 런타임/테스트/번들러 설정을 한 번에 맞춤
  • CI에서 실제 실행까지 검증

 

alias를 많이 만들수록 편해 보이지만, 나중에는 관리 포인트만 늘어나는 경우가 많습니다.

 


 

TypeScript에서 절대 경로 설정은 문법 기능이 아니라 빌드와 실행 환경을 함께 묶는 설정 작업에 가깝습니다. tsconfig만 맞춘다고 끝나지 않습니다.

 

컴파일러, 런타임, 테스트, 번들러가 같은 경로 규칙을 보도록 맞춰두면 상대 경로로 돌아가는 일은 거의 없습니다.

 

프로젝트와 팀 환경에 따라 구성은 달라질 수 있습니다. 다만 alias를 도입했다면, 어디까지 그 규칙이 적용되는지는 초기에 한 번 정리해 두는 편이 나중에 디버깅 시간을 줄여줍니다.