백엔드

[자바/JAVA] Null Pointer Exception (NPE)

Newbie Developer 2025. 2. 8. 16:45

 

Java 개발을 하면서 가장 흔히 접하는 예외 중 하나가 바로 **Null Pointer Exception (NPE)**입니다. 이번 글에서는 NPE의 개념, 원인, 예제, 해결 방법, 그리고 방지하는 방법까지 자세히 살펴보겠습니다.


1. Null Pointer Exception이란?

**Null Pointer Exception (NPE)**은 Java에서 null 값을 참조하려고 할 때 발생하는 런타임 예외입니다. 즉, null인 객체에 대해 메서드를 호출하거나 필드에 접근하려고 하면 NullPointerException이 발생합니다.

NPE는 java.lang.NullPointerException 클래스를 통해 제공되며, 체크 예외(Checked Exception)가 아닌 **런타임 예외(Runtime Exception)**입니다. 따라서 개발자가 직접 핸들링하지 않으면 프로그램이 강제 종료될 수 있습니다.


2. Null Pointer Exception이 발생하는 원인

2.1. null 값을 참조하는 객체에서 메서드 호출

public class NullPointerExample {
    public static void main(String[] args) {
        String str = null;
        System.out.println(str.length()); // NullPointerException 발생
    }
}
  • str이 null인데 length() 메서드를 호출하려고 하면서 예외가 발생합니다.

2.2. null을 포함하는 배열 요소 접근

public class NullPointerArray {
    public static void main(String[] args) {
        String[] arr = new String[3];
        arr[0] = null;
        System.out.println(arr[0].length()); // NullPointerException 발생
    }
}
  • arr[0]이 null인데 .length()를 호출하려고 하면 NPE가 발생합니다.

2.3. null을 반환하는 메서드 호출

public class NullPointerMethod {
    public static String getNullString() {
        return null;
    }

    public static void main(String[] args) {
        String str = getNullString();
        System.out.println(str.length()); // NullPointerException 발생
    }
}
  • getNullString() 메서드가 null을 반환했지만, 이를 체크하지 않고 .length()를 호출하면 예외가 발생합니다.

2.4. null 값이 포함된 Map에서 값 조회

import java.util.HashMap;
import java.util.Map;

public class NullPointerMap {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("key", null);

        System.out.println(map.get("key").length()); // NullPointerException 발생
    }
}
  • map.get("key")가 null인데 .length()를 호출하면서 NPE가 발생합니다.

2.5. null 객체에서 필드 접근

public class NullPointerField {
    static class Person {
        String name;
    }

    public static void main(String[] args) {
        Person person = null;
        System.out.println(person.name); // NullPointerException 발생
    }
}
  • person 객체가 null인데 person.name을 호출하려고 하면 NPE가 발생합니다.

3. Null Pointer Exception 해결 방법

3.1. null 체크 후 사용

public class NullCheckExample {
    public static void main(String[] args) {
        String str = null;

        if (str != null) {
            System.out.println(str.length());
        } else {
            System.out.println("str is null");
        }
    }
}
  • null 체크를 하면 NPE를 방지할 수 있습니다.

3.2. Optional 사용 (Java 8 이상)

import java.util.Optional;

public class OptionalExample {
    public static void main(String[] args) {
        String str = null;
        Optional<String> optionalStr = Optional.ofNullable(str);
        System.out.println(optionalStr.map(String::length).orElse(0));
    }
}
  • Optional을 사용하면 null을 안전하게 처리할 수 있습니다.

3.3. 기본값 설정

public class DefaultValueExample {
    public static void main(String[] args) {
        String str = null;
        System.out.println((str != null) ? str.length() : 0);
    }
}
  • 삼항 연산자를 활용하여 null일 때 기본값을 설정할 수 있습니다.

3.4. Objects.requireNonNull() 사용

import java.util.Objects;

public class RequireNonNullExample {
    public static void main(String[] args) {
        String str = null;
        System.out.println(Objects.requireNonNull(str, "str은 null일 수 없습니다."));
    }
}
  • Objects.requireNonNull()을 사용하면 null일 경우 명확한 예외 메시지를 제공할 수 있습니다.

4. Null Pointer Exception을 방지하는 방법

4.1. @NonNull 어노테이션 활용

Lombok 또는 Java의 @NonNull 어노테이션을 활용하면 컴파일 단계에서 null을 방지할 수 있습니다.

import lombok.NonNull;

public class NonNullExample {
    public void print(@NonNull String str) {
        System.out.println(str.length());
    }

    public static void main(String[] args) {
        NonNullExample example = new NonNullExample();
        example.print(null); // 컴파일 단계에서 경고
    }
}

4.2. Optional 적극 활용

Java 8 이상에서는 Optional을 활용하여 null 처리를 더욱 명확하게 할 수 있습니다.

4.3. final 키워드 활용

final 키워드를 사용하여 객체가 null이 되지 않도록 강제할 수 있습니다.

public class FinalExample {
    private final String message;

    public FinalExample() {
        this.message = "Hello, World!";
    }

    public String getMessage() {
        return message;
    }
}
  • message는 한 번 초기화되면 null이 될 수 없습니다.

4.4. 방어적 프로그래밍

  • 메서드에서 null이 반환될 가능성이 있다면 호출하는 쪽에서 반드시 체크하는 습관을 가지세요.
  • API를 설계할 때 null을 반환하는 대신 **빈 객체(empty object)**나 Optional을 반환하는 것이 좋습니다.

5. 결론

Null Pointer Exception은 Java 개발에서 가장 흔한 예외 중 하나이지만, 올바른 코딩 습관과 방어적 프로그래밍을 통해 충분히 방지할 수 있습니다. 다음과 같은 원칙을 지키면 NPE를 줄일 수 있습니다.

✅ null 체크를 철저히 한다.
✅ Optional을 적극 활용한다.
✅ Objects.requireNonNull()을 사용한다.
✅ @NonNull 어노테이션을 활용하여 코드 품질을 높인다.
✅ final 키워드를 활용하여 필드가 null이 되지 않도록 한다.