인프런 커뮤니티 질문&답변

비가싫어요님의 프로필 이미지

작성한 질문수

실전! 코틀린과 스프링 부트로 도서관리 애플리케이션 개발하기 (Java 프로젝트 리팩토링)

Class나 Entity 만들 때 접근제어자 관련해서 질문이 있습니다!

23.09.08 11:35 작성

·

292

1

자바에서는 Entity나 클래스를 만들 때 접근 제어자로 private을 붙이는게 일반적이었는데요. 코틀린에서는 그렇게 하면 객체를 생성하고도 밖에서 바로 접근이 안 되는 거 같네요ㅠ

private을 붙여주고 custom getter 같은걸로 객체 생성 후 호출하게 해주는 것이 좋은가요? 아니면 접근 제어자를 안 붙이고 그냥 쓰는게 좋은가요..?

답변 1

0

최태현님의 프로필 이미지
최태현
지식공유자

2023. 09. 08. 13:00

안녕하세요, JUNN님! 😊 정말 좋은 질문 감사드립니다! 👍

질문 주신 내용에 대해 차근차근 답변드려보겠습니다!

 

[일반적인 Java의 클래스]

Java와 Kotlin의 가장 큰 차이 중 하나라 한다면, Java는 필드와 getter/setter를 구분해 작성해야 하고, Kotlin은 필드와 getter/setter가 합쳐져 있다는 점입니다.

예를 들어, 말씀해주신 것과 같이 Java에서는 다음과 같은 클래스를 흔히 사용합니다.

public class User {
  private String name;
  private int age;
}

특징은 다음과 같습니다.

  1. 일단 필드에는 private을 붙인다.

  2. getter가 필요하면 그때 getter를 만들고 setter가 필요하면 그때 setter를 만든다. 이때 get/set 함수에 public, private 등을 구분한다. (물론 lombok을 활용할 수도 있습니다)

 

반면 코틀린은 비슷하지만 다른 측면이 있습니다.

 

[일반적인 Kotlin의 클래스]

class User(
  private val name: String,
  private val age: Int,
)

동일한 User 클래스를 코틀린으로 만들어보았습니다. 이는 다음과 같은 특징을 갖고 있습니다.

  1. 일단 필드에는 private을 붙인다.

  2. getter가 필요하면 private을 제거해 public으로 만들고, setter가 필요하면 val 대신 var로 만든다.

 

// 예를 들어 name은 getter만 public으로,
// age는 getter/setter를 public으로 만들어 보았습니다!
class User(
  val name: String,
  var age: Int,
)

(이 과정에 익숙해지면 시작부터 private val name: String 대신 val name: String을 활용하기도 합니다)

 

자 여기서!! 한 가지 애매한 지점이 있습니다.
바로, getter 혹은 setter가 필요하긴 한데~~ public 대신 다른 접근 지시자를 사용하고 싶은 경우입니다!

 

[Kotlin의 getter]

먼저 getter부터 살펴보겠습니다. 사실 getter의 경우는 외부에 노출 되더라도 setter보다는 안전하다는 특징을 갖고 있습니다. 또한, getter는 접근 지시자 관리가 용이한 편입니다. 프로퍼티 앞에 적절한 접근 지시어를 붙이기만 하면 되죠!

class User(
  val name: String, // public이 생략된 형태
  internal val age: Int,
  private val hobby: String,
)

때문에 보통은 setter의 접근 지시자를 관리할 때 조금 더 번거로운 편입니다.

 

[Kotlin의 setter]

다음으로는 setter를 살펴보겠습니다. setter 역시 getter와 마찬가지로 var 앞에 private 혹은 internal 등을 붙이면 되지만, 다음과 같은 경우가 애매합니다.

getter는 public으로 열고 싶은데, setter는 private으로 닫고 싶은 경우!

 

이런 경우는 <14강. Kotlin과 JPA를 함께 사용할 때 이야기 거리 3가지>에서 설명드리고 있는 것처럼 backing property 혹은 custom setter를 사용해줘야 하고, 이 때는 문법적으로 불편함이 존재합니다. 😭 그래서 setter를 열어는 두되 사용하지 않는 방법을 선택할 수도 있죠.

 

[결론 - 질문에 대한 답변]

자바에서는 Entity나 클래스를 만들 때 접근 제어자로 private을 붙이는게 일반적이었는데요. 코틀린에서는 그렇게 하면 객체를 생성하고도 밖에서 바로 접근이 안 되는 거 같네요ㅠ

  • 조금 더 엄밀하게 말씀 드려 보면, 자바에서도 private 필드만 있으면 접근이 불가능하고, 이는 코틀린에서도 마찬가지입니다.

 

private을 붙여주고 custom getter 같은걸로 객체 생성 후 호출하게 해주는 것이 좋은가요? 아니면 접근 제어자를 안 붙이고 그냥 쓰는게 좋은가요..?

  • 코틀린에서는 보통 val name: String 과 같이 getter는 public으로 열어두는 경우가 많은 것 같습니다. 즉, "접근 제어자를 안 붙이고 그냥 쓰는 편"입니다. 😊

  • 다만, setter의 경우에는 객체의 값을 변경할 수 있다 보니, 열어두고 사용하지 않기 vs 조금 더 엄밀하게 관리하기 로 의견이 나뉘는 편입니다.

 

답변이 도움이 되었으면 좋겠네요~~ ㅎㅎㅎ 관련해서 더 궁금한 점 있으시면 편하게 질문 남겨주세요! 감사합니다! 🙇

비가싫어요님의 프로필 이미지

2023. 09. 10. 00:06

아 이전에 답글을 달고 다시 좀 이것저것 찾아보면서 생각을 해보니 제가 생각을 잘못 했던 것 같습니다.

프로퍼티 자체가 필드 + getter + setter 인데 프로퍼티를 private으로 하는 순간 getter까지 private이 되기 때문에 객체를 생성해도 프로퍼티에 접근이 안 되는게 당연했던거네요.

저는 아직 자바 생각이 남아있어서 프로퍼티(이지만 제 머리속엔 필드)를 public으로 열어두면 캡슐화에 위배되는 것 아닌가 하는 생각을 계속 들어서 코틀린에서 왜 이렇게 했을까 하는 생각을 했었거든요..(사실 그게 제일 이해가 안 돼서 계속 뭔가 이상한 찝찝함이 있었습니다 ㅎㅎ)

근데 코틀린은 프로퍼티에 게터, 세터가 모두 있기 때문에 선생님 말씀처럼 프로퍼티 자체를 public으로 열어두는거였군요..! 자바에서도 필드는 private으로 생성하지만 getter와 setter 모두 다 public으로 생성하기 때문에 이게 너무 당연한 거였네요..(멍청쓰 ㅠ)

아 이제 좀 머리속에서 정말 정리가 되는 것 같습니다. 쉬운 내용이었는데도 먼가 머릿속에서 꼬이니까 정리가 쉽지 않네요 ㅎㅎ

친절한 답변 정말 감사드립니다.