Part2_Type
김용현
책 읽기

Study

2장. 타입

2.1 타입이란

2.1.1 자료형의로서의 타입

  • 변수에 저장할 수 있는 값의 종류는 프로그래밍 언어마다 다르다.
  • 최신 ECMAScript 표준을 따르는 자바스크립트는 다음과 같은 7가지 데이터 타입(자료형)을 정의한다.
    • undefined
    • null
    • Boolean (불리언)
    • String (문자열)
    • Symbol (심볼)
    • Numeric (Number와 BigInt)
    • Object
  • 이와 같은 유형을 데이터 타입 또는 자료형이라고 한다.

2.1.2 집합으로서의 타입

  • 타입은 값이 가질 수 있는 유효한 범위의 집합을 말한다.
  • 어떤 값이 T 타입이라면 컴파일러(또는 개발자)는 이 값으로 어떤 일을 할 수 있고, 어떤 일을 할 수 없는지를 사전에 알 수 있다.

2.1.3 정적 타입과 동적 타입

  • 타입을 결정하는 시점에 따라 타입을 정적 타입과 동적 타입으로 분류할 수 있다.
  • 정적 타입
    • 정적 타입 시스템에서는 모든 변수의 타입이 컴파일타임에 결정된다.
    • 코드 수준에서 개발자가 타입을 명시해줘야 하는 C, 자바, 타입스크립트 등이 정적 타입 언어에 속한다.
    • 컴파일타임에 타입 에러를 발견할 수 있기 때문에 프로그램의 안정성을 보장할 수 있다.
  • 동적 타입
    • 동적 타입 시스템에서는 변수 타입이 런타임에서 결정된다.
    • 파이썬, 자바스크립트가 대표적인 동적 타입 언어로 개발자는 직접 타입을 정의해줄 필요가 없다.
    • 프로그램을 실행할 때 타입 에러가 발견되기 때문에 개발 과정에서 에러 없이 마음껏 코드를 작성할 수 있지만 언제 프로그램에 오류가 생길지 모르는 불안감에 휩싸이게 된다.

💡 컴파일타임과 런타임

  • 개발자가 작성한 소스코드를 실행하려면 몇 가지 과정을 거쳐야 하는데 시점에 따라 컴파일타임과 런타임으로 구분할 수 있다. 기계(컴퓨터, 엔진)가 소스코드를 이해할 수 있도록 기계어로 변환되는 시점을 컴파일타임이라고 하며 이후 변환된 파일이 메모리에 적재되어 실행되는 시점을 런타임이라고 부른다.

2.1.4 강타입과 약타입

  • 개발자가 의도적으로 타입을 명시하거나 바꾸지 않았는데도 컴파일러 또는 엔진 등에 의해서 런타임에 타입이 자동으로 변경되는 것을 암묵적 타입 변환이라고 한다.
  • 암묵적 타입 변환 여부에 따라 타입 시스템을 강타입과 약타입으로 분류할 수 있다.
  • 강타입
    • 강타입 특징을 가진 언어에서는 서로 다른 타입을 갖는 값끼리 연산을 시도하면 컴파일러 또는 인터프리터에서 에러가 발생한다.
  • 약타입
    • 약타입 특징을 갖는 언어에서 서로 다른 타입을 갖는 값끼리 연산할 때는 컴파일러 또는 인터프리터가 내부적으로 판단해서 특정 값의 타입을 변환하여 연산을 수행한 후 값을 도출한다.
  • 타입 검사기가 프로그램에 타입을 할당하는 데 사용하는 규칙 집합을 타입 시스템이라고 한다. 타입 시스템은 크게 두 가지로 구분한다.
    • 어떤 타입을 사용하는지를 컴파일러에 명시적으로 알려줘야 하는 타입 시스템
    • 자동으로 타입을 추론하는 타입 시스템

2.1.5 컴파일 방식

  • 컴파일의 일반적인 의미는 사람이 이해할 수 있는 방식으로 작성한 코드를 컴퓨터가 이해할 수 있는 기계어로 바꿔주는 과정을 말한다.

2.2 타입스크립트의 타입 시스템

2.2.1 타입 애너테이션 방식

  • 타입 애너테이션이란 변수나 상수 혹은 함수의 인자와 반환 값에 타입을 명시적으로 선언해서 어떤 타입 값이 저장될 것인지를 컴파일러에 직접 알려주는 문법이다.

