๐Ÿ—‚๏ธ 09. ๋ฐฐ์—ด ๊ณ ์ฐจํ•จ์ˆ˜ โ€” mapยทfilterยทreduce๋ฅผ ์ œ๋Œ€๋กœ ์“ฐ๋Š” ์‹œ๋‹ˆ์–ด์˜ ์‚ฌ๊ณ ๋ฒ•

2026๋…„ 3์›” 8์ผ ์ˆ˜์ •๋จ

๐Ÿ“‹ ๊ฐœ์š”

map, filter, reduce, find, some, every, flatMap โ€” ๋งค์ผ ์“ฐ๋Š” ๋ฐฐ์—ด ๋ฉ”์„œ๋“œ์˜ ์˜ฌ๋ฐ”๋ฅธ ์‚ฌ์šฉ๋ฒ•๊ณผ ์„ฑ๋Šฅ ๊ณ ๋ ค์‚ฌํ•ญ, ํ•จ์ˆ˜ํ˜• ์กฐํ•ฉ ํŒจํ„ด.

๐ŸŽฏ ์ด ์„น์…˜์„ ์ฝ๊ณ  ๋‚˜๋ฉด:

  • map, filter, reduce์˜ ์ฐจ์ด์™€ ๊ฐ๊ฐ์˜ ์ ์ ˆํ•œ ์‚ฌ์šฉ ์‹œ์ ์„ ๋ช…ํ™•ํžˆ ์•ˆ๋‹ค.
  • reduce ํ•˜๋‚˜๋กœ map๊ณผ filter๋ฅผ ๋™์‹œ์— ์ˆ˜ํ–‰ํ•˜๋Š” ์ตœ์ ํ™” ํŒจํ„ด์„ ์ดํ•ดํ•œ๋‹ค.
  • ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ๋ฐฐ์—ด์„ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณ€ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜ํ˜• ํŒจํ„ด์„ ์ž‘์„ฑํ•œ๋‹ค.

๐Ÿ“‹ ๋ชฉ์ฐจ


๐Ÿ“Œ ์ด ๋ฌธ์„œ๋ฅผ ์ฝ๊ธฐ ์ „์—

โฑ๏ธ ์˜ˆ์ƒ ์ฝ๊ธฐ ์‹œ๊ฐ„: 20๋ถ„(์ „์ฒด) / ํ•ต์‹ฌ ํŒŒํŠธ๋งŒ: 12๋ถ„

๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ํ๋ฆ„
[map/filter/reduce ์ฐจ์ด] โ†’ [find/some/every] โ†’ [ํ•จ์ˆ˜ํ˜• ์กฐํ•ฉ] โ†’ [์„ฑ๋Šฅ ๊ณ ๋ ค]

๐ŸŽฏ ์ด ๋ฌธ์„œ๋ฅผ ๋‹ค ์ฝ์œผ๋ฉด ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ

  • "reduce๋กœ map๊ณผ filter๋ฅผ ํ•œ ๋ฒˆ์— ํ•˜๋ผ"๋Š” ๋ง์˜ ์˜๋ฏธ์™€ ๊ตฌํ˜„์„ ์•ˆ๋‹ค.
  • for ๋ฃจํ”„ ๋Œ€์‹  ์ ์ ˆํ•œ ๋ฐฐ์—ด ๋ฉ”์„œ๋“œ๋ฅผ ์„ ํƒํ•œ๋‹ค.
  • ๊ฑฐ๋Œ€ํ•œ ๋ฐฐ์—ด ์ฒ˜๋ฆฌ ์‹œ ์„ฑ๋Šฅ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋ฅผ ๊ณ ๋ คํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ๋ฐฐ๊ฒฝ ์„ธ๊ณ„๊ด€: '์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ'

๐Ÿฃ ์˜์ฒ : "์˜ํ˜ธ ๋‹˜, ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก์—์„œ '๊ณต๊ฐœ๋œ ๊ฒŒ์‹œ๊ธ€๋งŒ ๋ฝ‘์•„์„œ, ์ œ๋ชฉ๊ณผ ์กฐํšŒ์ˆ˜๋งŒ ๊ฐ€์ง„ ๊ฐ์ฒด ๋ฐฐ์—ด๋กœ ๋งŒ๋“ค์–ด์„œ, ์กฐํšŒ์ˆ˜ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ'ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์งฐ๋Š”๋ฐ์š”... filter ํ•œ ๋ฒˆ, map ํ•œ ๋ฒˆ, sort ํ•œ ๋ฒˆ ๋Œ๋ฆฌ๋‹ˆ๊นŒ ๋ฐฐ์—ด์„ ์„ธ ๋ฒˆ ์ˆœํšŒํ•˜๋”๋ผ๊ณ ์š”. ์ด๊ฑฐ ์ข€ ๋А๋ฆฐ ๊ฑฐ ์•„๋‹Œ๊ฐ€์š”?"

