React로 컴포넌트를 작성하다 보면 자식 컴포넌트에 props를 전달할 때 todo={todo}
처럼 객체 전체를 넘기는 방식과 {...todo}
처럼 전개 연산자(spread)를 사용하는 방식이 있습니다.
이 두 방식은 비슷해 보이지만, 컴포넌트 내부에서 데이터를 접근하는 방법이 완전히 달라집니다.
잘못 사용하면 undefined
에러가 발생할 수 있으므로, 각각의 차이와 올바른 사용법을 명확히 이해하는 것이 중요합니다.
예를 들어 List
라는 컴포넌트가 있고, 그 안에서 TodoItem
컴포넌트를 반복적으로 렌더링한다고 가정합니다.
{todos.map((todo) => (
<TodoItem key={todo.id} {...todo} onUpdate={onUpdate} />
))}
위 코드에서 ...todo
는 todo
객체를 전개해서 각각의 속성을 TodoItem
에 개별적으로 전달하는 방식입니다. 즉 다음과 같은 형태로 변환됩니다:
<TodoItem
id={todo.id}
isDone={todo.isDone}
content={todo.content}
date={todo.date}
onUpdate={onUpdate}
/>
이때 TodoItem
컴포넌트는 아래처럼 작성해야 정상적으로 동작합니다:
const TodoItem = (props) => {
console.log(props.id); // ✅ 가능
console.log(props.content); // ✅ 가능
};
만약 아래처럼 props.todo.id
처럼 작성한다면?
const TodoItem = (props) => {
console.log(props.todo.id); // ❌ 에러 발생 (props.todo는 undefined)
};
→ todo
라는 이름의 prop 자체가 존재하지 않기 때문에 undefined
오류가 발생합니다.
{...todo}
방식 - 전개 연산자 사용<TodoItem {...todo} onUpdate={onUpdate} />
todo
객체의 속성들이 모두 개별 props로 전달됨id
, isDone
, content
, date
각각 별도로 넘어감props.id
, props.content
등으로 직접 접근 가능props.todo
는 존재하지 않음컴포넌트 내부 사용 예:
const TodoItem = (props) => {
console.log(props.id); // ✅ 정상
console.log(props.todo); // ❌ undefined
};
todo={todo}
방식 - 객체 자체를 prop으로 전달<TodoItem todo={todo} onUpdate={onUpdate} />
todo
라는 하나의 객체가 prop으로 전달됨props.todo.id
, props.todo.content
등으로 접근 가능props.id
등은 존재하지 않음컴포넌트 내부 사용 예:
const TodoItem = (props) => {
console.log(props.todo.id); // ✅ 정상
console.log(props.id); // ❌ undefined
};
전달 방식 | 내부 접근 방식 | 주의할 점 |
---|---|---|
{...todo} |
props.id , props.content |
전개된 개별 props로 전달됨 |
todo={todo} |
props.todo.id |
todo 객체 전체가 하나의 prop으로 전달됨 |
❌ 혼용 시 에러 | props.todo 또는 props.id 접근 오류 발생 |
전달 방식과 접근 방식이 일치해야 함 |
...todo
방식이 간결해서 좋습니다.todo
자체를 한 객체로 묶어서 다루고 싶을 때, 또는 하위 컴포넌트에서 객체 단위로 넘겨받고 싶은 경우는 todo={todo}
방식이 더 유리합니다.타입스크립트를 쓰는 경우 todo
객체 전체를 넘기는 방식이 타입 정의가 더 간단해지는 경우가 많습니다.
interface Todo {
id: number;
content: string;
isDone: boolean;
date: string;
}
interface TodoItemProps {
todo: Todo;
onUpdate: (id: number) => void;
}
const TodoItem = ({ todo, onUpdate }: TodoItemProps) => {
return (
<div>
<input onChange={() => onUpdate(todo.id)} />
<span>{todo.content}</span>
</div>
);
};
React에서 props를 전달할 때는 전달 방식과 접근 방식이 반드시 일치해야 합니다.
원하는 방식 | List에서 넘기는 방식 | TodoItem 내부에서 접근 방식 |
---|---|---|
개별 속성으로 전달 | <TodoItem {...todo} /> |
props.id , props.content , ... |
todo 객체 자체로 전달 | <TodoItem todo={todo} /> |
props.todo.id , props.todo.content |
혼용하면 런타임 에러가 발생하므로, props를 어떻게 넘길지와 어떻게 받을지를 항상 세트로 고려하세요!
React - useMemo를 사용한 코드 vs 사용하지 않은 코드 비교 (0) | 2025.06.07 |
---|---|
React - useState를 useReducer로 대체하는 간단 예제 (0) | 2025.06.05 |
React - useEffect를 이용한 컴포넌트 라이프사이클 제어 정리 (1) | 2025.06.05 |
♻️ 리액트 컴포넌트 생명 주기(Lifecycle) 핵심 정리 (0) | 2025.06.03 |
React - 상태 끌어올리기(State Lifting) (0) | 2025.06.01 |