Kotlin 지연 초기화 방법 정리
10 Oct 2022패스트 캠퍼스 실무 프로젝트로 배우는 Kotlin & Spring 강의 정리
지연 초기화
- 대상에 대한 초기화를 미뤘다가 실제 사용 시점에 초기화하는 방법
- 초기화 과정에서 자원을 많이 쓰거나 오버헤드가 발생할 경우 유리할 수 있음
- 예제
- 무한 스크롤
- 싱글톤 패턴의 지연 초기화
- JPA의 엔티티 lazy loading
- 코틀린에서는 두 가지 방식의 지연 초기화 제공
by lazy- 불변 속성에서만 사용 가능
- 사용 시점에 한 번만 초기화 로직 실행
- 멀티 스레드 환경에서도 안전하게 동작
- 내부에
synchronized블록으로 구현되어 있음 LazyThreadSafetyMode멀티 스레드에서 어떻게 lazy 인스턴스 초기화를 동기화할지 설정 가능LazyThreadSafetyMode.NONE: 멀티 스레드 환경이 아닌 경우, 동기화 작업이 오버헤드가 될 수 있으므로 스레드 세이프 모드 해제 가능LazyThreadSafetyMode.PUBLICATION: 초기화되지 않은 lazy 인스턴스를 동시에 접근할 때는 여러번 초기화 함수를 호출할 수 있지만, 처음 반환된 lazy 인스턴스의 값만 사용LazyThreadSafetyMode.SYNCHORINIZED: 기본 설정. 잠금이 단일 스레드만 lazy 인스턴스를 초기화하도록 사용됨
class HelloBot {
val greeting: String by lazy { getHello() }
fun sayHello() = println(greeting)
}
fun getHello() = "안녕하세요"
fun main() {
val helloBot = HelloBot()
helloBot.sayHello()
}
lateinit- 가변 속성에 대한 지연 초기화가 필요할 경우 사용
- nullable 하게 사용하면 컴파일 에러 발생
- 항상 non null 타입
- 값을 초기화하지 않고 사용하게 되면 예외 발생
- 스프링 등의 프레임워크 또는 라이브러리에서의 DI와 외부에서 초기화 하는 경우에 염두하고 만들어진 기능
- 초기화 전에 사용하더라도 컴파일 에러가 발생하지 않으므로 주의해야 함
- 클래스 내부에서는
isInitialized메서드 이용해서 초기화 여부 확인 가능
class Example {
lateinit var text: String
fun printText() {
println(text)
text = "Hello" // UninitializedPropertyAccessException 발생
}
}
fun main() {
val example = Example()
example.printText()
}
class Example {
lateinit var text: String
fun printText() {
if (!this::text.isInitialized) { // 초기화 여부 확인
text = "Hello"
}
println(text)
}
}
fun main() {
val example = Example()
example.printText()
}