
며칠 전, 평소와 다름없이 JS(JavaScript)와 React 공부를 하고 있던 나는 갑자기 현타(?) 비슷한 것이 찾아와 최근까지 개발 공부를 좀 게을리 하고 있었다. 그러다가 이렇게 된 이유가 뭘까 고민하다가, 그 이유가 "뭔가 새로운 것을 공부해야 하는데 무엇을 공부해야 할지 모르겠다"는 점이라는 결론을 내렸다. 뭔가 나만의 로드맵이 필요한 느낌이었다.
그런데 이유를 알면서도 문제를 해결하지 못했다. 그렇게 한참 더 고민하다가 "뭔가 특별한 것이 아니어도 그냥 유명한 것이라도 공부해보자"라는 생각이 들어 TS(TypeScript) 공부를 시작했다. 근데 무작정 시작하면 가장 중요한 그 기술을 사용하는 이유를 모르고 넘어갈 수 있기에 이 글을 쓰게 됐다.
TS는 JS의 단점을 보완하기 위해 Microsoft에서 개발한 정적 타입 언어(static type language)이다.
JS가 확장된 언어이기 때문에 기존 JS의 기능을 모두 사용할 수 있으며, 브라우저에서 실행시키기 위해서는 컴파일(compile)이라는 변환 과정을 거쳐야 한다.
컴파일은 특정 언어로 작성된 프로그램의 코드를 다른 언어로 변환하는 과정이다.
(예시: C언어 → 어셈블리어 → 기계어)
TS의 가장 큰 특징은 변수, 매개변수, 함수 반환 값 등에 타입을 지정할 수 있다는 것이다. 이를 통해 코드 작성 시점에 타입 오류를 발견할 수 있으며, 보다 안전하게 코드를 작성할 수 있게 된다.

아까도 말했지만 변수, 매개변수, 함수 반환 값 등에 타입을 지정(에러 사전 방지)할 수 있어서 사용한다.
// js
function sum(a, b) {
return a + b;
}
// ts
function sum(a: number, b: number) {
return a + b;
}
숫자 a와 b를 인자로 받아 더한 값을 리턴해주는 sum이라는 함수다. 그런데 인자로 숫자가 아닌 문자열 "10"과 "20"을 넣어서 sum("10", "20")을 실행하면, JS에서는 오류 없이 "1020"이라는 값이 출력될 것이다."
sum("10", "20")
// Argument of type 'string' is not assignable to parameter of type 'number'.
// 'string' 타입의 인수는 'number' 타입의 매개변수에 할당할 수 없습니다.
하지만 TS에서 동일한 함수를 실행한다면 위와 같이 number 타입에 문자열을 할당할 수 없다고 에러가 발생하게 되어 의도하지 않은 코드의 동작을 예방할 수 있다. 예를 들어, API 요청으로 받아온 데이터의 타입이 예상과 다를 경우 에러가 발생할 수 있는데, TS를 사용하면 이러한 에러를 빠르게 찾아낼 수 있다.
function divide(a, b) {
return a / b;
}
console.log(divide("xxx")) // NaN
그리고 위 코드는 JS를 처음 배울 때도 좀 신선한 충격이였다.
TS에는 JS에서도 사용할 수 있는 타입과 TS에서만 사용할 수 있는 타입을 포함해 정말 다양한 타입이 있다.
let num: number = 10;
let str: string = "Hello, world!";
let isLogin: boolean = true;
let arr: number[] = [1,2,3];
let arr: Array<number> = [1,2,3];
object 타입은 원시 타입을 제외한 모든 타입에 할당할 수 있다. 하지만 TS에서 object 타입으로 지정된 변수는 그저 객체임을 의미할 뿐, 그 안에 어떤 속성이 있는지는 알 수 없어서 거의 사용하지 않는다.
let obj: object = {name: "전준연", age: 17};
tuple은 배열의 길이가 고정되고, 각 요소의 타입이 지정된 배열 형식을 의미한다.
let arr: [string, number] = ["Hello", 10];
모든 타입을 허용하는 타입이다. 타입 검사가 필요 없을 때 사용하지만, 권장되지는 않는다.
let str: any = 'hi';
let num: any = 10;
let arr: any = ['a', 2, true];
반환 값이 없는 함수의 반환 타입에 주로 사용된다. 반환 값이 없는 함수의 기본 타입이기 때문에 굳이 사용하지 않아도 무방하다.
function Message(message: string): void {
console.log(message);
}
각각 null과 undefined 값만을 가질 수 있다.
let nullableValue: null = null;
let undefinedValue: undefined = undefined;
절대 발생하지 않는 값을 의미하며, 주로 오류를 발생시키거나 끝나지 않는 함수의 반환 타입으로 사용된다. (거의 사용되지 않는다.)
function throwError(message: string): never {
throw new Error(message);
}
any와 유사하지만, 안전한 타입으로 알려지기 전까지는 조작이 제한된다.
let value: unknown = "Hello";
if (typeof value === "string") {
console.log(value.toUpperCase()); // 타입 확인 후 사용 가능
}
특정 값들의 집합을 열거하여 사용할 수 있다.
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT"
}
let move: Direction = Direction.Up;
오늘은 TypeScript가 무엇인지, 사용하는 이유, 그리고 TypeScript에서 사용하는 다양한 타입들에 대해 알아봤다. 어느 블로그에서, '본인이 쓴 코드를 완벽하게 기억하고 이해하고 있을 자신이 있다면, 그냥 JS 써도 된다.'라는 글을 봤는데, 당연한 말이지만, 나는 그럴 수 없으니 TS 공부를 열심히 해야 할 것 같다...
제네릭 타입 설명해 주세요