LogoSEO Jing
  • All Posts
  • SEO Jing
  • KD Team
  • CLab CoreTeam
  • Study

Contact Me

© 2026 SEOJing. All rights reserved.

프론트엔드스터디JavaScript배열ES6구조분해할당스프레드

프론트엔드 스터디 9주차: React 입문 전 필수 JS 문법 — map, 구조 분해, 스프레드

2026년 5월 25일·29분 읽기

9주차 학습 자료

  • 입문 강의 (처음이라면): 얄코 JS 입문 강의

    배열 메서드, 구조 분해, 스프레드, 클래스 챕터

  • 강의 스킵 가능: 아래 스킵 진단 문제 10개를 모두 맞히면 강의 시청 스킵 가능합니다.
  • 심화 자료 (딥다이브 대비):

    딥다이브 요약 GitHub

안녕하세요. 9주차입니다. 다음 주부터 React를 시작합니다. React 코드를 처음 열면 거의 모든 줄에서 이번 주에 다루는 문법들이 등장합니다. 개념을 암기하기보다는 언제, 왜 쓰는지에 집중하며 읽어보세요. 이번 주 내용을 자연스럽게 읽을 수 있다면, 다음 주 React 코드가 훨씬 편하게 느껴질 것입니다.


스킵 진단 문제

아래 10문제를 막힘없이 풀 수 있다면,

이번 주 학습 자료를 생략하거나, 모르는 부분만 선택적으로 읽으셔도 좋습니다.

바로 하단의 본문 섹션들을 확인해보세요.

Quiz1 / 10
Q.Array.prototype.map()에 대한 설명으로 옳은 것은 무엇인가요?

  1. map / filter / reduce — React에서 리스트를 다루는 핵심

고차함수(Higher-Order Function)는 함수를 인자로 받거나 반환하는 함수입니다. 배열 메서드 중 React에서 가장 자주 사용하는 세 가지를 살펴봅니다.

map — 각 요소를 변환하여 새 배열 만들기

map은 배열의 각 요소에 콜백 함수를 적용하고, 변환된 값으로 이루어진 새 배열을 반환합니다. 원본 배열은 변경되지 않습니다.

js
const numbers = [1, 2, 3, 4, 5];

// 각 요소를 2배로
const doubled = numbers.map((n) => n * 2);
// [2, 4, 6, 8, 10]

// 객체 배열에서 특정 값만 추출
const users = [
  { id: 1, name: "철수" },
  { id: 2, name: "영희" },
];
const names = users.  user

React에서는 배열 데이터를 화면에 렌더링할 때 map을 사용합니다. 아래 코드는 다음 주부터 매일 보게 될 패턴입니다.

jsx
// React에서 리스트 렌더링 — 다음 주부터 이 패턴을 매일 씁니다
function UserList({ users }) {
  return (
    <ul>
      {users.map((user) => (
        <UserCard key={user.id} {...user} />
      ))}
    </ul>
  );
}

filter — 조건에 맞는 요소만 걸러내기

filter는 콜백이 true를 반환하는 요소만 모아 새 배열을 반환합니다.

js
const products = [
  { name: "사과", price: 1000 },
  { name: "한우", price: 50000 },
  { name: "배", price: 2000 },
];

// 1만원 이하 상품만
const affordable = products.filter((p) => p.price <= 10000);
// [{ name: "사과", ... }, { name: "배", ... }]

reduce — 배열을 하나의 값으로 누적하기

reduce는 배열의 각 요소를 순회하며 하나의 값으로 누적합니다. 합계 계산, 그룹핑 등에 사용됩니다.

js
const cart = [
  { name: "사과", price: 1000, qty: 2 },
  { name: "배", price: 2000, qty: 1 },
];

// 총 금액 계산
const total = cart.reduce((acc, item) => acc + item.price * item.qty, 0);
// 1000*2 + 2000*1 = 4000

// reduce로 객체 만들기 (그룹핑)
const byName  cart  

체이닝 — 여러 메서드를 연결해서 사용

map, filter, reduce는 모두 새 배열(또는 값)을 반환하므로, 점(.)으로 이어서 조합할 수 있습니다.

js
const scores = [85, 42, 93, 67, 55, 78, 91];

