본문 바로가기

Language

[Kotlin] Property와 Data Class

 

 비즈니스 도메인을 자바로 개발하다 보면, 흔히 'Value Object' 라고도 불리는 - 물론 단순히 값을 저장하는 객체의 의미는 아니지만 - 자바 빈즈(Java Beans) 컴포넌트를 작성해야 할 때가 많다. 이  자바 빈즈에는 귀찮은 규약이 하나 있는데, 접근자(Getter)와 수정자(Setter)가 바로 그것이다. 물론, IDE의 자동완성 기능이라던가, 해당 메서드들 뿐만 아니라 품질 좋은 `equals`와 `hashcode`그리고 `toString` 메서드까지 생성해주는  'Lombok' 이라는 녀석 덕분에 많은 개발자들이 조금 이나마 타이핑을 덜 하게 되기는 했다. 다만 이러한 것들을 언어의 런타임 레벨에서 지원하지 않는다는 것은 자바의 한계를 보여준다.

 

프로퍼티

 코틀린에서는 언어 자체에서 이를 지원한다. 먼저 프로퍼티가 바로 그 중 하나인데, 이 프로퍼티는 단순히 '속성' 이라는 뜻이라기 보다는 클래스의 필드와 접근자를 한데 묶어 부르는 것이다. 선언은 다음과 같다.

class Person(
    val name: String,
    var age: Int
)

 

`val` 은 변할 수 없는 상수를 뜻하고 `var` 는 변수를 뜻하는데, 이러한 키워드만으로 접근자와 수정자가 자동 제공된다. 직관적으로 알 수 있지만, `val` 로 선언한 필드는 접근자만 제공되고, `var` 로 선언한 필드는 접근자와 수정자 모두 제공된다.

val person = Person("hong", 20)
    
println(person.name)
    
person.age = 36 // 수정자 사용
println(person.age)

 

 접근자와 수정자를 사용할 때 `getName()` `setAge(36)` 같은 메서드를 사용하지 않았음에 주목하자. 사실 가만히 생각해 본다면 키워드 자체가 캡슐화(encapsulation)을 지원하기때문에, `public`접근 또는 수정자가 필요 없다는 것은 금방 알 수 있을 것이다. `.` 으로 모든 걸 할 수 있다(해도 된다?)는 이야기.

 

아주 당연하게도, 아래 처럼 접근자(또는 수정자)를 커스터마이징 할 수 있다. 

class Rectangle(
    val width: Int,
    val height: Int
) {
    val isSquare: Boolean
        get() {
            return width == height
        }
}

 

Data Class

 더 나아가 Data Class라는 놈은 가려운 곳을 마저 긁어 준다. 바로 서두에 언급한 `equals` `hashcode` `toString` 메서드를 자동 생성해주는 기능이다! 자바에서 아무리 롬복이 대단하다고 해도, 아래처럼 어노테이션이 덕지덕지 붙게 되는건 어쩔 수 없지 않았던가.

@Setter
@Getter
@ToString
@EqualsAndHashCode
public class Person {
    private String name;
    private int age;
}

 

하지만 코틀린에서는 이거면 충분하다.

data class Person(val name: String, var age: Int)

 

단지 `data` 라는 키워드 하나만 추가했을 뿐인데도, 클래스의 모든 프로퍼티의 동등성을 비교해주는 `equals`, 해시 기반 컨테이너에서 사용할 키를 생성해주는 `hashcode`, 각 필드를 순서대로 표시하는 `toString` 까지 모두 생성 되었다. +@ 로 원본 객체를 해치지 않게 복사해주는 `copy` 메서드 까지 제공 한다. 참 멋지다.

 

사실 더 어마무시한 기능까지 지원하는데, 바로 `componentN` 메서드의 자동 생성이다. 이 메서드'들'이 있는 클래스는 '구조분해 선언' 이라는 편리한 개념을 사용할 수 있게 된다. 쉽게 말해 자바스크립트의 '해체 할당' 이라고 보면 되지만, 아래 코드로 단번에 설명이 될 것이다.

data class Point(val x: Int, val y: Int)

val p = Point(10, 20)
val (x, y) = p // 이게 구조 분해 선언

 

'구조분해 선언' 관련해서는 추후 다시 정리 해야겠다.

 

마치며

 이미 많은 개발 조직에서 코틀린을 프로덕션 환경에서 사용하고 있다. 때문에 지금에야 빡공(?) 하는게 뭔가 뒷북을 치는 감이 없잖아 있긴 하지만, 뒷북을 치든 앞북을 치든 사실 중요하지 않다고 본다. 내가 배우기에 즐겁고, 배운 것을 실무에 '잘' 사용하면 그만이다.

 

 오늘은 코틀린을 배우면서 가장 인상 깊었던 feature에 대해 다뤘다. 뭐 내용은 별거 없지만, 정리하면서 다시 내 머릿속에 각인 되었으니 그걸로 만족스럽다. 앞으로 정리할게 많으니 오늘은 여기까지..

 

참고 서적 - Kotlin In Action