본문으로 건너뛰기

1.5 개발 도구 설정

코드를 올바르게 작성하는 것도 중요하지만, 좋은 개발 도구를 갖추면 실수를 훨씬 줄일 수 있다. TypeScript는 IDE와의 깊은 통합을 통해 자동완성, 즉각적인 오류 표시, 안전한 리팩토링을 제공한다. 이 장에서는 VS Code 최적화 설정, ESLint로 코드 품질 유지, Prettier로 코드 스타일 통일, 그리고 에러 코드를 읽는 법까지 개발 환경 전반을 다룬다.

VS Code TypeScript 지원​

TypeScript는 Microsoft가 만들었고, VS Code 역시 Microsoft가 만들었다. 이 두 도구는 처음부터 함께 설계되었다. VS Code는 별도 플러그인 없이도 TypeScript를 완벽하게 지원한다.

내장 TypeScript 서버 (tsserver)​

VS Code는 내부적으로 tsserver라는 TypeScript 언어 서버를 실행한다. tsserver가 백그라운드에서 코드를 분석하고 다음 기능을 제공한다.

  • IntelliSense: 타입 정보를 기반으로 객체의 속성, 함수의 매개변수, 반환 타입을 자동으로 제안한다
  • 즉시 오류 표시: 파일을 저장하지 않아도 코드를 작성하는 순간 빨간 밑줄로 오류를 표시한다
  • 호버 타입 정보: 변수나 함수 위에 마우스를 올리면 타입 정보가 표시된다
  • Go to Definition: F12 또는 Ctrl+클릭으로 함수/타입 정의로 즉시 이동한다
  • Find All References: Shift+F12로 함수나 타입이 사용된 모든 위치를 찾는다
  • Rename Symbol: F2로 변수/함수명을 안전하게 일괄 변경한다

VS Code TypeScript 버전 전환​

프로젝트에 로컬로 설치된 TypeScript 버전과 VS Code 내장 TypeScript 버전이 다를 수 있다. 프로젝트의 TypeScript 버전을 사용하도록 설정하는 것이 권장된다.

  1. .ts 파일을 열고 Ctrl+Shift+P (명령 팔레트 열기)
  2. "TypeScript: Select TypeScript Version" 검색
  3. "Use Workspace Version" 선택

이 설정은 .vscode/settings.json에 저장된다.

{
"typescript.tsdk": "node_modules/typescript/lib"
}

유용한 VS Code 설정 (settings.json)​

.vscode/settings.json에 프로젝트별 VS Code 설정을 추가한다. 팀원이 동일한 설정을 사용하도록 이 파일을 Git에 커밋한다.

{
// TypeScript 버전 — 프로젝트 로컬 버전 사용
"typescript.tsdk": "node_modules/typescript/lib",

// 자동 임포트 제안 활성화
"typescript.suggest.autoImports": true,

// 파일 이동 시 임포트 경로 자동 업데이트
"typescript.updateImportsOnFileMove.enabled": "always",

// 인레이 힌트 — 추론된 타입을 코드에 직접 표시
"typescript.inlayHints.parameterNames.enabled": "literals",
"typescript.inlayHints.variableTypes.enabled": false,
"typescript.inlayHints.returnTypes.enabled": true,
"typescript.inlayHints.functionLikeReturnTypes.enabled": true,

// 저장 시 자동 포맷팅 (Prettier 사용 시)
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",

// 저장 시 ESLint 자동 수정
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
}
}

인레이 힌트 (Inlay Hints)​

인레이 힌트는 코드에 타입 정보를 반투명하게 오버레이로 표시하는 기능이다. 타입 어노테이션 없이도 어떤 타입이 추론되는지 에디터에서 바로 볼 수 있다.

// inlayHints.parameterNames.enabled: "all" 설정 시 보이는 것
const result = arr.reduce(/*accumulator:*/ (acc, /*currentValue:*/ cur) => acc + cur, 0);

// inlayHints.returnTypes.enabled: true 설정 시
function add(a: number, b: number) /*: number*/ {
return a + b;
}

ESLint + typescript-eslint​

