본문 바로가기

자바스크립트와 타입스크립트의 차이점

런타임 중심 JavaScript와 컴파일 전 정적 검사를 더하는 TypeScript의 실행 과정과 개발 경험 차이를 비교합니다.

타입스크립트에 입문할 때 가장 자주 생기는 오해는 문법이 거의 같으니 큰 차이도 없겠지라는 판단입니다.

실제로 파일 확장자만 바꾸면 돌아가는 코드도 많아서, 처음엔 차이를 체감하기 어렵습니다.

하지만 프로젝트 규모가 커질수록 두 언어의 차이는 문법이 아니라 개발 방식 전체에서 드러납니다.

오류를 언제 발견하는지, 리팩터링을 얼마나 안전하게 할 수 있는지, 협업 중 의사소통 비용이 얼마나 줄어드는지가 달라지기 때문입니다.

이 절에서는 자바스크립트와 타입스크립트의 차이를 기능 표로만 비교하지 않고, 실제 개발 과정에서 어떤 선택이 어떤 결과를 만드는지까지 연결해 설명합니다.

읽고 나면 같은 코드에서 어떤 오류가 정적 검사로 드러나고 어떤 조건은 실행 중에 확인해야 하는지 구분할 수 있습니다.


핵심은 '정적 타입' 시스템

자바스크립트와 타입스크립트의 가장 근본적인 차이점은 바로 타입 시스템에 있습니다.

  • 자바스크립트: 동적 타입 언어 (Dynamically Typed Language) 자바스크립트는 동적 타입 언어입니다.

    이는 변수의 타입이 프로그램이 실행되는 시점(런타임)에 결정된다는 의미입니다.

    코드를 작성할 때는 변수에 특정 타입을 지정할 필요가 없으며, 같은 변수에 숫자, 문자열, 객체 등 어떤 타입의 값이라도 자유롭게 할당할 수 있습니다.

    let value = 10; // 숫자
    value = "hello"; // 문자열
    value = true; // 불리언

    이러한 유연성은 개발 초기 단계에서 빠른 프로토타이핑을 가능하게 합니다.

    하지만 코드의 규모가 커지고 복잡해질수록, 예상치 못한 타입 오류로 인해 프로그램이 비정상적으로 동작할 위험이 커집니다.

    타입 계약을 표현하지 않은 이 예제에서는 실행값을 추적해야 합니다. JavaScript에도 테스트, JSDoc 기반 검사 같은 별도 도구를 적용할 수 있습니다.

  • 타입스크립트: 정적 타입 언어 (Statically Typed Language) 반면 타입스크립트는 정적 타입 언어의 특성을 가집니다.

    즉, 변수의 타입이 프로그램이 실행되기 전(컴파일 시점)에 검사됩니다.

    개발자는 변수나 함수의 매개변수, 반환값 등에 타입을 명시할 수 있고, 많은 경우에는 타입스크립트가 초기값과 사용 문맥을 보고 타입을 추론합니다.

    let value: number = 10; // 숫자
    // value = "hello"; // 오류: 'string' 형식은 'number' 형식에 할당될 수 없습니다.

    보시는 것처럼, value를 number 타입으로 선언한 후 문자열을 할당하려 하면, 타입스크립트 컴파일러가 즉시 오류를 알려줍니다.

    이런 정적 검사는 타입 불일치를 컴파일 단계에서 드러내며, 런타임에 뒤늦게 발견되는 버그를 줄입니다.


컴파일 과정의 차이

두 언어의 또 다른 중요한 차이점은 컴파일 과정에 있습니다.

  • 자바스크립트: 자바스크립트 코드는 웹 브라우저나 Node.js와 같은 런타임 환경에서 바로 실행 대상이 됩니다. 런타임 내부에서는 파싱과 최적화가 일어나지만, 개발자가 타입 제거를 위한 별도 변환 단계를 거칠 필요는 없습니다.

  • 타입스크립트: 웹 브라우저는 타입스크립트 문법을 직접 실행하지 않습니다. 보통 타입스크립트 컴파일러(TypeScript Compiler, tsc)를 통해 먼저 자바스크립트 코드로 변환(Transpile)합니다. 이 과정에서 타입 검사가 이루어지고, 타입 선언 같은 타입스크립트 문법이 제거된 순수 자바스크립트 코드가 생성됩니다.

    최신 Node.js에는 타입 표기만 제거해 실행하는 제한적 type stripping 기능도 있지만, 이 기능은 tsconfig 기반 변환이나 타입 검사를 대신하지 않습니다.

