한 입 크기로 잘라먹는 타입스크립트(TypeScript) by 이정환
중급 프로젝트 시작!
발등에 불 떨어졌다. 아이고 따뜻해.🤗
TypeScript by 2012년 마이크로소프트의 개발자이자 C#의 창시자로도 알려진 덴마크 출신의 개발자 Anders Hejlsberg(앤더스 하일스버그어떻게 개발자 이름이 버그? 그 버그가 아니잖아.)
뭐, 그래서 C#과 비슷하다고도 한다더라.
따라서 많은 프로그래머들이 이 언어의 개발과 유지보수로 참여
-> 발전 가능성 창창☀️
현재 자바스크립트 개발자 사이 굉장히 인기있는 언어
근데 진짜 내가 귀로도(주변 지인) 눈으로(공신력 있는 자료) 봐도 인기 있는 언어가 맞음
타입스크립트는,
자바스크립트를 더 안전하게 사용할 수 있도록 타입 관련된 여러가지 기능을 추가한 언어
왼쪽의 자바스크립트에서는 변수를 선언할 때 변수의 타입 미지정
자바스크립트는 동적 타이핑 언어로, 변수의 자료형을 바꿔서 사용 가능
-> 개발자가 마음대로 편하게 변수를 쓸 수 있음 / 실수하기 쉽고 실수를 발견하기 어려움
오른쪽의 타입스크립트에서는 변수의 이름 뒤에 :과 함께 변수의 타입 지정
= 변수 a와 b 모두 number 숫자 타입을 가지도록 정의
-> 이제 이 변수에는 숫자 타입 외의 값을 넣을 수 없음
즉, 타입스크립트 = 기존 자바스크립트 문법 + 정적 타이핑 문법
변수나 함수에 타입을 지정하고, 그 타입만 사용하는 방식
자바스크립트는 이미 잘나가는 중
그래서 타입스크립트가 왜 필요하냐고요?
너무 잘나가서요...
자바스크립트는 웹 브라우저에서만 동작하도록 만들어졌고, 또 아주 간단한 사용자 상호작용을 처리하기 위해 만들어짐
(쉽게 말해서, 버튼을 클릭하면 경고창을 띄워주는 정도의 상호작용을 만들어지기 위해 만들어진 언어)
그래서 자바스크립트는 엄격한 문법을 갖출 필요❌
& 매우 유연하게 설계
-> 안정성이나 견고함 포기 + 쉽고 빠르고 간결하게 코드 작성
그리하여, 자바스크립트는 아주 간결한 프로그램이나 웹 브라우저에서만 동작해왔음
그러던 중, Node.js 가 등장
자바스크립트의 런타임, 즉 실행환경
-> 자바스크립트 코드를 읽어 프로그램을 실행하는 구동기
Node.js가 등장함에 따라 자바스크립트를 어디서든 실행 가능해짐
즉, 어떤 프로그램이든 자바스크립트를 이용해 만들 수 있음
-> 개발자들이 자바스크립트를 이용해 다양한 프로그램 개발
like 웹 서버, 모바일 앱, 데스크탑 앱 등
위와 같이 다양하게 활용하는데,
그러다 보니 문제가 생김
간단한 프로그램을 개발하기 위해 사용하던 자바스크립트로 복잡한 프로그램을 개발하니,
-> 자바스크립트의 유연함이, 안정성을 떨어뜨리는 단점
즉, 버그 발생 확률이 높아짐
그래서 이 문제점을 극복하기 위해
자바스크립트의 기존 문법은 유지한 채 + 안정성을 추가한 새로운 언어 필요
-> 타입스크립트 탄생
자바스크립트를 포함해서 우리가 알고 있는 모든 프로그래밍 언어에는 타입 시스템이 존재
언어에서 사용할 수 있는 여러가지 값들을 어떤 기준으로 묶어서 타입으로 정할지 결정하고,
코드의 타입을 언제 검사할지 그리고 어떻게 검사할지 등의
우리가 프로그래밍 언어를 사용할 때, 타입과 관련해서 지켜야 하는 규칙을 모아둔 체계
이 타입 시스템은 두 가지로 나뉨
자바스크립트 같은 동적 타입 시스템은 기본적으로 변수의 타입들을 코드가 실행되는 도중에 결정
-> 미리 변수의 타입을 설정하지 않음
변수의 타입이 어떤 하나의 타입으로 고정되지 않고, 현재 변수에 담긴 값에 따라서 변수의 타입이 동적으로 계속해서 달라짐
let a = "hello" // 문자열
a = 20250830; // 숫자
a가 문자열을 담기도 하고, 숫자를 담기도 함
-> 그때그때 타입이 바뀜
위와 같이 하나의 변수에 다양한 타입의 값을 넣을 수 있기 때문에
변수 하나로 여기저기 활용 가능한 유연함이 장점
let a = "hello" // 문자열
a = 20250830; // 숫자
a.toUpperCase();
toUpperCase()는 문자열 전용 메서드
-> 이대로 실행 시, 실행은 되지만 오류가 발생
문자열 전용 메서드를 숫자가 들어 있는 변수와 사용하려 했으니까.
애초에 실행 전에 오류가 나면 좋았을 텐데... 라고 생각한 적이 있었다.(진짜로. 자바스크립트 처음 공부할 때. 자바 공부할 때 제일 좋은 예외 처리는 컴파일 단계라고 했던 것 같단 말이지.)
아무튼 이런 오류는, 지금이야 쉽게 어떤 이유로 발생했는지 파악이 가능하지만,
복잡한 프로그램에서 갑자기 터진 오류는 원인을 찾기 어려움
-> "컴파일 단계에서 잡았으면 좋을 텐데..."
예기치 못한 버그나 오류는 프로그램을 갑작스럽게 종료하게 되고, 서비스가 마비될 수 있음
-> 고객은? 개빡치겠죠
C, JAVA 같은 정적 타입 시스템은 코드를 실행하기 전에 모든 변수의 타입 결정
따라서 위의 동적 타입 시스템에서 발생한 문제는 정적 타입 시스템에서 잘 발생하지 않음
정수형 타입의 변수 c에 문자열과 숫자를 곱한 값을 넣으려고 하니 퉤, 뱉는 중
근데 애초에 IDE에서부터 타입을 잘못 썼다고 알려줌
위처럼
타입 관련 오류가 있으면 IDE에서 애초에 오류를 바로 알려주고 실행
-> 타입을 잘못 쓰지 않았는지 검사까지 모두 마치고 실행되기 때문에 오류가 있다면 실행이 불가능
모든 변수에 일일히 타입을 정의해야 하기 때문에 귀찮고 코드의 양이 늘어남
자바스크립트의 장점이 유연함이었는데, 이렇게 타입을 다 정의해야 한다면 자바스크립트를 쓸 이유❌
타입스크립트는 자바스크립트의 동적 타입 시스템과 자바의 정적 타입 시스템 혼합한 독특한 타입 시스템 사용
-> 이렇게 변수의 타입을 직접 정의하지 않아도, 변수에 담기는 초깃값을 기준으로 자동으로 타입을 추론
이런 식으로,
점진적으로 타입을 결정한다고 해서 점진적 타입 시스템이라고 함
-> 타입이 정의된 변수들에 대해서는 타입을 미리 결정하고, 타입이 정의되지 않은 변수들에 대해서는 타입을 자동으로 추론하는 타입 시스템
프로그래밍 언어는 컴퓨터보다 인간에게 더 친화적
컴퓨터는 바이트 코드나 기계어, 이진수와 같은 단순한 형태의 언어를 기반으로 동작
-> 우리가 작성한 프로그래밍 언어로 된 코드를 실행하기 위해, 이 코드를 자기가 해석하기 쉬운 형태로 변환 필요
= 컴파일
코드를 컴파일하는 녀석
자바나 자바스크립트 같은 언어를 컴파일하면 바이트코드 형식으로 변환됨
근데 컴파일러는 우리가 작성한 코드를 바로 바이트코드로 변환하는 게 아니라
AST(추상 문법 트리)라는 형태로 먼저 변환
정확히 위와 같은 형태는 아니지만,
주석이나 탭 등의 코드 실행에 관계없는 요소는 전부 제거하고
트리 형태의 자료 구조에 코드를 쪼개 저장
그 다음 컴파일러는 AST를 다시 바이트코드로 변한
이후 변환된 바이트코드를 컴퓨터가 실행
대다수의 프로그래밍 언어는 이렇게 동작한다고 함
그래서 타입스크립트는 어떻게 동작하는가?
먼저 타입스크립트 문법으로 작성된 코드를 AST로 변환하는 건 같음
그 다음 AST를 보고 바이트코드로 변환하는 게 아니라,
AST를 보고 코드 상에 오류가 없는지 검사 = 타입 오류
만약 타입 검사를 해서,
오류가 있다면 -> 타입 검사가 실패하고 컴파일이 중단
오류가 없다면 -> AST를 바이트코드가 아닌 자바스크립트 코드로 변환
그리고 컴파일 종료
컴파일(및 타입 검사) 후 만들어진 자바스크립트 코드를 Node.js나 웹 브라우저로 실행하면,
앞서 살펴본 대다수의 언어들과 동일한 과정을 거쳐 컴파일 되어 실행
즉, 타입스크립트는 타입 검사 후에 자바스크립트 코드를 만들기 때문에
해당 자바스크립트 코드는 타입 검사를 통과한 자바스크립트
= 타입 오류가 발생할 가능성이 낮은 안전한 자바스크립트
타입스크립트에 작성한 타입 관련 코드는 결국 자바스크립트로 변환될 때 사라짐
-> 프로그램 실행까지 영향을 주지는 않음
-> 자바스크립트를 보다 더 안전하게 사용 가능
타입스크립트의 컴파일은 우리가 작성한 코드에 타입 오류가 있는지 검사하고
오류가 없다면 자바스크립트 코드로 변환
이때 컴파일 과정에서 아주 세부적인 사항들
예를 들어 얼마나 엄격하게 타입 오류를 검사할 건지,
또는 컴파일 결과 생성되는 자바스크립트 코드의 버전은 어떻게 할 것인지 세세하게 정할 수 있다.
➡️ 컴파일 옵션을 통해!
특히 타입스크립트는 다른 언어에 비해 컴파일러 옵션을 자유롭게 설정할 수 있음
타입스크립트 컴파일러 옵션은 노드 패키지 단위로 설정 가능
타입스크립트 컴파일러 옵션은
패캐지의 루트 폴더 아래에 tsconfig.json이라는 파일에 설정 가능
터미널 프롬프트 창에 tsc --init을 입력하면 위와 같이 파일이 생성됨
tsconfig.json 파일의 내용을 전부 지움
{
}
중괄호 하나만 남김
기존에는 tsc [경로/파일] 형식으로 컴파일 해옴
근데 만약, 파일이 많을 경우?
100개의 파일을 컴파일해야 하면 이 명령어를 100번 입력해야 함
➡️ include라는 옵션을 이용하여 한 번의 명령으로 컴파일하도록 설정
컴파일할 범위 설정
➡️ src 폴더 아래 모든 폴더
그러면
tsc
명령어 한 번에 ts파일이 컴파일 됨
파일이 여러 개여도 마찬가지
타입스크립트 코드를 컴파일해서 만들어지는 자바스크립트 코드의 버전 설정
위와 같이 target을 ES5라고 설정하면,
옛날 버전의 자바스크립트 코드가 생성됨
ES5에는 화살표 함수가 없어서
함수 표현식으로 바뀜
만약 ESNext라는 자바스크립트 최신 버전을 사용하면
자바스크립트 파일도 화살표 함수를 갖게 됨
근데 이걸 어디 써먹냐?!
컴파일러 옵션의 target 옵션을 이용하면
자바스크립트 코드의 버전을 마음대로 조정 가능
➡️ 타입스크립트를 통해 만드는 프로덕트가 무조건 ES6을 지원하는 곳에서 동작하리라는 보장따라서 옛날 자바스크립트의 버전을 사용하는 구형 브라우저나
예전의 서버 환경 같은 곳에서 동작하게 하려면
예전의 자바스크립트 버전을 사용해야 할 일이 은근 있음!
이 target 옵션은 include 옵션과는 다르게 컴파일러 옵션 안에 들어가 있음
이렇게 타입스크립트를 자바스크립트로 변환하는 과정이나
타입 검사 등 상세한 옵션을 설정할 때는
compilerOptions라는 항목 안에 옵션을 설정한다고 이해
자바스크립트 코드의 모듈 시스템을 설정하는 module 옵션
module 옵션을 CommonJS로 설정할 경우,
자바스크립트의 ES 모듈 시스템과 유사한 형태로 내보냄
만약 module 옵션을 ESNext로 설정하면
자바스크립트 코드가 ES 모듈 시스템을 사용하는 걸 확인
컴파일 결과 생성할 자바스크립트 코드의 위치를 결정
앞으로 생길 수많은 자바스크립트 코드를 따로 저장하기 위해 사용
컴파일러가 타입을 검사할 때 얼마나 엄격하게 할지 결정하는 옵션
엄격하게 할 경우, 위와 같 오류 발생
(왜? 매개변수의 타입이 뭐가 될지 알 수 없기 때문)
타입스크립트는 대부분의 상황에서 변수의 타입을 추론하지만
매개변수는 추론이 어려움!
따라서 엄격하게 검사하면 오류가 발생
만약 tsconfig.json에서 이 옵션을 false로 설정하면
오류가 사라지고 코드가 허용됨
단, 코드에 오류가 있을지는 모름...
우리는 이것을 켜고 개발할 거임
가끔 회사에서 자바스크립트에서 타입스크립트로 마이그레이션하는 경우
이 옵션을 켰다가는
수많은 빨간 줄을 마주하므로
끄기도 함
타입스크립트의 모든 파일은 기본적으로 전역 파일로 취급됨
// a.ts
const a = 1; // ❌
// b.ts
const a = 1; // ❌
따라서 다른 파일이지만,
타입스크립트는 이를 같은 스코프라고 여기고
동일한 이름의 변수를 사용하지 못하게 함
아니 타입스크립트는 그런 거 알겠는데,
어쨌든 육안으로 다른 파일인데?
(자바스크립트는 각각의 파일이 개별 모듈로 취급받아서
파일별로 동일한 변수명을 작성해도 문제가 발생하지 않음)
그래서 이것 때문에
매번 변수를 다르게 써야 하면?
파일을 나누는 의미가????
export나 import 같은 모듈 시스템을 사용하는 문법 키워드를 파일 내에 한 번이라도 작성하면
이 파일은 그때부터 독립된 공간, 독립된 모듈로 바라봄
tsconfig.json에 옵션 추가
이건 타입스크립트가 각각의 파일을 어떤 모듈로 감지할 것인가를 결정하는 옵션
자바스크립트 파일에 자동으로 추가되어 있음
기본적으로 모든 타입스크립트 파일은 전역 모듈로 취급받기 때문에
개별 모듈로 취급받으려면 파일 안에 export 같은 모듈 시스템을 사용하는 키워드를 하나라도 넣어둬야 하는데
export 같은 모듈 시스템이 없는 키워드도
위와 같이 moduleDetection 옵션을 force로 설정해두면
타입스크립트 컴파일러가 자동적으로 모듈 시스템을 사용하는 코드를 추가하면서
모든 파일이 결국 개별 모듈로 취급되도록 만들어줌
참고로 이때 ESModule 시스템의 export로 추가된 건
우리가 변환되는 자바스크립트의 모듈 시스템을 ESNext로 설정했기 때문임
@types 버전이 20버전 이상으로 업데이트되면서 특정 라이브러리에서 타입 검사 오류가 발생하고 있으므로,
아래와 같이 skipLibCheck 추가