๐Ÿฆ ์˜ํ˜ธ: "๋‚ ์นด๋กญ๊ฒŒ ์ž˜ ๋ดค์–ด. ๋ฐฐ์—ด ๋ฉ”์„œ๋“œ๋ฅผ ์ฒด์ด๋‹ํ•˜๋ฉด ๊ฐ ๋‹จ๊ณ„๋งˆ๋‹ค ์ƒˆ ๋ฐฐ์—ด์ด ๋งŒ๋“ค์–ด์ง€๊ณ  ์ˆœํšŒ๊ฐ€ ์ผ์–ด๋‚˜. ๋ฐ์ดํ„ฐ๊ฐ€ ์†Œ๋Ÿ‰์ด๋ฉด ๊ดœ์ฐฎ์ง€๋งŒ, ๋Œ€์šฉ๋Ÿ‰์ด๋ผ๋ฉด reduce ํ•˜๋‚˜๋กœ filter + map์„ ํ•œ ๋ฒˆ์˜ ์ˆœํšŒ์— ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒŒ ํšจ์œจ์ ์ด์•ผ. ์˜ค๋Š˜ ๋ฐฐ์—ด ๊ณ ์ฐจํ•จ์ˆ˜๋ฅผ ์ œ๋Œ€๋กœ ๋ฐฐ์šฐ๋ฉด ์–ธ์ œ ์–ด๋–ค ๋ฉ”์„œ๋“œ๋ฅผ ์“ธ์ง€ ํŒ๋‹จ์ด ์„œ๊ฒŒ ๋ผ."


๐Ÿค” 1. ์™œ ์•Œ์•„์•ผ ํ•˜๋Š”๊ฐ€?

๋ฐฐ์—ด ๊ณ ์ฐจํ•จ์ˆ˜๋Š” React ๊ฐœ๋ฐœ์—์„œ ๋งค์ผ ์‚ฌ์šฉ๋œ๋‹ค:

  • ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ โ†’ JSX ๋ณ€ํ™˜: map
  • ์กฐ๊ฑด ํ•„ํ„ฐ๋ง: filter
  • ์ง‘๊ณ„/๋ณ€ํ™˜: reduce
  • ํด๋ฆญํ•œ ํ•ญ๋ชฉ ์ฐพ๊ธฐ: find
  • ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ: some, every

for ๋ฃจํ”„๋ณด๋‹ค ์˜๋„๊ฐ€ ๋ช…ํ™• ํ•˜๊ณ , ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ ํ•˜๊ธฐ ์‰ฝ๋‹ค. ๋‹จ, ์ž˜๋ชป ์“ฐ๋ฉด ๋ถˆํ•„์š”ํ•œ ์ˆœํšŒ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.


๐Ÿ”„ 2. map โ€” ๋ณ€ํ™˜

์˜ํ˜ธ ๋ฆฌ๋“œ ๋‹˜์ด ์˜์ฒ ์ด์˜ PR์— "์—ฌ๊ธด map์„ ์“ฐ๋ฉด ๋” ๊น”๋”ํ•  ๊ฒƒ ๊ฐ™์•„์š”"๋ผ๊ณ  ๋‚จ๊ธฐ์…จ๋˜ ๊ทธ ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. ์›๋ณธ ๋ฐฐ์—ด๊ณผ ๊ฐ™์€ ๊ธธ์ด์˜ ์ƒˆ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, ๊ฐ ์›์†Œ๋ฅผ ์›ํ•˜๋Š” ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•  ๋•Œ ์ œ๋ฒ•์ž…๋‹ˆ๋‹ค.

const posts = [
  { id: 1, title: "ํด๋กœ์ €", viewCount: 1234, isPublished: true },
  { id: 2, title: "this ๋ฐ”์ธ๋”ฉ", viewCount: 567, isPublished: false },
  { id: 3, title: "Promise", viewCount: 890, isPublished: true },
];
 
// โŒ ์ˆœ์ง„ํ•œ ์ฝ”๋“œ โ€” ๋ช…์‹œ์  for ๋ฃจํ”„ + ์ƒˆ ๋ฐฐ์—ด
const titles = [];
for (const post of posts) {
  titles.push(post.title);
}
 
// โœ… map โ€” ์˜๋„ ๋ช…ํ™•, ํ•œ ์ค„
const titles = posts.map((post) => post.title);
// ["ํด๋กœ์ €", "this ๋ฐ”์ธ๋”ฉ", "Promise"]
 
// ๊ฐ์ฒด ๋ณ€ํ™˜ (DTO ํŒจํ„ด)
const postSummaries = posts.map(({ id, title, viewCount }) => ({
  id,
  title,
  viewCount,
  // ์„œ๋ฒ„ ์‘๋‹ต ๊ทธ๋Œ€๋กœ ๋…ธ์ถœํ•˜์ง€ ์•Š๊ณ  ํ”„๋ก ํŠธ ์ „์šฉ ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜
  formattedViews: viewCount.toLocaleString(),
}));
 