일반 JavaScript는 소스가 런타임으로 전달된다. TypeScript 경로는 TS소스, 정적 검사와 emit 정책, JavaScript 산출물, 런타임으로 이어진다. 검사 없이 타입 표기만 제거하는 실행 도구는 정적 검사와 별개이다.

TYPE / RUNTIME / CONTRACT

TypeScript 검사는 JavaScript 실행을 앞서 확인한다

TypeScript 소스에는 정적 검사와 JavaScript 출력 단계가 더해집니다. 일반 JavaScript 실행과 두 경로를 비교하되, 런타임의 외부 입력 검증은 양쪽 모두 필요합니다.

JavaScript 실행과 TypeScript 검사·출력 경로서로 독립인 두3노드2간선 경로다. JavaScript 소스→런타임→실제값동작과 TypeScript 소스→정적검사및emit정책→JavaScript실행을 비교한다. 출력 허용 여부는 설정에 따르며 type stripping은 정적검사와 별개이다.일반 JavaScriptJavaScript 소스타입 표기 없음JavaScript 런타임실제 값으로 실행동작 관찰출력 · 오류 확인TypeScriptTypeScript 소스명시 · 추론한 타입정적 검사 · emit출력 정책 적용JavaScript 실행외부 입력은 별도 검증
JavaScript 실행과 TypeScript 검사·출력 경로 · 모바일서로 독립인 두3노드2간선 경로다. JavaScript 소스→런타임→실제값동작과 TypeScript 소스→정적검사및emit정책→JavaScript실행을 비교한다. 출력 허용 여부는 설정에 따르며 type stripping은 정적검사와 별개이다. 모바일에서도 노드와 연결 방향·독립 경로가 같다.일반 JavaScriptJavaScript 소스타입 표기 없음JavaScript 런타임실제 값으로 실행동작 관찰출력 · 오류 확인TypeScriptTypeScript 소스명시 · 추론한 타입정적 검사 · emit출력 정책 적용JavaScript 실행외부 입력은 별도 검증

JAVASCRIPT

같은 변수에 서로 다른 값 할당

본문의 JavaScript value는10, "hello", true로 바뀝니다. 런타임은 실제 값의 동작을 따릅니다. JavaScript에도 별도 도구로 정적 검사를 적용할 수 있습니다.

TYPESCRIPT

number 선언 뒤 문자열 할당을 진단

TypeScript value:number=10에는 문자열을 할당할 수 없다고 진단합니다. 명시한 타입뿐 아니라 초기값과 문맥에서 추론한 타입도 검사에 사용합니다.

OUTPUT POLICY

타입 오류만으로 출력이 항상 막히지는 않는다

tsc의 기본 정책에서는 오류가 있어도 JavaScript가 출력될 수 있습니다. noEmitOnError를 켜면 오류가 있는 출력물을 막고, noEmit은 산출물 없이 검사합니다.

RUNTIME / TOOLING

입력 검증과 type stripping을 구분

타입 표기가 제거되어도 외부 입력의 정확성이 자동으로 보장되지 않습니다. Node의 type stripping은 제한된 문법의 타입 표기 제거 기능이며 tsc의 타입 검사나 tsconfig 변환을 대신하지 않습니다.

일반 JavaScript는 소스가 런타임으로 전달된다. TypeScript 경로는 TS소스, 정적 검사와 emit 정책, JavaScript 산출물, 런타임으로 이어진다. 검사 없이 타입 표기만 제거하는 실행 도구는 정적 검사와 별개이다.

이러한 컴파일 과정 덕분에 타입스크립트는 자바스크립트의 모든 기능을 활용하면서도, 타입 검사라는 추가적인 안정성을 확보할 수 있게 됩니다.

최종적으로 실행되는 코드는 여전히 자바스크립트이므로, 기존 자바스크립트 생태계의 풍부한 라이브러리와 프레임워크를 그대로 사용할 수 있다는 큰 장점이 있습니다.


타입을 생략한 변수도 검사됩니다 아래 예제를 별도의 파일에서 확인하세요. 값에서 추론한 타입도 이후 대입을 제한합니다.

let attempts = 1;
attempts = 2;
// attempts = "두 번";
console.log(attempts);

