프로그래밍 언어별 흔한 에러 해결 가이드 | C++, Python, Java, JavaScript
이 글의 핵심
프로그래밍 언어별 흔한 에러 해결 가이드입니다. 컴파일 에러, 런타임 에러, 논리 에러를 체계적으로 해결하는 방법을 제시합니다.
들어가며: 에러는 배움의 기회
”에러 메시지가 무슨 뜻인지 모르겠어요”
프로그래밍을 하다 보면 수많은 에러를 만나게 됩니다. 에러는 버그가 아니라 컴파일러나 런타임이 보내는 힌트입니다.
이 글에서 다루는 것:
- 언어별 흔한 에러와 해결법
- 에러 메시지 읽는 법
- 체계적인 디버깅 방법
- 예방 전략
목차
1. C++ 흔한 에러
1.1 Segmentation Fault (세그멘테이션 폴트)
에러 메시지:
Segmentation fault (core dumped)
원인:
- 널 포인터 역참조
- 배열 범위 초과
- 해제된 메모리 접근
- 스택 오버플로
예제:
// 원인 1: 널 포인터 역참조
int* ptr = nullptr;
*ptr = 10; // ❌ Segmentation fault
// 해결
if (ptr != nullptr) {
*ptr = 10;
}
// 원인 2: 배열 범위 초과
int arr[5] = {1, 2, 3, 4, 5};
arr[10] = 100; // ❌ 미정의 동작, Segfault 가능
// 해결: vector 사용 (at()으로 범위 체크)
std::vector<int> vec = {1, 2, 3, 4, 5};
try {
vec.at(10) = 100; // ✅ 예외 발생
} catch (const std::out_of_range& e) {
std::cerr << "범위 초과: " << e.what() << std::endl;
}
// 원인 3: 댕글링 포인터 (해제된 메모리 접근)
int* ptr2 = new int(10);
delete ptr2;
*ptr2 = 20; // ❌ 이미 해제된 메모리
// 해결: 스마트 포인터 사용
std::unique_ptr<int> smart_ptr = std::make_unique<int>(10);
// 자동 해제, 댕글링 포인터 방지
디버깅 도구:
# GDB로 디버깅
g++ -g main.cpp -o main
gdb ./main
(gdb) run
(gdb) backtrace # 크래시 위치 확인
# Valgrind로 메모리 에러 검사
valgrind --leak-check=full ./main
# AddressSanitizer (ASan)
g++ -fsanitize=address -g main.cpp -o main
./main
1.2 Undefined Reference (링커 에러)
에러 메시지:
undefined reference to `myFunction()'
원인:
- 함수 선언만 있고 정의가 없음
- 라이브러리 링크 누락
- 네임스페이스 불일치
예제:
// header.h
void myFunction();
// main.cpp
#include "header.h"
int main() {
myFunction(); // ❌ undefined reference
return 0;
}
// 해결: 정의 추가
// impl.cpp
#include "header.h"
void myFunction() {
// 구현
}
// 컴파일
g++ main.cpp impl.cpp -o main // ✅
라이브러리 링크 누락:
# 에러
g++ main.cpp -o main
# undefined reference to `pthread_create'
# 해결: -lpthread 추가
g++ main.cpp -o main -lpthread
1.3 Template 에러
에러 메시지:
error: no matching function for call to 'std::vector<int>::push_back(std::string)'
원인: 템플릿 타입 불일치
예제:
std::vector<int> vec;
vec.push_back("hello"); // ❌ 타입 에러
// 해결
std::vector<std::string> vec;
vec.push_back("hello"); // ✅
2. Python 흔한 에러
2.1 IndentationError
에러 메시지:
IndentationError: expected an indented block
원인: 들여쓰기 불일치
예제:
# ❌ 에러
def greet():
print("Hello") # 들여쓰기 없음
# ✅ 해결
def greet():
print("Hello")
# ❌ 탭과 스페이스 혼용
def calculate():
x = 10 # 스페이스 4칸
y = 20 # 탭 1개
return x + y # IndentationError
# ✅ 해결: 스페이스로 통일
def calculate():
x = 10
y = 20
return x + y
예방:
- 에디터 설정: 스페이스 4칸
.editorconfig사용
# .editorconfig
[*.py]
indent_style = space
indent_size = 4
2.2 NameError
에러 메시지:
NameError: name 'x' is not defined
원인: 변수를 정의하기 전에 사용
예제:
# ❌ 에러
print(x) # x가 정의되지 않음
# ✅ 해결
x = 10
print(x)
# ❌ 함수 내부에서 전역 변수 수정
count = 0
def increment():
count += 1 # UnboundLocalError
# ✅ 해결: global 키워드
count = 0
def increment():
global count
count += 1
2.3 TypeError
에러 메시지:
TypeError: unsupported operand type(s) for +: 'int' and 'str'
원인: 타입 불일치
예제:
# ❌ 에러
result = 10 + "20" # int + str
# ✅ 해결
result = 10 + int("20") # 30
result = str(10) + "20" # "1020"
# ❌ None 타입 연산
def get_value():
return None
x = get_value()
y = x + 10 # TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
# ✅ 해결: None 체크
x = get_value()
if x is not None:
y = x + 10
2.4 IndexError
에러 메시지:
IndexError: list index out of range
원인: 리스트 범위 초과
예제:
# ❌ 에러
arr = [1, 2, 3]
print(arr[5]) # IndexError
# ✅ 해결: 범위 체크
if len(arr) > 5:
print(arr[5])
else:
print("인덱스 범위 초과")
# ✅ 또는 try-except
try:
print(arr[5])
except IndexError:
print("인덱스 범위 초과")
3. Java 흔한 에러
3.1 NullPointerException
에러 메시지:
java.lang.NullPointerException
원인: null 객체의 메서드 호출
예제:
// ❌ 에러
String str = null;
int len = str.length(); // NullPointerException
// ✅ 해결: null 체크
String str = null;
if (str != null) {
int len = str.length();
}
// ✅ Java 8+ Optional 사용
Optional<String> opt = Optional.ofNullable(str);
int len = opt.map(String::length).orElse(0);
// ✅ Java 14+ 패턴 매칭
if (str instanceof String s) {
int len = s.length();
}
3.2 ClassCastException
에러 메시지:
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
원인: 잘못된 타입 캐스팅
예제:
// ❌ 에러
Object obj = "Hello";
Integer num = (Integer) obj; // ClassCastException
// ✅ 해결: instanceof 체크
Object obj = "Hello";
if (obj instanceof Integer) {
Integer num = (Integer) obj;
} else {
System.out.println("Integer가 아닙니다");
}
// ✅ 제네릭 사용 (타입 안전)
List<Integer> list = new ArrayList<>();
list.add(10);
Integer num = list.get(0); // 캐스팅 불필요
3.3 ConcurrentModificationException
에러 메시지:
java.util.ConcurrentModificationException
원인: 순회 중 컬렉션 수정
예제:
// ❌ 에러
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
for (Integer num : list) {
if (num % 2 == 0) {
list.remove(num); // ConcurrentModificationException
}
}
// ✅ 해결: Iterator 사용
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
Integer num = it.next();
if (num % 2 == 0) {
it.remove();
}
}
// ✅ 또는 removeIf 사용 (Java 8+)
list.removeIf(num -> num % 2 == 0);
4. JavaScript 흔한 에러
4.1 TypeError: Cannot read property of undefined
에러 메시지:
TypeError: Cannot read property 'name' of undefined
원인: undefined 객체의 속성 접근
예제:
// ❌ 에러
const user = undefined;
console.log(user.name); // TypeError
// ✅ 해결: Optional Chaining (ES2020)
console.log(user?.name); // undefined (에러 안 남)
// ✅ 기본값 설정
const name = user?.name ?? 'Guest';
console.log(name); // 'Guest'
// ✅ 명시적 체크
if (user && user.name) {
console.log(user.name);
}
4.2 ReferenceError: x is not defined
에러 메시지:
ReferenceError: x is not defined
원인: 선언되지 않은 변수 사용
예제:
// ❌ 에러
console.log(x); // ReferenceError
// ✅ 해결
const x = 10;
console.log(x);
// ❌ 호이스팅 문제
console.log(y); // undefined (var는 호이스팅)
var y = 10;
// ✅ let/const 사용 (TDZ)
console.log(z); // ReferenceError
const z = 10;
4.3 Promise 에러
에러 메시지:
UnhandledPromiseRejectionWarning: Error: Failed to fetch
원인: Promise rejection 미처리
예제:
// ❌ 에러 (catch 없음)
fetch('https://api.example.com/data')
.then(res => res.json())
.then(data => console.log(data));
// 네트워크 에러 시 UnhandledPromiseRejection
// ✅ 해결: catch 추가
fetch('https://api.example.com/data')
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error('에러:', err));
// ✅ async/await 사용
async function fetchData() {
try {
const res = await fetch('https://api.example.com/data');
const data = await res.json();
console.log(data);
} catch (err) {
console.error('에러:', err);
}
}
4.4 this 바인딩 문제
에러 메시지:
TypeError: Cannot read property 'name' of undefined
원인: this가 예상과 다른 객체를 가리킴
예제:
// ❌ 에러
class Person {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hello, ${this.name}`);
}
}
const person = new Person('Alice');
setTimeout(person.greet, 1000); // TypeError: this is undefined
// ✅ 해결 1: 화살표 함수
setTimeout(() => person.greet(), 1000);
// ✅ 해결 2: bind
setTimeout(person.greet.bind(person), 1000);
// ✅ 해결 3: 클래스 필드 (화살표 함수)
class Person {
constructor(name) {
this.name = name;
}
greet = () => {
console.log(`Hello, ${this.name}`);
}
}
5. 디버깅 전략
체계적 디버깅 프로세스
flowchart TD
A[에러 발생] --> B[에러 메시지 읽기]
B --> C{컴파일 에러?}
C -->|예| D[문법/타입 체크]
C -->|아니오| E{런타임 에러?}
E -->|예| F[스택 트레이스 확인]
E -->|아니오| G[논리 에러]
D --> H[에러 위치 수정]
F --> I[디버거로 추적]
G --> J[로그/테스트 추가]
H --> K[재컴파일]
I --> L[원인 파악]
J --> L
L --> M[수정 및 테스트]
디버깅 도구 비교
| 언어 | 디버거 | 로깅 | 테스트 |
|---|---|---|---|
| C++ | GDB, LLDB, Visual Studio Debugger | spdlog, glog | Google Test, Catch2 |
| Python | pdb, ipdb | logging, loguru | pytest, unittest |
| Java | IntelliJ Debugger, jdb | Log4j, SLF4J | JUnit, TestNG |
| JavaScript | Chrome DevTools, VS Code | console, winston | Jest, Mocha |
디버깅 팁
1. 에러 메시지를 정확히 읽기
❌ "에러가 났어요" (너무 모호)
✅ "TypeError: Cannot read property 'name' of undefined at line 42" (구체적)
2. 최소 재현 코드 만들기
// 복잡한 코드에서 에러 발생
// → 최소한의 코드로 재현
// 원본 (100줄)
function complexFunction() {
// ... 복잡한 로직
const result = data.map(x => x.value).filter(x => x > 10);
// ... 더 복잡한 로직
}
// 최소 재현 (5줄)
const data = [{ value: 5 }, { value: 15 }];
const result = data.map(x => x.value).filter(x => x > 10);
console.log(result); // [15]
3. 이분 탐색으로 원인 찾기
# 코드가 100줄인데 어디서 에러가 나는지 모름
# → 절반씩 주석 처리하며 범위 좁히기
# 1-50줄 주석 → 에러 안 남 → 1-50줄에 원인
# 1-25줄 주석 → 에러 남 → 26-50줄에 원인
# 26-37줄 주석 → 에러 안 남 → 26-37줄에 원인
# ...
4. 로그 추가
// C++
#include <iostream>
void process(int x) {
std::cout << "DEBUG: x = " << x << std::endl;
// ... 로직
}
# Python
import logging
logging.basicConfig(level=logging.DEBUG)
def process(x):
logging.debug(f"x = {x}")
# ... 로직
5. 디버거 사용
# Python pdb
python -m pdb script.py
# Node.js
node --inspect-brk script.js
# Chrome에서 chrome://inspect 열기
6. 정리
핵심 요약
C++ 흔한 에러:
- Segmentation Fault: 메모리 접근 에러
- Undefined Reference: 링커 에러
- Template 에러: 타입 불일치
Python 흔한 에러:
- IndentationError: 들여쓰기 불일치
- NameError: 변수 미정의
- TypeError: 타입 불일치
Java 흔한 에러:
- NullPointerException: null 접근
- ClassCastException: 잘못된 캐스팅
- ConcurrentModificationException: 순회 중 수정
JavaScript 흔한 에러:
- TypeError: undefined 접근
- ReferenceError: 변수 미정의
- Promise rejection: 비동기 에러 미처리
디버깅 체크리스트
- 에러 메시지 정확히 읽기
- 스택 트레이스 확인
- 최소 재현 코드 만들기
- 로그 추가
- 디버거 사용
- 테스트 코드 작성
다음 단계
각 언어의 자세한 디버깅 방법은 아래 글을 참고하세요:
- C++ 크래시 디버깅
- Python 디버깅
- JavaScript 디버깅
관련 주제:
- 단위 테스트 작성법
- 로깅 전략
- 에러 처리 패턴