// React์—์„œ์˜ ์‚ฌ์šฉ
const PostList = ({ posts }) => (
  <ul>
    {posts.map((post) => (
      <li key={post.id}>{post.title}</li> // key ํ•„์ˆ˜!
    ))}
  </ul>
);

map ์‚ฌ์šฉ ๊ธฐ์ค€: ๋ฐฐ์—ด์˜ ๋ชจ๋“  ์›์†Œ๋ฅผ ๋ณ€ํ™˜ํ•ด์•ผ ํ•  ๋•Œ. ์›์†Œ๋ฅผ ์ œ๊ฑฐํ•˜๊ฑฐ๋‚˜ ๊ฐœ์ˆ˜๋ฅผ ๋ฐ”๊พธ๋ฉด ์•ˆ ๋จ.


๐Ÿ” 3. filter โ€” ์„ ํƒ

์กฐ๊ฑด์— ๋งž๋Š” ์›์†Œ๋งŒ ์™์™ ๊ณจ๋ผ ๋‹ด์€ ์ƒˆ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ๋ฌผ์€ ์›๋ณธ๋ณด๋‹ค ์งง๊ฑฐ๋‚˜ ๊ฐ™์„ ์ˆ˜๋ฐ–์— ์—†๊ฒ ์ฃ ?

// ๊ณต๊ฐœ๋œ ๊ฒŒ์‹œ๊ธ€๋งŒ
const publishedPosts = posts.filter((post) => post.isPublished);
// [{ id: 1, ...}, { id: 3, ...}]
 
// ์กฐํšŒ์ˆ˜ 500 ์ด์ƒ์ธ ๊ฒŒ์‹œ๊ธ€
const popularPosts = posts.filter((post) => post.viewCount >= 500);
 
// ๋ณตํ•ฉ ์กฐ๊ฑด
const featuredPosts = posts.filter(
  (post) => post.isPublished && post.viewCount >= 1000
);
 
// ์ค‘๋ณต ์ œ๊ฑฐ (์›์‹œ๊ฐ’)
const tags = ["js", "react", "js", "css", "react"];
const uniqueTags = tags.filter((tag, index) => tags.indexOf(tag) === index);
// ["js", "react", "css"]
 
// ๋” ํ˜„๋Œ€์ : Set์œผ๋กœ ์ค‘๋ณต ์ œ๊ฑฐ
const uniqueTags2 = [...new Set(tags)];

โš™๏ธ 4. reduce โ€” ์ถ•์•ฝ

์˜คํ”„๋‹์—์„œ ์˜์ฒ ์ด๊ฐ€ "๋ฐฐ์—ด์„ ์—ฌ๋Ÿฌ ๋ฒˆ ์ˆœํšŒํ•˜๋ฉด ๋А๋ฆฌ์ง€ ์•Š์„๊นŒ์š”?"๋ผ๊ณ  ๊ฑฑ์ •ํ–ˆ๋˜ ๋ถ€๋ถ„์˜ ํ•ด๋‹ต์ž…๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์›์†Œ๋ฅผ ํ•˜๋‚˜์˜ ๊ฐ’์œผ๋กœ ์‘์ถ•ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ™œ์šฉ๋„๊ฐ€ ๋ฌด๊ถ๋ฌด์ง„ํ•˜์ง€๋งŒ, ๊ทธ๋งŒํผ ์‹ ์ค‘ํ•˜๊ฒŒ ์จ์•ผ ํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ฃ .

// ๊ธฐ๋ณธ ํ˜•ํƒœ: reduce(callback, initialValue)
// callback(accumulator, currentValue, index, array) โ†’ nextAccumulator
 
// ํ•ฉ๊ณ„
const totalViews = posts.reduce((sum, post) => sum + post.viewCount, 0);
// 1234 + 567 + 890 = 2691
 
// ๊ฐ์ฒด ๊ทธ๋ฃนํ•‘ (๋งค์šฐ ์ž์ฃผ ์“ฐ์ด๋Š” ํŒจํ„ด)
const users = [
  { id: 1, name: "์˜์ฒ ", role: "junior" },
  { id: 2, name: "์˜ํ˜ธ", role: "lead" },
  { id: 3, name: "์˜์ˆ˜", role: "lead" },
  { id: 4, name: "์˜์ˆ™", role: "designer" },
];
 
const byRole = users.reduce((groups, user) => {
  const { role } = user;
  return {
    ...groups,
    [role]: [...(groups[role] ?? []), user],
  };
}, {});
// {
//   junior: [{ id: 1, name: "์˜์ฒ ", ... }],
//   lead: [{ id: 2, ... }, { id: 3, ... }],
//   designer: [{ id: 4, ... }]
// }
 