주석 그대로는 2가 출력됩니다. 마지막 대입 주석을 해제하면 attempts에 추론된 number와 문자열이 맞지 않아 진단을 받습니다. JavaScript의 실행값은 여전히 동적이지만, TypeScript의 이름 사용에 대한 정적 계약은 별도로 검사합니다.

스스로 확인하기 다음 두 상황을 “타입 불일치 진단”과 “검사는 통과하지만 실행값·업무 조건 확인 필요”로 나누세요. 덧셈 함수의 매개변수는 둘 다 number라고 가정합니다.

  1. sumNumbers(10, "20")를 호출한다.
  2. 두 number의 나눗셈을 반환하는 함수에 10과 0을 전달한다.
풀이 확인

첫 호출은 문자열 인수 때문에 정적 진단 대상입니다. 두 번째는 타입이 모두 number여서 검사할 수 있지만, 자바스크립트의 10 / 0은 Infinity입니다. 유한 결과나 0으로 나누기 금지라는 요구는 타입 표기 하나가 보장하지 않습니다.

tsc의 기본 출력 정책에서는 타입 오류가 있어도 JavaScript가 생성될 수 있습니다. noEmit은 파일을 만들지 않고 검사하며, noEmitOnError는 오류가 있을 때 새 출력을 막습니다. 기존에 만들어 둔 JavaScript까지 자동으로 지우지는 않습니다. 공식 noEmitOnError 설명을 참고하세요.

개발 경험의 변화

정적 타입 시스템과 컴파일 과정의 차이는 개발자의 개발 경험에 지대한 영향을 미칩니다.

  • 오류 조기 발견: 타입스크립트는 코드를 작성하는 즉시, 혹은 컴파일 시점에 타입 오류를 알려주기 때문에 런타임 오류로 인해 디버깅에 소모되는 시간을 획기적으로 줄여줍니다.
  • 강력한 도구 지원: IDE(통합 개발 환경)는 타입스크립트의 타입 정보를 활용하여 훨씬 더 정확하고 강력한 코드 자동 완성, 코드 탐색, 리팩터링 기능을 제공합니다. 이는 개발 생산성을 크게 향상시킵니다.
  • 코드의 명확성 및 협업 용이성: 타입 정보는 코드의 의도를 명확하게 드러내어 코드 가독성을 높이고, 여러 개발자가 함께 작업할 때 발생할 수 있는 소통의 오류를 줄여줍니다. 마치 코드에 상세한 사용 설명서가 붙어 있는 것과 같습니다.
  • 리팩터링의 안정성: 코드를 변경할 때, 타입 시스템이 변경으로 인해 발생할 수 있는 잠재적인 오류를 미리 경고해주므로, 더욱 안심하고 대규모 리팩터링을 진행할 수 있습니다.

요약하자면, 타입스크립트는 자바스크립트의 유연성을 유지하면서 타입 안정성과 도구 지원을 추가하는 언어입니다.

규모가 큰 코드베이스에서는 공개 API, 데이터 모델, 리팩터링 범위를 타입으로 확인할 수 있지만, 타입 설계와 빌드 설정 비용도 함께 고려해야 합니다.

물론 도입 비용도 분명히 존재합니다.

초기에 타입 설계와 설정에 시간이 들고, 팀이 타입 시스템에 익숙해질 때까지 학습 부담이 생깁니다.

그래서 좋은 도입 전략은 전체를 한 번에 전환하는 것보다 경계가 명확한 모듈부터 점진적으로 타입을 강화하는 방식입니다.

아래 다이어그램은 자바스크립트 코드베이스에 타입스크립트를 점진적으로 적용할 때의 현실적인 전환 순서를 보여줍니다.

기존 실행과 테스트 기준선이 없으면 먼저 기준선을 마련한다. 기준선이 준비되면 외부 입력의 unknown과 검증, 공용 API 타입, strict 검사 유지 순서로 전환한다. 이 절은 실제 마이그레이션 명령이나 완료 테스트를 제공하지 않는 전략 설명이다.

TYPE / RUNTIME / CONTRACT

기존 실행 기준을 유지하며 경계부터 타입을 강화한다

이 흐름은 기존 JavaScript 프로젝트의 점진적 전환 전략입니다. 기준선이 없으면 먼저 실행과 테스트를 고정하고, 외부 입력과 공용 계약을 작은 범위부터 옮긴 뒤 검사 강도를 유지합니다.

