TIL 23. 12. 13

타입스크립트 등장 배경

타입스크립트는 자바스크립트의 상위 집합으로서, 기본적으로 자바스크립트의 모든 기능을 포함하고 있다. 이 말은 곧 자바스크립트를 배우지 않고서는 타입스크립트를 배울 수 없음을 뜻한다. 타입스크립트의 기반이 되는 자바스크립트를 알아보며 타입스크립트가 등장한 이유를 살펴보려 한다.

자바스크립트의 탄생

초기 웹 페이지는 정적인 HTML로만 구성되었고, 사용자와의 상호작용이 제한적이었다. 기존의 정적인 웹 페이지를 “어떻게 동적인 웹 페이지를 만들 수 있을까?”를 고민하였고 ‘자바스크립트’가 탄생했다.

자바스크립트는 웹 브라우저에서 동작하는 간단한 사용자 상호작용을 위한 언어로 개발되었다. 웹 페이지에 삽입되는 스크립트 언어로 브라우저에서 바로 실행되었고 자바스크립트를 통해 웹 페이지에 동적인 기능과 상호작용을 추가할 수 있었다.

스크립트 언어(scripting language)란 응용 소프트웨어를 제어하는 컴퓨터 프로그래밍 언어를 가리킨다. 스크립트 프로그래밍 언어라고도 한다. 스크립트 언어 - 위키백과

스크립트 언어, 자바스크립트

자바스크립트는 1995년에 불과 10일 만에 만들어진 언어로, 웹 브라우저에서만 동작하고 경고창 띄우기와 같은 아주 간단한 사용자 상호작용을 처리하였다. 엄격한 문법을 갖출 필요가 없었다.

대신 아주 유연하게 설계되어 버그로부터의 안정성이나 견고함은 일부 포기하는 대신 프로그래머가 쉽고 빠르고 간결하게 코드를 작성하는데 중점을 두고 만들어졌다. 초기 웹 브라우저들은 인터넷 속도가 느리고, 컴퓨터의 성능이 현재와 비교해 상당히 낮았으므로 가벼운 스크립트 언어를 사용한 것.

더 깊은 이해를 위해서는 - Typescript는 어떻게 공부해야 하나요?

그러나 웹이 발전하고 자바스크립트 실행 환경 Node.js가 등장하면서 웹 브라우저뿐만 아니라 어디서든 자바스크립트를 실행할 수 있게 되었다. 오늘날에는 웹 개발부터 모바일 애플리케이션을 만들거나 데스크탑 애플리케이션을 만드는 등 자바스크립트로 다양한 프로그램을 만들고 있다.

자바스크립트 이상하다

여기서 문제가 발생한다. 프로그램의 규모가 커지자 자바스크립트의 유연함이 버그 발생 가능성을 높이고 프로그램의 안정성을 떨어뜨리는 결과로 이어졌다. 아래의 예를 살펴보자

  • 자바스크립트의 동일 비교 연산자는(==) 인수를 강제로 변환하여, 예기치 않은 동작을 유발한다.

    • (+) JS Is Weird: 자바스크립트의 이상한 문법 퀴즈 풀어보기
      if ("" == 0) {
       // true, Number("") == 0 => 0 == 0 => true
      }
      if (1 < x < 3) {
       // 어떤 x 값이던 true 
      }
      true == "true" // false
      "b" + "a" + +"a" + "a" // "baNaNa" 
      
  • 자바스크립트는 존재하지 않는 프로퍼티의 접근을 허용한다

    • 문법 오류가 있더라도 오류를 출력하지 않고 실행된다

      const obj = { width: 10, height: 15 };
      const area = obj.width * obj.heigth; // NaN, 10 * undefined
      

자바스크립트의 유연함에서 발생하는 문제는 규모가 큰 프로그램에서 더욱 부각된다. 디버깅이 어렵고 예기치 않은 결과로 이어질 가능성이 높다.

Node.js의 등장으로 자바스크립트로 백엔드 개발도 가능해졌다. 더욱 치명적인 것은 예외 처리가 제대로 되지 않은 백엔드의 단순한 에러 하나로 서버가 다운된다.

이를 극복하기 위해 자바스크립트의 기존 문법은 유지하되 안정성을 확보한 언어가 필요해졌다. 이렇게 등장한 언어가 ‘타입스크립트’이다.

자바스크립트의 한계점

자바스크립트는 개발자의 실수로 인한 오류를 프로그램을 실행할 때 알려준다. 자바스크립트는 동적 타입 시스템을 사용하여 변수의 타입이 실행 시간에 결정되기 때문이다.

위의 문장을 이해하기 위해 먼저 타입 시스템에 대해 알아볼 필요가 있다. 자바스크립트를 포함한 프로그래밍 언어는 타입 시스템이라는게 존재한다.

타입 시스템이란? 언어에서 사용할 수 있는 아주 여러가지 값들을 어떤 기준으로 묶어서 타입으로 정할지 결정하고 또 코드의 타입을 언제 검사할지 그리고 어떻게 검사할지 등의 우리가 프로그래밍 언어를 사용할때 타입과 관련해서 지켜야 하는 규칙들을 모아둔 체계.

타입 시스템은 크게 두 가지로 나뉜다.

  • 코드를 실행하기 전에는 타입을 결정하지 않고 코드를 실행하고 나서 유동적으로 변수의 타입을 결정하는 ‘동적 타입 시스템’
  • 코드 실행전에 모든 변수의 타입을 고정적으로 결정하는 ‘정적 타입 시스템’