// ID๋ฅผ ํ‚ค๋กœ ํ•˜๋Š” Map ์ƒ์„ฑ (O(1) ์กฐํšŒ์šฉ)
const postsById = posts.reduce((map, post) => {
  map[post.id] = post;
  return map;
}, {});
postsById[1]; // { id: 1, title: "ํด๋กœ์ €", ... } โ€” O(1)!

reduce๋กœ filter + map์„ ํ•œ ๋ฒˆ์˜ ์ˆœํšŒ์—:

๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋ฐฐ์—ด์„ ๋‘ ๋ฒˆ ๋งŒ๋“œ๋Š” ๋Œ€์‹ , ํ•œ ๋ฒˆ์˜ ๊ฐ€์œ„์งˆ๊ณผ ํ•œ ๋ฒˆ์˜ ๋ฐ”๋А์งˆ๋กœ ๋๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ํ˜ธ ๋ฆฌ๋“œ ๋‹˜์ด ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด ์•Œ๋ ค์ค€ ์ตœ์ ํ™” ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค.

// โŒ filter + map โ€” ๋‘ ๋ฒˆ ์ˆœํšŒ (๊ฐ๊ฐ ์ƒˆ ๋ฐฐ์—ด ์ƒ์„ฑ)
const result = posts
  .filter((post) => post.isPublished)
  .map(({ id, title, viewCount }) => ({ id, title, viewCount }));
 
// โœ… reduce ํ•˜๋‚˜๋กœ โ€” ํ•œ ๋ฒˆ ์ˆœํšŒ, ๋ฐฐ์—ด ํ•˜๋‚˜๋งŒ ์ƒ์„ฑ
const result = posts.reduce((acc, post) => {
  if (!post.isPublished) return acc; // filter ์—ญํ• 
  acc.push({ id: post.id, title: post.title, viewCount: post.viewCount }); // map ์—ญํ• 
  return acc;
}, []);
 
// ์ฃผ์˜: ์†Œ๋Ÿ‰ ๋ฐ์ดํ„ฐ์—์„œ๋Š” filter + map์ด ๋” ๊ฐ€๋…์„ฑ์ด ์ข‹๋‹ค.
// reduce ์ตœ์ ํ™”๋Š” ๋ฐฐ์—ด์ด ์ถฉ๋ถ„ํžˆ ํด ๋•Œ ์˜๋ฏธ ์žˆ๋‹ค.

๐Ÿ”Ž 5. find / findIndex / some / every

์›ํ•˜๋Š” ๋‹จ ํ•˜๋‚˜๋ฅผ ์ฐพ๊ฑฐ๋‚˜, ์ƒํƒœ๋ฅผ ๋น ๋ฅด๊ฒŒ ํ™•์ธํ•  ๋•Œ ์œ ์šฉํ•œ ๋ฉ”์„œ๋“œ๋“ค์ž…๋‹ˆ๋‹ค.

const posts = [
  { id: 1, title: "ํด๋กœ์ €", isPublished: true },
  { id: 2, title: "Promise", isPublished: false },
  { id: 3, title: "async/await", isPublished: true },
];
 
// find โ€” ์กฐ๊ฑด์— ๋งž๋Š” ์ฒซ ๋ฒˆ์งธ ์›์†Œ ๋ฐ˜ํ™˜ (์—†์œผ๋ฉด undefined)
const foundPost = posts.find((p) => p.id === 2);
// { id: 2, title: "Promise", isPublished: false }
 
// ์ฐพ์ž๋งˆ์ž ์ˆœํšŒ ์ค‘๋‹จ โ†’ filter๋ณด๋‹ค ํšจ์œจ์  (ํ•˜๋‚˜๋งŒ ์ฐพ์„ ๋•Œ)
 
// findIndex โ€” ์ธ๋ฑ์Šค ๋ฐ˜ํ™˜ (์—†์œผ๋ฉด -1)
const index = posts.findIndex((p) => p.id === 2); // 1
// ๋ฐฐ์—ด์—์„œ ํŠน์ • ํ•ญ๋ชฉ ๊ต์ฒด/์‚ญ์ œ ์‹œ ์œ ์šฉ
 
// ๋ฐฐ์—ด์—์„œ ํ•ญ๋ชฉ ๊ต์ฒด ํŒจํ„ด (๋ถˆ๋ณ€)
const togglePublish = (posts, targetId) =>
  posts.map((p) =>
    p.id === targetId ? { ...p, isPublished: !p.isPublished } : p
  );
 
// some โ€” ํ•˜๋‚˜๋ผ๋„ ์กฐ๊ฑด ์ถฉ์กฑํ•˜๋ฉด true (๋‹จ๋ฝ ํ‰๊ฐ€)
const hasUnpublished = posts.some((p) => !p.isPublished); // true
// ์ฐพ์ž๋งˆ์ž true ๋ฐ˜ํ™˜ โ€” ์ „์ฒด ์ˆœํšŒ ์•ˆ ํ•จ
 