// 70점 이상인 점수만 골라 평균 구하기
const passing = scores.filter((s) => s >= 70); // [85, 93, 67, 78, 91]
const avg = passing.reduce((sum, s) => sum + s, 0) / passing.length;
// 82.8

그 외 자주 쓰는 배열 메서드

js
const arr = [1, 2, 3, 4, 5];

arr.find((n) => n > 3); // 4 — 조건에 맞는 첫 번째 요소
arr.findIndex((n) => n > 3); // 3 — 조건에 맞는 첫 번째 인덱스
arr.some((n) => n > 4); // true — 하나라도 조건 충족
arr.every((n) => n > 0); // true — 모두 조건 충족
arr 

2. 구조 분해 할당 — React props와 useState의 문법

구조 분해 할당(Destructuring)은 배열이나 객체에서 원하는 값을 변수로 한 번에 꺼내는 문법입니다. React에서 props, useState, API 응답 처리 등 어디서나 사용합니다.

객체 구조 분해

js
const user = { name: "철수", age: 25, role: "admin" };

// 원하는 프로퍼티만 변수로 추출
const { name, age } = user;
// name="철수", age=25

// 다른 이름으로 받기
const { name: userName } = user;
// userName="철수"

// 기본값 지정 — 프로퍼티가 없으면 기본값 사용
const { name = "익명" } = {};
// name="익명"

