tsconfig.json 설정으로 프로젝트 품질 높이기

Adam Kim·2026년 1월 16일

angular

목록 보기
95/102

tsconfig.json은 많은 개발자들이 초기에 생성된 그대로 두고 잘 들여다보지 않는 파일 중 하나입니다. 하지만 이 파일은 TypeScript 컴파일러의 '두뇌' 역할을 하는 매우 중요한 설정집입니다.

tsconfig.json을 제대로 이해하고 활용하면 코드의 안정성을 높이고, 최신 JavaScript 기능을 적극적으로 사용하며, 개발 생산성까지 향상시킬 수 있습니다. 오늘은 tsconfig.json이 Angular 프로젝트에서 어떻게 작동하는지, 그리고 어떤 키를 조정하여 프로젝트의 활용도를 극대화할 수 있는지 알아보겠습니다.


1. Angular의 tsconfig.json 삼형제: 역할 분담

Angular CLI로 생성된 프로젝트의 루트 폴더를 보면 tsconfig.json 파일이 여러 개 있는 것을 발견할 수 있습니다. 이는 각기 다른 목적을 위해 설정을 분리하고 상속하기 위함입니다.

  • tsconfig.json (루트)
    • 워크스페이스 전체의 기본(Base) TypeScript 설정입니다.
    • 여기에 정의된 설정은 아래의 다른 tsconfig 파일들로 상속됩니다.
    • 주로 모든 프로젝트(애플리케이션, 라이브러리, 테스트 등)에 공통으로 적용될 규칙을 정의합니다.
  • tsconfig.app.json
    • 실제 애플리케이션을 빌드할 때 사용되는 설정 파일입니다.
    • 루트 tsconfig.json을 상속(extends)받아, 애플리케이션에만 특화된 설정을 추가하거나 덮어씁니다.
    • files나 include 속성을 통해 컴파일할 소스 파일의 범위를 지정합니다.
  • tsconfig.spec.json
    • 단위 테스트(Karma/Jasmine)를 실행할 때 사용되는 설정 파일입니다.
    • 마찬가지로 루트 tsconfig.json을 상속받으며, 테스트 환경에 필요한 타입(jasmine 등)이나 설정을 추가합니다.

이러한 구조 덕분에 우리는 빌드용, 테스트용 설정을 분리하여 깔끔하게 관리할 수 있습니다.


2. Angular 관점에서 핵심 compilerOptions 파헤치기

tsconfig.json의 가장 중요한 부분은 compilerOptions 객체입니다. 여기에 명시된 키와 값에 따라 TypeScript 코드가 JavaScript로 어떻게 변환될지 결정됩니다. Angular 프로젝트에 큰 영향을 미치는 핵심 옵션들은 다음과 같습니다.

Key역할 및 Angular에 미치는 영향추천 값 (Angular 18)
target컴파일 결과로 나올 JavaScript 버전을 지정합니다. Angular는 최신 브라우저를 타겟으로 하므로 모던한 버전을 사용합니다."ES2022"
module모듈 시스템을 지정합니다. 동적 import() 등 최신 기능을 위해 ESNext나 ES2022를 사용합니다."ES2022"
lib컴파일 시 포함할 기본 타입 정의(라이브러리) 목록입니다. 브라우저 환경이므로 DOM은 필수입니다.["ES2022", "DOM"]
strict가장 중요한 옵션 중 하나. true로 설정하면 strictNullChecks, noImplicitAny 등 여러 엄격한 타입 검사 규칙이 한 번에 활성화됩니다. 코드의 안정성을 비약적으로 높여주므로 반드시 true로 유지해야 합니다.true
forceConsistentCasingInFileNamestrue일 경우, 파일 이름의 대소문자를 엄격하게 구분합니다. 협업 시 OS 차이(Windows vs macOS/Linux)로 인한 잠재적 버그를 예방합니다.true
experimentalDecoratorsAngular의 핵심인 @Component, @Injectable 같은 데코레이터를 사용하기 위해 반드시 필요한 옵션입니다. 이게 false면 Angular 앱이 동작하지 않습니다.true
emitDecoratorMetadata데코레이터가 붙은 클래스나 프로퍼티에 대한 타입 정보를 메타데이터로 저장합니다. Angular의 의존성 주입(Dependency Injection) 시스템이 타입을 인식하고 객체를 주입하기 위해 필수적입니다.true
paths모듈을 불러올 때 경로에 별칭(alias)을 부여합니다. 복잡한 상대 경로(../../../)를 깔끔하게 만들어줍니다. (아래 예제 참고)(사용자 정의)

3. tsconfig.json 활용도 200% 높이기: 실전 예제

