Skip to content

ENUM 적용 트러블슈팅

nawhes edited this page Dec 5, 2021 · 1 revision
tags: techtalk

ENUM 적용 트러블슈팅

서론

어제 겪었던 문제상황은 프로젝트 전역에서 사용하는 enum을 설정하려는 데에서 시작했습니다.

// tsconfig.json
    ...
    "compilerOptions": {
        ...
        "typeRoots": [
          "./node_modules/@types",
          "./src/types"
        ],
        ...
    }

사전에 tsconfig.json에 typeRoots를 지정해둔 상태에서

이렇게 index.d.ts에 enum에 대한 정의를 한다면 전역변수로 정의되었을 것이고

별도의 import 구문없이도 lint도 정상적으로 동작하기 때문에 컴파일과정이나 런타임에서도 잘 동작할 거라고 생각했지만

ReferenceError: x is not defined 에러와 함께 정상적으로 동작하지 않습니다.

types/*.d.ts 는 함수나 변수를 정의하는 용도가 아니다.

enum은 TS의 데이터 타입으로 변수를 실제 메모리에 공간을 차지하고 값을 정의할 때 사용합니다.

declare 구문은 JS가 아닌 TS에만 있는 키워드로 변수나 함수등의 타입을 선언하는 용도로 쓰입니다. 그리고 이 과정을 통해 타입 추론이나 메소드 유추와 같은 기능이 가능합니다. 단, 실제로 메모리에 공간을 차지하지는 않고 컴파일과정에서 타입확인에만 활용됩니다.

즉, d.ts의 declare enum은 변수가 메모리에 공간을 차지하지 않기 때문에 런타임에서는 정의되지 않았습니다.

import를 하지도 않았는데 lint는 왜 알고있을까요?

서론에서 얘기한 것처럼 컴파일러가 추론에 필요한 정보가 types 디렉토리에 정의되있기 때문입니다.

package.json의 devDependencies에만 있지만 import하지 않았던 @types/foobar는

이렇게 해당 패키지를 사용할 때 필요한 타입에 대한 정보를 가지고 있었습니다.

이런 동작들을 ambient declaration라고 칭한다고 합니다.

(찾아보면서 알게 된 내용인데 typeRoots에 정의하지 않아도 타입스크립트는 프로젝트 루트에서 모든 디렉토리를 탐색하면서 @types 라는 이름의 디렉토리의 내용을 활용한다고 합니다.) https://www.typescriptlang.org/tsconfig#typeRoots

그럼 프로젝트 전역변수를 선언할 방법은 없는건가요?

우리의 소스들은 모듈로 분리되어있기 때문에 다른 파일에서 정의된 변수 혹은 함수를 import 하지 않고 사용하는 것은 불가능합니다.

하지만 편법을 사용하면 가능합니다. 런타임 최하단에 존재하는 제네시스 오브젝트(웹브라우저에선 window, nodejs에선 global)에 속성으로 정의를 한다면 모든 파일에서 해당 오브젝트에 접근해서 사용할 수 있습니다.

(global 오브젝트에 숨어있던 typeorm)

하지만 전역변수를 선언하고 namespace를 관리하는 것보다 common.ts에 정의하고 모듈로써 관리하는 방법이 더 편해보입니다.

Clone this wiki locally