// 중첩 객체 구조 분해
const response = { data: { user:      

배열 구조 분해

js
const [a, b, c] = [1, 2, 3];
// a=1, b=2, c=3

// 일부만 추출 (건너뛰기)
const [first, , third] = [10, 20, 30];
// first=10, third=30

// 기본값
const [x = 0, y = 0] = [5];
// x=5, y=0

React의 useState가 바로 배열 구조 분해의 대표적인 사용 예입니다. 다음 주에 가장 먼저 만나게 될 패턴입니다.

jsx
// React useState — 배열 구조 분해의 핵심 활용
const [count, setCount] = useState(0);
// count = 현재 상태값, setCount = 상태를 변경하는 함수

함수 파라미터에서 구조 분해

React 컴포넌트의 props를 받을 때 가장 자주 사용하는 패턴입니다.

jsx
// React 컴포넌트 — 파라미터에서 바로 구조 분해
function Card({ title, description, onClick }) {
  return (
    <div onClick={onClick}>
      <h2>{title}</h2>
      <p>{description}</p>
    </div>
  );
}

// 사용할 때
<Card    

3. 스프레드 & Rest — 불변 상태 업데이트 패턴

스프레드(...)는 배열이나 객체를 펼치는 문법이고, Rest는 나머지를 모으는 문법입니다. 같은 ... 기호를 사용하지만 역할이 다릅니다.

스프레드 — 펼치기

js
// 배열 복사 & 합치기
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const merged = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]

// 배열에 새 요소 추가 (원본 변경 없이)
const newArr = [...arr1, 7]; // [1, 2, 3, 7]

React에서 상태를 업데이트할 때, 기존 객체를 직접 수정하지 않고 스프레드로 새 객체를 만드는 패턴을 사용합니다. 이것이 React의 불변 업데이트입니다.

jsx
// React 상태 업데이트 — 스프레드로 새 객체 만들기
const [user, setUser] = useState({ name: "철수", age: 25 });

// age만 변경한 새 객체 생성
setUser((prev) => ({ ...prev, age: prev.age + 1 }));
// { name: "철수", age: 26 } — 새 객체, 원본은 그대로

// 배열 상태에 항목 추가
const [items, setItems] = useState(["사과", "배"]);
setItems(  prev 

Rest 파라미터 — 나머지 모으기

js
// 함수의 나머지 인자 모으기
function sum(...nums) {
  return nums.reduce((acc, n) => acc + n, 0);
}
sum(1, 2, 3, 4); // 10

// 구조 분해에서 나머지 모으기
const { id, ...rest } = { id: 1, name: "철수", age: 25 };
// id=1, rest={ name: "철수", age: 25 }

const head tail      

Rest 패턴은 React에서 특정 props만 꺼내고 나머지를 하위 컴포넌트에 전달할 때 유용합니다.

jsx
// className만 꺼내고, 나머지 props는 button에 전달
function Button({ className, ...rest }) {
  return <button className={`btn ${className}`} {...rest} />;
}

  1. 옵셔널 체이닝(?.) & null 병합(??) — 안전한 데이터 접근

API에서 받아온 데이터는 특정 필드가 null이거나 undefined일 수 있습니다. 이때 안전하게 접근하기 위한 두 가지 연산자를 알아봅니다.

옵셔널 체이닝 (?.)

?.는 앞의 값이 null 또는 undefined이면 에러 없이 undefined를 반환합니다.

js
const user = null;

// 기존 방식 — 매번 null 체크를 해야 함
const city = user && user.address && user.address.city;

// 옵셔널 체이닝 — 간결하게
const city2 = user?.address?.city; // undefined (에러 없음)

// 메서드 호출에도 사용 가능
user?.greet?.(); // user가 null이면 undefined, 에러 없음

// 배열 요소 접근에도 사용 가능
const first = arr?.[0]; // arr이 null이면 undefined

null 병합 연산자 (??)

??는 왼쪽 값이 null 또는 undefined일 때만 오른쪽 기본값을 반환합니다. ||와의 차이가 중요합니다.

js
// ?? — null/undefined일 때만 기본값
const name = user?.name ?? "익명";

// || vs ?? 차이 — 이 차이를 반드시 이해하세요
const count1 = 0 || "기본값"; // "기본값" — 0은 falsy이므로
const count2 = 0 ?? "기본값"; // 0 — null/undefined가 아니므로

const text1 = "" || "기본값"; // "기본값" — 빈 문자열은 falsy
const text2 = "" ?? "기본값"; // "" — null/undefined가 아니므로

실무에서 0이나 빈 문자열("")이 유효한 값인 경우가 많습니다. 이때 ||를 쓰면 의도치 않게 기본값으로 대체되므로, ??를 사용하는 것이 안전합니다.


  1. 모듈 (import / export) — 컴포넌트를 파일로 나누는 방법

모듈은 파일 단위로 코드를 분리하고, 필요한 것만 import/export하는 시스템입니다. React 프로젝트는 전부 모듈 기반으로 작성됩니다. 하나의 컴포넌트가 하나의 파일이 되는 구조입니다.

named export — 여러 개 내보내기

js
// math.js — 유틸 함수는 named export
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

// 다른 파일에서 import — 중괄호 필수
import { add, subtract } from "./math.js";

// 이름 변경도 가능
import { add as sum } from "./math.js";

default export — 파일당 한 개

jsx
// Button.jsx — React 컴포넌트는 보통 default export
export default function Button({ label }) {
  return <button>{label}</button>;
}

// 다른 파일에서 import — 중괄호 없이, 원하는 이름으로
import Button from "./Button.jsx";
import MyButton from "./Button.jsx"; // 이름 자유롭게 지정 가능

React 프로젝트의 관례

React 프로젝트에서는 일반적으로 컴포넌트는 default export, 유틸 함수나 상수는 named export로 내보냅니다. 실제 React 코드를 열면 이런 구조를 볼 수 있습니다.

jsx
// components/UserCard.jsx — 컴포넌트 (default export)
import { formatDate } from "../utils/date";
import styles from "./UserCard.module.css";

export default function UserCard({ name, createdAt }) {
  return (
    <div className={styles.card}>
      <h3>{name}</h3>
      <span>{formatDate(createdAt)
js
// utils/date.js — 유틸 함수 (named export)
export function formatDate(date) {
  return new Date(date).toLocaleDateString("ko-KR");
}

export function isToday(date) {
  return new Date(date).toDateString() === new Date().toDateString();
}

6. try/catch — API 호출에서 에러 처리하기

실제 앱에서는 네트워크 요청이 실패하거나, 예상치 못한 데이터가 올 수 있습니다. try/catch는 이런 에러를 잡아서 앱이 멈추지 않도록 처리하는 문법입니다.

기본 구조

js
try {
  // 에러가 발생할 수 있는 코드
  const result = JSON.parse("잘못된 JSON");
} catch (error) {
  // 에러 발생 시 실행되는 코드
  console.error("파싱 실패:", error.message);
} finally {
  // 에러 여부와 관계없이 항상 실행 (선택사항)
  console.log("처리 완료");
}

async/await + try/catch

API 호출은 비동기(async)로 이루어지므로, async/await와 try/catch를 함께 사용합니다. 이 패턴은 React에서 데이터를 불러올 때 기본이 됩니다.

js
async function fetchUser(userId) {
  try {
    const response = await fetch(`/api/users/${userId}`);

    if (!response.ok) {
      throw new Error(`HTTP 에러: ${response.status}`);
    }

    const user = await response.json();
    return user

React에서의 에러 처리 패턴

React에서는 useEffect 안에서 API를 호출하고, try/catch로 에러를 처리합니다. 아래 패턴은 다음 주에 React를 배우면서 직접 작성하게 됩니다.

jsx
// React useEffect에서의 데이터 fetching — 미리 눈에 익혀두세요
function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function loadUser() {
      try {
        const response = await fetch

📝 학습 이해 퀴즈

아래 코드를 브라우저 콘솔에서 직접 실행해보고 결과를 예측해보세요.

Quiz1 / 3
Q.아래 코드의 출력 결과는 무엇인가요?
js
const numbers = [1, 2, 3, 4, 5];

const result = numbers
.filter((n) => n % 2 !== 0)
.map((n) => n * n);

console.log(result);

📝 9주차 스터디 인증 미션

다가오는 스터디 모임 전, 아래 질문에 대해 찾아보고 본인만의 말로 정리한 뒤 댓글로 남겨주세요.

Quiz1 / 4
Q.React의 useState는 왜 객체가 아닌 배열을 반환할까요? 배열 구조 분해로 받으면 어떤 점이 편리한지 설명해보세요.

포스트 목록

/study/clab-26-1
파일 13개, 폴더 2개
프론트엔드 스터디 1주차: 마크업 그 이상, 실무를 위한 중급 HTML 가이드프론트엔드 스터디 2주차: 사용자와 소통하는 폼 & CSS의 시작프론트엔드 스터디 3주차: 프론트엔드의 첫 번째 벽, 박스 모델과 스타일링프론트엔드 스터디 4주차: 자유자재 레이아웃 (포지션과 플렉스박스)프론트엔드 스터디 5주차: JavaScript 시작 — 타입, 변수, 그리고 JS가 이상한 이유프론트엔드 스터디 6주차: 객체, 함수, 그리고 스코프프론트엔드 스터디 7주차: 불변성, 프로토타입, 타입 체크프론트엔드 스터디 8주차: 클로저, Promise, async/await프론트엔드 스터디 9주차: React 입문 전 필수 JS 문법 — map, 구조 분해, 스프레드프론트엔드 스터디 10주차: React 기초 1 — 컴포넌트, JSX, props, useState프론트엔드 스터디 11주차: React 기초 2 — useEffect, 이벤트 처리, 폼프론트엔드 스터디 심화: this, 실행 컨텍스트, 이터러블프론트엔드 스터디 심화: 에러 처리와 정규 표현식
map
(
(
user
)
=>
.
name
)
;
// ["철수", "영희"]
=
.
reduce
(
(
acc, item
)
=>
{
acc[item.name] = item.price;
return acc;
}, {});
// { 사과: 1000, 배: 2000 }
.
includes
(
3
)
;
// true — 포함 여부
{
name
:
"철수"
}
}
}
;
const {
data: {
user: { name: apiUserName },
},
} = response;
// apiUserName="철수"
title
="인사"
description
="안녕하세요"
onClick
={handleClick}
/>
;
(
prev
)
=>
[
...
,
"포도"
]
)
;
// ["사과", "배", "포도"]
[
,
...
]
=
[
1
,
2
,
3
,
4
,
5
]
;
// head=1, tail=[2, 3, 4, 5]
}
</span>
</div>
);
}
;
} catch (error) {
console.error("사용자 조회 실패:", error.message);
return null;
}
}
(
`/api/users/${userId}`
)
;
const data = await response.json();
setUser(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}
loadUser();
}, [userId]);
if (loading) return <p>로딩 중...</p>;
if (error) return <p>에러: {error}</p>;
return <h1>{user?.name}</h1>;
}