Cannot read properties of null (reading 'x') — 원인·해결·예방
자바스크립트에서 "TypeError: Cannot read properties of null (reading 'x')"이 뜨면, null인 값에서 x라는 속성을 읽으려 했다는 뜻이다. 앞서 다룬 undefined 버전과 메시지가 거의 같지만, 비어 있던 값이 undefined가 아니라 null이라는 점이 다르다. 그리고 이 null 버전에는 압도적으로 흔한 범인이 하나 있다. 바로 DOM 요소를 못 찾은 경우다. document.querySelector나 getElementById가 요소를 찾지 못하면 null을 돌려주는데, 그 null에 대고 .value나 .addEventListener를 부르는 순간 터진다. 스크립트가 화면(DOM)보다 먼저 실행됐거나 선택자가 틀렸을 때가 대부분이다. 이 글은 이 에러의 의미, null이 생기는 원인, 그리고 스크립트 타이밍을 비롯한 해결을 정리한다.

이 글의 구성
🔎 에러 메시지의 의미
이 에러는 TypeError의 한 종류로, null인 값의 속성에 접근할 때 발생한다. null은 "값이 비어 있음"을 의도적으로 나타내는 특수한 값인데, 비어 있는 것에서 무언가를 꺼내려 하니 엔진이 멈추고 에러를 던진다. 메시지의 (reading 'x')는 "x라는 속성을 읽으려다 막혔다"는 뜻이고, 정작 null이었던 건 점 바로 왼쪽 값이다.
가장 흔한 형태가 el.value처럼 DOM 요소를 다룰 때다. document.querySelector나 getElementById로 요소를 찾았는데 그 요소가 페이지에 없으면, 이 메서드들은 null을 반환한다. 그 null을 el에 담아 두고 el.value나 el.addEventListener를 부르면 "Cannot read properties of null"이 난다. 예전 브라우저는 같은 상황을 "Cannot read property 'x' of null"이라는 옛 문구로 보여줬는데, 의미는 같다.
핵심 — 대개 "요소를 못 찾았다"
이 에러의 상당수는 DOM 조회 결과가 null인 경우다. 즉 querySelector·getElementById가 요소를 못 찾았다는 신호다. 그래서 디버깅의 첫 질문은 "이 선택자가 실제로 요소를 찾았는가, 그리고 그 시점에 그 요소가 화면에 존재했는가?"다. console.log로 그 조회 결과를 찍어 null인지부터 확인한다.
⚖️ null vs undefined
이 에러를 이해하려면 null과 undefined의 차이를 잡아야 한다. 메시지가 "of null"이냐 "of undefined"냐로 원인의 방향이 갈린다.
| 구분 | null | undefined |
|---|---|---|
| 뜻 | 비었음을 의도적으로 표시 | 아직 값이 할당 안 됨 |
| 주로 어디서 | DOM 못 찾음, 명시적 초기화, API의 null | 없는 속성, 미반환 함수, 비동기 전 |
| typeof 결과 | "object" (유명한 함정) | "undefined" |
쉽게 말해 undefined는 "아직 안 채워짐", null은 "비었다고 일부러 표시함"이다. 그래서 "of null" 에러는 대개 무언가를 못 찾아 null이 반환된 상황, 특히 DOM 조회 실패를 가리킨다. 참고로 typeof null이 "object"로 나오는 건 자바스크립트의 오래된 버그로 유명한데, null 여부를 확인할 때는 typeof 대신 값 === null이나 옵셔널 체이닝을 쓰는 게 안전하다.
🧩 자주 나오는 발생 원인 4가지
원인 1 — 스크립트가 DOM보다 먼저 실행됨
가장 흔하다. script를 head에 넣어 페이지 본문이 그려지기 전에 실행되면, 그 시점엔 요소가 아직 없어 querySelector가 null을 반환한다. 그 null에 접근해 터진다. 타이밍 문제다.
원인 2 — 선택자 오타·잘못된 선택자
아이디는 #으로, 클래스는 .으로 시작해야 하는데 빠뜨리거나, 실제 마크업과 다른 이름을 쓴 경우다. 요소는 화면에 있어도 선택자가 안 맞으면 못 찾아 null이 된다.
원인 3 — 아직 생성되지 않은 동적 요소
자바스크립트나 프레임워크가 나중에 그려 넣는 요소를, 그려지기 전에 조회한 경우다. 조건부 렌더링·비동기 데이터로 생기는 요소를 이른 시점에 찾으면 null이 나온다.
원인 4 — API·데이터가 null을 반환
서버 응답의 어떤 필드가 null이거나, 변수를 null로 초기화한 뒤 값을 안 채운 경우다. 그 null의 하위 속성에 접근하면 DOM과 무관하게 같은 에러가 난다.
💻 재현과 스크립트 타이밍
가장 흔한 재현이다. 요소를 못 찾아 null이 된 결과에 접근하는 경우다.
// #username 요소가 없거나, 아직 안 그려짐
const el = document.querySelector("#username");
console.log(el.value);
// ✗ TypeError: Cannot read properties of null (reading 'value')
// 조회 결과부터 확인 — null 이면 범인
console.log(el); // null
특히 스크립트 위치가 원인일 때가 많다. script가 head에서 먼저 실행되면 본문 요소가 아직 없다. 이때는 스크립트를 body 끝으로 옮기거나, script 태그에 defer를 붙이거나, DOMContentLoaded 이벤트 안에서 코드를 실행하면 요소가 준비된 뒤에 돌게 된다.
// ✓ DOM이 준비된 뒤 실행
document.addEventListener("DOMContentLoaded", () => {
const el = document.querySelector("#username");
if (el) console.log(el.value);
});
// ✓ 또는 script 에 defer, 혹은 body 끝에 배치
<script src="app.js" defer></script>
🛠 해결 방법과 예방
핵심은 두 가지다. 요소가 존재하는 시점에 조회하고, 조회 결과가 null일 수 있음을 방어하는 것이다.
| 원인 | 해결 |
|---|---|
| 스크립트 타이밍 | script를 body 끝·defer·DOMContentLoaded 안에서 실행 |
| 선택자 오류 | #·. 접두사·이름을 실제 마크업과 대조, 개발자도구로 확인 |
| null 가능성 | if (el) 가드 또는 옵셔널 체이닝 el?.value로 방어 |
| 동적 요소 | 요소가 생성된 뒤(렌더 완료·이벤트 후) 조회 |
| API의 null | 응답 필드 null 방어(?.·기본값), 스키마 확인 |
값이 null일 수 있는 자리라면 옵셔널 체이닝과 가드로 막는다. 옵셔널 체이닝은 undefined와 null을 똑같이 안전하게 처리한다.
// ✓ 요소가 있을 때만 접근
const el = document.querySelector("#username");
if (el) {
el.addEventListener("click", handler);
}
// ✓ 옵셔널 체이닝 — null/undefined 모두 안전
const value = document.querySelector("#username")?.value ?? "";
다만 방어만으로 끝내지 말자. if (el)로 에러는 막았는데 정작 요소를 못 찾는 원인(오타·타이밍)이 그대로면, 기능이 조용히 동작하지 않는다. 에러를 막는 것과 요소를 제대로 찾는 것은 다른 문제다. 왜 null이 나오는지도 함께 고쳐야 한다.
"of null"이면 대개 요소를 못 찾은 것이다. 선택자와 스크립트 타이밍부터 보라. 방어는 옵셔널 체이닝으로.
— 조회 결과부터 console.log
💬 자주 묻는 질문 5가지
Q1요소가 분명 있는데 null이 나와요.
스크립트가 그 요소보다 먼저 실행됐을 가능성이 큽니다. script가 head에 있으면 본문이 그려지기 전에 돌아 null이 나옵니다. script를 body 끝으로 옮기거나 defer를 붙이거나 DOMContentLoaded 안에서 실행하세요. 선택자 오타도 함께 확인하고요.
Q2"of null"이랑 "of undefined"는 뭐가 다른가요?
비어 있던 값의 종류가 다릅니다. null은 "비었다고 의도적으로 표시함"이라 주로 DOM 못 찾음·명시적 초기화·API의 null에서, undefined는 "아직 안 채워짐"이라 없는 속성·미반환 함수·비동기 전에서 나옵니다. 해결 도구(옵셔널 체이닝·널 병합)는 양쪽에 공통입니다.
Q3querySelector는 왜 null을 주나요?
일치하는 요소가 없을 때 querySelector와 getElementById는 null을 반환합니다. 반면 querySelectorAll은 못 찾아도 null이 아니라 빈 목록(NodeList)을 돌려줍니다. 그래서 단일 요소 조회 결과는 항상 "null일 수 있다"고 보고 방어하는 게 안전합니다.
Q4typeof로 null을 확인하면 되나요?
안 됩니다. typeof null은 "object"로 나오는 오래된 함정이 있어 null 판별에 부적합합니다. 값 === null로 직접 비교하거나, 옵셔널 체이닝(?.)과 널 병합(??)으로 null과 undefined를 함께 안전하게 처리하세요.
Q5옵셔널 체이닝만 붙이면 되나요?
에러는 막지만 근본 해결은 아닙니다. el?.value는 el이 null이어도 안전하지만, 정작 요소를 못 찾는 원인(선택자 오타·스크립트 타이밍)이 남아 있으면 기능이 조용히 안 됩니다. 방어와 함께 왜 null이 나오는지도 고쳐야 합니다.
📌 결론
"Cannot read properties of null (reading 'x')"은 null인 값의 속성을 읽으려다 나는 TypeError다. undefined 버전과 메시지는 같지만, 비어 있던 값이 null이라는 점이 다르고, 그 상당수는 querySelector·getElementById가 요소를 못 찾아 null을 반환한 경우다.
실무 원칙은 다음과 같다.
🔍 조회 결과부터 확인한다. "of null"이 뜨면 그 앞의 DOM 조회가 null인지 console.log로 보고, 선택자가 실제 요소를 찾는지 대조한다.
🕐 실행 타이밍을 맞춘다. 스크립트를 body 끝·defer·DOMContentLoaded 안에서 실행해, 요소가 준비된 뒤에 조회한다.
🛡 방어와 원인을 함께 잡는다. if 가드·옵셔널 체이닝으로 null을 막되, 요소를 못 찾는 근본 원인(오타·타이밍·동적 생성)도 고친다.
of null 에러 체크리스트
본 글은 자바스크립트 TypeError(of null)의 일반적 원인과 해결 방법을 정리한 자료다. 코드 수정은 영향 범위를 확인한 뒤 신중히 적용한다.
#JavaScript #TypeError #Cannotreadproperties #null #자바스크립트에러 #querySelector #getElementById #DOM #옵셔널체이닝 #DOMContentLoaded #defer #프론트엔드 #JS디버깅 #null과undefined #웹개발
'IT' 카테고리의 다른 글
| Unexpected end of JSON input — JSON.parse 원인·해결·예방 (1) | 2026.07.01 |
|---|---|
| Cannot set properties of undefined (setting 'x') — 원인·해결·예방 (0) | 2026.07.01 |
| Maximum call stack size exceeded — 무한 재귀 원인·해결 (0) | 2026.06.30 |
| Uncaught (in promise) — 처리 안 된 Promise 거부 원인·해결 (0) | 2026.06.30 |
| x is not a function — 원인·해결·예방 (0) | 2026.06.30 |
댓글