2.2.2 구조적 타이핑

  • 타입을 사용하는 여러 프로그래밍 언어에서 값이나 객체는 하나의 구체적인 타입을 가지고 있다. 타입은 이름으로 구분되며 컴파일타임 이후에도 남아있다. 이것을 명목적으로 구체화한 타입 시스템이라고 부르기도 한다.
  • 서로 다른 클래스끼리 명확한 상속 관계나 공통으로 가지고 있는 인터페이스가 없다면 타입은 서로 호환되지 않는다.

2.2.3 구조적 서브타이핑

  • 타입스크립트의 타입은 값의 집합으로 생각할 수 있다. 타입은 단지 집합에 포함되는 값이고 특정 값은 많은 집합에 포함될 수 있다.
  • 구조적 서브타이핑이란 객체가 가지고 있는 속성을 바탕으로 타입을 구분하는 것이다. 이름이 다른 객체라도 가진 속성이 동일하다면 타입스크립트는 서로 호환이 가능한 동일한 타입으로 여긴다.

2.2.4 자바스크립트를 닮은 타입스크립트

  • 타입스크립트의 타입 시스템은 구조적 서브타이핑을 사용한다.

💡 덕 타이핑

  • 어떤 타입에 부합하는 변수와 메서드를 가질 경우 해당 타입에 속하는 것으로 간주하는 방식이다.

2.2.5 구조적 타이핑의 결과

  • 타입스크립트 구조적 타이핑의 특징 때문에 예기치 못한 결과가 나올 때도 있다. 이러한 한계를 극복하고자 타입스크립트에 명목적 타이핑 언어의 특징을 가미한 식별할 수 있는 유니온 같은 방법이 생겨났다.

2.2.6 타입스크립트의 점진적 타입 확인

  • 점진적 타입 검사란 컴파일 타임에 타입을 검사하면서 필요에 따라 타입 선언 생략을 허용하는 방식이다.

💡 any 타입

  • 타입스크립트에서 any 타입은 타입스크립트 내 모든 타입의 종류를 포함하는 가장 상위 타입으로 어떤 타입 값이든 할당할 수 있다. 단 타입스크립트 컴파일 옵션인 noImplicitAny 값이 true일 때는 에러가 발생한다. noImplicitAny는 타입 애너테이션이 없을 때 변수가 any 타입으로 추론되는 것을 허락하지 않는다.

2.2.7 자바스크립트 슈퍼셋으로서의 타입스크립트

2.2.8 값 vs 타입

  • 타입스크립트에서 어떠한 심볼이 값으로 사용된다는 것은 컴파일러를 사용해서 타입스크립트 파일을 자바스크립트 파일로 변환해도 여전히 자바스크립트 파일에 해당 정보가 남아있음을 의미한다.
  • 반면 타입으로만 사용되는 요소는 컴파일 이후에 자바스크립트 파일에서 해당 정보가 사라진다.

💡 트리쉐이킹(tree-shaking)

  • 자바스크립트, 타입스크립트에서 사용하지 않는 코드를 삭제하는 방식이다. ES6 이후의 최신 애플리케이션 개발 환경에서는 웹팩, 롤업 같은 모듈 번들러를 사용한다. 이러한 도구로 번들링 작업을 수행할 때 사용하지 않는 코드는 자동으로 삭제된다. CommonJS 모듈은 트리쉐이킹을 지원하지 않지만 ES6 이후에는 파일 내 특정 모듈만 임포트하면 해당 모듈을 사용하지 않는 파일 코드는 삭제되어 더 작은 크기의 번들링 파일을 생성할 수 있게 되었다.

2.2.9 타입을 확인하는 방법

  • typeof 는 연산하기 전에 피연산자의 데이터 타입을 나타내는 문자열을 반환한다.
  • 값에서 사용된 typeof 는 자바스크립트 런타임의 typeof 연산자가 된다.
    const v1 = typeof person; // 값은 'object'
    const v2 = typeof email; // 값은 'function'
  • 타입에서 사용된 typeof는 값을 읽고 타입스크립트 타입을 반환한다.
    type T1 = typeof person; // 타입은 Person
    type T2 = typeof email; // 타입은 (options: { person: Person; subject: string; body: string; }) => void
  • 자바스크립트에서 instanceof 연산자를 사용하면 프로토타입 체이닝 어딘가에 생성자의 프로토타입 속성이 존재하는지 판단할 수 있다.
  • typeof 연산자처럼 instanceof 연산자의 필터링으로 타입이 보장된 상태에서 안전하게 값의 타입을 정제하여 사용할 수 있다.

