16. public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라
📝 전체 내용 간단 요약
public 클래스에서 멤버 필드(데이터)를 직접 외부에 노출하지 말고, 접근자(getter)와 변경자(setter) 메서드를 통해 간접적으로 접근하도록 설계해야 합니다.
이렇게 하면 코드의 안정성, 유지보수성, 유연성을 높일 수 있습니다.
📚 미리 알아야 할 내용 요약
📍 접근자(getter), 변경자(setter) 메서드란?
접근자(getter)
클래스의 멤버변수(필드)의 값을 읽을 때 사용하는 메서드입니다.
public int getAge() { return age; }
변경자(setter)
클래스의 멤버변수(필드)에 새로운 값을 설정할 때 사용하는 메서드입니다.
public void setAge(int age) { this.age = age; }
📌 접근자와 변경자를 쓰는 이유
public 필드를 바로 사용하면 코드 변경이 어렵습니다.
접근자와 변경자를 사용하면 코드의 내부 구조(표현 방식)를 바꾸더라도 외부 코드는 수정하지 않아도 됩니다. (캡슐화의 장점)
필드를 직접 공개하면 다음 문제가 생깁니다.
필드의 유효성(불변식, invariant)을 보장할 수 없습니다.
표현 방식을 바꾸려면 모든 코드를 수정해야 합니다.
필드의 값을 읽거나 쓸 때 추가 작업(예: 검증)을 수행할 수 없습니다.
📚 미리 알아야 할 용어
불변식
invariant
객체가 유지해야 하는 항상 변하지 않는 규칙
캡슐화
encapsulation
데이터를 보호하고 접근을 제한하여 내부를 숨기는 것
접근자
accessor(getter)
데이터를 읽을 때 사용하는 메서드
변경자
mutator(setter)
데이터를 변경할 때 사용하는 메서드
🚩 주의사항
public 필드는 외부에서 누구나 접근 및 변경 가능하므로 사용하면 위험합니다.
모든 필드를 public이 아닌 private로 두고 필요한 경우에만 getter와 setter를 만드세요.
테스트 때문에 접근 제어 수준을 public으로 높이면 안 됩니다.
⭐ 중요한 점
public 클래스가 필드를 공개하면 API 변경이 어려워집니다.
불변 객체라도 public 필드를 사용하는 건 바람직하지 않습니다. 내부 구현 방식이 고정되기 때문입니다.
접근자 메서드를 쓰면 코드가 더 유연해지고 유지보수가 쉬워집니다.
❌ 잘못된 예제
// 나쁜 예: 필드를 모두 public으로 노출
public class Point {
public double x;
public double y;
}
// 사용 예시
Point point = new Point();
point.x = 10; // 잘못된 값이 들어가도 검증할 방법이 없음
point.y = -9999; // 문제가 있어도 막을 수 없음
이러한 방식은 절대 쓰지 마세요!
✅ 좋은 예제 (접근자와 변경자 사용한 예시)
public class Point {
private double x;
private double y;
public Point(double x, double y) {
setX(x);
setY(y);
}
public double getX() {
return x;
}
public void setX(double x) {
if(x < 0) {
throw new IllegalArgumentException("x는 음수가 될 수 없습니다.");
}
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
if(y < 0) {
throw new IllegalArgumentException("y는 음수일 수 없습니다.");
}
this.y = y;
}
}
외부에서 접근 시 값이 항상 올바른지 확인 가능하며, 값이 잘못 들어가는 걸 막을 수 있습니다.
📌 예외 상황: private 중첩 클래스와 package-private 클래스의 경우
외부에 절대 노출되지 않고 내부에서만 사용하는 클래스라면 필드를 직접 노출해도 괜찮습니다. (범위가 제한적이기 때문)
외부에 공개된 클래스(public 클래스)는 반드시 접근자와 변경자를 사용해야 합니다.
⚠️ 주의사항
클래스 내부 데이터를 변경하지 않는다면, setter는 생략하고 getter만 제공하는 것이 좋습니다. (불변 객체를 권장)
public static final
필드도 가변 객체(배열이나 List 등)는 절대 직접 공개하면 안 됩니다. 불변 객체만 공개 가능!
예시:
// 안전한 불변 클래스 예시
public final class Time {
private final int hour;
private final int minute;
public Time(int hour, int minute) {
this.hour = hour;
this.minute = minute;
}
public int getHour() { return hour; }
public int getMinute() { return minute; }
}
이처럼 불변 객체는 변경 불가능하므로 안전합니다.
🤔 어려운 점
처음에는 public 필드를 그냥 쓰는 게 쉬웠지만, 접근자와 변경자가 가지는 진정한 장점을 이해하는 게 어려웠습니다.
처음에 getter, setter를 만드는 과정이 불필요한 과정처럼 느껴졌지만, 객체가 복잡해질수록 필드를 보호하는 게 매우 중요하다는 걸 이해했습니다.
🗣️ 느낀 점
처음에는 그냥 편해서 public 필드를 많이 썼는데, 시간이 지날수록 이 방법이 매우 위험하다는 걸 체감했습니다.
특히 여러 사람이 협업하는 큰 프로젝트에서는 데이터가 노출되면 정말 유지보수가 어렵겠다고 느껴졌고, 접근자와 변경자의 중요성을 강력하게 느끼게 되었습니다.
앞으로는 습관적으로라도 무조건 private 필드를 기본으로 설정하고, 필요한 경우에만 접근자를 통해 접근할 수 있게 만들어야겠다고 생각했습니다.
🎯 한 줄로 다시 보는 요약 (Nutshell)
🔑 public 클래스의 필드는 절대 그대로 노출하지 말고 접근자(getter/setter)로 데이터를 보호하고 관리하자!
Last updated