- GraphQL
- API
GraphQL Update 뮤테이션에서의 Changeset
GraphQL의 nullable 필드 값은 '값 또는 null'이므로 undefined에 의미를 부여하면 안됩니다.
Mutation 정의
GraphQL 뮤테이션으로 Update 작업을 수행한다고 하면 보통 이런 식으로 접근합니다.
mutation UpdatePost($input: UpdatePostInput) {
updatePost(input: $input)
}
아래처럼 변경의 changeset을 정의해 전달하는 방식입니다.
input UpdatePostInput {
id: ID!
title: String
content: String
}
Changeset에서 null이 갖는 의미
정의된 changeset은 변수로 아래처럼 전달됩니다(JSON).
{
"id": "UG9zdDoxMzEyNDI1Ng==",
"title": "새로운 제목",
"content": "이렇게 내용을 바꿀거에요"
}
UpdatePostInput
의 title
, content
필드는 nullable 합니다.
{
"id": "UG9zdDoxMzEyNDI1Ng==",
"title": "새로운 제목",
"content": null
}
{
"id": "UG9zdDoxMzEyNDI1Ng==",
"title": "새로운 제목"
}
null값을 제공하면 nullify 하는 것이고 필드가 아예 포함되지 않으면(undefined) 아무 액션을 수행하지 않는다는 의미를 부여해도 될까요?
그렇게 해서 의미를 함축적으로 전달하고 싶은 마음이 들 수는 있지만 그렇게 해선 안됩니다.
위의 두 경우는 GraphQL 시맨틱에서는 차이가 없습니다.
인풋 오브젝트 필드가 값
, null
, undefined
의 세 타입을 갖는 것이 아니기 때문입니다.
이런 방식으로 의미를 전달하는 게 될지 안 될지는 호스트 언어나 전송규격(보통 JSON)에 따라 다릅니다.
전송량을 줄이기 위해 ‘changeset에 명시되지 않은 값은 변경되지 않는다’는 의미를 담으려면 필드의 null 값을 ‘해당 필드 값을 사용하는 액션 없음’이라는 의미에 매핑해야 합니다.
그럼, 어떤 필드에 null을 대입하는 의미의 호출은 어떻게 해야 할까요? 일단 그런 의미의 뮤테이션은 거의 필요하지 않다는 점을 명심해야 합니다. null을 대입해야 한다고 생각할 때는 무언가 잘못되었을 가능성이 크고 보통 더 나은 방법이 많았습니다.
정 필요하다면 별도의 clearPostContent
같은 뮤테이션 필드를 만듭니다.
뮤테이션 호출 시 여러 필드를 순차적으로 호출하게 지시할 수 있으므로
nullify 액션을 별도의 필드로 만들어도 한 번에 요청을 보낼 수 있습니다.
mutation UpdatePost($input: UpdatePostInput) {
updatePost(input: $input) # ...
clearPostContent # ...
}
UpdatePostInput은 항상 Changeset인가?
한편, 이런 뮤테이션을 단순히 Update(CRUD)로 취급할 필요는 없습니다.
뮤테이션 필드를 updatePost
, updateReply
, updateUser
처럼 CRUD per table 구현의 의무감으로
만드는 것은 데이터 레이어를 API에 불필요하게 노출하기 때문에 좋지 않습니다.
대신 GraphQL mutation은 비즈니스 로직에서의 트랜잭션을 구현해야 합니다. 여기에 대해서는 Shopify의 튜토리얼이 도움이 많이 되었습니다.