본문 바로가기
Framework/Spring Framework

[Spring] 스프링에서 멤버 필드에 의존성 주입을 표현할 때 'final'은 괜찮지만 'static final'은 안되는 이유

by gf0308 2022. 3. 5.

(참조: https://djkeh.github.io/articles/Why-should-final-member-variables-be-conventionally-static-in-Java-kor/)

 

 

상황

스프링에서 멤버 필드에 의존성 주입을 표현하는 코드를 보면 으레 다음과 같이 'private final 타입 필드명'으로 돼있다.

public class MovieRecommender {

    private final CustomerPreferenceDao customerPreferenceDao; // <------ here

    @Autowired
    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
        this.customerPreferenceDao = customerPreferenceDao;
    }

    // ...
}

해당 부분을 하나씩 살펴보면

private - 클래스 외부에 비가시적이어야 하니 private 한 접근제어

final - 객체가 생성되어 이 필드에 주입되면 계속 그것만 쓰이면 되고, 굳이 다시 재할당 될 이유/필요도 없고 그럴 일도 없음 -> 굳이 (시스템적으로) 재할당 자체는 가능함을 열어둘 필요가 없으므로 final 설정

CustomerPreferenceDao - 변수의 타입

customerPreferenceDao - 변수명

 

멤버 필드에 의존성 주입을 표현할 때 'final'은 해줬지만 static까지 붙여줘서 'static final' 이도록 하지 않은 이유

일단 final과 static의 차이에 대해 명확히 해보자.

- final : 재할당 가능 여부에 관한 것

    --final이면 재할당 불가; 그 인스턴스에서 한번 할당되었으면 인스턴스 소멸시까지 그대로 유지.

    --final이 아니면 재할당 가능; 그 인스턴스에서 한번 할당되었어도 얼마든지 값이 변경될 수 있음(일반적인 '변수')

static : 해당 멤버의 메모리 상 수명주기에 대한 것

    --static이면 T메모리에서 static 영역에 로드; 프로그램이 메모리에 올라와있는 동안엔 계속 존재

    --non static이면 stack 영역에 로드; 인스턴스가 존재하는 동안엔 계속 존재, 인스턴스 소멸 시 같이 소멸)

멤버 필드에 의존성 주입을 표현할 때 'final'은 해줬지만 'static final' 은 안 되는 이유는

단도직입적으로 말하면 "시스템에 불필요한 부하를 가하고 성능 이슈를 유발할 수 있기 때문이다."

 

의존성 주입이 되는 필드를

"private final CustomerPreferenceDao customerPreferenceDao" 으로 final 처리해놓은 것은 

필드 customerPreferenceDao가 한번 초기화가 되면 다시 재할당이 일어날 일이 없기 때문이다.

 

근데 만약 여기에 static을 적용하면 해당 필드 객체는 static 영역에 로드되어지고, 프로그램이 메모리에 올라와있는 동안은 메모리에 계속 존재하게 된다.

 

근데 문제가 되는 점은 이런 의존성 주입이 일어나는 필드가 실무의 엔터프라이즈 급 애플리케이션에서는 수천수만 개가 될 수 있다는 것이다. 

(흔히 public static final 로 해서 쓰는 클래스 상수 경우처럼) 몇 개 안된다면 그리 시스템에 부담이 가지 않겠지만)

이 수천 수만 개의 필드들로의 주입을 위해 생성되는 객체들이, 만약 "private static final CustomerPreferenceDao customerPreferenceDao" 식으로 되어 있어 계속 static 영역에 적재되어 있게 된다면,

이는 시스템에 큰 부하가 되며 결국 성능 이슈가 발생하게 될 것이다.

 

정리

스프링에서 필드(field)에 의존성을 표현할 때 'final'만 붙이고 'static final'까지 해놓지 않은 이유는

(stack 영역에 객체가 올라가는) 인스턴스 변수로 둬서 인스턴스 소멸 시 같이 소멸되도록 해도 되는 객체들을,

그것도 수없이 많을 객체들을 굳이 (static 영역에 객체가 올라가는) 정적 변수[클래스 변수]로 해놓아서 시스템에 상시 부하가 가게 할 필요가 없기 때문이다.