ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 코틀린 setter, 어디까지 써봤니?
    Java & Kotlin 2023. 5. 30. 01:46
    반응형

    1) 서론

    혹시 이도저도 못 하는 경험을 해보신 적 있으신가요?
     
    저는 식당에서 메뉴를 고르는 것을 어려워하는데요. 특히 중국집에서 절정에 다다릅니다.
     
    짜장면을 시키면, 매콤한 짬뽕국물이 먹고 싶어 집니다. 하지만 짬뽕을 시켰을 때 너무 매우면 어쩌지 하며, 짜장면이 먹고 싶기도 합니다. 그러면서 볶음밥을 먹는 게 더 좋지 않을까 고민합니다.
     
    중요한 것은 무엇을 먹든 trade-off가 존재합니다. 짜장면을 먹으면 매운 것을 피할 수 있지만 국물을 포기해야 합니다. 
     
    개발에서도 마찬가지인데요.
     
    이번에 코틀린으로 개발하며 entity를 만드는데 고민이 들었습니다. 자바에서 lombok @getter + priavte 필드로 생성하던 것을 코틀린에서는 어떤 방식이 좋을지 고민됐습니다.
     
    이번 글에서는 위의 문제에 대해서 정답이 아닌, 다양하게 고민한 내용을 공유드립니다.
     

    출처: 대한항공


    2) private 생성자 프로퍼티 방식

    코틀린의 특징은 생성자를 통해서 프로퍼티를 받을 수 있습니다. private val을 이용하는데요. 아래와 같은 장점이 있습니다.

    • setter를 열어두지 않고 불변성을 유지 가능

     
    하지만 엔티티를 만들 때 아주 큰 단점이 있습니다.

    User 도메인의 use case를 나타내는 함수입니다. 즉 유저의 정보 변경은 닉네임과 휴대폰 번호를 변경할 수 있다는 의미인데요.
     
    하지만 entity의 필드들은 val 불변이기 때문에 수정할 수가 없습니다. 객체와 함수를 이용해서 use case를 나타낼 수 없고, querydsl 등을 이용해서 직접 update 쿼리를 사용해야 합니다. 특히 JPA를 사용하면서 dirty checking을 사용할 수 없는 것은 아주 큰 단점입니다.
     
    그리고 프로퍼티를 모두 private로 감추었는데요.
     
    이렇게 설정하면 외부에서 getter도 사용할 수 없게 됩니다. 자바에서는 보통 lombok @Getter를 이용해서 private 필드도 편하게 사용할 수가 있는데요.
     
    Lombok을 지원하지 않는 코틀린에서는 아래와 같이 직접 getter를 만들어줘야 합니다.

    하지만 이렇게 되면 모든 필드에 대해서 getter를 추가해줘야 하는 번거로움이 생깁니다. 자바에 비해서 간결한 문법을 자랑하는 코틀린의 장점이 없어지게 되는데요.


    3) public var 생성자 프로퍼티 방식

    위에서 나온 priavte val 생성자 프로퍼티 방식의 단점은 이렇습니다.

    • gettter를 직접 만들어야 해서 코틀린의 장점인 간결함이 없어진다
    • 도메인의 use case를 나타내는 메서드로 변경할 수가 없다

     
    그래서 아래와 같이 public var를 사용하여 자유로운 형식을 고민할 수 있는데요.

    이전의 priavte val과 비교했을 때 아래의 장점이 생겼습니다

    • 도메인 use case를 나타내는 함수 사용 가능
    • public getter 사용 가능

     
    User 도메인의 행위를 함수로서 나타낼 수 있습니다. 단순히 특정 필드만 수정하는 게 아니라, '유저의 정보를 변경한다'라는 행위를 표현할 수 있게 되었는데요.
     
    그리고 코틀린의 간결함을 유지하면서 getter를 사용할 수 있게 되었습니다.
     
    하지만 문제는 setter도 함께 공개됩니다.

    즉 도메인을 나타내지 못 하고 개발자의 실수로 setter가 무분별하게 사용될 수 있습니다. 개인적으로 setter를 공개하여 도메인을 변경하는 것을 선호하지 않기 때문에 다른 방법을 찾아보겠습니다.


    4) field를 이용한 custom private setter

    • private setter로 외부에서의 필드 변경 방지
    • public getter로 외부에서 필드 조회 가능
    • var field 사용으로 도메인을 표현하는 메서드 사용

     
    이전 방법들에 비해 변경은 제한적이고, 조회는 자유롭게 되었습니다. 그리고 도메인 use case를 나타내며 데이터를 수정할 수 있습니다.
     
    하지만 이 방법도 단점이 보이는것 같습니다.

    • pirvate setter를 일일이 작성해줘야 한다

     
    나름 괜찮다고 생각했지만 코틀린 프로퍼티 장점을 살리지 못 하고, boilierplate가 생겼습니다. 심지어 자동완성도 지원되지 않아서, 일일이 수기로 작성해줘야 합니다. 엄청 귀찮은데요.


    5) 결론

    개인적으로는 custom private setter를 생성하더라도, setter를 막는 것이 더 좋지 않을까 생각은 합니다.

    • 생성자 프로퍼티를 이용하여 생성과 동시에 값 할당
    • setter를 이용한 개별 필드 수정 방지로 코드 안정성
    • getter를 열어둠으로서 자유로운 조회 가능
    • 오직 도메인 나타내는 메서드로 값 수정 가능

     
    물론 코틀린스럽지 않는 boilerplate가 생기는 것이 큰 단점입니다. 이럴거면 자바처럼 lombok를 사용하는 게 더 좋은 것 아닐까 생각이 들기도 하는데요.
     
    차선책으로 3번(public var 생성자 프로퍼티) 방식도 사용할 수 있을 것 같습니다. boilerplate를 줄이고, getter를 열어둡니다.
     
    setter를 이용해서 코드의 안정성이 떨어지지지만, 엄격한 코드리뷰와 개발 규칙을 정해서 한다면 문제없을 수도 있습니다. 실제로 자바에서 DTO 같은 경우 맵핑을 위해 setter를 열어두지만, 맵핑 용도 외 사용될 때는 코드리뷰를 통해서 최대한 방지했던 경험도 있습니다.
     
    다만 사람이 많아지고, 시간이 급하다는 이유로 setter를 한 번이라도 사용하게 되면 걷잡을 수 없이 번져나간다고 생각합니다. 그래서 개인적으로는 4번(custom private setter)을 사용하는 것을 선호합니다.
     
    혹시 이 글을 읽는분들은 어떠한 방법을 주로 사용하는지 궁금합니다. 많은 의견 부탁드립니다!

    반응형

    댓글

Designed by Tistory.