SyntaxError: Unexpected token — 원인·해결·예방
자바스크립트에서 코드가 아예 실행조차 안 되고 "Uncaught SyntaxError: Unexpected token"이 뜰 때가 있다. 해석하면 "파서가 예상하지 못한 토큰을 만났다", 즉 문법이 어긋났다는 뜻이다. 괄호 짝이 안 맞거나, 콤마를 빠뜨렸거나, 따옴표를 안 닫았거나, JSON이 깨졌을 때 흔하다. 앞서 다룬 TypeError·ReferenceError와 결정적으로 다른 점이 하나 있다. 이 둘은 코드가 돌다가 터지는 런타임 에러지만, SyntaxError는 코드를 읽어 들이는 파싱 단계에서 막혀 아예 실행이 시작되지 않는다. 이 글은 이 에러의 의미, 런타임 에러와의 차이, 원인과 해결을 정리한다.

이 글의 구성
🔎 에러 메시지의 의미
SyntaxError는 자바스크립트 엔진이 코드를 실행하기 전, 글자를 의미 단위(토큰)로 쪼갠 뒤(렉싱) 그 토큰들이 문법에 맞는지 분석하는 파싱 단계에서 발생한다. 엔진은 "여기엔 이런 토큰이 와야 한다"는 문법 규칙을 들고 코드를 읽는데, 규칙에 맞지 않는 토큰을 만나면 더 진행하지 못하고 "예상치 못한 토큰"이라며 멈춘다.
메시지를 보면 단서가 있다. Unexpected token 뒤에 문제의 토큰이 따라온다. Unexpected token '}'라면 닫는 중괄호가 엉뚱한 자리에 있다는 뜻이고, Unexpected token ')'라면 닫는 소괄호가 예상 밖이라는 뜻이다. 토큰 자체가 잘못이라기보다, 그 앞에서 무언가(여는 괄호·콤마·값 등)가 빠지거나 어긋나 그 토큰이 "갑자기" 나타난 것이다.
핵심 — 실행이 아니라 "읽기"에서 막혔다
SyntaxError는 코드가 돌다가 난 게 아니라, 엔진이 코드를 다 읽지도 못하고 막힌 것이다. 그래서 그 파일·스크립트는 한 줄도 실행되지 않는다. 메시지가 알려주는 위치(줄·열)는 "여기서 이상함을 느꼈다"는 지점이라, 진짜 실수는 보통 그 직전에 있다.
⚖️ SyntaxError vs 런타임 에러
같은 에러처럼 보여도 SyntaxError와 TypeError·ReferenceError는 발생 시점이 다르다. 이 차이가 디버깅 방식을 가른다.
| 구분 | SyntaxError | 런타임 에러 (Type·Reference) |
|---|---|---|
| 발생 시점 | 파싱(읽기) 단계, 실행 전 | 실행 도중 |
| 영향 범위 | 그 파일·스크립트 전체가 실행 안 됨 | 그 줄까지는 실행됨 |
| try-catch | 같은 스크립트의 정적 문법 오류는 못 잡음 | try-catch로 잡힘 |
핵심은 "전체가 안 돈다"는 점이다. 런타임 에러는 문제의 줄에 닿기 전까지는 코드가 실행되지만, SyntaxError가 있으면 파서가 그 파일을 끝까지 읽지 못해 한 줄도 실행되지 않는다. 그래서 같은 스크립트 안의 정적 문법 오류는 try-catch로 잡을 수도 없다. 잡을 코드 자체가 실행되기 전에 막히기 때문이다. (단, JSON.parse나 eval처럼 실행 중에 동적으로 코드·문자열을 해석할 때 나는 SyntaxError는 try-catch로 잡을 수 있다.)
🧩 자주 나오는 발생 원인 4가지
원인 1 — 괄호·중괄호·대괄호 짝 불일치
가장 흔하다. 여는 괄호는 있는데 닫는 괄호가 없거나 그 반대, 또는 짝이 엇갈린 경우다. 함수·객체·배열·조건문에서 괄호 하나가 빠지면 그 뒤 토큰이 "예상 밖"이 된다.
원인 2 — 콤마·세미콜론 누락 또는 과다
객체·배열 항목 사이 콤마를 빠뜨리거나, 마지막에 콤마를 잘못 넣거나, 콤마 자리에 다른 걸 쓴 경우다. 항목과 항목 사이 구분이 어긋나면 다음 토큰에서 막힌다.
원인 3 — 따옴표·백틱 안 닫음
문자열 따옴표를 안 닫거나, 문자열 안의 같은 따옴표를 이스케이프하지 않은 경우다. 문자열이 끝나지 않으면 그 뒤 코드가 전부 문자열로 빨려 들어가 엉뚱한 곳에서 에러가 난다.
원인 4 — 깨진 JSON·HTML을 파싱
JSON.parse에 잘못된 JSON을 넣거나, 서버가 JSON 대신 HTML 오류 페이지를 돌려줬을 때다. 후자는 Unexpected token '<'로 나타나는데, 응답 첫 글자가 HTML의 <라서 그렇다.
💻 재현과 위치 읽는 법
전형적인 재현이다. 콤마 하나가 빠지면 그다음 토큰에서 막힌다.
// 첫 줄 끝에 콤마 누락
const user = {
name: "김개발"
age: 30
};
// ✗ Uncaught SyntaxError: Unexpected token 'age' (또는 ':')
메시지는 위치를 알려준다. 브라우저는 보통 파일명과 줄:열(line:column)을, 콘솔은 문제 줄에 표시를 띄운다. 다만 표시된 위치는 "엔진이 이상을 감지한 지점"이라, 진짜 실수는 그 한두 줄 위에 있는 경우가 많다. age에서 막혔다고 age가 잘못이 아니라, 그 윗줄 끝 콤마가 빠진 게 원인이다.
// 서버가 JSON 대신 HTML 오류 페이지를 반환
const data = JSON.parse(res);
// ✗ Unexpected token '<' ... (res가 <!DOCTYPE html>... 로 시작)
🛠 해결 방법과 예방
SyntaxError는 "문법을 바로잡는" 문제다. 사람 눈으로 괄호를 세는 것보다 도구가 훨씬 빠르고 정확하다.
| 상황 | 해결·예방 |
|---|---|
| 괄호 짝 | 에디터 괄호 매칭·자동 들여쓰기로 어긋난 짝 찾기 |
| 문법 전반 | ESLint 같은 린터로 저장 시 즉시 오류 표시 |
| 위치 파악 | 메시지의 줄:열 확인, 그 한두 줄 위까지 함께 점검 |
| JSON 파싱 | 응답이 진짜 JSON인지 확인, JSON.parse는 try-catch로 감싸기 |
| HTML 응답 | API URL·상태 코드 확인(오류 페이지가 HTML로 왔는지) |
가장 확실한 예방은 도구를 켜 두는 것이다. 코드 에디터의 괄호 매칭과 문법 하이라이트는 어긋난 짝을 즉시 보여주고, ESLint 같은 린터는 저장하는 순간 문법 오류에 빨간 줄을 긋는다. 사람이 큰 파일에서 괄호를 일일이 세다 보면 놓치기 쉬운데, 도구는 놓치지 않는다.
// ✓ 동적 파싱은 try-catch 로 안전하게
try {
const data = JSON.parse(res);
} catch (e) {
console.error("JSON 파싱 실패:", e.message);
}
💬 자주 묻는 질문 5가지
Q1표시된 줄엔 아무 문제가 없어 보여요.
메시지의 위치는 "엔진이 이상을 느낀 지점"이라, 진짜 실수는 보통 그 한두 줄 위에 있습니다. 윗줄 끝의 콤마 누락이나 안 닫힌 괄호·따옴표를 의심하세요. 표시된 토큰 자체보다 그 직전을 보는 게 핵심입니다.
Q2왜 코드가 한 줄도 안 돌아요?
SyntaxError는 실행 전 파싱 단계에서 막히기 때문입니다. 엔진이 파일을 끝까지 읽지 못하면 그 스크립트 전체가 실행되지 않습니다. 런타임 에러(문제 줄까지는 실행됨)와 다른 점이죠. 그래서 문법부터 고쳐야 나머지가 돕니다.
Q3try-catch로 감쌌는데 왜 안 잡혀요?
같은 스크립트 안의 정적 문법 오류는 try-catch로 못 잡습니다. 잡을 코드 자체가 파싱 단계에서 막혀 실행되지 않기 때문입니다. 단, JSON.parse·eval처럼 실행 중에 동적으로 해석하는 코드에서 나는 SyntaxError는 try-catch로 잡힙니다.
Q4Unexpected token '<' 는 뭔가요?
서버가 JSON 대신 HTML을 돌려줬을 때 흔합니다. 응답 첫 글자가 HTML 태그의 <라서, JSON.parse나 JS 로더가 그걸 만나 막히는 것이죠. API 주소가 맞는지, 상태 코드가 정상인지(오류 페이지가 HTML로 온 건 아닌지) 먼저 확인하세요.
Q5Unexpected end of input은 같은 거예요?
비슷한 SyntaxError지만 방향이 다릅니다. "Unexpected token"은 예상 밖 토큰을 만난 것이고, "Unexpected end of input"은 닫는 괄호·따옴표가 없어 코드가 끝나버린 것입니다. 후자는 무언가를 닫지 않았다는 신호라, 열린 괄호·문자열을 찾아 닫으면 됩니다.
📌 결론
"SyntaxError: Unexpected token"은 파서가 예상하지 못한 토큰을 만나 문법 분석을 멈춘 에러다. TypeError·ReferenceError가 코드가 돌다 나는 런타임 에러라면, 이건 실행 전 읽기 단계에서 막혀 파일 전체가 안 도는 점이 다르다. 그래서 문법부터 바로잡아야 한다.
실무 원칙은 다음과 같다.
🔣 토큰의 직전을 본다. 표시된 토큰이 잘못이 아니라, 그 앞에서 콤마·괄호·따옴표가 빠지거나 어긋난 경우가 대부분이다.
📍 위치를 읽되 위로 거슬러 본다. 메시지의 줄:열은 "이상을 느낀 곳"이라, 진짜 실수는 그 한두 줄 위에 있을 때가 많다.
🧰 도구로 막는다. 에디터 괄호 매칭과 ESLint 린터로 저장 시 즉시 잡고, 동적 파싱(JSON.parse)은 try-catch로 감싼다.
Unexpected token 에러 체크리스트
본 글은 자바스크립트 SyntaxError의 일반적 원인과 해결 방법을 정리한 자료다. 코드 수정은 영향 범위를 확인한 뒤 신중히 적용한다.
#JavaScript #SyntaxError #Unexpectedtoken #자바스크립트에러 #문법오류 #괄호짝 #JSONparse #ESLint #린터 #파싱에러 #프론트엔드 #JS디버깅 #런타임에러 #웹개발 #코딩초보
'IT' 카테고리의 다른 글
| Uncaught (in promise) — 처리 안 된 Promise 거부 원인·해결 (0) | 2026.06.30 |
|---|---|
| x is not a function — 원인·해결·예방 (0) | 2026.06.30 |
| ReferenceError: x is not defined — 원인·해결·예방 (1) | 2026.06.29 |
| Cannot read properties of undefined (reading 'x') — 원인·해결·예방 (0) | 2026.06.29 |
| HTTP 상태 코드 완전 정리 — 1xx~5xx 분류와 4xx·5xx 차이 (1) | 2026.06.28 |
댓글