2026. 7. 1.
AI가 만든 React 목록이 map 오류로 멈출 때, 3분 복구 5칸
AI가 만든 React 목록 화면에서 Cannot read properties of undefined reading map 오류가 뜰 때, 전체 컴포넌트를 다시 만들기 전에 오류 줄, 데이터 모양, 배열 기본값, 로딩 상태, AI 수정 프롬프트를 3분 안에 확인합니다.

AI가 만든 투두 목록, 게시글 카드, 관리자 테이블을 처음 실행했는데 화면 대신 Cannot read properties of undefined (reading 'map')이 뜨면 초보자는 바로 막힙니다. 방금 받은 코드를 버리고 다시 만들어야 할지, API가 틀린 건지, React 문법을 다시 배워야 하는지 구분이 안 됩니다. 이 오류는 대부분 목록으로 돌릴 값이 아직 배열이 아닌 상태에서 map()을 호출해서 생깁니다.
오늘 목표는 전체 파일 재작성이 아닙니다. 오류 줄과 데이터 모양을 확인한 뒤 배열 기본값으로 화면을 살리는 것입니다. 3분 동안 아래 5칸만 보면 AI에게도 훨씬 정확한 수정을 맡길 수 있습니다.
react.dev의 React 공식 문서는 배열 데이터를 map()으로 JSX 목록으로 바꾸는 방식을 설명합니다. developer.mozilla.org의 Array.prototype.map() 문서도 map()을 배열 메서드로 설명합니다. 그래서 오류의 핵심은 React가 어렵다는 뜻이 아니라, 지금 map() 앞에 있는 값이 배열인지부터 확인해야 한다는 뜻입니다.
30초 안에 오류 줄에서 map 앞의 이름을 잡습니다
먼저 콘솔이나 터미널의 오류 줄을 그대로 봅니다. 보통 이런 모양입니다.
TypeError: Cannot read properties of undefined (reading 'map')
at TodoList (TodoList.jsx:14:12)
여기서 초보자가 볼 것은 두 가지입니다. 파일 이름과 줄 번호, 그리고 코드에서 map 앞에 붙은 이름입니다.
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
이 예시에서는 todos가 문제 후보입니다. todos가 undefined이거나 배열이 아니면 todos.map()은 실행될 수 없습니다. developer.mozilla.org의 TypeError 설명처럼, 기대한 타입이 아닌 값에 연산을 시도하면 타입 오류가 납니다. 그러니 첫 30초에는 고칠 코드를 넓히지 말고 map 앞의 값 하나만 표시합니다.
AI에게 물어볼 때도 "React map 오류 고쳐줘"보다 아래처럼 말하는 편이 낫습니다.
TodoList.jsx 14번째 줄에서 todos.map 때문에 오류가 납니다.
전체 컴포넌트를 다시 만들지 말고 todos가 어디서 undefined가 되는지 먼저 확인해 주세요.
수정 후보를 3개 이하로 좁혀 주세요.
1분 안에 데이터 모양이 배열인지 확인합니다
AI가 만든 코드에서는 변수 이름이 맞아 보여도 실제 응답 모양이 다를 때가 많습니다. 예를 들어 코드는 todos.map()을 쓰는데 API 응답은 아래처럼 한 단계 안에 들어 있을 수 있습니다.
{
"items": [
{ "id": 1, "title": "첫 항목" }
]
}
이 경우 todos에 응답 전체가 들어가면 todos.map()이 아니라 todos.items.map()이어야 합니다. 반대로 처음 렌더링 순간에는 아직 fetch가 끝나지 않아 todos가 비어 있을 수도 있습니다.
확인용으로는 잠깐만 로그를 넣습니다.
console.log("todos:", todos);
로그에 undefined가 나오면 값이 아직 없습니다. { items: [...] }처럼 객체가 나오면 경로가 틀렸습니다. [] 또는 [ ... ]가 나오면 배열은 맞고, 다른 문제가 있을 가능성이 큽니다. 여기서 바로 any나 임시 문자열로 덮어버리면 다음 오류가 늦게 터집니다. 화면을 살리되 데이터 모양은 숨기지 않는 수정이 필요합니다.
2분 안에 배열 기본값을 넣고 렌더링을 막지 않습니다
가장 작은 복구는 map() 앞에 항상 배열이 오게 만드는 것입니다. state라면 처음 값을 빈 배열로 둡니다.
const [todos, setTodos] = useState([]);
props나 API 응답에서 꺼내는 값이라면 Array.isArray()로 확인한 뒤 배열만 통과시킵니다. developer.mozilla.org 문서는 Array.isArray(value)가 값이 실제 배열인지 확인한다고 설명합니다.
const todoItems = Array.isArray(data?.items) ? data.items : [];
return (
<ul>
{todoItems.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
이 수정은 오류를 숨기는 꼼수가 아닙니다. React 목록은 배열을 기준으로 렌더링되므로, 아직 데이터가 없을 때 빈 배열을 넘기면 화면은 멈추지 않습니다. 다만 API 경로가 틀린 문제까지 해결한 것은 아닙니다. 그래서 다음 칸에서 로딩과 빈 상태를 나눠야 합니다.
3분 안에 로딩, 빈 배열, 실패를 나눕니다
빈 배열 기본값만 넣으면 화면은 살지만 "데이터가 아직 오는 중"인지 "진짜 항목이 없음"인지 "요청 실패"인지 구분하기 어렵습니다. react.dev의 조건부 렌더링 문서는 조건에 따라 다른 JSX를 반환하는 방식을 안내합니다. 목록 오류를 줄일 때도 이 구분이 필요합니다.
if (loading) {
return <p>목록을 불러오는 중입니다.</p>;
}
if (error) {
return <p>목록을 불러오지 못했습니다.</p>;
}
if (todoItems.length === 0) {
return <p>표시할 항목이 없습니다.</p>;
}
return (
<ul>
{todoItems.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
이렇게 나누면 undefined.map은 줄고, 사용자도 빈 화면을 오류로 오해하지 않습니다. react.dev 문서가 말하는 key 규칙도 같이 지킵니다. map() 안에서 반복되는 항목에는 안정적인 key가 필요합니다. 이미 API에 id가 있다면 key={todo.id}처럼 데이터의 고유값을 쓰는 편이 안전합니다.
AI에게는 수정 명령보다 확인 자료를 먼저 줍니다
AI 코딩 도구에 "이 오류 고쳐줘"라고만 쓰면 전체 컴포넌트를 다시 짜거나, 응답 구조를 추측해서 다른 문제를 만들 수 있습니다. 아래 프롬프트를 그대로 채워 넣습니다.
상황:
AI가 만든 React 목록 화면에서 아래 오류가 납니다.
오류:
[콘솔 오류 전체와 파일명:줄번호 붙여넣기]
문제 코드:
[map이 있는 return 부분 15줄 정도 붙여넣기]
현재 데이터 로그:
console.log로 확인한 값은 [undefined / [] / { items: [...] } / 다른 모양]입니다.
요청:
전체 컴포넌트를 다시 작성하지 말고, map 앞의 값이 항상 배열이 되도록 최소 수정만 해 주세요.
로딩 상태, 빈 배열 상태, 실패 상태를 구분해 주세요.
수정한 줄과 이유를 짧게 설명해 주세요.
이 프롬프트의 핵심은 최소 수정과 데이터 로그입니다. AI가 추측으로 구조를 바꾸지 못하게 만들고, 지금 오류가 난 줄 주변만 고치게 합니다. 실행할 명령을 여러 개 받기보다 수정 범위를 먼저 좁히는 것이 초보자에게 더 안전합니다.
마지막에는 다시 실행해서 5칸을 체크합니다
수정이 끝나면 화면이 뜨는지만 보지 말고 아래 5칸을 확인합니다.
1. 콘솔에서 reading 'map' 오류가 사라졌는가
2. 데이터가 오기 전 로딩 문구가 보이는가
3. 빈 배열일 때 빈 상태 문구가 보이는가
4. 실제 배열 데이터가 들어오면 목록이 보이는가
5. key 경고가 새로 생기지 않았는가
map 오류는 React 전체를 다시 배워야 한다는 신호가 아닙니다. 목록 화면에서 배열이어야 하는 값이 아직 배열이 아닌 순간을 찾으라는 신호에 가깝습니다. 오늘은 오류 줄, 데이터 모양, 배열 기본값, 상태 분기, AI 프롬프트까지만 잡으면 됩니다. 이 다섯 칸을 채운 뒤에도 실패한다면 그때는 API 응답 구조나 fetch 위치를 따로 보면 됩니다.
참고 출처
- React Docs, Rendering Lists: https://react.dev/learn/rendering-lists
- React Docs, Conditional Rendering: https://react.dev/learn/conditional-rendering
- MDN, Array.isArray(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
- MDN, Array.prototype.map(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
- MDN, TypeError: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Unexpected_type
다음으로 읽을 기사
같은 흐름으로 이어 읽기 좋은 기사만 추려 보여줍니다.
첫 번째 댓글을 남겨보세요
여러분의 생각이 다른 독자에게 도움이 됩니다.
댓글 0
이 글을 읽은 독자들의 생각을 나눠보세요.