최근 typescript 환경에서 코딩을 하고 있다.
배우면 배울수록 언어 자체의 괴악한 사용방법에 계속 놀라고 있는데... 너무 좋다! 이런게 가능하다니!
그러다가 이번에 요구사항을 받고 타입스크립트의 사용법을 이용해 정말 상상도 못한 기능을 구현하는데 성공하여 이렇게 공유하게 되었다.
우선 요구사항은 다음과 같다.
- 저희는 서버에서 에러를 처리할 거에요!
- 그런데 에러의 정의가 여러군데에 따로 있으면 불편해요!
- 에러는 메시지가 아니라, 코드 기반이여야 되요!(ex: E0001, E0002 같이)
*.ts
파일에 직접 에러를 정의했더니 코드가 더럽네요!- 에러는 코드와 메시지로 이루어 져 있어요, 두개가 동시에 정의되어 있으면 좋겠네요!
- 메시지는 동적으로 변경 가능하도록 템플릿이 적용되면 좋겠어요!
E1000 = "'${id}' is not exist in user database"
대략 이런 느낌의 메시지 템플릿을 의미합니다.
많은 분들에게 궁금한건 이걸 어떻게 만들었냐가 아니라 어떤 식으로 짤수 있는가일테니 바로 최종 결과물을 보고 원리가 뭔지 이야기하겠다.
import errorc from "error-c";
const DEFINE_ERRORS = {
E0001: "This is error!",
E0002: "I'm error too!",
E0003: "I'm ${whoareyou}!",
E0004: "I'm not ${notyou}, i'm ${whoareyou}!",
} as const;
const fail = errorc(
DEFINE_ERRORS,
process.env.NODE_ENV === "production" ? "release" : "debug",
(msg) => msg
);
console.log(fail("E0004", { notyou: "pizza", whoareyou: "potato" }));
해당 코드는 일반적인 에러 정의와 템플릿을 이용한 에러처리 파일이란 것을 알 수 있다.
여기서 마법은 저 errorc
함수인데 바로 본론으로 이녀석을 쓰는 경우의 장점을 말하면 아래와 같다.
더 이상 말이 필요한가, 놀랍게도 문자열을 분석해서 문자열의 템플릿만 넣을 수 있도록 강제하게 만들었다.
해당 패키지는 errorc
라고 불리우는 함수 제네레이터와 내부 타입 분석용 중간 타입들로 구성된 매우 작은 프레임워크이다.
라이브러리라고 하지 않는 이유는 해당 패키지를 이용하기 위해서는 해당 패키지의 사용에 반드시 지켜야 하는 규칙이 있기 때문이다.
놀랍게도 이 패키지는 상수로 정의된 타입스크립트 오브젝트로부터 상수 문자열들을 정적분석해 문자열 템플릿에서 필요한 필드만 사용할 수 있도록 제한해 주는 프레임워크이다.
어짜피 이 프레임워크를 쓰는 법은 npm과 github에 올려 놨으니 앞으로 이 블로그에서는 구현 방법을 시리즈로 정리할 것이다.
설치 :
npm i error-c
소스코드
사실 구현부를 보면 알겠지만 100라인 이하의 정말 작은 패키지인데, 내 생각에 이와 유사한 것을 본 적이 없는 것 같다.
이 기능은 타입스크립트의 제네릭에서 리터럴 템플릿의 형태를 추론할 수 있는 기능을 이용해서 만들어졌다.
다른 언어에서는 이와 유사한 기능을 구현하기 위해서, 일반적으로 빌드 스크립트를 이용해 코드를 자동생성하는 툴을 이용하거나, 아니면 rust, c++의 매크로를 쥐어짜내서 만들 수 있는데 타입스크립트는 놀랍게도 외부 툴이나 매크로 없이 자체 문법만으로 해당 기능 정의가 가능했다.
유사한 방법은 다른 언어에도 있지만 구현 방식은 다른 언어에서는 본 적도 없는 해괴하고도, 놀라운 방법이였다.