아폴로(Apollo)는 GraphQL을 사용하는 클라이언트 및 서버 개발 도구이며, 지연 로딩(Delay Loading) 기능을 지원합니다. 지연 로딩은 서버로부터 필요한 데이터를 효율적으로 가져오는 데 도움이 됩니다. 이번 블로그 포스트에서는 아폴로 서버에서 지연 로딩을 구현하는 방법에 대해 알아보겠습니다.
1. GraphQL 쿼리에서 디렉티브 추가
지연 로딩을 구현하기 위해 먼저 GraphQL 쿼리에 @defer
디렉티브를 추가해야 합니다. @defer
디렉티브는 해당 필드가 지연 로딩되어야 함을 나타냅니다. 예를 들어, 다음과 같은 쿼리를 작성합니다.
query {
user {
id
name
posts @defer {
id
title
}
}
}
위의 예시에서 posts
필드에 @defer
디렉티브를 추가하여 지연 로딩을 설정했습니다.
2. 필드 리졸버에서 데이터 로딩
이제 지연 로딩을 처리하기 위해 필드 리졸버에서 데이터를 로딩해야 합니다. 아폴로 서버는 @defer
디렉티브가 있는 필드의 데이터를 별도로 로딩합니다. 필드 리졸버에서는 로딩된 데이터를 반환하도록 설정해야 합니다. 예를 들어, 아래와 같이 필드 리졸버를 작성합니다.
const resolvers = {
Query: {
user: async (parent, args, context) => {
const userData = await fetchUserData();
// 사용자 데이터 로딩
return userData;
},
},
User: {
posts: async (parent, args, context) => {
const postIdList = await fetchPostIdList(parent.id);
// 게시글 ID 목록 로딩
return postIdList;
},
},
...
};
위 예시에서 posts
필드 리졸버에서는 게시글 ID 목록을 로딩한 후 반환하도록 작성되어 있습니다.
3. 로딩된 데이터 전송
데이터를 로딩하고 난 후에는 해당 데이터를 클라이언트로 전송해야 합니다. 아폴로 서버는 로딩된 데이터를 클라이언트로 전송할 때 subscribed
이벤트를 사용합니다. 아래 코드는 로딩된 데이터를 subscribed
이벤트로 전송하는 예시입니다.
context.res.subscribe('subscribed', {
onListen: async (signal) => {
const userData = await fetchUserData();
const postData = await fetchPostData(userData.posts);
// 로딩된 사용자 데이터 및 게시글 데이터 전송
context.res.emit('subscribed', {
data: {
user: userData,
posts: postData,
},
});
},
});
위의 예시에서 fetchUserData
및 fetchPostData
함수를 사용하여 데이터를 로딩한 후, subscribed
이벤트로 클라이언트에 데이터를 전송합니다.
4. 클라이언트에서 데이터 수신
아폴로 클라이언트에서는 @defer
디렉티브로 지연 로딩된 필드를 처리할 수 있습니다. 지연 로딩된 필드가 필요한 경우 해당 필드가 로딩될 때까지 기다린 후 데이터를 수신합니다. 예를 들어, 아래 코드와 같이 클라이언트에서 지연 로딩된 필드를 처리할 수 있습니다.
import Apollo
...
client.fetch(query: YourQuery()) { result in
switch result {
case .success(let graphQLResult):
let user = graphQLResult.data?.user
let posts = user?.posts
// 로딩된 데이터 사용
case .failure(let error):
// 오류 처리
}
}
위의 예시에서 YourQuery
는 앞서 작성한 GraphQL 쿼리를 나타냅니다. 클라이언트는 fetch
메서드를 사용하여 데이터를 요청하고, 결과를 받은 후에는 로딩된 데이터를 사용할 수 있습니다.
결론
지연 로딩은 아폴로 서버에서 데이터를 효율적으로 가져오기 위해 사용되는 유용한 기능입니다. 쿼리에 @defer
디렉티브를 추가하고, 필드 리졸버에서 데이터를 로딩한 후에는 클라이언트로 데이터를 전송합니다. 클라이언트에서는 로딩된 데이터를 받아 처리할 수 있습니다. 이를 통해 네트워크 사용량을 줄이고 클라이언트 응답 시간을 개선할 수 있습니다.