Search
Duplicate
🛶

8장. 타입스크립트로 마이그레이션하기

item 58. 모던 자바스크립트로 작성하기

ECMAScript 모듈 사용하기
ES2015부터는 importexport를 사용하는 ECMAScript 모듈이 표준이 되었고 만약 마이그레이션 대상이 자바스크립트 코드가 단일 파일이거나 비표준 모듈 시스템이라면 전환하는 것이 좋다.
프로토타입 대신 클래스 사용하기
과거 자바스크립트는 프로토타입 기반의 객체 모델을 사용했으나 많은 개발자들이 견고하게 설계된 클래스 기반 모델을 선호해 ES2015에 class 키워드를 사용하는 클래스 기반 모델이 도입되었다.
기존 코드가 단순한 객체를 다룰 때 프로토타입을 사용하고 있다면 클래스로 전환하는 것이 좋다.
var 대신 let/const 사용하기
자바스크립트 var 키워드의 스코프 규칙에 문제가 있다는 것은 널리 알려진 사실이다.
반면 letconst는 제래도 된 블록 스코프 규칙을 가지며 개발자들이 일반적으로 기대하는 방식으로 동작한다.
for(;;)대신 for-of 또는 배열 메소드 사용하기
for-of 루프는 코드가 짧고 인덱스 변수를 사용하지도 않기 때문에 실수를 줄일 수 있다. 인덱스 변수가 필요한 경우엔 배열의 forEach 메소드를 사용하면 된다.
for-in 문법도 존재하지만 몇 가지 문제점이 존재하기 때문에 사용하지 않는 것이 좋다.
함수 표현식보다 화살표 함수 사용하기
this 키워드는 일반적인 변수들과 다른 스코프 규칙을 가지기 때문에 다음과 같은 상황에서 상위 스코프의 this를 유지해야 한다면 화살표 함수를 사용하는 것이 적절하다.
class Foo { method() { console.log(this); [1, 2].forEach(i => { console.log(this); }); } } const f = new Foo(); f.method(); // Always prints Foo, Foo, Foo
TypeScript
복사
단축 객체 표현과 구조 분해 할당 사용하기
선언하려는 변수와 사용되는 객체의 속성 이름이 같다면 다음 코드처럼 간결하게 작성할 수 있다.
const x = 1, y = 2, z = 3; const pt = { x, y, z };
TypeScript
복사
후자의 코드가 더 간결하고 중복된 이름을 생략하기 때문에 가독성이 좋고 실수가 적다.
함수 매개변수 기본값 사용하기
자바스크립트 함수의 모든 매개변수는 선택적이며 매개변수를 지정하지 않으면 undefined로 간주된다.
매개변수에 기본값을 지정하면 코드가 간결해질 뿐만 아니라 base가 선택적 매개변수임을 명확히 나타내는 효과도 줄 수 있다.
저수준 프로미스나 콜백 대신 async/await 사용하기
asyncawait을 사용하면 코드가 간결해져서 버그나 실수를 방지할 수 있고 비동기 코드에 타입 정보가 전달되어 타입 추론에 용이하다.
function getJSON(url: string) { return fetch(url).then(response => response.json()); } function getJSONCallback(url: string, cb: (result: unknown) => void) { // ... }
TypeScript
복사
위 코드 대신 다음과 같이 작성하라.
async function getJSON(url: string) { const response = await fetch(url); return response.json(); }
TypeScript
복사
연관 배열에 객체 대신 Map과 Set 사용하기
타입스크립트에 use strict 넣지 않기
타입스크립트가 수행하는 안전성 검사가 엄격 모드보다 훨씬 더 엄격한 체크를 하기때문에 타입스크립트 코드에선 무의미하다.
요약
타입스크립트 개발 환경은 모던 자바스크립트도 실행할 수 있으므로 모던 자바스크립트의 최신 기능들을 적극적으로 사용하라. 코드 품질을 향상시킬 수 있고 타입 추론도 더 나아진다.
타입스크립트 개발 환경에서는 컴파일러와 언어 서비스를 통해 클래스, 구조 분해, async/await 같은 기능을 쉽게 배울 수 있다.
use strict는 타입스크립트 컴파일러 수준에서 사용되므로 코드에서 제거해야 한다.
TC39의 깃허브 저장소와 타입스크립트의 릴리스 노트를 통해 최신 기능을 확인하면 좋다.

item 59. 타입스크립트 도입 전에 @ts-check와 JSDoc으로 시험해 보기

타입스크립트로 전환하기에 앞서 @ts-check를 이용해 전환 시 어떤 문제가 발생하는지 미리 시험해볼 수 있다.
@ts-check 지시자를 사용하면 타입 체커가 파일을 분석하고 발견된 오류를 보고하도록 지시한다. 그러나 이는 매우 느슨한 수준으로 타입 체크를 수행하는 점을 주의해야 한다.
다음은 @ts-check가 찾아내는 몇 가지 의미있는 오류들이다.
선언되지 않은 전역 변수
알 수 없는 라이브러리
부정확한 JSDoc
요약
파일 상단에 //@ts-cehck를 추가하면 자바스크립트에서도 타입 체크를 수행할 수 있다.
JSDoc 주석을 잘 활용하면 자바스크립트 상태에서도 타입 단언과 타입 추론을 할 수 있다.

item 60. allowJs로 타입스크립트와 자바스크립트 같이 사용하기

allowJs 컴파일러 옵션을 사용하면 타입스크립트 파일과 자바스크립트 파일을 서로 임포트할 수 있게 해준다.
이 과정에서 빌드와 테스트가 동작하게 해야한다. 제대로 된 점진적 마이그레이션을 달성하기 위해 필요하다.
요약
점진적 마이그레이션을 위해 자바스크립트와 타입스크립트를 동시에 적용할 수 있게 allowJs 컴파일러 옵션을 사용하자.
대규모 마이그레이션 작업을 진행하면서 테스트와 빌드 체인에 타입스크립트를 적용해야 한다.

item 61. 의존성 관계에 따라 모듈 단위로 전환하기

점진적 마이그레이션을 수행할 때, 모듈 단위로 진행하는 것이 이상적이다. 그러나 한 모듈을 골라서 타입 정보를 추가하면 해당 모듈이 의존하는 모듈에서 비롯되는 타입 오류가 발생하게 된다.
의존성과 관련된 오류없이 작업을 성공적으로 끝마치려면 다른 모듈에 의존하지 않는 최하단 모듈부터 작업을 시작해서 의존성의 최상단에 있는 모듈을 마지막으로 완성해야 한다.
먼저 서드파티 라이브러리의 타입 정보를 해결해야 한다.
이들은 내부 모듈에 의존하지 않기 때문이다. 일반적으로 @types 모듈을 설치하면 되는데 보편적으로 @types/라이브러리명이 타입 정보를 담고 있기 때문이다.
외부 API를 호출하는 경우도 있기 때문에 외부 API의 타입 정보도 추가해야 한다.
이후 마이그레이션을 진행하는 데, 이때 타입 정보 추가만하고 리팩토링을 수행해서는 안 된다.
코드 개선이 아닌 마이그레이션이 목표기 때문이다.
이 과정에서 item 59이 다루지 않은 나머지 발생 가능한 오류들에 대해서 알아보자.
선언되지 않은 클래스 멤버
자바스크립트는 클래스 멤버 변수를 선언할 필요가 없다. 따라서 존재하지 않을 수 있다.
이는 IDE의 빠른 수정으로 간단히 해결할 수 있다. 언어 서비스가 타입 추론을 통해 멤버를 추가해준다. 이후 타입을 훑어보면서 적절히 바꿔주자.
타입이 바뀌는 값
이후 테스트 코드를 타입스크립트로 전환하면 된다.
요약
마이그레이션의 첫 단계는 서드파티 모듈과 외부 API 호출에 대한 @types 의존성을 추가하는 것이다.
의존성 관계도의 아래에서부터 위로 올라가며 마이그레이션을 수행하면 된다. 첫 번째 모듈은 보통 유틸리티 모듈이다.
이 과정에서 의존성 관계도를 시각화하여 진행 과정을 추적하는 것이 좋다.
리팩토링을 해선 안 된다. 마이그레이션 작업은 타입스크립트 전환에 집중해야 하며, 나중의 리팩토링을 위해 목록을 작성해두자.
타입스크립트로 전환하며 발견하게 되는 일반적인 오류들을 놓치지 않아야 한다.
때에 따라 타입 정보를 유지하기 위해 JSDoc 주석을 활용해야 할 수도 있다.

item 62. 마이그레이션의 완성을 위해 noImplicitAny 사용하기

프로젝트 전체를 .ts로 마이그레이션한 후, 마지막 단계는 noImplicitAny를 설정하는 것이다.
해당 옵션이 설정되지 않은 상태에서는 타입 선언에서 비롯되는 실제 오류가 숨어 있기 때문에 완전하게 마이그레이션되었다고 할 수 없다.
처음에는 해당 옵션을 로컬에서만 설정하는 것이 좋다. 로컬에서만 오류로 인식되기 때문에 수정된 부분만 커밋할 수 있기 때문이다.
타입 체크의 강도는 팀 내의 모든 사람이 타입스크립트에 익숙해진다음 천천히 올리는 것이 좋다.
요약
noImplicitAny 설정을 활성화하여 마이그레이션의 마지막 단계를 진행해야 한다.
noImplicitAny 설정이 없다면 타입 선언과 관련된 실제 오류가 드러나지 않는다.
noImplicitAny를 전면 적용하기 전에 로컬에서부터 타입 오류를 점진적으로 수정해야 한다.