// every โ€” ๋ชจ๋‘ ์กฐ๊ฑด ์ถฉ์กฑํ•˜๋ฉด true
const allPublished = posts.every((p) => p.isPublished); // false
// ์‹คํŒจํ•˜์ž๋งˆ์ž false ๋ฐ˜ํ™˜ โ€” ์ „์ฒด ์ˆœํšŒ ์•ˆ ํ•จ
 
// includes โ€” ์›์‹œ๊ฐ’ ํฌํ•จ ์—ฌ๋ถ€
const tags = ["js", "react", "css"];
tags.includes("react"); // true (find๋ณด๋‹ค ๊ฐ„๋‹จ)

๐Ÿ“ 6. ํ•จ์ˆ˜ํ˜• ์กฐํ•ฉ ํŒจํ„ด

์‹ค์ œ ์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก์„ ํ•„ํ„ฐ๋งํ•˜๊ณ  ์ •๋ ฌํ•˜๊ณ  ํŽ˜์ด์ง€๋„ค์ด์…˜ํ•˜๋Š” '๋ฐ์ดํ„ฐ ํŒŒ์ดํ”„๋ผ์ธ'์„ ์–ด๋–ป๊ฒŒ ๊ตฌ์„ฑํ•˜๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

// ์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ โ€” ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก ํ•„ํ„ฐ๋ง/์ •๋ ฌ/ํŽ˜์ด์ง€๋„ค์ด์…˜ ํŒŒ์ดํ”„๋ผ์ธ
 
const getPaginatedPosts = ({
  posts,
  category,
  minViews = 0,
  sortBy = "viewCount",
  page = 1,
  pageSize = 10,
}) => {
  return posts
    .filter((p) => !category || p.category === category) // ์นดํ…Œ๊ณ ๋ฆฌ ํ•„ํ„ฐ
    .filter((p) => p.isPublished && p.viewCount >= minViews) // ๊ณต๊ฐœ + ์กฐํšŒ์ˆ˜ ํ•„ํ„ฐ
    .sort((a, b) => b[sortBy] - a[sortBy]) // ์ •๋ ฌ (๋‚ด๋ฆผ์ฐจ์ˆœ)
    .slice((page - 1) * pageSize, page * pageSize); // ํŽ˜์ด์ง€๋„ค์ด์…˜
};
 
// ์‚ฌ์šฉ
const result = getPaginatedPosts({
  posts: allPosts,
  category: "javascript",
  minViews: 100,
  sortBy: "viewCount",
  page: 2,
  pageSize: 10,
});
 
// ํ•จ์ˆ˜ํ˜• ํŒŒ์ดํ”„๋ผ์ธ โ€” compose/pipe ํŒจํ„ด
const pipe =
  (...fns) =>
  (value) =>
    fns.reduce((acc, fn) => fn(acc), value);
 
const processUsers = pipe(
  (users) => users.filter((u) => u.isActive),
  (users) => users.map((u) => ({ ...u, displayName: `${u.name} (${u.role})` })),
  (users) => users.sort((a, b) => a.name.localeCompare(b.name))
);

โš ๏ธ 7. ์„ฑ๋Šฅ ๊ณ ๋ ค์‚ฌํ•ญ

์˜ํ˜ธ ๋ฆฌ๋“œ ๋‹˜์ด ์˜์ฒ ์ด์˜ ์ฝ”๋“œ์—์„œ ๋ฐœ๊ฒฌํ•œ ์„ฑ๋Šฅ ํ•จ์ •์ž…๋‹ˆ๋‹ค. "์˜์ฒ  ๋‹˜, ๋ฃจํ”„ ์•ˆ์—์„œ find๋ฅผ ๊ณ„์† ํ˜ธ์ถœํ•˜๋ฉด ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์•„์งˆ ๋•Œ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํž˜๋“ค์–ดํ•ด์š”. ๋ฏธ๋ฆฌ ์ง€๋„๋ฅผ ๋งŒ๋“ค์–ด๋‘๋Š” ๊ฒŒ ์ข‹๊ฒ ์ฃ ?"

// โŒ ๋ฃจํ”„ ์•ˆ์—์„œ ๋ฐฐ์—ด ๋ฉ”์„œ๋“œ ์ค‘๋ณต ํ˜ธ์ถœ
const isValidComment = (commentId) => {
  // posts.find๋ฅผ comment๋งˆ๋‹ค ํ˜ธ์ถœ โ†’ O(n * m)
  const post = posts.find((p) => p.comments.includes(commentId));
  return !!post;
};
 
// โœ… ๋จผ์ € Set์œผ๋กœ ๋ณ€ํ™˜ โ†’ O(1) ์กฐํšŒ
const commentIdSet = new Set(
  posts.flatMap((p) => p.comments)
);
const isValidComment = (commentId) => commentIdSet.has(commentId); // O(1)
 