TypeScript 컴파일러는 타입 오류를 잡는다. ESLint는 그 외의 코드 품질 문제를 잡는다. 예를 들어 사용하지 않는 변수, 불필요한 any 타입 사용, 잠재적인 버그 패턴 등이다. TypeScript 프로젝트에서는 typescript-eslint를 함께 사용한다.

설치​

npm install --save-dev eslint @eslint/js typescript-eslint

eslint.config.mjs 설정 (ESLint v9 Flat Config)​

ESLint v9부터는 eslint.config.mjs 파일을 사용한다(Flat Config 방식).

// eslint.config.mjs
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default tseslint.config(
// JavaScript 기본 권장 규칙
eslint.configs.recommended,

// TypeScript 권장 규칙
...tseslint.configs.recommended,

// 프로젝트 커스텀 규칙
{
rules: {
// any 타입 사용 시 경고 (에러 대신 경고로 설정)
'@typescript-eslint/no-explicit-any': 'warn',

// 사용하지 않는 변수 에러 처리
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' }
],

// 빈 함수 허용
'@typescript-eslint/no-empty-function': 'off',
},
}
);

argsIgnorePattern: '^_'는 이름이 _로 시작하는 변수는 미사용이어도 무시한다. 의도적으로 사용하지 않는 매개변수를 _name처럼 표시하는 관례와 호환된다.

@typescript-eslint/recommended 주요 규칙​

tseslint.configs.recommended에 포함된 대표적인 규칙들:

규칙설명
no-explicit-anyany 타입 사용 금지/경고
no-unused-vars사용하지 않는 변수 오류
no-non-null-assertion! 단언 연산자 금지
prefer-as-constas const 사용 권장
ban-typesObject, String 등 래퍼 타입 사용 금지
no-inferrable-types추론 가능한 곳에 타입 명시 금지

package.json 스크립트 추가​

{
"scripts": {
"lint": "eslint src",
"lint:fix": "eslint src --fix"
}
}
npm run lint       # 오류 목록 출력
npm run lint:fix # 자동 수정 가능한 오류 수정

Prettier 연동​

ESLint가 코드 품질을 잡는다면, Prettier는 코드 스타일(들여쓰기, 따옴표, 세미콜론 등)을 통일한다. 팀원 모두가 동일한 포맷으로 코드를 작성하게 된다.

설치​

npm install --save-dev prettier eslint-config-prettier
  • prettier: 코드 포맷터
  • eslint-config-prettier: Prettier와 충돌하는 ESLint 규칙을 비활성화

.prettierrc 설정​

프로젝트 루트에 .prettierrc 파일을 생성한다.

{
"semi": true,
"trailingComma": "all",
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2,
"endOfLine": "lf"
}
옵션기본값설명
semitrue세미콜론 추가
trailingComma"all"마지막 항목 뒤 쉼표
singleQuotefalse작은따옴표 사용
printWidth80줄 최대 길이
tabWidth2들여쓰기 칸 수
endOfLine"lf"줄바꿈 문자 (LF/CRLF)

ESLint와 Prettier 통합​

eslint.config.mjs에 eslint-config-prettier를 추가한다. 반드시 마지막에 위치해야 한다.

// eslint.config.mjs
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
import eslintConfigPrettier from 'eslint-config-prettier';

export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
{
rules: {
'@typescript-eslint/no-explicit-any': 'warn',
},
},
// 마지막에 추가 — Prettier와 충돌하는 규칙을 모두 비활성화
eslintConfigPrettier,
);

package.json에 포맷팅 스크립트 추가​

{
"scripts": {
"format": "prettier --write src",
"format:check": "prettier --check src"
}
}
npm run format        # 모든 파일 자동 포맷팅
npm run format:check # 포맷팅 필요 여부만 확인 (CI에서 사용)

.editorconfig 설정​

.editorconfig는 에디터 간 기본 코딩 스타일을 통일한다. VS Code, IntelliJ, Vim 등 다양한 에디터가 이 파일을 인식한다. Prettier와 함께 사용하면 에디터 수준의 기본 설정도 통일된다.

프로젝트 루트에 .editorconfig 파일을 생성한다.

# .editorconfig
root = true

