싱글톤 객체 사용 시 NullPointerException 발생 원인과 해결 방법

밀초·2025년 4월 8일
0

spring

목록 보기
25/34

Spring 기반의 웹 애플리케이션에서 컨트롤러 클래스에 싱글톤 객체를 필드에 선언했을 때, 서버 기동 중 빈 초기화 단계에서 NullPointerException이 발생하는 문제를 해결하는 방법을 공유하려고 합니다.

문제의 원인

아래와 같은 코드에서 문제가 발생합니다:

@RestController
public class TestController {
    private final Tests tests = Tests.getInstance(); // 여기서 예외 발생
    ...
}

Spring 컨테이너는 컨트롤러를 빈으로 등록하면서 필드 초기화를 수행합니다. 이 시점에 Tests.getInstance() 내부에서 사용하는 DAO가 아직 초기화되지 않아 NullPointerException이 발생하게 됩니다.

에러 메시지

Caused by: java.lang.NullPointerException: Cannot invoke "TestDao.select(String)" because the return value of "TestDao.getInstance()" is null
at Tests.init(Tests.java:28)
at Tests.<init>(Tests.java:14)
at Tests.getInstance(Tests.java:35)
at TestController.<init>(TestController.java:27)

해결 방법 – Lazy Initialization

이 문제를 해결하기 위해 필드에서 직접 초기화하지 않고, 필요할 때만 메서드 내부에서 호출하도록 변경했습니다.

수정된 코드

@RestController
public class TestController {
    // 원래 호출 했던 부분
    // private final Tests tests = Tests.getInstance();

    @RequestMapping("/test/api")
    public TestResponse doTest(HttpServletRequest req) {
        Tests tests = Tests.getInstance(); // 메서드 내부 호출: 이 시점에는 모든 객체가 정상 초기화된 상태
        ...
    }
}

대안: Spring Bean 주입 방식

@Service, @Component 등을 사용한 Spring Bean 주입 방식(@Autowired)으로도 문제를 해결할 수 있지만, 이 경우 기존 구조의 변경이 불가피합니다.

반면, 메서드 내부에서 호출하는 Lazy 패턴은 코드 변경 범위를 최소화하면서도 싱글톤 객체를 안정적으로 사용할 수 있는 간단하고 효과적인 방법입니다. 기존 코드의 변경이 어려운 상황이라면 Lazy 패턴을 추천드립니다.

감사합니다.

profile
안녕하세요 :) 성장하는 개발자 밀초입니다 !

0개의 댓글