Skip to content

Instantly share code, notes, and snippets.

@vreality64
Last active October 21, 2021 15:58
Show Gist options
  • Save vreality64/4125f09d8295c7ce5e5f7660694fe0df to your computer and use it in GitHub Desktop.
Save vreality64/4125f09d8295c7ce5e5f7660694fe0df to your computer and use it in GitHub Desktop.
GraphQL 주의사항

DB 스키마와 GraphQL Type 과의 연관성

결론부터 말하자면, 전혀 없다.

DB 스키마로부터 GraphQL Type 을 자동으로 만들어 낼 수는 있다. 이는 GraphQL Type 을 작성하는 노력을 줄이고, 하나의 스키마로부터 동일한 개념을 생성하겠다는데 목적이 있다.

그런데 잘 생각해보자. 이게 옳은 것인가?

서버에서 DB 스키마를 변환한 내용으로, Query 를 정의해 API 엔드포인트를 열어두었다고 생각해보자.

DB 스키마가 잘 정규화되지 않은, 아래 형태의 도큐먼트가 있다고 가정해보자

{
    "restaurant": {
        "ja": {
            "name": "string",
            "street": "string"
        },
        "fr": {
            "name": "string",
            "street": "string"
        }
    }
}

언어별로 필드가 있고, 내부적으로 데이터를 가지고 있다. 이게 클라이언트에 어떻게 노출이 될까?

# DB 로부터 정의된 GraphQL 타입 스키마
type Restaurant {
    ja: RestaurantJa
    fr: RestaurantFr
}

type RestaurantJa {
    name: String
    street: String
}

type RestaurantFr {
    name: String
    street: String
}

# 클라이언트에 노출하는 쿼리
type Query {
    home(first: Int): [Restaurant]
}

클라이언트가 일본어로 된 레스토랑 정보를 받으려면 어떻게 쿼리를 날려야 할까?

query home {
	restaurant {
        ja {
            name,
            strret
        }
	}
}

이게 정말로 GraphQL 철학에 맞는다고 생각하는가?

클라이언트는 자신이 필요한 데이터를 모델링하고, 서버에 선언적으로 요청하면 된다. DB 스키마와 전혀 별개로 작성할 수 있어야 한다는 뜻이다. 아래 쿼리를 보자.

query home(lang: "jr") {
    restaurant {
        name,
        street
    }
}

---
# 서버에서 클라이언트와 통신할 인터페이스 정의
type Restaurant {
    name: String
    street: String
}

# 클라이언트에 노출하는 쿼리
type Query {
    home($lang: Language): [Restaurant]
}

# 해당 쿼리를 처리할 함수
const resolver = ({ lang }, projection) => Restaurant.find({}).select({
	[lang]: true,
	...projection,
})

느낌이 어떤가? 아직도 DB 스키마를 클라이언트까지 엮는게 좋다고 생각하는가? 이렇게 강한 의존성은 끊고 추상화위에서 쿼리를 작성해야 한다.

다시 한번 말하지만, GraphQL 서버는 어떤 DB 를 사용하는가에 전혀 영향을 받지 않는다. 클라이언트가 DB 스키마 모델의 정보를 알게 되는 것 자체가 이상하다는 뜻이다.

서버에서는 각 필드를 어떻게 처리할지, resolver 를 선언하면서 비즈니스 로직을 처리하면 된다.

비즈니스 로직에서는 적절하게 DB 를 접근하여 데이터를 가져오거나 수정하면 된다.

각 레이어 사이의 의존성을 끊고, 자신의 역할에 충실하라. 편하게 가려다 철학을 위배하는 상황을 만들고, Bad Practice 로 남을 수 있으니 말이다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment