Studying/React
리액트 공부하기 - 옵셔널 체이닝(Optional Chaining) ?.
creamymood
2025. 5. 19. 18:16
옵셔널 체이닝이란?
?. 문법을 사용해서 객체의 중첩된 속성에 접근할 때, 중간에 null이나 undefined가 있어도 에러를 발생시키지 않고 undefined를 반환하게 해주는 문법.
리액트(React)에서 **옵셔널 체이닝 (Optional Chaining)**은 매우 자주 쓰이는 문법인데, 특히 실무에서 API 호출 결과나 객체 안에 값이 있는지 확인할 때 정말 많이 사용한다.
기본 예제
const user = {
name: "Jane",
profile: {
age: 20,
country: "Korea"
}
};
console.log(user.profile?.age); // 20
console.log(user.profile?.gender); // undefined
console.log(user.address?.city); // undefined (에러 안남)
옵셔널 체이닝 안 쓰면:
console.log(user.address.city); // ❌ TypeError: Cannot read properties of undefined
왜 에러가 뜰까 ? ↓
더보기
문제 코드
console.log(user.address.city);
예를 들어, 아래처럼 user 객체가 있을 때:
const user = {
name: "Jane",
// address가 아예 없음!
};
실행 순서 이해하기
자바스크립트는 왼쪽부터 차례대로 평가한다.
- 먼저 user.address를 보는데, address가 없기 때문에 이 값은 undefined.
- 그런데 그다음 .city를 호출하려고 시도.
그런데 undefined.city는 존재하지 않음. - 그래서 자바스크립트가 에러 보여줌
- TypeError: Cannot read properties of undefined (reading 'city')
왜 에러일까?
- 자바스크립트에서 undefined나 null은 객체가 아닌데, 마치 객체처럼 .city 같은 속성을 접근하려고 하면 **"너 undefined인데 뭘 읽으려고 해?"**라고 하면서 에러.
그래서 옵셔널 체이닝이 필요한 것!
console.log(user?.address?.city); // ✅ undefined 반환, 에러 안 남
- user.address가 없으면, 바로 undefined를 반환하고 멈춤.
- 그다음 .city를 시도하지 않기 때문에 에러가 발생하지 않음.
음.. 일반 점 표기법(.) 이랑 다른 점이 있어 ? ↓
더보기
구분 | . (점 표기법) | ?. (옵셔널 체이닝) |
역할 | 객체의 속성에 접근 | 객체의 속성에 안전하게 접근 |
안전성 | 중간 값이 null/undefined이면 에러 발생 | 중간 값이 없어도 에러 없이 undefined 반환 |
사용 목적 | 값이 무조건 존재할 때 | 값이 있을 수도 없을 수도 있을 때 |
리액트에서는 비동기 데이터가 많아서 이런 경우 자주 생겨:
function UserCard({ user }) {
return (
<div>
<p>{user.name}</p> // ❌ user가 undefined면 에러
<p>{user?.name}</p> // ✅ 안전하게 처리
</div>
);
}
요약
- .는 값이 반드시 있다고 확신할 때만 사용
- ?.는 값이 없을 수도 있는 경우에 안전하게 접근할 때 사용
- 실무에선 대부분 ?.가 훨씬 많이 쓰여! 특히 API 데이터 다룰 때!
리액트 실무 예제
예제 1: API 응답 받아오기 (비동기 데이터)
function UserProfile({ user }) {
return (
<div>
<h2>{user?.name || "이름 없음"}</h2>
<p>국가: {user?.profile?.country || "정보 없음"}</p>
</div>
);
}
이런 구조는 API 응답 전에 user가 아직 undefined일 수 있어서, 옵셔널 체이닝을 안 쓰면 앱이 깨질 수 있어.
실무에서 자주 쓰이는 예시
1. API 데이터 안전 접근
const productName = product?.details?.name || "상품명 없음";
2. 이벤트 객체에서 값 꺼낼 때
const handleClick = (e) => {
const id = e?.target?.dataset?.id;
console.log(id);
};
3. 라우터에서 넘어온 state
const location = useLocation();
const userId = location?.state?.userId;