[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

VS Code에서 .editorconfig를 적용하려면 "EditorConfig for VS Code" 확장 프로그램을 설치한다.

TypeScript 에러 코드 읽는 법​

TypeScript 에러 메시지는 처음에 낯설게 느껴지지만 패턴을 이해하면 빠르게 해석할 수 있다.

에러 메시지 구조​

src/index.ts:10:20 - error TS2345: Argument of type 'string' is not assignable
to parameter of type 'number'.
  • src/index.ts:10:20 — 파일 경로, 줄 번호(10), 열 번호(20)
  • error — 심각도 (error / warning)
  • TS2345 — TypeScript 에러 코드
  • 나머지 — 사람이 읽을 수 있는 설명

자주 만나는 에러 코드​

TS2322 — Type 'X' is not assignable to type 'Y'

가장 자주 만나는 에러. 타입이 맞지 않는 값을 할당하려 할 때 발생한다.

const age: number = "30";
// TS2322: Type 'string' is not assignable to type 'number'.

TS2345 — Argument of type 'X' is not assignable to parameter of type 'Y'

함수에 잘못된 타입의 인수를 전달할 때 발생한다.

function greet(name: string): void { }
greet(42);
// TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.

TS2339 — Property 'X' does not exist on type 'Y'

객체에 존재하지 않는 속성에 접근할 때 발생한다.

const user = { name: "Alice" };
console.log(user.age);
// TS2339: Property 'age' does not exist on type '{ name: string; }'.

TS2531 — Object is possibly 'null'

strictNullChecks가 켜진 상태에서 null일 수 있는 값에 접근할 때 발생한다.

const element = document.getElementById("app");
element.textContent = "Hello";
// TS2531: Object is possibly 'null'.

// 해결
element?.textContent = "Hello"; // 옵셔널 체이닝
// 또는
if (element) element.textContent = "Hello";

TS7006 — Parameter 'X' implicitly has an 'any' type

strict 모드에서 함수 매개변수에 타입을 명시하지 않으면 발생한다.

function process(data) {  // data의 타입 없음
// TS7006: Parameter 'data' implicitly has an 'any' type.
}

// 해결
function process(data: string) { }

TS2304 — Cannot find name 'X'

선언되지 않은 변수나 타입을 사용할 때 발생한다.

console.log(undeclaredVariable);
// TS2304: Cannot find name 'undeclaredVariable'.

실전 예제: 완전한 개발 환경 세팅 단계별 가이드​

새 TypeScript 프로젝트의 개발 환경을 처음부터 구성하는 전체 과정이다.

1단계: 프로젝트 초기화​

mkdir my-typescript-app
cd my-typescript-app
npm init -y
mkdir src

2단계: 핵심 패키지 설치​

# TypeScript 및 실행 도구
npm install --save-dev typescript tsx @types/node

# ESLint 및 TypeScript 플러그인
npm install --save-dev eslint @eslint/js typescript-eslint

# Prettier 및 ESLint 통합
npm install --save-dev prettier eslint-config-prettier

3단계: tsconfig.json 설정​

npx tsc --init

tsconfig.json을 다음과 같이 수정한다.

{
"compilerOptions": {
"target": "ES2022",
"module": "CommonJS",
"lib": ["ES2022"],
"rootDir": "./src",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"sourceMap": true,
"resolveJsonModule": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}

4단계: ESLint 설정​

// eslint.config.mjs
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
import eslintConfigPrettier from 'eslint-config-prettier';

export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
{
rules: {
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
],
},
},
eslintConfigPrettier,
);

5단계: Prettier 설정​

// .prettierrc
{
"semi": true,
"trailingComma": "all",
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2,
"endOfLine": "lf"
}

6단계: VS Code 설정​

// .vscode/settings.json
{
"typescript.tsdk": "node_modules/typescript/lib",
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"typescript.inlayHints.parameterNames.enabled": "literals",
"typescript.inlayHints.returnTypes.enabled": true
}

7단계: .editorconfig 설정​

root = true