동적 타입 시스템(Dynamic Type System)

변수의 타입을 코드가 실행되는 도중에(런타임에) 결정하기 때문에 개발자가 변수의 타입을 명시적으로 정의하지 않아도 된다.

let a = 'hello';

그리고 변수의 타입이 어떤 하나의 타입으로 딱 고정되지 않고 현재 변수에 담긴 값에 따라서 변수의 타입이 동적으로 계속해서 달라진다.

let a = 'hello';
a = 2147483647

이처럼 유연하게 타입을 결정하고 간결한 코드 작성이 동적 타입 시스템의 장점이다. 반면에 큰 단점도 있다.

let a = 'hello';
a = 2147483647;
a.toUpperCase(); // ❌ Error 발생

위의 코드를 실행하면 실행은 되지만 오류가 발생하며 비정상적으로 종료된다. toUpperCase은 문자열에만 사용할 수 있는 메서드로 문자열을 대문자로 변환해 반환한다. 변수 a 값의 타입은 숫자(number)이므로 숫자 타입인 변수에 문자열에만 사용하는 메서드를 사용해 오류가 발생한다.

문제는 이 코드가 실행이 되기는 된다는 것이다. 오류가 발생할 코드라면 실행 이전에 검사하여 실행되지 않도록 막는 것이 좋다. 복잡한 프로그램에서는 언제 터질지 모르는 시한폭탄과 같은 코드이기 때문이다.

동적 타입 시스템은 프로그램이 런타임에 오류가 발생한다는 것이 치명적인 문제이다.

정적 타입 시스템(Static Type System)

반면에 정적 타입 시스템은 코드를 실행하기 전에 모든 변수의 타입을 결정한다. 변수에 할당되는 값의 타입을 미리 명시하여 타입 오류를 사전에 방지할 수 있다.

include <stdio.h>

int main() {
  int a = 123;
  char b[] = "hello";
    
  int c = a * b; // ❌ Error 발생
    
  return 0;
}

C 언어를 사용해 예를 들면 변수 a에는 정수 타입으로 값은 123을, 변수 b에는 문자열 배열로 값은 hello를 저장한다. a * b 연산은 정수 a와 문자열 b을 곱하는 불가능한 연산이므로 코드 실행 전에 타입 오류를 보여준다. 프로그래머가 실수를 하더라도 에디터 상에서 오류를 알려주기 때문에 바로잡을 기회가 있다.

그러나, 정적 타입 시스템에도 단점은 있다. 모든 변수에 타입을 지정해주어야 하므로 개발 시간이 늘어날 수 있고 많은 타입 선언이 필요한 프로젝트의 경우 유지보수하는 것이 어려울 수 있다.

정리) 동적 타입 시스템과 정적 타입 시스템의 장단점

  동적 타입 시스템 정적 타입 시스템
장점 개발 속도와 유연성 타입 안정성
  짧은 코드 길이 코드 가독성
  자유로운 타입 변환이 가능 자동 완성과 코드 어시스트
단점 런타임 타입 오류 타입 선언의 부담
  타입 오류 발견의 어려움 개발 시간 증가
  디버깅 & 유지보수의 어려움 유연성 감소

타입스크립트의 독특한 타입 시스템

그래서 타입스크립트는 동적 타입 시스템과 정적 타입 시스템을 혼합한 것 같은 독특한 타입 시스템을 사용한다.

let a: number = 2147483647;

정적 타입 시스템과 같이 변수의 타입을 실행 전에 결정하고 타입 오류를 실행 전에 검사하여 알려준다. 타입스크립트는 정적 타입 시스템의 타입 안정성을 확보하면서도 동적 타입 시스템처럼 모든 변수의 타입을 직접 명시하지 않아도 된다.

그 이유는 타입스크립트에서는 변수의 타입을 직접 정의하지 않아도 변수에 담기는 초기값을 기준으로 자동으로 타입을 알아서 추론하기 때문이다.

let a = 2147483647;
a.toUpperCase(); // ❌ Property 'toUpperCase' does not exist on type 'number'

타입스크립트의 이런 독특한 타입 시스템은 안전하지 않은 동적 타입 시스템의 문제를 해결하면서도 정적 타입 시스템의 귀찮음도 동시에 해결하는 멋진 타입 시스템이다.

이런 타입시스템을 “점진적으로 타입을 결정한다”라고 해서 점진적 타입 시스템(Gradual Type System)이라고 부른다. 타입이 정의된 변수들에 대해서는 타입을 미리 결정하고 타입이 정의되지 않은 변수들은 타입을 자동으로 추론하는 타입 시스템.

정리하자면 타입스크립트는

자바스크립트를 더 안전하게 사용할 수 있도록 “타입 관련 기능들을 추가한 언어”로 자바스크립트의 확장판이라고 볼 수 있다.

타입스크립트는 점진적 타입 시스템을 채택해서 정적 타입 시스템처럼 프로그램 실행 전에 타입을 올바르게 썼는지 타입 검사를 해 타입 안정성을 확보하면서도 동적 타입 시스템처럼 모든 변수에 일일히 타입을 지정해주지 않아도 되는 유연함까지 확보한 독특한 타입 시스템을 갖추고 있는 언어!

카테고리:

업데이트:

댓글남기기