개발바닥곰발바닥
728x90

getter와 setter를 사용해야 하는 이유

java 공부를 하면서, getter와 setter를 만들어 사용했었는데 문득 어차피 이 객체의 속성을 외부에서 읽거나 쓸 필요가 있다면 그냥 public으로 선언하면 될텐데 왜 굳이 불편하게 getter와 setter를 사용해서 불필요한 코드를 늘려야 하는가에 대한 궁금증이 생겼다.

그래서 찾아보니, 다음과 같은 이유들이 있었다.

  1. 속성을 읽거나 쓰는 것과 관련된 동작의 캡슐화 (이를 통해 유효성 검사 등의 추가 기능을 쉽게 추가할 수 있다.)
  2. getter와 setter를 사용하여 속성을 노출하면서도 속성의 내부 표현을 숨길 수 있다.
  3. 공용 인터페이스를 변경으로부터 격리하여 구현이 변경되는 동안 공용 인터페이스가 일정하게 유지되도록 한다.
  4. 속성의 수명 및 메모리 관리(폐기) 제어 - C++ 또는 Objective-C 등에서 메모리 관리를 제어한다.
  5. 런타임에 속성이 변경될 때 디버깅 중단점 지점 제공 (속성이 특정 값으로 변경된 시기와 위치를 디버깅하기 위해)
  6. getter/setter에 대해 작동하도록 설계된 라이브러리와의 상호 운용성 (Mocking, Serialization 및 WPF)
  7. 자식 클래스가 getter/setter 메서드를 재정의하여 속성이 읽고 쓰이는 체게를 변경할 수 있게 한다.
  8. getter/setter가 값이 아닌 람다식으로 전달되도록 허용할 수 있다.
  9. getter와 setter는 서로 다른 접근 수준을 허용할 수 있다. 예를 들어 getter는 public일 수 있지만 setter는 그렇지 않게 할 수 있다는 말.

위의 이유들을 보고 납득이 갔는데 웬걸 다른 답변들엔 다른 의견들도 있었다.

public으로 선언하는 것이 getter/setter 쌍을 사용하는 것보다 나쁘지 않다는 것이었는데,
두 방법이 대부분의 언어에서 기능적 차이가 없다는 것이었다. getter/setter의 자주 언급되는 장점은 옳지 않다는 것인데. 구현을 변경할 수 있고, 유효성 검사와 같은 기능을 추가할 수 있다는 장점이 위에도 언급되지만 사실 setter에 유효성 검사를 추가하는 것은 속성에 자료형에 맞는 어떤 값도 들어갈 수 있고, 나중에 getter에서 동일한 것을 얻을 수 있다는 이전 계약을 위반하는 것이라고 할 수 있다.

 

또한 로깅 등의 수정이 아닌 파생 클래스의 기본 기능을 재정의 하면 기본 클래스의 계약을 위반하는 것으로 Liskov 치환 원칙에 대한 위반이라고 설명하고 있다.

그리고 가장 인상 깊었던 의견 중 하나는 클래스 사용자가 클래스 내부에 액세스해야 하는 경우 해당 클래스가 충분한 추상화를 제공하지 않는다는 신호라는 답이었다.

 

내 수준에 객체 지향을 완전히 이해했다고 말하긴 어렵겠지만, 객체 지향적으로 구현된 애플리케이션이라면 사실 객체의 속성(상태)에 접근하지 않고 객체들간의 메시지를 통해 메서드(행동)를 실행시켜 동작하는 것이라고 이해하고 있는데, 그렇다면 사용자는 객체가 어떤 행동을 하는 지는 알 수 있지만 객체의 속성이 어떻게 변하는지는 직접 관여할 수 없도록 하는 것이 올바른 OOP라고 생각된다.

 

둘 중에 어떤게 더 나은가에 대한 궁금증으로 시작한 질문의 결론은 public든 setter든 객체의 속성에 직접 관여할 필요가 없는 객체를 만드는 것이 정답이라고 이해하면 제대로 이해가 된 건지는 아직 잘 모르겠지만 일단 머릿속에 기억해두기로 했다.

 

참고 링크

https://stackoverflow.com/questions/1568091/why-use-getters-and-setters-accessors

내 포스팅에 비해 getter/setter를 사용하면 안되는 이유에 대해 잘 정리된 글

https://log.hodol.dev/typescript/oop/9

728x90
profile

개발바닥곰발바닥

@bestinu

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!