// flatMap โ€” map + flat(1) ๊ฒฐํ•ฉ
const nestedTags = [
  { title: "React ๊ธฐ์ดˆ", tags: ["react", "js"] },
  { title: "Next.js ์‹ฌํ™”", tags: ["nextjs", "react", "ssr"] },
];
 
// โŒ map + flat
const allTags = nestedTags.map((p) => p.tags).flat();
 
// โœ… flatMap โ€” ํ•œ ๋ฒˆ์—
const allTags = nestedTags.flatMap((p) => p.tags);
// ["react", "js", "nextjs", "react", "ssr"]
 
// sort์˜ ๋ถˆ๋ณ€์„ฑ ์ฃผ์˜
const posts = [{ id: 3 }, { id: 1 }, { id: 2 }];
 
// โŒ sort๋Š” ์›๋ณธ ๋ฐฐ์—ด์„ ๋ณ€๊ฒฝํ•จ!
const sorted = posts.sort((a, b) => a.id - b.id); // posts๋„ ๋ณ€๊ฒฝ๋จ!
 
// โœ… ๋ณต์‚ฌ ํ›„ ์ •๋ ฌ
const sorted = [...posts].sort((a, b) => a.id - b.id);
// ๋˜๋Š” (ES2023)
const sorted = posts.toSorted((a, b) => a.id - b.id); // ์›๋ณธ ๋ถˆ๋ณ€ ์ƒˆ ๋ฉ”์„œ๋“œ

๐Ÿ“ ๋งˆ๋ฌด๋ฆฌ ํ€ด์ฆˆ

Q1. find์™€ filter์˜ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•˜๊ณ , ๊ฐ๊ฐ ์–ธ์ œ ์จ์•ผ ํ•˜๋Š”๊ฐ€?

โœ… ์ •๋‹ต:

  • filter: ์กฐ๊ฑด์— ๋งž๋Š” ๋ชจ๋“  ์›์†Œ๋ฅผ ์ƒˆ ๋ฐฐ์—ด ๋กœ ๋ฐ˜ํ™˜ (ํ•ญ์ƒ ๋ฐฐ์—ด ๋ฐ˜ํ™˜)
  • find: ์กฐ๊ฑด์— ๋งž๋Š” ์ฒซ ๋ฒˆ์งธ ์›์†Œ ๋ฅผ ๋ฐ˜ํ™˜, ์—†์œผ๋ฉด undefined (๋ฐฐ์—ด ์•„๋‹˜)

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • filter๋Š” "์กฐ๊ฑด์— ๋งž๋Š” ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก ์ „์ฒด" โ†’ ๊ฒฐ๊ณผ๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ์ผ ๋•Œ
  • find๋Š” "ID๊ฐ€ 42์ธ ๊ฒŒ์‹œ๊ธ€" โ†’ ๊ฒฐ๊ณผ๊ฐ€ ํ•˜๋‚˜์ผ ๋•Œ (๋” ํšจ์œจ์ , ์ฐพ์ž๋งˆ์ž ์ค‘๋‹จ)
  • find๋กœ ์ฐพ์€ ๊ฒฐ๊ณผ๋Š” null ์ฒดํฌ๋ฅผ ํ•ด์•ผ ํ•œ๋‹ค: const post = posts.find(...); if (post) { ... }
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: "filter๋Š” '์ „๋ถ€ ๋‹ค', find๋Š” '๋”ฑ ํ•˜๋‚˜'. ํ•˜๋‚˜๋งŒ ์ฐพ์„ ๊ฑฐ๋ผ๋ฉด find๊ฐ€ ๋น ๋ฅด๋‹ค."

Q2. ์•„๋ž˜ reduce ์ฝ”๋“œ๊ฐ€ ํ•˜๋Š” ์ผ์„ ์„ค๋ช…ํ•˜๊ณ , ๋” ์ฝ๊ธฐ ์‰ฌ์šด ์ฝ”๋“œ๋กœ ๋ฆฌํŒฉํ† ๋งํ•˜๋ผ.

const result = posts.reduce((acc, p) => ({
  ...acc,
  total: acc.total + 1,
  views: acc.views + p.viewCount,
  published: acc.published + (p.isPublished ? 1 : 0),
}), { total: 0, views: 0, published: 0 });

