본문 바로가기

# GraphQL/TypeGraphQL

[TypeGraphQL] Scalar

스칼라

TypeGraphQL에서는 스칼라라는 이름으로 유저가 직접 Primitive Type을 정의하여 사용할 수 있습니다. 여기서는 RGB라는 스칼라 타입을 만들어보겠습니다.


1. 내부표현, 외부표현 설계하기

먼저 RGB 타입을 어떻게 디자인할지 생각해야 합니다. 여기서 내부적인 표현이란 구현, 외부적인 표현이란 직렬화에 관련됩니다. 사용자는 외부적인 표현을 사용하여 데이터를 표현하고, 서버는 외부적인 표현을 내부적인 표현으로 변환(파싱)하여 사용합니다.


먼저, 내부적으로는 다음과 같이 디자인하면 될 것 같습니다.

class RGB {
    r: number;
    g: number;
    b: number;

    toHex(): string;
    static fromHex(hex: string): RGB;
    static fromRGB(rgb: { r: number; g: number; b: number }): RGB;
}

외부적인 표현으로는 hex표현식을 사용하겠습니다.

(r: 0, g: 15, b: 255) => "#000fff";

2. 스칼라 생성하기

아쉽게도 TypeGraphQL은 스칼라를 생성하기 위한 데코레이터가 존재하지 않습니다. 여기서는 다음 코드와 같이 직접 GraphQLScalarType을 정의하여 사용해야 합니다.

import { GraphQLScalarType, ValueNode, Kind } from "graphql";

class RGB {
    ...
}

const RGBScalarType = new GraphQLScalarType({
    //
    // 클래스 명과 동일하지 않아도 괜찮습니다.
    name: "RGB",
    description: "My RGB Scalar Type.",

    /**
     * input-variables에서 인자를 받아 RGB를 생성한다.
     * value는 반드시 string으로 전달된다.
     */
    parseValue(value: string): RGB {
        return RGB.fromHex(value);
    },

    /**
     * literal에서 인자를 받아 RGB를 생성한다.
     */
    parseLiteral(ast: ValueNode): RGB {
        //
        // 문자열 리터럴인 경우에만 파싱한다.
        if (ast.kind === Kind.STRING) {
            return RGB.fromHex(ast.value);
        }
        throw new Error(`문자열만 허용됩니다.`);
    },

    /**
     * RGB를 문자열로 직렬화한다.
     */
    serialize(value: RGB): string {
        return value.toHex();
    },
});

input-variabelsliteral의 차이점을 모른다면 이전 장을 먼저 읽어주세요.


3. 스칼라 등록하기

스키마를 빌드할 때 scalarsMap실제 클래스스칼라 타입을 함께 넘깁니다. 이후로는 Primitive 자료형처럼 사용할 수 있습니다.

const schema = buildSchemaSync({
    resolvers: [...],
    scalarsMap: [{ type: RGB, scalar: RGBScalarType }],
});

예제 다운로드

이 포스팅에 사용된 전체 코드는 여기에서 확인할 수 있습니다.