2.3 원시 타입

💡 원시 값과 원시 래퍼 객체

  • 타입을 파스칼 표기법으로 표기하면 자바스크립트에서 이것을 원시 래퍼 객체라고 부른다. null과 undefined를 제외한 모든 원시 값은 해당 원시 값을 래핑한 객체를 가진다.
  • 원시 래퍼 객체는 이름에서 알 수 있듯이 원시 값이 아닌 객체라는 점에 주의하자.
  • 따라서 타입스크립트에서는 내장 원시 타입에 해당하는 타입을 파스칼 표기법으로 쓰지 않도록 주의해야 한다.
  • 타입 스크립트에도 원시 래퍼 객체가 존재하는데 이것은 고유한 타입으로 분류되기 때문에 둘은 엄연히 다르다.

2.3.1 boolean

  • 오직 true와 false 값만 할당할 수 있는 타입.

2.3.2 undefined

  • 정의되지 않았다는 의미의 타입으로 오직 undefined 값만 할당할 수 있다.
  • 초기화되어 있지 않거나 존재하지 않음을 나타낸다.

2.3.3 null

  • 오직 null만 할당할 수 있다.
  • 자바스크립트에서 보통 빈 값을 할당해야 할 때 null을 사용한다.

2.3.4 number

  • 자바스크립트의 숫자에 해당하는 모든 원시 값을 할당할 수 있다.
  • 자바스크립트에서 숫자에 해당하는 원시 값 중 NaN이나 Infinity도 포함된다.

2.3.5 bigInt

  • 이전의 자바스크립트에서 가장 큰 수인 Number.MAX_SAFE_INTEGER(2^53-1)을 bigInt를 사용하면 처리할 수 있다.

2.3.6 string

  • 문자열을 할당할 수 있는 타입이다.
  • 공백도 string 타입에 해당한다.

2.3.7 symbol

  • Symbol() 함수를 사용하면 어떤 값과도 중복되지 않는 유일한 값을 생성할 수 있다.

2.4 객체 타입

  • 앞의 7가지 원시 타입에 속하지 않는 값은 모두 객체 타입으로 분류할 수 있다.

2.4.1 object

  • 자바스크립트 객체의 정의에 맞게 이에 대응하는 타입스크립트 타입 시스템은 object 타입이다.

2.4.2 {}

  • 중괄호는 자바스크립트에서 객체 리터럴 방식으로 객체를 생성할 때 사용한다.
  • 타입스크립트에서 객체를 타이핑할 때도 중괄호를 쓸 수 있는데 중괄호 안에 객체의 속성 타입을 지정해주는 식으로 사용한다.

2.4.3 array

  • 타입스크립트에서는 배열을 array라는 별도 타입으로 다룬다.
  • 타입스크립트 배열 타입은 하나의 타입 값만 가질 수 있다는 점에서 자바스크립트 배열보다 조금 더 엄격하다.

2.4.4 type과 interface 키워드

  • 타입스크립트에서는 일반적으로 변수 타입을 명시적으로 선언하지 않아도 컴파일러가 자동으로 타입을 추론한다. 이 말은 타입스크립트 컴파일러가 변수 사용 방식과 할당된 값의 타입을 분석해서 타입을 유추한다는 것을 의미한다. 따라서 모든 변수에 타입을 일일이 명시적으로 선언할 필요가 없다.

2.4.5 function

  • 타입스크립트에서도 함수를 별도 함수 타입으로 지정할 수 있다.
    • 자바스크립트에서 typeof 연산자로 확인한 function이라는 키워드 자체를 타입으로 사용하지는 않는다.
    • 함수는 매개변수 목록을 받을 수 있는데 타입스크립트에서는 매개변수도 별도 타입으로 지정해야 한다.

💡 호출 시그니처(Call Signature)

  • 타입스크립트에서 함수 타입을 정의할 때 사용하는 문법이다. 함수 타입은 해당 함수가 받는 매개변수와 반환하는 값의 타입으로 결정된다. 호출 시그니처는 이러한 함수의 매개변수화 반환 값의 타입을 명시하는 역할을 한다.