타입스크립트란
1. 강의에 대하여
이 강의는 JavaScript를 알고 있는 사용자를 대상으로 합니다. 만약 JavaScript를 모르신다면 위니북스 교안에 JavaScript 베이스캠프 강의를 먼저 수강하시기 바랍니다.
자바스크립트 베이스캠프2. 타입스크립트란
타입스크립트는 JavaScript를 기반으로 하는 오픈소스 프로그래밍 언어입니다. Microsoft에서 개발하며 유지 관리를 유지 관리하는 자바스크립트의 '수퍼셋'입니다. '수퍼셋'이란 자바스크립트의 모든 기능을 포함하면서도, 정적 타입, 인터페이스, 제네릭 등과 같은 추가 기능을 제공합니다.
이러한 특성 덕분에 아래와 같은 여러 장점들을 가집니다.
- 컴파일 시점 오류 감지: 코드를 실행하기 전에 오류를 발견할 수 있습니다.
- 향상된 코드 가독성: 타입 정보가 코드에 명시되어 있어 코드의 의도를 쉽게 파악할 수 있습니다.
- 강력한 IDE 지원: 자동완성, 리팩토링 등의 기능을 더 정확하게 사용할 수 있습니다.
- 최신 JavaScript 기능: 아직 브라우저에서 지원하지 않는 최신 기능들도 사용 가능합니다.
3. 타입스크립트의 필요성
자바스크립트만으로도 충분한 케이스가 있습니다. 먼저 간단한 예제부터 살펴보겠습니다.
3.1 자바스크립트로도 충분한 경우
// 버튼 클릭 시 메시지 출력
const button = document.querySelector('button');
button.addEventListener('click', () => {
alert('버튼이 클릭되었습니다!');
});
// 버튼 클릭 시 메시지 출력
const button = document.querySelector('button');
button.addEventListener('click', () => {
alert('버튼이 클릭되었습니다!');
});
위의 코드는 버튼 클릭 시 메시지를 출력하는 간단한 자바스크립트 코드입니다. 이와 같이 코드만 읽어도 어떤 자료형인지 알 수 있거나, 자료형을 알 필요가 없는 코드의 경우에는 타입스크립트를 사용하지 않아도 충분하다고 볼 수 있습니다.
또 다른 예시를 살펴보겠습니다.
// 간단한 계산기 함수
function calculate(operation, a, b) {
if (operation === 'add') return a + b;
if (operation === 'subtract') return a - b;
if (operation === 'multiply') return a * b;
if (operation === 'divide') return a / b;
}
console.log(calculate('add', 5, 3)); // 8
// 간단한 계산기 함수
function calculate(operation, a, b) {
if (operation === 'add') return a + b;
if (operation === 'subtract') return a - b;
if (operation === 'multiply') return a * b;
if (operation === 'divide') return a / b;
}
console.log(calculate('add', 5, 3)); // 8
이런 간단한 경우에는 자바스크립트만으로도 충분히 의도가 명확합니다.
3.2 타입스크립트가 필요한 경우
이번에는 좀 더 복잡한 자바스크립트 코드를 살펴보겠습니다.
function add(a, b) {
return a + b;
}
const result = add(1, '2');
console.log(result); // '12'
function add(a, b) {
return a + b;
}
const result = add(1, '2');
console.log(result); // '12'
두 개의 '숫자'를 입력 받아 더한 값을 반환해주는 함수를 만들었습니다. 그런데 실수로 문자열을 전달하면 어떻게 될까요?
// 숫자와 문자열을 더하면?
console.log(add(1, '2')); // '12' (예상: 3)
console.log(add('10', '20')); // '1020' (예상: 30)
// 숫자와 문자열을 더하면?
console.log(add(1, '2')); // '12' (예상: 3)
console.log(add('10', '20')); // '1020' (예상: 30)
이렇게 예상하지 못한 결과가 발생합니다. 왜 이런 일이 발생할까요?
- 타입 강제 변환: JavaScript는
+
연산자를 만나면 문자열이 하나라도 있으면 모두 문자열로 변환합니다. - 의도와 다른 동작: 숫자 더하기를 원했지만 문자열 연결이 발생했습니다.
- 런타임 오류: 이런 문제는 코드를 실행하기 전까지는 발견하기 어렵습니다.
실제 프로젝트에서 이런 문제가 발생한 예시를 더 살펴보겠습니다.
// 장바구니 총액 계산 함수
function calculateTotal(items) {
let total = 0;
for (let item of items) {
total = add(total, item.price); // price가 문자열이라면?
}
return total;
}
// 실수로 price가 문자열로 저장된 경우
const cart = [
{ name: '사과', price: 1000 },
{ name: '바나나', price: '2000' }, // 문자열!
{ name: '오렌지', price: 1500 }
];
console.log(calculateTotal(cart)); // '010002000' 같은 이상한 결과
// 장바구니 총액 계산 함수
function calculateTotal(items) {
let total = 0;
for (let item of items) {
total = add(total, item.price); // price가 문자열이라면?
}
return total;
}
// 실수로 price가 문자열로 저장된 경우
const cart = [
{ name: '사과', price: 1000 },
{ name: '바나나', price: '2000' }, // 문자열!
{ name: '오렌지', price: 1500 }
];
console.log(calculateTotal(cart)); // '010002000' 같은 이상한 결과
해당 함수의 올바른 사용법을 알려주기 위해 다음과 같은 주석을 달아보겠습니다. 이러한 형태의 주석을 JSDoc이라고 부릅니다.
/**
* 두 수의 차를 구한다.
* @param {number} a - 첫번째 매개변수 입니다.
* @param {number} b - 두번째 매개변수 입니다.
* @returns {number} - 리턴값 입니다.
*/
function add(a, b) {
return a + b;
}
/**
* 두 수의 차를 구한다.
* @param {number} a - 첫번째 매개변수 입니다.
* @param {number} b - 두번째 매개변수 입니다.
* @returns {number} - 리턴값 입니다.
*/
function add(a, b) {
return a + b;
}
이제 VSCode에서 커서를 가져가면 아래와 같이 볼 수 있습니다.

