아이템 15. 클래스와 멤버의 접근 권한을 최소화 하라
1. 정보은닉(Information Hiding) 과 캡슐화(Encapsulation)의 중요성
정보 은닉은 내부 구현을 숨기고 외부에서 접근할 수 없도록 제한하는 개념이다.
캡슐화는 객체의 상태를 외부에서 직접 변경하지 못하도록 하고, 필요한 경우에만 공개하는 설계 원칙이다.
접근 제한을 통해 코드의 유지보수성을 높이고, 오류 발생 가능성을 줄이며, 보안성을 강화할 수 있다.
2. 접근 수준(Access Level)과 사용 원칙
자바에서는 네 가지 접근 수준을 제공하며, 가장 제한적인 수준부터 적용하는 것이 좋다.
접근 수준 | 적용 대상 | 같은 클래스 | 같은 패키지 | 자식 클래스 | 전체 접근 |
---|---|---|---|---|---|
private | 클래스 내부 |
|
|
|
|
package-private(기본 접근제어자) | 같은 패키지 내에서만 접근 가능 |
|
|
|
|
protected | 같은 패키지 + 상속 관계에서 접근 가능 |
|
|
|
|
public | 어디서든 접근 가능 |
|
|
|
|
설계 원칙
가장 제한적인 접근 수준부터 적용하고, 꼭 필요한 경우에만 공개한다.
private --> public 순서
클래스 자체를 public 으로 만들지 않는 것이 좋다.
만약 특정 클래스를 라이브러리 사용자에게 공개할 필요가 없다면, package-private 로 설정하여 내부 구현을 감출 수 있다.
3. 멤버(필드 및 메서드) 접근 제어
필드는 private 으로 선언하고, 필요하면 접근자(getter)를 제공한다.
클래스 내부 데이터를 직접 노출하지 말고, 접근 메서드를 통해 제공해야 한다.
필드를 public 으로 선언하면 객체의 내부 표현이 외부 API 에 노출되므로, 유지보수가 어려워 질 수 있다.
불변 필드(final)의 경우, public 으로 공개해도 괜찮다.
불변 객체는 상태가 변경되지 않으므로 public final 로 공개해도 안전하다.
하지만 가변 객체(List, Map) 를 public static final 로 공개하면 내부 상태가 변경될 위험이 있다.
배열 필드는 private 으로 선언하고, 복사본을 반환한다.
배열을 public 으로 직접 노출하면 외부에서 배열 내용을 변경할 수 있어 보안상 취약하다.
4. 패키지 프라이빗(package-private) 클래스 활용
내부 구현 클래스는 public 으로 만들지 말고, package-private 으로 설정하는 것이 좋다.
라이브러리를 만들 때, 내부에서만 사용하는 클래스는 package-private 으로 숨길 수 있다.
이렇게 하면 외부에서는 InternalHelper 클래스를 사용할 수 없으므로 내부 구현이 보호된다.
5. 상속을 고려한 접근제어 (protected 사용 주의)
protected 는 같은 패키지의 다른 클래스에서 접근이 가능하므로,
상속용이 아닌 클래스에서는 protected를 사용할 필요가 거의 없다.
상속을 허용하려면 설계상 의도가 분명해야 하며, 무분별한 protected 사용은 지양해야 한다.
6. 결론
모든 클래스와 멤버의 접근 수준을 가능한 한 제한해야 한다.
클래스의 필드는 private로 선언하고, 직접 노출을 피해야 한다.
불변 필드(final)는 public으로 공개할 수 있지만, 가변 객체는 반드시 보호해야 한다.
내부 구현 클래스는 package-private으로 유지하여 외부 노출을 방지해야 한다.
protected는 신중하게 사용하고, 상속이 정말 필요한 경우에만 활용해야 한다.
부록 ; 느낀점
정보은닉, 캡슐화의 설명은 대부분 추상적이지만, 객체지향을 제대로 접목시키면 그 이점이 특히 두드러지게 나타난다.
특히 유지보수성이 높아진다는 이점이 가장 크게 와닿았던 것 같다.
상속을 허용하려면 설계상 의도가 분명해야 한다는 점에서 상속 자체를 개인적으론 지양해야 된다는 생각도 있다.
상속 관계의 객체끼리 지나치게 의존도가 높아지기 때문에, '역할'을 고려한 설계가 아니라면 상속은 되도록 지양해야 한다.