[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

8단계: .gitignore 추가​

node_modules/
dist/
*.js.map
.DS_Store

9단계: package.json 스크립트 추가​

{
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "npm run type-check && tsc",
"start": "node dist/index.js",
"type-check": "tsc --noEmit",
"lint": "eslint src",
"lint:fix": "eslint src --fix",
"format": "prettier --write src",
"format:check": "prettier --check src"
}
}

10단계: 첫 소스 파일 작성 및 동작 확인​

// src/index.ts
interface User {
id: number;
name: string;
email: string;
}

function createWelcomeMessage(user: User): string {
return `환영합니다, ${user.name}! (${user.email})`;
}

const user: User = {
id: 1,
name: '개발자',
email: 'dev@example.com',
};

console.log(createWelcomeMessage(user));
npm run dev
# 환영합니다, 개발자! (dev@example.com)

npm run type-check
# 타입 오류 없음

npm run lint
# 린트 오류 없음

고수 팁​

// @ts-expect-error vs // @ts-ignore​

두 주석 모두 다음 줄의 TypeScript 오류를 억제한다. 그러나 중요한 차이가 있다.

// @ts-ignore — 오류가 있든 없든 무조건 억제
// @ts-ignore
const x: number = "hello"; // 오류 억제됨

// @ts-expect-error — 오류가 있을 때만 억제, 오류가 없으면 자체적으로 오류 발생
// @ts-expect-error
const y: number = "world"; // 오류 억제됨

// @ts-expect-error를 붙였는데 오류가 없으면?
// @ts-expect-error
const z: number = 42; // 오류: Unused '@ts-expect-error' directive.

@ts-expect-error가 더 안전하다. 나중에 코드가 수정되어 오류가 사라졌을 때 @ts-expect-error 주석 자체가 오류가 되어 알려준다. 반면 @ts-ignore는 오류가 사라져도 조용히 남아 있다.

실무에서는 @ts-ignore보다 @ts-expect-error를 사용하자. 그리고 왜 오류를 억제하는지 이유를 주석으로 반드시 남긴다.

// @ts-expect-error — 외부 라이브러리 타입 정의 오류, 버전 업데이트 후 제거 예정
someLibrary.undocumentedMethod();

"Go to Definition"으로 내장 타입 탐색​

Ctrl+클릭 (또는 F12)으로 TypeScript 내장 타입의 정의로 이동할 수 있다. Array, Promise, Map 같은 내장 타입의 메서드와 속성이 어떻게 정의되어 있는지 직접 볼 수 있다.

예를 들어 Array.prototype.map의 타입 정의로 이동하면 다음과 같은 코드를 볼 수 있다.

// lib.es5.d.ts (TypeScript 내장 타입 정의)
interface Array<T> {
map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
}

이 타입 정의를 보면 map이 제네릭을 어떻게 활용하는지, 콜백 함수의 매개변수가 무엇인지 정확히 알 수 있다. 라이브러리 문서를 찾아보는 것보다 더 정확한 정보를 얻을 수 있다.

팀 프로젝트에서 VS Code 확장 프로그램 공유​

.vscode/extensions.json에 프로젝트 권장 확장 프로그램 목록을 추가하면, 팀원이 프로젝트를 열었을 때 VS Code가 설치를 자동으로 제안한다.

// .vscode/extensions.json
{
"recommendations": [
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"EditorConfig.EditorConfig",
"usernamehw.errorlens"
]
}

정리​

도구역할설정 파일
VS Code tsserver타입 검사, 자동완성, 에러 표시.vscode/settings.json
ESLint + typescript-eslint코드 품질, 안티패턴 감지eslint.config.mjs
Prettier코드 스타일 통일.prettierrc
eslint-config-prettierESLint + Prettier 충돌 방지eslint.config.mjs 마지막
.editorconfig에디터 기본 설정 통일.editorconfig
에러 코드의미
TS2322타입 불일치 할당
TS2345함수 인수 타입 불일치
TS2339존재하지 않는 속성 접근
TS2531null/undefined 가능성
TS7006암묵적 any 타입 (매개변수)
TS2304선언되지 않은 이름 사용

다음 장에서는 TypeScript의 기본 타입 시스템을 본격적으로 배운다. string, number, boolean부터 시작해 union, intersection, 리터럴 타입까지 TypeScript 타입의 기초를 다진다.