본문 바로가기
IT

x is not a function — 원인·해결·예방

by 샤나엘 2026. 6. 30.
반응형

x is not a function — 원인·해결·예방

자바스크립트에서 무언가를 호출했더니 "Uncaught TypeError: x is not a function"이 뜬다. 해석하면 "x는 함수가 아닌데 함수처럼 호출했다"는 뜻이다. 이름 뒤에 ()를 붙여 실행하려 했는데, 정작 그 자리에 있던 값이 함수가 아니었던 것이다. 메서드 이름 오타, 라이브러리가 안 불러와진 상태, this가 엉뚱한 걸 가리켜 메서드를 못 찾는 경우, 배열 메서드를 배열이 아닌 값에 쓴 경우가 단골이다. 다행히 메시지가 친절해서 "무엇이 함수가 아닌지"를 그대로 알려준다. 이 글은 이 에러의 의미, 원인, 그리고 typeof 가드를 비롯한 해결·예방을 정리한다.

x is not a function

 

이 글의 구성

 

🔎에러 메시지의 의미
🧩자주 나오는 발생 원인 4가지
💻재현과 진단
🛠해결 방법과 안전 호출
⚖️this 손실로 인한 경우
💬자주 묻는 질문 5가지

🔎 에러 메시지의 의미

이 에러는 TypeError의 한 종류다. 자바스크립트에서 어떤 값 뒤에 ()를 붙이면 "이걸 함수로 실행하라"는 뜻인데, 그 값이 실제로 호출 가능한 함수가 아니면 엔진이 "이건 함수가 아니다"라며 TypeError를 던진다. 숫자·문자열·객체·undefined 같은 값을 함수처럼 부르려 할 때 발생한다.

 

메시지가 꽤 구체적이다. obj.method is not a function이라면 obj.method가 함수가 아니라는 뜻이고, doSomething is not a function이라면 doSomething이 함수가 아니라는 신호다. 즉 () 바로 앞에 있던 그 이름이 함수가 아니었던 것이다. 무엇을 호출하려다 막혔는지 메시지가 정확히 짚어 주므로, 그 값의 정체부터 확인하면 된다.

핵심 — () 앞의 값이 함수가 아니었다

메시지의 "x"는 호출하려던 대상이다. 그 x가 undefined인지, 다른 타입의 값인지, 아니면 이름을 잘못 썼는지를 확인하는 게 첫걸음이다. console.log(typeof x)를 찍어 보면 "function"이 아닌 무엇이 들어 있는지 바로 드러난다.


🧩 자주 나오는 발생 원인 4가지

원인 1 — 메서드 이름 오타·대소문자

가장 흔하다. toLowerCase를 toLowercase로, getElementById를 getElementByID로 쓰는 식이다. 없는 이름으로 접근하면 그 값은 undefined가 되고, undefined를 호출하니 "is not a function"이 난다.

원인 2 — 변수에 함수가 아닌 값이 들어 있음

같은 이름의 변수가 함수를 덮어썼거나, 함수라고 생각한 값이 사실 숫자·문자열·객체인 경우다. 또 API 응답을 함수처럼 호출하거나, 함수를 반환할 줄 알았는데 값을 반환한 경우도 여기 해당한다.

원인 3 — 라이브러리 미로드·버전 차이

라이브러리가 안 불러와졌거나, 버전이 달라 그 메서드가 없거나 이름이 바뀐 경우다. 스크립트 순서가 틀려 라이브러리보다 내 코드가 먼저 실행되면 메서드를 못 찾아 호출에서 터진다.

원인 4 — 타입에 없는 메서드 호출

배열 메서드(map·forEach)를 배열이 아닌 값에 쓰거나, 유사 배열(arguments·일부 DOM 컬렉션)에 배열 메서드를 바로 호출하는 경우다. 그 타입에는 그런 메서드가 없어 함수가 아니라고 막힌다.


💻 재현과 진단

