[Javascript] Map vs find : 배열 대신 키-값 조회로 빠른 탐색하기

hyejinJo·2025년 9월 19일
0
post-thumbnail

인스타그램 클론 프로젝트 J-Stagram 의 피드 형식 게시글 기능을 만드는 과정에서, 게시글 리스트를 불러오는 것까지 완성 후 해당 게시글의 작성자를 불러오는 작업을 진행중이었다. 이를 Supabase 의 Admin API 인 listUsers() 를 통해 현재 가입된 모든 사용자 리스트를 불러왔다. 그 이후 게시글의 user_id(supabase 의 User 와 연결됨) 에 해당하는 유저를 찾아 작성자의 프로필 사진 및 이름을 담은 user 정보 객체를 담고자 했다.

export async function getPosts({ searchInput = '' }): Promise<PostWithImages[]> {
  const supabase = await createServerSupabaseClient();

  const { data: posts, error } = await supabase
    .from('posts')
    .select(
      `
      id,
      title,
      content,
      user_id,
      created_at,
      images (url)
    `,
    )
    .eq('is_public', true)
    .like('title', `%${searchInput}%`)
    .order('created_at', { ascending: true });

  if (error) handleError(error);

  // Admin client 사용
  const supabaseAdmin = await createServerSupabaseAdminClient();
  const { data: allUsers, error: usersError } = await supabaseAdmin.auth.admin.listUsers();

  if (usersError) handleError(usersError);

 ...
}

listUsers() 를 통해 모든 사용자 데이터를 allUsers 라는 이름으로 가져왔는데, 이를 posts 데이터를 return 하기 전에 user_info 형태로 끼워줄 생각이었다.

이때 find 메서드를 사용하려다, 커서를 활용하여 더 좋은 방법이 없는지 검색해보니 Map 객체를 활용하면 더 좋을 것이라는 내용이 있었다.

MDN 문서에 따르면, Map은 키와 값 쌍을 저장하고, 넣은 순서를 기억하며 숫자, 문자, 객체 등 어떤 값도 키로 쓸 수 있는 객체라고 한다. 즉 효율 좋고 빠른 키-값 저장소로, id → 객체 형태로 매핑할 수 있는 훨씬 깔끔한 구조를 만들 수 있었다.

const userMap = new Map(
  allUsers.users.map((u) => [
    u.id,
    {
      email: u.email,
      user_metadata: u.user_metadata,
    },
  ]),
);

return posts.map((post) => ({
  ...post,
  images: post.images ?? [],
  user_info: userMap.get(post.user_id) ?? null,
}));

Map 을 사용하면 위와 같이 유저 데이터를 매핑 할 수 있다. get 은 Map이나 객체에서 특정 키에 해당하는 값을 가져오는 메서드인데, 이를 통해 게시글의 작성자 user_id 로 키 값인 user 의 id 와 바로 대조하여 값을 찾을 수 있다.

결과를 봤을 때, posts 의 각 post 마다 해당하는 유저 데이터가 잘 삽입이 된 것을 확인할 수 있었다.

{
  "id": 2,
  "title": "게시글1",
  "content": "게시글 내용입니드아아앙",
  "user_id": "e007aca1-3f90-48fe-acaf-7d6ee201e56a",
  "created_at": "2025-09-12T07:40:11.341386+00:00",
  "images": [
    {
      "url": "https://ejxzslfkaxsbcabuiqzs.supabase.co/storage/v1/object/public/gallery/IMG_2576.JPG"
    },
    {
      "url": "https://ejxzslfkaxsbcabuiqzs.supabase.co/storage/v1/object/public/gallery/IMG_5620.jpg"
    }
  ],
  "user_info": {
    "email": "konnimey@naver.com",
    "user_metadata": {
      "avatar_url": "http://k.kakaocdn.net/dn/bvW2Ym/btsQcnFilfU/tDTGJkVGS1ps69BHoAHwr1/img_640x640.jpg",
      "email": "konnimey@naver.com",
      "email_verified": true,
      "full_name": "혜진",
      "iss": "https://kapi.kakao.com",
      "name": "혜진",
      "phone_verified": false,
      "preferred_username": "혜진",
      "provider_id": "4363702432",
      "sub": "4363702432",
      "user_name": "혜진"
    }
  }
}

사용자의 프로필 사진과 이름이 잘 뜨는 것도 확인할 수 있었다

Map vs find 둘의 차이를 더 쉽게 알아보자

new Mapfind 는 둘 다 "특정 데이터를 찾아내는 역할"을 할 수 있는데, 내부 동작 방식이 달라서 성능 차이가 있다.

1. find

배열에서 조건에 맞는 첫 번째 요소를 찾는 메서드

const users = [
  { id: '1', name: '철수' },
  { id: '2', name: '영희' },
  { id: '3', name: '민수' },
];

// id가 '2'인 사용자 찾기
const user = users.find((u) => u.id === '2');
console.log(user); // { id: '2', name: '영희' }

이는 조건에 맞는 요소를 찾을 때까지 배열을 앞에서부터 끝까지 검사하며, 최악의 경우 배열 전체를 다 돌아야 한다. 지금같은 사이드 프로젝트에서처럼 사용자 데이터가 적을 때는 괜찮지만, 이후 실제 운영업무를 수행할 때 데이터가 수천~수만 건 이상이되면 성능이 저하될 우려가 있다.

2. Map

키-값 쌍을 저장하는 자료구조이며, 키로 바로 접근이 가능하다.

const userMap = new Map([
  ['1', { id: '1', name: '철수' }],
  ['2', { id: '2', name: '영희' }],
  ['3', { id: '3', name: '민수' }],
]);

const user = userMap.get('2');
console.log(user); // { id: '2', name: '영희' }

get() 을 사용하면 바로 해당하는 값을 찾으며, 데이터가 많아져도 성능이 거의 일정하다. 다만 find처럼 조건부 탐색(ex. "name이 영희인 사용자")에는 적합하지 않다는 단점이 있다.

두 개념 모두 장단점이 있지만, find 의 경우엔 매번 전체 배열을 돌면서 찾아야 하기 때문에 성능이 나빠지므로 조건이 붙지 않는 탐색의 경우엔 Map 객체를 적극 사용하는 것이 좋을 것 같다..!

profile
Frontend Developer 💡

0개의 댓글