[swift] 아폴로 서버의 지연 로딩 기능 구현 방법

아폴로(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,
      },
    });
  },
});

위의 예시에서 fetchUserDatafetchPostData 함수를 사용하여 데이터를 로딩한 후, 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 디렉티브를 추가하고, 필드 리졸버에서 데이터를 로딩한 후에는 클라이언트로 데이터를 전송합니다. 클라이언트에서는 로딩된 데이터를 받아 처리할 수 있습니다. 이를 통해 네트워크 사용량을 줄이고 클라이언트 응답 시간을 개선할 수 있습니다.

참고 자료