전형적인 재현이다. 메서드 이름 오타로 undefined를 호출하게 되는 경우다.

// toLowerCase 를 toLowercase 로 오타
const name = "Kim";
console.log(name.toLowercase());
// ✗ TypeError: name.toLowercase is not a function

// 정체 확인 — function 이 아니면 범인
console.log(typeof name.toLowercase); // "undefined"

진단의 핵심은 () 앞 값의 타입을 찍어 보는 것이다. typeof로 확인했을 때 "function"이 아니라 "undefined"·"object"·"string" 등이 나오면, 그 값이 왜 함수가 아닌지(오타·미로드·잘못된 값)를 추적하면 된다.

// 유사 배열(arguments)에 배열 메서드 → not a function
function sum() {
  return arguments.map(n => n * 2); // arguments엔 map 없음
}
// ✗ TypeError: arguments.map is not a function

🛠 해결 방법과 안전 호출

원인별로 손볼 곳이 다르다. 대부분은 "정말 함수인지"를 확인하는 데서 풀린다.

원인 해결
오타 메서드 철자·대소문자 확인(toLowerCase 등), 자동완성 활용
함수 아님 typeof x === "function" 가드, 그 값이 무엇인지 추적
미로드·버전 스크립트 순서·로드 확인, 라이브러리 버전별 메서드 존재 확인
유사 배열 Array.from()·전개([...x])로 진짜 배열로 변환 후 메서드 호출
this 손실 화살표 함수·bind로 this 고정(아래 섹션 참고)

값이 함수일 수도 아닐 수도 있는 자리라면, 호출 전에 확인하거나 옵셔널 호출을 쓴다.

// ✓ 함수일 때만 호출
if (typeof callback === "function") {
  callback();
}

// ✓ 옵셔널 호출 — 단, null/undefined 일 때만 건너뜀
obj.method?.();

여기서 옵셔널 호출 ?.()의 동작을 정확히 알아 둘 필요가 있다. obj.method?.()는 obj.method가 null이나 undefined일 때만 호출을 건너뛰고 undefined를 돌려준다. 만약 obj.method에 함수가 아닌 다른 값(숫자·문자열 등)이 들어 있다면, ?.()로도 막지 못하고 여전히 "is not a function"이 난다. 그래서 "없을 수도 있는 콜백"엔 ?.()가 알맞고, "값은 있는데 함수가 아닌" 상황까지 막으려면 typeof 검사가 필요하다.


⚖️ this 손실로 인한 경우

메서드 이름이 분명 맞는데도 이 에러가 난다면 this 문제일 수 있다. 객체의 메서드를 떼어내 콜백으로 넘기거나 다른 함수로 호출하면, 그 메서드 안의 this가 원래 객체를 잃어버려 내부에서 부르는 다른 메서드를 못 찾는다.

// 메서드를 떼어 콜백으로 넘기면 this 손실
const obj = {
  value: 10,
  show() { return this.getValue(); },
  getValue() { return this.value; }
};
setTimeout(obj.show, 100);
// ✗ this가 obj가 아니게 되어 this.getValue is not a function

// ✓ bind 또는 화살표로 this 고정
setTimeout(obj.show.bind(obj), 100);
setTimeout(() => obj.show(), 100);

this 바인딩은 그 자체로 깊은 주제라 별도로 다루지만, 여기서 기억할 것은 하나다. "메서드 이름은 맞는데 not a function이라면 this가 엉뚱한 걸 가리키고 있지 않은지" 의심해 보는 것이다. bind나 화살표 함수로 this를 원래 객체에 고정하면 풀린다.

메시지가 "무엇이" 함수가 아닌지 짚어 준다. () 앞 값의 typeof부터 찍어라. 이름이 맞는데도면 this를 의심하라.

 

— 정말 함수인지부터 확인


💬 자주 묻는 질문 5가지

Q1분명 그 메서드가 있는데 왜 not a function이죠?

