본문 바로가기
2024 활동/Kotlin·Android

[Kotlin] Backing Field가 뭔가요?

by 은행장 노씨 2024. 4. 12.

뿌셔뿌셔

 

코틀린 기초 공부를 시작했다. 

코틀린은 자바 플랫폼 위에서 돌아가는 언어이기 때문에 객체 지향 패러다임을 가지고 있다. 

객체 지향에서 가장 중요한 건 '클래스'이다. 

 

코틀린 클래스를 공부하며 'Backing Field'라는 것을 알게되었다. 

 


Kotlin의 Backing Field 이해하기

Kotlin에서는 'Backing Field'를 제공하여 개발자들에게 훨씬 유연한 속성 관리 방법을 제공해준다고 한다. 

이 글에서는 Backing Field가 무엇인지, 그리고 왜 필요한지를 알아보고, 실제 사용 예제도 알아보자.

 

 

Backing Field란 무엇인가?

Backing Field는 프로퍼티에 대한 접근을 감시하고, 제어하는 숨겨진 필드를 말한다.

속성은 기본적으로 getter, setter를 갖는다. 하지만, getter/setter 이것들이 속성값에 직접 접근하지 않고, Backing Field를 통해 값을 저장하고 처리한다.

 

코틀린은 생성자를 만들 때 내부적으로 getter/ setter를 만들기 때문에 특별히 구현하지 않아도 된다. 

하지만! 어떤 속성값을 설정할 때 옵션을 주고 싶다면 setter 내부에 로직을 추가해야 한다. 이때, setter가 무한 루프에 빠지지 않도록 하기 위해 Backing Field에 값을 할당해야 한다. 

 

🚧 java.lang.StackOverflowError
getter에서 자신을 참조하기 위해 단순히 this.title을 쓰니 에러가 떴다. 자바에서는 이렇게 했는데…
→ 해결 : 'field' 를 사용하자

 

꼬리에 꼬리는 무는 질문..

❓ 왜 코틀린에서 this.property는 무한 재귀가 발생할까?
코틀린의 프로퍼티 할당 문법 this.property = value는 실제로 프로퍼티의 setter를 호출하는 코드입니다. 따라서, setter 내에서 this.property = value와 같이 프로퍼티를 직접 할당하려고 하면, setter는 자기 자신을 계속해서 재귀적으로 호출하게 되어 무한 루프에 빠지게 됩니다.

 

❓ 왜 자바는 무한 재귀가 발생하지 않을까?
자바는 field와 메소드가 명확히 분리되어 있다.
→ field에 this 키워드를 사용해 직접 접근할 수 있습니다.

 

❓ 왜 코틀린은 자바처럼 Field와 메소드를 명확히 분리하지 않을까?
코틀린이 property라는 개념을 통해 필드에 접근하고 수정하는 메커니즘을 추상화하기 때문이다.
→ 더 안전한 캡슐화를 제공한다. 더 추상화된 접근 방식.

 

예시 코드1 

간단하게 field를 이용한 코드를 작성해보자. 

// getter/ setter
class Book() {
    var title : String = "default"
        get() {
            return field.capitalize()   // 대문자로 반환
        }
        set(value) {
            field = value.trim()    // 공백 제거
        }
}

 

예제에서 title 값을 설정하려 할 때, set 함수가 호출된다.

만약 전달된 value가 비어있지 않다면 field (Backing Field)에 value를 할당한다.

여기서 field title 속성의 현재 값을 나타낸다. 그냥 this.title -> field 로 생각하고 코드를 짜면 될 것 같다. 

 

 

예시 코드2 - 속성 값이 여러 개일 경우

// 속성 값이 여러 개일 경우
class Book() {
    var title: String = "default"
        get() = field.capitalize() // 첫 글자를 대문자로 변환
        set(value) {
            field = value.trim() // 앞뒤 공백 제거
        }
    
    var author: String = "unknown"
        get() = field.capitalize() // 첫 글자를 대문자로 변환
        set(value) {
            field = value.trim() // 앞뒤 공백 제거
        }
}

 

여러 개의 속성 값을 다룰 때도 각각 custom getter와 setter를 설정할 수 있다. 이렇게 보니 자바보다 간단한 것 같기도.. 

그리고 해당 속성 값을 굳이 변형하지 않는 경우에는 굳이 쓸 필요 없다. 

 

 

Kotlin vs Java

문득 자바와 코틀린이 어떤 점이 다른지 궁금해졌다. 

그래서 GPT에게 표로 비교해달라고 했다.

  코틀린 자바
백킹 필드 선언 명시적으로 선언하지 않음. field 식별자를 통해 자동으로 제공될 수 있음. this 키워드를 사용하거나 필드 이름만으로 직접 접근.
커스텀 접근자 getter와 setter 로 속성의 접근 및 갱신 로직을 정의할 수 있음. 메소드
field 식별자 getter와 setter 내에서만 사용되는 특별한 식별자로 백킹 필드를 참조. 해당 없음
백킹 필드의 필요성 getter와 setter에 로직이 있을 때 컴파일러가 자동으로 백킹 필드를 생성함. 모든 필드에 대해 백킹 필드가 존재.

 

 

코틀린에서 백킹 필드의 장점 

코틀린에서 명시적으로 백킹 필드를 선언하지 않으면, 컴파일러가 필요에 따라 자동으로 백킹 필드를 생성하고 관리한다.

다음의 장점을 가진다. 

  • 개발자가 비즈니스 로직에 더 집중할 수 있게 해줌
  • getter와 setter를 별도로 관리할 필요가 없음
  • 코드가 더 깨끗하고 유지 관리하기 쉬워짐.

 

 

 


 

마지막으로...

📌 요약 정리 : Backing Field
    - 코틀린에서 속성의 값을 저장하는 데 사용하는 내부 저장소
  1. 자동 생성
    : 코틀린에서는 속성에 대한 getter/setter를 사용할 때, 컴파일러가 필요에 따라 자동으로 백킹 필드를 생성한다.
  2. 직접 접근 불가
    : 백킹 필드에는 프로퍼티의 getter 또는 setter 내부에서 field 키워드를 사용하여 접근할 수 있으며, 프로퍼티 외부에서는 직접 접근할 수 없다. get(), set() 으로 커스텀 할 수 있다.
  3. 무한 재귀 방지
    : setter에서 **field**를 사용하여 백킹 필드에 값을 할당함으로써, 자기 자신을 호출하는 무한 재귀를 방지한다.
  4. 캡슐화 유지
    : 백킹 필드를 사용함으로써 속성의 캡슐화를 유지한다.

 

 

 

자바를 단지 쉽게 최적화한 게 코틀린인 줄 알았는데,

내부 로직적으로도 차이가 있다니 놀랐다. 

 

이런 것도 이해하면서 코틀린 개념 공부를 해야겠다.