요즘 이펙티브 타입스크립트 스터디를 진행하고 있다. 벌써 절반 정도 읽었는데, 타입스크립트도 제대로 안써본 내게는 어려운 내용이지만, 실제로 사용하게 되면 도움될만한 내용들이 많았다. 이제 프론트엔드에게 타입스크립트가 필수가 되어버린 시대인데 아직 제대로 써본 경험이 없어 조금 부끄럽다.. 이전 회사에서도 안정성을 위해 무작정 써보자고만 했었지, 정확한 이유를 설명하진 못했다.(물론 클라이언트사에서 거절 당해 결국 써보진 못했지만 말이다..)
이펙티브 타입스크립트와 별개로 실제 코드에서 어떻게 활용하면 되는지 궁금해서 우아한 타입스크립트 with 리액트 책도 구매해서 보는 중이다. 책을 읽다 보니 문득 타입스크립트를 왜 쓰는지 그 이유를 명확히 이해하고 넘어가는 것이 중요하다는 생각이 들었다. 더 이상 나는 신입이 아니기에 남들이 쓰니까 나도 사용해야 한다는 단순한 이유로는 부족하다. 나는 대부분 타입스크립트 없이 리액트를 사용했었는데 솔직히 크게 불편함을 느끼진 못했다. 오히려 개발 속도가 빨라서 만족스러웠고, 타입을 관리할 필요도 없었기 때문에 폴더 구조도 복잡하지 않았다. 타입으로 인한 예상치 못한 오류를 마주친 적이 없던 것도 한 몫 한다.
그래서 구글링만 해도 나와있는 수많은 "타입스크립트를 써야하는 이유"들에 대해서 정확하게 이해를 하고 넘어가야 할 것 같다고 생각했다.
버그 예방
자바스크립트의 버그 중 15%는 타입스크립트의 사용으로 미리 예방할 수 있는 연구가 있다고 한다. 자바스크립트는 선언할 때 타입을 지정하지 않기 때문에, 동작하면서 내가 모르는 사이에 형변환이 되어 있는 부분이 예상치 못한 오류를 발생시킬 수 있다. 자바스크립트의 동적 타입 특성상 이런 버그들을 찾기 힘들기 때문에 컴파일 단계에서 에러를 알려주는 타입스크립트를 사용해 이를 미리 방지할 수 있다.
타입스크립트는 tsc라는 컴파일러를 통해 자바스크립트로 변환된다. 보통 컴파일은 고수준 언어(사람이 이해하기 쉬운 언어)가 저수준 언어(컴퓨터가 이해하기 쉬운 언어)로 변환될 때 사용하는 용어인데, 타입스크립트는 고수준 언어 -> 고수준 언어로 변환되기 때문에 컴파일이 아닌 트랜스파일이라고 부르기도 한다. (바벨 또한 트랜스파일이지만 컴파일과 트랜스파일을 통틀어 그냥 컴파일이라고 부른다고 한다.)
자바스크립트는 별도의 컴파일 단계없이 프로그램이 바로 실행되는데, 엄밀히 말하자면 JS를 해석하고 실행하는 V8엔진에서 JS코드를 최적화하는 컴파일 단계를 거친다고 한다.
그렇다면 타입스크립트의 컴파일러은 어떻게 동작하는 것일까?
1. 파일 로드 및 파싱
tsc는 컴파일할 타입스크립트 파일을 로드하고 구문분석을 한다. 이 단계에서 tsconfig.json 파일이 있다면 이 설정을 기반으로 컴파일할 파일의 목록과 설정을 로드한다. 또한 타입스크립트 파일의 코드를 AST(Abstract Syntax Tree, 최소 구문 트리)로 변환하여 구문적 구조를 이해한다.
2. 타입 검사 (Type Checking)
자바스크립트의 상위 집합인 타입스크립트는 명시적 혹은 추론된 타입을 기반으로 코드를 검사한다. 컴파일러는 각 변수, 함수, 객체의 타입을 검사하고 타입이 일치하지 않거나 오류가 있으면 이 단계에서 에러가 발생한다.
3. JavaScript 코드 생성
타입 검사가 끝나면 타입스크립트는 코드를 자바스크립트로 변환한다. 이때 타입스크립트의 고유 문법(interface, type, enum, 제네릭 등)은 모두 제거되거나 대응되는 자바스크립트의 코드로 변환된다.
// TypeScript 코드
interface Person {
name: string;
age: number;
}
const person: Person = { name: "Alice", age: 30 };
// 컴파일 후의 JavaScript 코드
const person = { name: "Alice", age: 30 };
4. 출력 및 번들링
컴파일된 자바스크립트 파일을 지정된 디렉토리나 기본 디렉토리에 출력한다. tsconfig.json을 통해 자바스크립트의 버전(ES5, ES6 등)과 출력 형식을 결정할 수 있다. 또한, 여러 파일을 하나의 파일로 번들링하거나, 모듈 시스템에 맞게 출력 형식을 지정할 수도 있다.
위 과정들을 거쳐 오류를 뱉거나, 정상적으로 자바스크립트 파일을 생성하는 것이 tsc의 역할이다. 만약 타입스크립트를 사용하지 않은 경우에는 어떤 오류가 발생하는지 아래 코드를 보자
// 이 함수는 숫자 a,b의 합을 반환한다
const sumNumber = (a,b) => {
return a+b;
}
sumNumber(1,2) // 3
이 코드를 실행하면 어떤 에러도 발생하지 않고 정상적으로 잘 작동한다. 그러나 함수 호출할 때 인자에 다른 값을 넘겨주면 어떻게 될까?
sumNumber(100) // NaN (100+undefined)
sumNumber("a", "b") // ab
만약 함수에 인자를 하나만 전달하게 된다면 NaN이 뜨게 되고, 숫자가 아닌 문자열을 전달해도 문자를 더하며 정상적으로 동작하게 된다. 함수의 이름과 전혀 다른 동작을 하게 되는 코드가 되는 것이다. 자바스크립트는 동적 타입 언어이기 때문에 상당히 관대하다. 이는 곧 개발자의 의도와 코드가 다르게 동작할 수 있고, 오류가 발생되어야 할 부분에서 정상적으로 동작해 디버깅이 어려워질 수 있다. 이러한 문제들로 인해 타입스크립트를 사용함으로써 버그를 예방할 수 있다.
자동 완성으로 인한 DX 향상
주변 프론트엔드 개발자들에게 물어봤을 때 가장 큰 이유를 차지했었는데, 바로 더 나은 개발자 경험이다. 타입스크립트는 정적 타입 정보를 제공하기 때문에 편집기에서 자동완성 기능을 제공하는데 이 기능 덕분에 코드를 작성하는 속도가 빨라지고, 함수나 변수 사용법을 빠르게 파악할 수 있기 때문에 정확성 향상 및 오류가 줄어든다는 점이었다. 게다가 오타를 방지할 수 있기 때문에 오타가 자주 발생했던 개발자들에게 특히 유용하다고 한다.
코드 가독성 향상 및 협업의 중요성
이전 회사에서 프로젝트의 프론트 업무를 혼자 도맡아 했기에 협업을 경험해보지 못했다. 그래서 나는 타입스크립트의 필요성을 더 느끼지 못했던 것 같다.
우아한 타입스크립트 책에 따르면, 서비스가 커질수록 개발 후에 유지보수를 하는 데 있어 협업의 중요성도 높아진다고 한다. 만약 내가 전날 만든 함수를 오늘 사용한다면 함수 사용법을 쉽게 파악할 수 있지만, 한 달이 지나 후에 다시 함수를 사용하려 한다면 어떤 인자를 넣어야 하고 무엇이 반환되는지 파악하는 데 약간의 시간이 더 들 것이다. 내가 만든 함수가 아니라면 어떨까? 개발에 투입된 인원이 5명, 10명 이상이라면 어떨까?
개발에 투입된 인원이 많아질수록 코드를 파악하기 어려운 것은 당연한 것이다. 게다가 다른 동료가 작성한 코드를 질문하기 위해서는 그 동료가 회사에 남아있어야 가능한 것이다. 따라서 타입스크립트는 규모가 큰 프로덕트를 개발할 때 효율적인 유지보수를 위한 협업 보완책으로 큰 도움이 된다.
결론
타입스크립트를 사용하면 안전성, 생산성, 유지보수성 등 다양한 측면에서 유리한 점을 알게 되었다. 타입스크립트가 장점만 존재하지는 않지만 이 글에서는 사용해야 하는 이유에 대해서 중점적으로 알아봤다. (단점으로는 러닝 커브, 컴파일 시간 증가, 복잡성 등이 있다.)
왜 쓰는지 제대로 알지도 못한 상태에서 타입스크립트를 공부하기 보다는 '이렇게 쓰는 이유는 이러한 이유 때문이겠구나' 라고 생각할 수 있는 계기가 되었다. 이렇게 정리해도 이펙티브 타입스크립트는 아직까지 어렵겠지만.. 하다보면 안될 건 없겠지. 내 포트폴리오에 한 번 적용해보고, 사이드 프로젝트로 협업하면서 적용하고 하다 보면 나도 절실하게 필요성을 느낄 날이 오겠지. 여러 프론트 개발자들이 더 이상 타입스크립트가 없으면 개발을 제대로 못할 정도로 불편하다고 한다.. 또, 나는 앞으로 협업을 잘하는 개발자가 될 예정이니깐 얼른 공부하고 적용해보자 !
Reference
'개발 > 프론트엔드' 카테고리의 다른 글
[CI/CD]vercel에 무료로 organization레포지토리 배포하기 (0) | 2024.09.26 |
---|---|
[NextJS] NextJS와 TailwindCSS로 폰트 설정하기 (0) | 2024.09.18 |
[React] 리액트로 스톱워치 Chrome Extension 만들기 (0) | 2024.08.29 |
[NextJS]App Router - 앱 최적화와 캐싱 (0) | 2024.08.01 |
[NextJS]App Router - 라우팅(Routing) 종류 (0) | 2024.07.05 |