먼저 철자·대소문자를 확인하세요(toLowerCase vs toLowercase). 맞다면 그 값의 typeof를 찍어 보세요. "function"이 아니면 변수가 다른 값으로 덮였거나, 라이브러리가 안 불러와졌거나, this가 엉뚱한 걸 가리키는 경우입니다.

Q2이거랑 "Cannot read properties of undefined"는 뭐가 다른가요?

undefined의 속성을 읽으려 하면 "Cannot read properties of undefined"이고, 값을 함수로 호출하려는데 함수가 아니면 "is not a function"입니다. 다만 obj.method()에서 method가 undefined면 "obj.method is not a function"으로 나타나기도 합니다. 둘 다 결국 "그 자리에 기대한 게 없다"는 신호죠.

Q3map is not a function이 떠요.

대상이 진짜 배열이 아닐 가능성이 큽니다. arguments나 일부 DOM 컬렉션 같은 유사 배열, 또는 객체에 map을 호출하면 그 타입엔 map이 없어 막힙니다. Array.from()이나 전개 연산자([...x])로 진짜 배열로 바꾼 뒤 호출하세요. Array.isArray로 먼저 확인해도 좋습니다.

Q4?.() 만 붙이면 안전한가요?

부분적으로만 안전합니다. obj.method?.()는 method가 null이나 undefined일 때만 호출을 건너뜁니다. method에 함수가 아닌 다른 값(숫자·문자열 등)이 들어 있으면 ?.()로도 여전히 에러가 납니다. "값은 있는데 함수가 아닌" 경우까지 막으려면 typeof === "function" 검사를 쓰세요.

Q5라이브러리 메서드인데 not a function이에요.

라이브러리가 로드되기 전에 호출했거나, 버전이 달라 그 메서드가 없거나 이름이 바뀐 경우입니다. 스크립트 순서를 확인해 라이브러리를 먼저 로드하고, 사용 중인 버전의 문서에서 그 메서드가 실제로 존재하는지 확인하세요. CDN 로드 실패도 같은 증상을 만듭니다.


📌 결론

"x is not a function"은 함수가 아닌 값에 ()를 붙여 호출했을 때 나는 TypeError다. 메시지가 () 앞의 어떤 값이 함수가 아닌지 정확히 짚어 주므로, 그 값의 정체를 확인하는 데서 해결이 시작된다.

실무 원칙은 다음과 같다.

 

🧪 typeof부터 찍는다. () 앞 값의 typeof가 "function"이 아니면, 무엇이 들어 있는지(undefined·다른 타입)를 보고 원인을 좁힌다.

🔤 이름과 타입을 맞춘다. 메서드 철자·대소문자를 확인하고, 배열 메서드는 진짜 배열에만(Array.from으로 변환) 호출한다.

🔗 this와 로드를 의심한다. 이름이 맞는데도 나면 this 손실(bind·화살표로 고정)을, 라이브러리 메서드면 로드 순서·버전을 점검한다.

not a function 에러 체크리스트

 

01메시지가 짚은 () 앞 값의 typeof 확인.
02메서드 철자·대소문자 일치 점검.
03변수가 함수가 아닌 값으로 덮이지 않았는지 확인.
04배열 메서드면 대상이 진짜 배열인지(Array.isArray) 확인.
05이름 맞는데도면 this 손실(bind·화살표) 의심.
06라이브러리면 로드 순서·버전·메서드 존재 확인.

본 글은 자바스크립트 TypeError(is not a function)의 일반적 원인과 해결 방법을 정리한 자료다. 코드 수정은 영향 범위를 확인한 뒤 신중히 적용한다.

 

#JavaScript #TypeError #isnotafunction #자바스크립트에러 #함수호출 #메서드오타 #this바인딩 #typeof #Arrayfrom #옵셔널호출 #프론트엔드 #JS디버깅 #런타임에러 #웹개발 #코딩초보

반응형

댓글