โœ… ์ •๋‹ต: ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก์˜ ์ด ๊ฐœ์ˆ˜, ์ด ์กฐํšŒ์ˆ˜, ๊ณต๊ฐœ ๊ฒŒ์‹œ๊ธ€ ์ˆ˜๋ฅผ ํ•œ ๋ฒˆ์˜ ์ˆœํšŒ๋กœ ์ง‘๊ณ„ํ•œ๋‹ค.

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • ์ด ์ฝ”๋“œ๋Š” total, views, published ์„ธ ๊ฐ€์ง€ ๊ฐ’์„ ๋™์‹œ์— ์ง‘๊ณ„ํ•˜๋Š” reduce ํŒจํ„ด์ด๋‹ค.
  • ๋ฆฌํŒฉํ† ๋ง ๋ฐฉํ–ฅ:
    // ๊ฐ๊ฐ ๋ณ„๋„๋กœ ๊ณ„์‚ฐ (๊ฐ€๋…์„ฑ ์šฐ์„ , ์†Œ๋Ÿ‰ ๋ฐ์ดํ„ฐ)
    const total = posts.length;
    const views = posts.reduce((sum, p) => sum + p.viewCount, 0);
    const published = posts.filter((p) => p.isPublished).length;
     
    // ๋˜๋Š” ๋ช…์‹œ์  ๋ณ€์ˆ˜๋ช…์œผ๋กœ reduce ์œ ์ง€ (๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ)
    const stats = posts.reduce(
      (acc, post) => {
        acc.total++;
        acc.views += post.viewCount;
        if (post.isPublished) acc.published++;
        return acc;
      },
      { total: 0, views: 0, published: 0 }
    );
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: "reduce๋Š” ๋งŒ๋Šฅ์ด์ง€๋งŒ, ๊ฐ€๋…์„ฑ์„ ๋จผ์ € ์ฑ™๊ฒจ๋ผ. ๋ฐ์ดํ„ฐ๊ฐ€ ํฌ์ง€ ์•Š์œผ๋ฉด ๊ฐ๊ฐ ๊ณ„์‚ฐํ•˜๋Š” ๊ฒŒ ๋” ์ฝ๊ธฐ ์‰ฝ๋‹ค."

Q3. ์˜์ฒ ์ด์˜ ํ…Œ์ŠคํŠธ ํƒ€์ž„ โ€” ์‹ค๋ฌด ๋”œ๋ ˆ๋งˆ

์˜ํ˜ธ ๋ฆฌ๋“œ๊ฐ€ ์ฝ”๋“œ๋ฆฌ๋ทฐ์—์„œ ๋ฌป๋Š”๋‹ค: "์˜์ฒ  ๋‹˜, .sort()๋ฅผ ๊ทธ๋ƒฅ ์“ฐ๋ฉด ์›๋ณธ ๋ฐฐ์—ด์ด ๋ณ€๊ฒฝ๋ผ์š”. React state์—์„œ ์ด๊ฑธ ์“ฐ๋ฉด ์–ด๋–ค ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ์ฃ ?"

โœ… ์ •๋‹ต: sort()๋Š” ์›๋ณธ ๋ฐฐ์—ด์„ ๋ณ€๊ฒฝ(mutation)ํ•œ๋‹ค. React state ์ง์ ‘ ๋ณ€๊ฒฝ์€ ๋ฆฌ๋ Œ๋” ๊ฐ์ง€๊ฐ€ ์•ˆ ๋˜๊ณ  ์˜ˆ์ธก ๋ถˆ๊ฐ€๋Šฅํ•œ ๋ฒ„๊ทธ๋ฅผ ๋งŒ๋“ ๋‹ค. ๋ณต์‚ฌ ํ›„ ์ •๋ ฌํ•˜๊ฑฐ๋‚˜ toSorted()๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

// โŒ React state ์ง์ ‘ ๋ณ€๊ฒฝ โ€” ๋ฆฌ๋ Œ๋” ์•ˆ ๋จ!
const [posts, setPosts] = useState([...]);
 
const handleSort = () => {
  posts.sort((a, b) => a.viewCount - b.viewCount); // ์›๋ณธ ์ง์ ‘ ๋ณ€๊ฒฝ
  setPosts(posts); // ๋™์ผํ•œ ๋ฐฐ์—ด ์ฐธ์กฐ โ†’ React๊ฐ€ ๋ณ€๊ฒฝ์„ ๊ฐ์ง€ ๋ชปํ•จ
};
 
// โœ… ๋ณต์‚ฌ ํ›„ ์ •๋ ฌ โ€” ์ƒˆ ๋ฐฐ์—ด ์ฐธ์กฐ
const handleSort = () => {
  const sorted = [...posts].sort((a, b) => a.viewCount - b.viewCount);
  setPosts(sorted); // ์ƒˆ ๋ฐฐ์—ด ์ฐธ์กฐ โ†’ ๋ฆฌ๋ Œ๋” ๋ฐœ์ƒ
};
 
