2020. 12. 11. 16:47ㆍ재주껏 하는 Front-End/타입스크립트 (준비중)
타입 스크립트는 2012년 마이크로소프트에서 개발한 자바스크립트의 상위 호환 언어로 초기에는 크게 주목받지 못했지만, NodeJS와 ESNext의 등장으로 자바스크립트의 사용 범위가 프런트엔드, 백엔드, 심지어 데스크톱 애플리케이션까지 진출하면서 현재는 가장 많이 사용하는 인기 언어로 발전하게 되었다.
2019년 자바스크립트에 관련된 인기도를 조사한 stateofjs의 언어 인기도를 보면 2017년부터 전 세계의 자바스크립트 개발자들은 이미 타입 스크립트를 가장 많이 사용하는 것으로 조사되었다.
이처럼 이미 자바스크립트 개발 영역에서 타입 스크립트가 차지하는 비율은 매우 높은 수준이다. 이미 구글에서는 사내 기본 언어를 타입 스크립트로 지정하였으며, 국내에서도 IT 대기업들은 타입 스크립트를 사용하여 자신들만의 서비스를 제공하고 있다.
그렇다면 어떤 장점 때문에 타입 스크립트를 사용하는 것일까? 지금부터 타입 스크립트에 대해 자세하게 알아보자.
예측하기 힘든 자바스크립트의 문제
웹 개발에서 가장 중요한 언어인 자바스크립트는 1995년 넷스케이프에서 개발된 스크립트 언어로, 단조로운 HTML 페이지를 좀 더 동적으로 보여주기 위해 적용된 가벼운 스크립트 언어다. 1996년 표준화 기구인 ECMA International에서 ECMA-262로 표준화가 진행되었고 1997년 완성되었는데, 이미 SUN에서 등록한 JAVA로 인해 Javascript가 아닌 ECMA Script로 등록되었다.
자바스크립트가 개발된 주목적이 HTML 페이지를 "보조"하기 위한 것이다 보니, 웹 개발자들이 쉽게 접할 수 있도록 여러 개의 언어의 장점을 모아서 개발하게 되었다. 예를 들어, 변수 / 스코프 / 클로저는 Lisp에서 가져오고 프로토타입은 Self 프로그래밍에서 참고하였다. 또한, 넷스케이프 사는 JAVA와 Javascript의 문법이 비슷하길 원했기 때문에 JAVA의 문법과 흡사한 모양이 되어버렸다.
위와 같은 환경으로 자바스크립트는 당시에 유명한 언어의 특징들만 가져와서 섞어 만든 느낌이 크게 들었으며, 설계에서도 문제가 있음이 밝혀졌다. (실제로 자바스크립트를 개발한 개발자가 인정했다. > 더글라스 클락포드의 자바스크립트 책 참고.)
가장 대표적인 문제는 내장 함수 호출 시 This 연산자의 동작이 다른 경우가 있다는 것인데, 예제 코드로 한번 확인해보자.
const countObj = {
count: 1,
addCount () {
this.count++
console.log('Counter Value > ', this.count)
const addCount2 = function () {
this.count++
console.log('Counter Value 2 > ', this.count)
}
addCount2()
}
}
여러분이 보기에 이 코드의 결과 값이 어떻게 나올 것이라고 생각하는가? 일반적인 객체 지향 언어라면 당연히 2와 3이 출력되는 것이 정답이다. 그리고 여러분도 그렇게 나오는 것이 정상이라고 생각할 것이다. 하지만, 위의 코드의 실행 결과는 아래와 같다.
Counter Value > 2
Counter Value2 > NaN
상위 함수의 This 접근은 자기 자신을 제대로 가리켰지만, 내부 함수의 This는 엉뚱한 곳을 가리키고 있다. 내부 함수가 가리키는 곳은 자바스크립트 최상위 객체인 window 객체이다. window.count = 100을 추가하고 실행해보자.
window.count = 100
const countObj = {
count: 1,
addCount () {
this.count++
console.log('Counter Value > ', this.count)
const addCount2 = function () {
this.count++
console.log('Counter Value 2 > ', this.count)
}
addCount2()
}
}
결과는 아래와 같다.
Counter Value > 2
Counter Value2 > 101
이 문제는 자바스크립트 설계 결함의 대표적인 사례이며, 많은 개발자들을 멘붕 하게 한 문제이기도 하다. 내부 함수에 This를 사용한 것 만으로 프로그램에 엄청난 오류를 범할 수 있다고 생각하지 않는가? 만약, 프로젝트의 규모가 크고 countObj 객체가 매우 복잡하고 많은 곳에 영향을 미치는 것이라면 치명적인 실수가 될 수 있다. 또한, 이러한 오류는 찾기도 매우 힘들다.
자바스크립트의 결함 외에도 자바스크립트는 태생적으로 에러를 찾기가 쉽지 않다. 다른 명령형 언어의 경우 컴파일이라는 과정을 통해서 문법 오류를 쉽게 찾을 수 있는데, 자바스크립트의 경우 인터프리터가 실행하면서 읽는 스크립트이다 보니 컴파일 과정이 없다. 이미 많은 개발자들이 겪었겠지만, 정말 사소한 문법 오류가 있더라도 자바스크립트는 에러를 출력하지 않고 실행된다.
이러한 문법적인 에러를 막기 위해 ES Lint를 사용하여 사전에 방지하려고 하지만, 오류를 검출해내는 Lint 조차 잡지 못하는 에러들이 존재한다. 대표적인 문제로는 개발자들 간의 소통 부족 또는 실수가 있다. 아래와 같은 상황을 생각해보자.
아래의 함수는 개발자 A가 자동차 모델을 새로 생성하기 위해 정의한 createCar 함수로, model에는 자동차 이름이 전달되어야 하고, price에는 가격이 전달되어야 한다.
function createCar(model, price) {
...
}
개발자 B는 개발자 A가 만든 createCar 함수를 사용한다고 가정해보자. 그런데 개발자 B가 실수로 인자를 잘못 넘겨 출력하였다.
createCar(2400, 'The New Malibu')
개발자 B는 에러 없이 호출된 것을 보고 결과 값이 어떻게 나오나 확인해봤는데, 전혀 엉뚱한 값이 나왔음을 알아차렸다. 이 경우에 개발자 B는 어떤 에러가 발생하였는지 파악하기 위해 createCar의 내용을 모두 찾아봐야 한다. 다른 사람이 짠 코드를 분석하기를 좋아하는 개발자들은 아무도 없을 것이다. 심지어 createCar 내부의 내용이 매우 복잡하고 속된 말로 개판으로 작성되어 있다면 에러를 잡기 위해 많은 시간을 허비할 것이다. (그리고, 인자를 잘못 넣었다는 사실에 분노할 것이다.)
위의 사례는 실제 개발을 하면서 아주 빈번하게 일어나는 문제들이다. 만약, 자바스크립트가 인자 값이 잘못 전달되었음을 알려주는 에러를 출력했다면 에러를 찾기 위해 많은 시간을 허비하지 않아도 될 것이다. 하지만, 현재 자바스크립트에서는 이러한 문제를 해결하기 어렵다.
타입 스크립트의 장점
위와 같은 여러 가지 문제들로 인해 자바스크립트로 개발한 웹 애플리케이션은 네이티브 프로그램들과 달리 많은 잠재적인 오류를 가지고 있을 수밖에 없다. 이러한 문제들을 효과적으로 해결할 수 있는 방안은 없을까?
당연히 있다. 그것이 오늘부터 살펴볼 타입 스크립트이며, 이미 많은 기업들이 사용하여 효과적으로 오류율을 줄이고 있다. 타입 스크립트를 사용함으로써 얻어지는 장점에 대해 나열하면 아래와 같다.
1) 타입 스크립트는 컴파일러로 사전에 에러를 발견할 수 있다
타입 스크립트를 설치하면 tsc라는 명령어로 타입 스크립트 파일을 컴파일할 수 있다. 타입 스크립트가 컴파일된 결과물은 자바스크립트로 출력된다. 컴파일 단계에서 문법 에러를 잡을 수 있으므로, 사소한 실수들을 런타임 전에 모두 체크할 수 있다. 또한, tsconfig.js 파일에 명시된 ESMA 버전으로 자동으로 변환할 수도 있다. (기본값 - ES5)
2) 타입 스크립트는 타입을 강제화한다
자바스크립트는 변수에 값을 넣을 때 타입을 엄격하게 체크하지 않는 "세미 타입" 언어이다. 비슷한 언어로는 파이썬이 있는데, 이 언어들은 변수에 값을 대입할 때 입력된 값의 타입을 보고 자동으로 형 변환을 한다는 것이다. (타입 추론)
이러한 특징은 개발자 입장에서는 변수를 선언할 때 타입을 신경 쓰지 않아도 되므로 코딩은 편리하겠지만, 위에서 살펴본 개발자들 간의 소통 문제로 버그를 발생시킬 여지가 있다.
타입 스크립트는 모든 객체에 타입을 강제화하여 타입으로 발생하는 문제를 원천 차단한다. 위에 개발자 A, B의 문제를 타입 스크립트로 변경해보자. createCar 함수의 매개 변수 타입을 model은 문자열만, price는 숫자만 넘어올 수 있도록 강제화 하였다.
function createCar(model: string, price: number) {
...
}
개발자 B가 아래와 같이 잘못 호출하면...
createCar(2400, 'The New Malibu')
아래와 같이 어디에서 에러가 발생하였는지 친절하게 설명해준다.
createCar.ts:2:11 - error : TS2345: Argument of type '2400' is not assignable to paramater of type 'string'.
타입 스크립트는 이름에서도 알 수 있듯이 타입을 강제화 하는 것이 핵심이다. 타입 스크립트에서는 타입을 강제화하기 위해 다양한 문법을 제공한다.
3) 무료 IDE에서도 강력한 기능을 제공한다
타입 스크립트를 만든 마이크로소프트는 IDE 개발의 강자로, 대표적인 개발 툴로는 Visual Studio 시리즈가 있다. 특히, 2015년 무료로 배포한 VS Code는 버전이 업그레이드되면서 매우 강력한 개발 툴로 발전하게 되었다. 아마 대부분의 스타트업이나 중소기업에서는 VS Code를 커스텀하여 사용하고 있을 것으로 생각한다.
우리가 앞으로 살펴볼 예제들도 모두 VS Code로 진행할 예정이다. 타입 스크립트로 애플리케이션을 만들 때 VS Code만 있으면 충분하다. 타입 스크립트에 관련된 다양한 기능과 플러그인이 이미 넘쳐나기 때문이다.
4) 타입 스크립트는 ES Next를 완벽하게 활용할 수 있다
자바스크립트는 ECMA 4 버전에서 내부 정치로 인해 표준화되지 못하면서 오랜 시간 동안 발전하지 못했다. 다행히도 2009년 현재 사용하는 자바스크립트의 기본이라 할 수 있는 ECMA 5 버전과 NodeJS가 등장하면서 가장 상승세가 높은 인기 언어로 발전하였다.
특히, 2015년에 발표된 ECMA 2015 (이하 ES Next)에서 수많은 신기능이 대거 추가되면서 자바스크립트가 영역을 넓힐 수 있는 디딤돌이 되었다. 그러나, 너무 많은 것이 바뀐 나머지 수많은 모듈과 브라우저가 새로운 기능을 지원하지 않아 제대로 사용할 수 없었으며, 호환성을 해결하기 위해 Babel을 사용하여 이전 버전의 자바스크립트로 변환하는 등의 불편한 방법들이 추가로 필요하게 되었다.
타입 스크립트는 ES Next 문법을 사용해도 tsconfig.js에 지정된 자바스크립트 버전으로 자동으로 변환해주기 때문에, 개발자는 최신 자바스크립트의 편리한 기능들을 호환성 걱정 없이 사용할 수 있다. (일부 모듈에서는 여전히 Babel이 필요하다.)
5) 타입 스크립트는 객체 지향 언어 스타일로 코드를 작성한다
위에서 자바스크립트를 개발할 때 여러 가지 언어들의 특징을 섞어서 만들다 보니, 이도 저도 아닌 언어가 되어 버렸다고 설명했다. 클래스는 지원하지 않지만 객체를 생성하여 내부적으로 This를 사용하는 것을 대표적인 사례로 뽑을 수 있다.
즉, 객체 지향의 기본이 되는 클래스가 없는데 마치 객체 지향 언어처럼 객체를 생성하고 사용하는 것이다. 또한, 함수형 언어의 특징도 가지고 있어서 함수를 인자로 전달하고 변수에 할당하며 리턴 값으로 사용할 수도 있다. 심지어 프로토 타입 기반의 언어의 특징도 가지고 있어서 프로토 타입을 활용하여 객체의 공통적인 작업도 명시할 수 있다. (도대체 정체가 뭐야??)
다행히도 ES Next부터 Class가 도입되어 온전한 객체 지향 언어의 형태를 띠게 되었으며, 타입 스크립트에서는 타입의 포맷을 지정하는 인터페이스, 가상 클래스 등의 객체 지향 언어에서 사용하는 문법들을 추가로 지원한다. 객체 지향 언어에 익숙한 많은 개발자들이 좀 더 편하게 타입 스크립트와 친해질 수 있다.
타입 스크립트의 단점
위에서 살펴본 것처럼 타입 스크립트는 웹 애플리케이션의 품질을 좌우할 정도의 큰 장점들을 가지고 있다. 하지만, 타입 스크립트가 완벽한 것은 아니다. 타입 스크립트를 적용할 경우 발생하는 단점들에 대해서 알아보자.
1) 규모가 커지면 커질수록 귀찮은 타입 설정
타입 스크립트는 타입을 강제화하는 것이 주목적이기 때문에, 하나부터 열까지 모두 타입을 지정해야 한다. 일부 변수에 대해서는 타입 추론으로 자동으로 인식하지만, 배열 / 객체 / 함수의 경우 설정할 수 있는 포맷이 워낙 많다 보니 사용자가 타입을 선언하여 미리 제한해야 한다. 객체의 타입을 지정하는 인터페이스를 미친 듯이 선언해야 할 수도 있다.
2) 코드의 가독성이 떨어진다
타입 스크립트는 모든 객체에 대해 타입을 지정해야만 한다. 타입을 추론하기 힘든 경우, 컴파일러에게 알려주는 형 변환을 하거나, 제네릭을 사용하여 어떤 타입이 들어오더라도 동작할 수 있도록 선언해야 한다. 문제는, 이러한 문법을 적용하면 코드가 엄청 길어진다는 것에 있다. 간단히 예제를 살펴보자.
아래는 일반 자바스크립트의 함수의 예시이다.
function (model, price, callback = null) {
if(callback) {
callback()
}
return {
model,
price
}
}
아래는 타입 스크립트의 함수 예시이다.
const typescriptFunc = (model: string, price: number, callback: () => boolean) : {model: string, price: number} => {
if (callback) {
callback()
}
return {
model,
price
}
}
딱 봐도 타입 스크립트의 코드가 월등히 긴 것을 알 수 있다. 만약, 고차 함수나 제네릭 등을 사용하여 다양한 타입에 대응하는 함수라면 복잡도는 더욱 올라간다. 배열의 길이를 출력하는 함수를 자바스크립트와 타입 스크립트로 작성해보자.
// 자바스크립트
const length = (array) => array.length
const isEmpty = (array) => length(array) === 0
isEmpty([1,2,3,4,5]) // False
isEmpty([]) // True
// 타입 스크립트
const lengthT = <T>(array: T[]) : number => array.length
const isEmptyT = <T>(array: T[]) : boolean => lengthT<T>(array) === 0
isEmptyT([1,2,3,4,5]) // False
isEmptyT([]) // True
위와 같이 타입 스크립트의 코드는 자바스크립트와 달리 문법적으로 매우 복잡해질 수 있다.
3) 사용하는 프레임워크에 적용 시 상황에 따라 매우 귀찮아질 수 있다
자바스크립트로 작성한 모든 코드들은 타입 스크립트로 짤 수 있다. 하지만, 타입 스크립트로 작성되지 않은 복잡한 프레임워크의 경우 타입 스크립트로 코드를 작성하기 위해서는 매우 귀찮은 작업들이 동반될 수 있다. 아래는 Vue 2.x에서 타입 스크립트를 사용하기 위해 해줘야 하는 기본적인 작업들이다.
blog.logrocket.com/how-to-write-a-vue-js-app-completely-in-typescript/
다행히도, 프레임워크 3 대장 + Svelte의 경우에는 타입 스크립트를 기본적으로 제공하기 때문에 이 단점은 조만간 해소될 것으로 예상된다.
4) 근본적인 자바스크립트 오류는 해결할 수 없다
타입 스크립트는 자바스크립트의 슈퍼셋 언어이지만, 원본은 자바스크립트이기 때문에 앞에서 설명한 자바스크립트 결함인 내장 함수의 This 맵핑 버그를 여전히 가지고 있다. 즉, 자바스크립트에서 발견하기 힘든 난해한 버그가 여전히 타입 스크립트에서 나타날 수 있는 것이다.
타입 스크립트를 학습해야 하는 이유는?
위에서 타입 스크립트의 장점과 단점에 대해 살펴보았다. 이 글을 보고 느끼는 바는 모두 다르겠지만, 일단 본인 생각으로는 하루빨리 적용이 필요하다는 것이다. 여러 가지 이유가 있지만, 오류율을 줄일 수 있다는 것은 제품의 퀄리티에 매우 큰 영향을 미치는 부분이기 때문이다.
개발자들도 겪어봐서 알겠지만, 제품에 발생하는 대부분의 오류는 정말 사소한 오류들이 대부분이다. 그런데, 그 사소한 오류를 잡기 위해 몇 시간씩 코드를 붙잡고 있어야 되는 것이 문제이다. 특정 오류에 대해 2시간씩 코드를 분석해봤더니 함수 인자로 전달한 값이 잘못되었다고 생각해보자. 정말 열 받는 일이 아닐 수 없다. (진짜 빈번하게 일어난다.)
일부 블로그에서는 여전히 타입 스크립트의 적용에 대해 부정적인 의견을 내비치는 경우도 많이 봤으며, 사람마다 생각이 다르므로 그것이 잘못된 생각이라고 단언할 수 없다. 다만, 앞으로 나올 프런트엔드 프레임워크나 모듈들이 모두 타입 스크립트로 작성되고 있다는 것을 알아두자. (2020년 9월에 릴리즈한 Vue 3.0도 모두 타입 스크립트로 변경되었다)
이러한 이유로 나는 미래를 위해서 제품을 위해서 타입 스크립트의 학습을 적극 권장하는 의견임을 밝힌다.
지금까지 타입 스크립트의 기본적인 개념에 대해 알아보았다. 다음 글에서는 VS Code를 활용한 타입 스크립트 개발 환경 구성하기에 대해 알아보도록 하겠다.
오늘은 여기까지 ~
'재주껏 하는 Front-End > 타입스크립트 (준비중)' 카테고리의 다른 글
6. 인터페이스 (1) (0) | 2021.11.07 |
---|---|
5. 타입 추론 / 별칭 (0) | 2021.11.05 |
4. 기본 타입 (0) | 2021.10.31 |
3. JS DOC (0) | 2021.10.29 |
2. 타입 스크립트 개발 환경 구성 (0) | 2020.12.18 |