유저 정보를 캐싱하고, 캐싱된 유저를 조회하는 로직입니다.

const friendsDataMap = {}; // 친구 ID -> 사용자 정보 매핑
const uncachedFriendIds = []; // 캐시에 없는 친구 ID 목록

// 각 친구에 대해 캐시된 정보 확인
for (const friend of friends) {
  let cachedUserData;
  try {
    // 캐시에서 친구 정보 조회
    cachedUserData = await UserCacheClient.get(`friendData:${friend.userId}`);
  } catch (e) {
    logger.error('친구 정보 캐시 조회 중 오류 발생', {
      input: friends,
      error: e.message,
    });
  }
  
  if (!cachedUserData) {
    // 캐시에 정보가 없으면 나중에 조회할 목록에 추가
    uncachedFriendIds.push(friend.userId);
    continue;
  }
  
  friendsDataMap[friend.userId] = cachedUserData;
}

// 캐시되지 않은 친구 정보를 배치 처리하기 위한 준비
const batches = [];
const batchSize = 100;
for (let i = 0; i < uncachedFriendIds.length; i += batchSize) {
  // 배치 크기로 분할
  batches.push(uncachedFriendIds.slice(i, i + batchSize));
}

// 캐시에 없는 친구 정보를 데이터베이스에서 조회
let uncachedFriendsData = [];
for (const batch of batches) {
  // 일괄 조회로 성능 최적화
  const batchQueryResult = await UserDatabase.batchGetItems({
    Keys: batch.map((userId) => ({ id: userId })),
    // 필요한 속성만 선택적으로 가져오기
    ProjectionFields: '#id, nickname, profileUrl, bgImageUrl',
    ExpressionAttributeNames: { '#id': 'id' },
  });

  // 유효한 데이터만 필터링
  uncachedFriendsData = uncachedFriendsData.concat(
    batchQueryResult.filter((userData) => {
      return (userData && userData.nickname);
    }),
  );
}

// 데이터베이스에서 조회한 정보를 캐시에 저장
for (const friendData of uncachedFriendsData) {
  friendsDataMap[friendData.id] = friendData;
  try {
    // 캐시에 저장하고 TTL 설정
    await UserCacheClient.setWithExistingTtl({
      key: `friendData:${friendData.id}`,
      value: JSON.stringify(friendData),
    });
    await UserCacheClient.setExpiryIfMissing(
      `friendData:${friendData.id}`,
      config.friendDataCacheDuration,
    );
  } catch (e) {
    logger.error('친구 정보 캐싱 중 오류', {
      input: friends,
      error: e.message,
    });
  }
}

// 최종 결과 구성 - 필요한 정보를 합쳐서 반환
friends = friends.map((f) => {
  if (!friendsDataMap[f.userId]) return null;
  return {
    ...friendsDataMap[f.userId],
    id: f.userId,
    status: f.status,
    type: f.type,
  };
});

// 유효한 데이터만 필터링하여 최종 결과 반환
friends = friends.filter((f) => f !== null);