이론은 충분하니, 이제 tsconfig.json 설정을 변경하여 실제 프로젝트를 어떻게 개선할 수 있는지 구체적인 예시를 통해 살펴보겠습니다.

예제 1: strict 옵션으로 런타임 에러를 컴파일 시점에 잡기

가장 강력한 기능입니다. strict: true가 왜 중요한지 코드로 확인해 보겠습니다.

  • 문제 상황: 사용자 정보를 표시하는 컴포넌트가 있지만, 사용자가 로그인하지 않은 경우 currentUser가 null일 수 있습니다.
// user.service.ts
@Injectable({ providedIn: 'root' })
export class UserService {
  // 사용자가 없을 수도 있음 (null)
  currentUser: { name: string; email: string } | null = null;
}

// profile.component.ts
@Component({ ... })
export class ProfileComponent {
  constructor(private userService: UserService) {}

  // strict: false 라면 이 코드는 아무런 에러 없이 컴파일됩니다.
  // 하지만 런타임에 currentUser가 null이면 "Cannot read properties of null (reading 'name')" 에러가 발생합니다!
  welcomeMessage = `환영합니다, ${this.userService.currentUser.name}님!`;
}
  • 해결책 (strict: true 설정): tsconfig.app.json에 strict: true가 설정되어 있다면, TypeScript 컴파일러는 this.userService.currentUser가 null일 가능성을 인지하고 컴파일 시점에 즉시 에러를 발생시킵니다.

    컴파일 에러: Object is possibly 'null'.

    개발자는 이 에러를 보고 아래와 같이 코드를 수정하여 런타임 에러를 원천 차단할 수 있습니다.
// profile.component.ts (수정 후)
export class ProfileComponent {
  welcomeMessage: string;

  constructor(private userService: UserService) {
    // currentUser가 존재할 때만 name에 접근하도록 안전하게 처리 (null-safety)
    const userName = this.userService.currentUser?.name ?? '방문자';
    this.welcomeMessage = `환영합니다, ${userName}님!`;
  }
}

예제 2: paths 옵션으로 지저분한 import 경로 정리하기

프로젝트 구조가 깊어지면 상대 경로 지옥에 빠지기 쉽습니다.

  • 문제 상황:
// src/app/features/orders/components/order-details/order-details.component.ts
import { AuthService } from '../../../../core/services/auth.service';
import { Product } from '../../../../shared/models/product.model';
  • 해결책 (paths 설정): 루트 tsconfig.json의 compilerOptions에 paths를 추가하여 경로 별칭을 만듭니다.
// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": "./", // paths 옵션을 사용하려면 baseUrl이 필수
    "paths": {
      "@core/*": ["src/app/core/*"],
      "@shared/*": ["src/app/shared/*"],
      "@features/*": ["src/app/features/*"]
    }
  }
}
  • 개선된 코드: 이제 프로젝트 어디서든 깔끔한 절대 경로처럼 모듈을 가져올 수 있습니다. 코드가 간결해지고, 파일 위치를 옮기는 리팩토링도 훨씬 쉬워집니다.
// src/app/features/orders/components/order-details/order-details.component.ts
import { AuthService } from '@core/services/auth.service';
import { Product } from '@shared/models/product.model';

예제 3: noUnusedLocals로 코드 품질 관리하기

쓰지 않는 변수나 import는 코드 가독성을 해치고 잠재적인 버그의 원인이 될 수 있습니다.

  • 해결책 (noUnusedLocals 설정): tsconfig.app.json에 이 옵션을 추가하면, 사용되지 않는 지역 변수나 private 멤버가 있을 경우 컴파일 에러를 발생시켜 코드를 항상 깨끗하게 유지하도록 강제할 수 있습니다.
// tsconfig.app.json
{
  "compilerOptions": {
    "noUnusedLocals": true,
    "noUnusedParameters": true // 사용되지 않는 함수 파라미터도 잡아줍니다.
  }
}

결론

tsconfig.json은 단순한 설정 파일이 아니라, 우리 프로젝트의 코드 품질과 안정성을 지키는 든든한 가드레일입니다. 특히 Angular 18과 같은 최신 프레임워크는 TypeScript의 강력한 타입 시스템 위에서 동작하기 때문에, 컴파일러 옵션을 잘 이해하고 활용하는 것이 더욱 중요해졌습니다.

지금 바로 여러분의 tsconfig.json 파일을 열어 strict 모드가 켜져 있는지 확인하고, paths를 설정하여 코드를 더 깔끔하게 만들어보세요. 작은 설정 변경 하나가 여러분의 개발 경험과 애플리케이션의 품질을 크게 향상시킬 것입니다.

profile
Angular2+ Developer

0개의 댓글