작은 범위의 타입 전환과 결과 대조기준선→외부입력→공용API→검사강도→변경검증→다음작은범위의6노드5간선이다. 기준선이없으면 먼저준비한다. 실제마이그레이션실행이나strict도입을반드시마지막으로미룬다는규칙이아닌전략설명이다.
1 · 기준선실행 · 테스트 확인
연결 관계1 · 기준선 · 실행 · 테스트 확인 → 2 · 외부 입력 · unknown · 값 검증
2 · 외부 입력unknown · 값 검증
연결 관계2 · 외부 입력 · unknown · 값 검증 → 3 · 공용 API · 타입 계약 표현
3 · 공용 API타입 계약 표현
연결 관계3 · 공용 API · 타입 계약 표현 → 4 · 검사 강도 · strict 적용 범위
4 · 검사 강도strict 적용 범위
연결 관계4 · 검사 강도 · strict 적용 범위 → 변경 검증 · 기존 결과와 비교
변경 검증기존 결과와 비교
연결 관계변경 검증 · 기존 결과와 비교 → 다음 작은 범위 · 전환을 반복
다음 작은 범위전환을 반복
작은 범위의 타입 전환과 결과 대조 · 모바일기준선→외부입력→공용API→검사강도→변경검증→다음작은범위의6노드5간선이다. 기준선이없으면 먼저준비한다. 실제마이그레이션실행이나strict도입을반드시마지막으로미룬다는규칙이아닌전략설명이다. 모바일에서도 노드와 연결 방향·독립 경로가 같다.
1 · 기준선실행 · 테스트 확인
연결 관계1 · 기준선 · 실행 · 테스트 확인 → 2 · 외부 입력 · unknown · 값 검증
2 · 외부 입력unknown · 값 검증
연결 관계2 · 외부 입력 · unknown · 값 검증 → 3 · 공용 API · 타입 계약 표현
3 · 공용 API타입 계약 표현
연결 관계3 · 공용 API · 타입 계약 표현 → 4 · 검사 강도 · strict 적용 범위
4 · 검사 강도strict 적용 범위
연결 관계4 · 검사 강도 · strict 적용 범위 → 변경 검증 · 기존 결과와 비교
변경 검증기존 결과와 비교
연결 관계변경 검증 · 기존 결과와 비교 → 다음 작은 범위 · 전환을 반복
다음 작은 범위전환을 반복

PRECONDITION

기준선이 없다면 먼저 고정한다

현재 빌드와 실행 결과, 테스트가 비교 기준입니다. 경계나 테스트가 준비되지 않았다면 이 준비부터 하고 다음 단계로 진행합니다.

INPUT / CONTRACT

모르는 외부 값부터 감싼다

입력 경계에는 unknown과 런타임 검증을 두고, 공용 함수와 데이터 모델에는 타입 계약을 표현합니다. 단언으로 외부 값의 정확성을 보장하지 않습니다.

STRATEGY / CONFIG

검사 강도는 전환 범위와 함께 정한다

any를 줄이고 strict 옵션을 적용할 범위를 정합니다. 이 순서는 도입 전략의 예이며 모든 프로젝트가 마지막까지 strict를 미뤄야 한다는 규칙은 아닙니다.

LESSON SCOPE

작은 범위의 결과를 비교하며 반복한다

본문은 도입 비용과 협업상 장점을 설명합니다. 실제 저장소 전환이나 CI 실행 예제는 제공하지 않습니다. 적용할 때는 옮긴 범위의 진단과 기존 실행 결과를 함께 확인합니다.

기존 실행과 테스트 기준선이 없으면 먼저 기준선을 마련한다. 기준선이 준비되면 외부 입력의 unknown과 검증, 공용 API 타입, strict 검사 유지 순서로 전환한다. 이 절은 실제 마이그레이션 명령이나 완료 테스트를 제공하지 않는 전략 설명이다.

자바스크립트와 타입스크립트의 차이는 실행 결과보다 피드백을 받는 시점에서 더 크게 느껴집니다.

타입을 먼저 적어두면 함수와 모듈의 계약이 에디터와 빌드 단계에서 확인되어 리팩터링과 협업의 불확실성이 줄어듭니다.


다음 절에서는 타입스크립트 개발을 위한 환경을 어떻게 설정해야 하는지 구체적으로 알아보겠습니다.