이제는 이 함수를 사용하는 사람이 첫번째 매개변수와 두번째 매개변수 그리고 리턴값이 무엇인지 알 수 있게 되었습니다. 조금 더 명확하고 목적에 맞게 쓸 수 있겠네요. 하지만 아쉽게도 모두가 함수의 파라미터가 어떤 형태인지 확인하진 않습니다. 아래처럼 입력을 해도 여전히 에러 없이 동작됩니다.

주석을 항상 신뢰할 수 없다는 단점도 있습니다. 주석을 다는 사람이 실수를 했을 경우를 가정해보겠습니다. 아래는 잘못된 주석으로 함수를 오용하는 경우입니다.

3.3 JavaScript에서의 해결 시도
이러한 문제가 발생되면 더욱 견고한 코드를 작성하기 어렵습니다. 그렇다면 JavaScript에서는 이러한 문제를 어떻게 해결하고 있는지 살펴보겠습니다.
3.3.1 타입 검사 추가하기
가장 많이 사용하는 방법은 조건문으로 타입을 검사하는 것입니다.
function add(a, b) {
if (typeof a !== 'number' || typeof b !== 'number') {
throw new TypeError('인자는 모두 숫자여야 합니다.');
}
return a + b;
}
try {
const result = add(1, '2'); // 에러 발생!
console.log(result);
} catch (error) {
console.error(error.message); // "인자는 모두 숫자여야 합니다."
}
function add(a, b) {
if (typeof a !== 'number' || typeof b !== 'number') {
throw new TypeError('인자는 모두 숫자여야 합니다.');
}
return a + b;
}
try {
const result = add(1, '2'); // 에러 발생!
console.log(result);
} catch (error) {
console.error(error.message); // "인자는 모두 숫자여야 합니다."
}
위의 코드에서 add
함수는 두 개의 인자 a
와 b
가 모두 숫자인지 확인한 후 더한 값을 반환합니다. 만약 인자 중 하나라도 숫자가 아니라면 TypeError
를 발생 시킵니다.
이렇게 자바스크립트에서도 타입 검사를 수행할 수 있지만, 코드가 복잡해지고 가독성이 떨어집니다. 그리고 여전히 함수 자체에서 a, b가 number가 아닌데도 함수 실행이 가능합니다. 직접 작성한 throw new TypeError('인자는 모두 숫자여야 합니다.');
에러 메시지가 아니라면 개발자는 어떤 문제로 이러한 문제가 발생되는지 찾아야 하며 문제마다 타입에 대해서 예외사항을 만들어야 합니다.
1.2 타입스크립트의 등장
앞서 자바스크립트에서 발생하는 불편한 부분을 해결하는 것은 간단합니다. 타입이 number
가 아니라면 애초에 a
와 b
에 할당할 수 없음을 알리는 것입니다. 그리고 한 번 정해진 a
와 b
의 타입은 변하지 않습니다.
하나의 변수의 타입이 계속 바뀌는 자바스크립트의 타입 형태를 동적 타입이라고 부릅니다. 그리고 한번 정해진 변수의 타입이 바뀌지 않는 타입 형태를 정적 타입이라고 합니다.
그럼 타입스크립트에서는 앞서 살펴본 add
함수를 어떤 식으로 작성하고, 위와 같이 의도한 형태로 타입을 사용하지 않았을 때 어떻게 오류를 잡는지 살펴보겠습니다.
// a, b가 number타입임을 명시
// 이 함수가 반환하는 값이 number임을 명시
function add(a: number, b: number): number {
return a + b;
}
const result = add(1, '2'); // 에러: 인자 '2'의 타입이 'number'가 아님
console.log(result);
// a, b가 number타입임을 명시
// 이 함수가 반환하는 값이 number임을 명시
function add(a: number, b: number): number {
return a + b;
}
const result = add(1, '2'); // 에러: 인자 '2'의 타입이 'number'가 아님
console.log(result);
여기서 a: number, b: number
부분으로 a와 b가 number 타입임을 명시하고 있습니다. 그리고 : number
부분으로 이 함수가 반환하는 값이 number임을 명시하고 있습니다. 이렇게 타입을 명시함으로써 함수를 사용하는 사람이 함수의 사용법을 더 명확하게 알 수 있습니다.
이렇게 타입스크립트는 어떠한 값에 대해 타입을 명시적으로 작성할 수 있는 기능을 제공하고 있습니다. 이러한 점을 이용하여 코드를 작성하게 되면 이 함수를 사용하는 개발자는 '함수 add
가 문자열을 합치는 것인지?', '숫자를 더해주는 함수인지?'에서 주는 혼란에서 탈출할 수 있게 됩니다.
이렇게 타입을 제대로 작성하는 것만으로 많은 것들을 해결할 수 있고 편리함도 생길 수 있습니다. 앞서 자바스크립트코드에서 타입을 알리기 위해 주석을 작성했습니다.
이 주석은 함수 사용법에 대한 문서로 생각할 수도 있습니다. 그런데 우리는 이런 정보 전달을 타입스크립트에서 주석 없이 코드로만 작성했습니다. 코드만 작성했을 뿐인데 하나의 문서와 같은 역할 또한 하게 될 수 있습니다. 타입스크립트에서는 잘 만든 코드 자체가 문서가 될 수 있습니다. 그리고 타입을 넣어서 조금 더 문서처럼 작성하는 주석을 줄일 수도 있겠습니다.
이렇게 타입을 작성하는 것 만으로 많은 것을 전해 줄 수 있습니다.
4. 타입스크립트의 단점
타입스크립트가 많은 장점을 가지고 있지만, 모든 프로젝트에 적합한 것은 아닙니다. 실제로 타입스크립트를 회사 프로젝트에서 제외하는 경우도 종종 발생됩니다. 이번에는 타입스크립트를 사용하지 않는 이유에 대해 알아보겠습니다.
4.1 주요 단점들
-
학습 곡선: 자바스크립트 개발자에게 타입스크립트의 타입 시스템은 처음에 복잡하게 느껴질 수 있습니다. 타입스크립트의 고급 기능들(제네릭, 인터페이스, 네임스페이스 등)을 익히는 데 시간이 필요합니다.
-
개발 시간 증가: 코드에 타입을 명시해야 하기 때문에, 개발 초기 단계에서는 작성 시간이 더 걸릴 수 있습니다. 이는 특히 테스트용 프로토타입, MVP(Minimum Viable Product)를 빠르게 만들어야 하는 상황에서 단점이 될 수 있습니다.
-
서드파티 라이브러리 호환성: 외부 라이브러리 사용 시 타입 정의가 없거나 불완전할 수 있습니다.
4.2 업계 의견
타입스크립트에 대한 업계의 다양한 의견이 있습니다.
TypeScript 퇴출 논란 JS와 TS 사용 현황