// โœ… ES2023 toSorted โ€” ์›๋ณธ ๋ถˆ๋ณ€ ์ƒˆ ๋ฉ”์„œ๋“œ
const handleSort = () => {
  setPosts(posts.toSorted((a, b) => a.viewCount - b.viewCount));
};
  • ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ push, splice, reverse๋„ ์›๋ณธ ๋ณ€๊ฒฝ โ†’ React state์—์„œ ๊ธˆ์ง€.
  • ๋Œ€์‹  [...arr, newItem], arr.filter(...), [...arr].reverse() ๋˜๋Š” arr.toReversed()๋ฅผ ์‚ฌ์šฉ.
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: "React state๋Š” ๋ถˆ๋ณ€์ด์–ด์•ผ ํ•œ๋‹ค. ๋ฐฐ์—ด ๋ฉ”์„œ๋“œ ์ค‘ ์›๋ณธ์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ๋“ค(sort, push, splice, reverse)์€ state์—์„œ ์ ˆ๋Œ€ ์ง์ ‘ ์‚ฌ์šฉ ๊ธˆ์ง€."

๐Ÿฃ ์˜์ฒ ์ด์˜ ํ‡ด๊ทผ ์ผ๊ธฐ

๋ฐฐ์—ด ๊ณ ์ฐจํ•จ์ˆ˜๋Š” ๋งค์ผ ์“ฐ๋Š” ๊ฑด๋ฐ ์˜ค๋Š˜ ๋˜ ๋ฐฐ์šธ ๊ฒŒ ์žˆ์—ˆ๋‹ค. sort()๊ฐ€ ์›๋ณธ์„ ๋ฐ”๊พผ๋‹ค๋Š” ๊ฑด ์•Œ๊ณ  ์žˆ์—ˆ๋Š”๋ฐ, React state์—์„œ ๊ทธ๊ฒŒ ์™œ ์น˜๋ช…์ ์ธ์ง€ ์ด์ œ ๋ช…ํ™•ํ•˜๊ฒŒ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋๋‹ค.

reduce๋กœ filter + map์„ ๋™์‹œ์— ํ•˜๋Š” ํŒจํ„ด๋„ ์žฌ๋ฏธ์žˆ์—ˆ๋‹ค. ๊ทผ๋ฐ ์˜ํ˜ธ ๋‹˜์ด "๊ฐ€๋…์„ฑ์ด ๋” ์ค‘์š”ํ•˜๋‹ค, ๋Œ€์šฉ๋Ÿ‰ ์•„๋‹ˆ๋ฉด ๊ฐ๊ฐ ์“ฐ๋ผ"๊ณ  ํ–ˆ๋Š”๋ฐ โ€” ๊ทธ ๊ท ํ˜•๊ฐ์ด ์ง„์งœ ์‹œ๋‹ˆ์–ด์˜ ํŒ๋‹จ์ธ ๊ฒƒ ๊ฐ™๋‹ค. ๋‚˜๋Š” ๋ฌด์กฐ๊ฑด ์ตœ์ ํ™”๊ฐ€ ์ข‹์€ ์ค„ ์•Œ์•˜๋Š”๋ฐ.

๐Ÿ’ก ์˜ค๋Š˜์˜ ๊ตํ›ˆ: "๋ฐฐ์—ด ๊ณ ์ฐจํ•จ์ˆ˜๋Š” ์˜๋„๋ฅผ ์ฝ”๋“œ์— ์ƒˆ๊ธฐ๋Š” ๋„๊ตฌ๋‹ค. map์€ '์ „๋ถ€ ๋ณ€ํ™˜', filter๋Š” '์กฐ๊ฑด์œผ๋กœ ์„ ํƒ', reduce๋Š” 'ํ•˜๋‚˜๋กœ ์ถ•์•ฝ'. ์˜๋„์— ๋งž๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์“ฐ๋ฉด ์ฝ”๋“œ๊ฐ€ ์ž์—ฐ์–ด์ฒ˜๋Ÿผ ์ฝํžŒ๋‹ค."

์˜ค๋Š˜ ํ‡ด๊ทผํ•˜๋ฉด์„œ ์˜ํ˜ธ ๋‹˜์ด "๋‹ค์Œ์—” ๋ชจ๋“ˆ ์‹œ์Šคํ…œ์ด์•ผ"๋ผ๊ณ  ํ–ˆ๋Š”๋ฐ, ESM์ด๋ž‘ CJS ์ฐจ์ด๊ฐ€ ๋ญ”์ง€ ์–ด๋ ดํ’‹์ด๋Š” ์•Œ์ง€๋งŒ ์ œ๋Œ€๋กœ๋Š” ๋ชจ๋ฅธ๋‹ค. ๊ธˆ์š”์ผ์ด๋‹ˆ๊นŒ ์ฃผ๋ง์— ํ•œ ๋ฒˆ ๋” ์ฝ์–ด๋ด์•ผ์ง€. ์˜ค๋Š˜ ํ•˜๋ฃจ๋„ ์ˆ˜๊ณ ํ–ˆ๋‹ค!


๐Ÿ”— ๋” ์•Œ์•„๋ณด๊ธฐ