레슨 5: 다양한 사용자에 맞게 콘텐츠 커스터마이징
쿼리된 데이터(예: 로그인한 사용자의 역할)에 따라 필드에서 다른 응답을 반환할 수 있습니다.
다양한 사용자에 맞게 콘텐츠를 커스터마이징하는 GraphQL 쿼리
다음 GraphQL 쿼리는 게시물 콘텐츠를 가져오며, 관리자 사용자에 한해 콘텐츠 하단에 "이 게시물 편집" 링크를 추가합니다.
query InitializeDynamicVariables
@configureWarningsOnExportingDuplicateVariable(enabled: false)
{
isAdminUser: _echo(value: false)
@export(as: "isAdminUser")
@remove
}
query ExportConditionalVariables
@depends(on: "InitializeDynamicVariables")
{
me {
roleNames @remove
isAdminUser: _inArray(
value: "administrator",
array: $__roleNames
)
@export(as: "isAdminUser")
}
}
query RetrieveContentForAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@include(if: $isAdminUser)
{
post(by: { id : $postId }) {
originalContent: content @remove
wpAdminEditURL @remove
content: _sprintf(
string: "%s<p><a href=\"%s\">%s</a></p>",
values: [
$__originalContent,
$__wpAdminEditURL,
"(Admin only) Edit post"
]
)
}
}
query RetrieveContentForNonAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@skip(if: $isAdminUser)
{
post(by: { id : $postId }) {
content
}
}
query ExecuteAll
@depends(on: [
"RetrieveContentForAdminUser",
"RetrieveContentForNonAdminUser"
])
{
id @remove
}관리자 사용자의 경우 응답은 다음과 같습니다.
{
"data": {
"user": {
"isAdminUser": true
},
"post": {
"content": "\n<p>Welcome to WordPress. This is your first post. Edit or delete it, then start writing!<\/p>\n<p><a href=\"https:\/\/mysite.com\/wp-admin\/post.php?post=1&action=edit\">(Admin only) Edit post<\/a><\/p>"
}
}
}관리자가 아닌 사용자의 경우 응답은 다음과 같습니다.
{
"data": {
"user": {
"isAdminUser": false
},
"post": {
"content": "\n<p>Welcome to WordPress. This is your first post. Edit or delete it, then start writing!<\/p>\n"
}
}
}GraphQL 서버가 (가능한 모든 조건을 고려하여) 필드에 필요한 값을 동적으로 계산함으로써 다음과 같은 이점을 얻을 수 있습니다.
- 애플리케이션의 로직이 단순해집니다. 단일 신뢰 소스가 확립되고, 코드가 DRY해지며, 클라이언트 측에서 동일한 로직을 구현할 필요가 없어집니다.
- 애플리케이션의 신뢰성이 향상됩니다. 여러 클라이언트가 서버 데이터에 접근할 때, 동일한 로직을 서로 다른 구현으로 처리하면 불일치가 발생할 수 있으며 버그의 원인이 됩니다(특히 웹사이트용 JavaScript, Android 앱용 Java, iPhone 앱용 Swift 등 서로 다른 기술 기반의 클라이언트가 혼재하는 경우 더욱 두드러집니다).
단계별 안내: GraphQL 쿼리 작성하기
아래는 이 쿼리가 어떻게 동작하는지에 대한 상세한 분석입니다.
사용자가 관리자인지 확인하기
이 쿼리는 로그인한 사용자가 "administrator" 역할을 가지고 있는지 확인하고, 그 조건을 다이나믹 변수 $isAdminUser로 내보냅니다.
query
{
me {
roleNames
isAdminUser: _inArray(
value: "administrator",
array: $__roleNames
)
@export(as: "isAdminUser")
}
}오퍼레이션의 조건부 실행
Multiple Query Execution 이 활성화되면, 디렉티브 @include와 @skip을 오퍼레이션에도 적용할 수 있습니다. 이를 통해 다이나믹 변수의 값에 따라 오퍼레이션 실행 여부를 제어할 수 있습니다.
아래 쿼리에서는 두 오퍼레이션 중 하나만 실행됩니다.
RetrieveContentForAdminUser는$isAdminUser가true일 때만 실행됩니다.RetrieveContentForNonAdminUser는$isAdminUser가false일 때만 실행됩니다.
query RetrieveContentForAdminUser
@depends(on: "ExportConditionalVariables")
@include(if: $isAdminUser)
{
# ...
}
query RetrieveContentForNonAdminUser
@depends(on: "ExportConditionalVariables")
@skip(if: $isAdminUser)
{
# ...
}사용자가 관리자인지 여부에 따라 게시물의 content 필드에 대해 서로 다른 응답을 제공해 보겠습니다.
- 첫 번째 오퍼레이션은
content를 별칭으로 사용하며,_sprintf를 통해originalContent필드와wpAdminEditURL필드를 연결하여 필드의 값을 동적으로 계산합니다. - 두 번째 오퍼레이션은
content필드를 그대로 가져옵니다.
query RetrieveContentForAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@include(if: $isAdminUser)
{
post(by: { id : $postId }) {
originalContent: content
wpAdminEditURL
content: _sprintf(
string: "%s<p><a href=\"%s\">%s</a></p>",
values: [
$__originalContent,
$__wpAdminEditURL,
"(Admin only) Edit post"
]
)
}
}
query RetrieveContentForNonAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@skip(if: $isAdminUser)
{
post(by: { id : $postId }) {
content
}
}실행할 오퍼레이션 추가하기
이제 실행될 수 있는 두 개의 오퍼레이션이 생겼지만, 쿼리 실행 시 지정할 수 있는 ?operationName=...은 하나뿐입니다.
그래서 RetrieveContentForAdminUser와 RetrieveContentForNonAdminUser 양쪽에 의존하는 오퍼레이션 ExecuteAll을 추가합니다. 오퍼레이션 내에서 무언가를 쿼리해야 하므로, 간단한 필드 id를 포함합니다.
query ExecuteAll
@depends(on: [
"RetrieveContentForAdminUser",
"RetrieveContentForNonAdminUser"
])
{
id
}?operationName=ExecuteAll로 엔드포인트를 호출하면 두 오퍼레이션 모두 로드되지만, 실제로 실행되는 것은 그 중 하나뿐입니다.
불필요한 데이터 제거하기
마지막 단계는 보조적인 필드(응답에 출력할 필요가 없는 필드)를 모두 @remove로 제거하는 것입니다.
통합된 GraphQL 쿼리는 다음과 같습니다.
query InitializeDynamicVariables
@configureWarningsOnExportingDuplicateVariable(enabled: false)
{
isAdminUser: _echo(value: false)
@export(as: "isAdminUser")
@remove
}
query ExportConditionalVariables
@depends(on: "InitializeDynamicVariables")
{
me {
roleNames @remove
isAdminUser: _inArray(
value: "administrator",
array: $__roleNames
)
@export(as: "isAdminUser")
}
}
query RetrieveContentForAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@include(if: $isAdminUser)
{
post(by: { id : $postId }) {
originalContent: content @remove
wpAdminEditURL @remove
content: _sprintf(
string: "%s<p><a href=\"%s\">%s</a></p>",
values: [
$__originalContent,
$__wpAdminEditURL,
"(Admin only) Edit post"
]
)
}
}
query RetrieveContentForNonAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@skip(if: $isAdminUser)
{
post(by: { id : $postId }) {
content
}
}
query ExecuteAll
@depends(on: [
"RetrieveContentForAdminUser",
"RetrieveContentForNonAdminUser"
])
{
id @remove
}