코틀린 기초 공부를 시작했다.
코틀린은 자바 플랫폼 위에서 돌아가는 언어이기 때문에 객체 지향 패러다임을 가지고 있다.
객체 지향에서 가장 중요한 건 '클래스'이다.
코틀린 클래스를 공부하며 '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
- 코틀린에서 속성의 값을 저장하는 데 사용하는 내부 저장소
- 자동 생성
: 코틀린에서는 속성에 대한 getter/setter를 사용할 때, 컴파일러가 필요에 따라 자동으로 백킹 필드를 생성한다.- 직접 접근 불가
: 백킹 필드에는 프로퍼티의 getter 또는 setter 내부에서 field 키워드를 사용하여 접근할 수 있으며, 프로퍼티 외부에서는 직접 접근할 수 없다. get(), set() 으로 커스텀 할 수 있다.- 무한 재귀 방지
: setter에서 **field**를 사용하여 백킹 필드에 값을 할당함으로써, 자기 자신을 호출하는 무한 재귀를 방지한다.- 캡슐화 유지
: 백킹 필드를 사용함으로써 속성의 캡슐화를 유지한다.
자바를 단지 쉽게 최적화한 게 코틀린인 줄 알았는데,
내부 로직적으로도 차이가 있다니 놀랐다.
이런 것도 이해하면서 코틀린 개념 공부를 해야겠다.
'2024 활동 > Kotlin·Android' 카테고리의 다른 글
[Android] Intent로 ImageView 전달하기 (0) | 2024.05.28 |
---|---|
[Android Studio] 빌드 오류 해결 intent-filter (0) | 2024.05.08 |
[Kotlin] 인터페이스 이해하기 (0) | 2024.04.28 |
[Kotlin] 클래스 심화 : 상속, 오버라이딩, 형변환, 스마트 캐스트 (0) | 2024.04.18 |
[Kotlin] Null Safety 예제로 쉽게 이해하자! (0) | 2024.04.18 |