Topic (오늘의 주제)
자바의 접근 제어자 (Java Access Modifiers)
: 클래스, 메서드, 변수 등에 대한 외부의 접근 권한을 제어하여 불필요한 노출을 막고 객체 간의 결합도를 낮추는 문법적 도구.
Why (왜 사용하는가? 왜 중요한가?)
실무: 접근 제어자가 없으면(모두 public이라면) 외부에서 객체의 내부 데이터를 마음대로 변경할 수 있어 데이터 무결성이 깨지고, 예기치 않은 사이드 이펙트가 발생한다.
구조적 의미: '캡슐화(Encapsulation)'를 구현하는 핵심 도구로, 내부 구현은 감추고(Information Hiding) 필요한 인터페이스만 노출하여 유지보수성과 모듈 간 독립성을 높인다.
면접 의도: 객체지향의 기본 원칙인 캡슐화를 이해하고 있는지, 그리고 설계를 할 때 데이터 보호와 API 설계를 고려하는지 확인하려 한다.
Core Concept (핵심 개념 정리)
| 요소 | 내용 |
| 개념 정의 | 클래스 멤버(필드, 메서드, 생성자)나 클래스 자체에 붙여, 어디까지 접근을 허용할지 결정하는 키워드 (private, default, protected, public). |
| 동작 방식 | 컴파일 타임에 컴파일러가 접근 가능 여부를 체크한다. 허용되지 않은 범위에서 호출 시 Compile Error를 발생시킨다. |
| 범위 비교 | 1. private: 해당 클래스 내부에서만 접근 가능 (가장 엄격) 2. default (package-private): 같은 패키지 내에서만 접근 가능 (키워드 생략 시 적용) 3. protected: 같은 패키지 + **다른 패키지의 자식 클래스(상속)**에서 접근 가능 4. public: 프로젝트 내 어디서든 접근 가능 (가장 개방) |
| 장점 | 1. 데이터 보호: 잘못된 값 설정을 방지한다. 2. 복잡성 감소: 사용자가 몰라도 되는 내부 로직을 숨겨 API를 단순화한다. 3. 변경 용이성: private 멤버는 외부 영향 없이 수정 가능하다. |
| 필요 조건 | 클래스 레벨에는 public과 default만 사용 가능하며, 멤버 레벨에는 4가지 모두 사용 가능하다. |
| 비교 (vs) | C++: friend 키워드 등으로 예외를 두지만, 자바는 패키지와 상속 구조로만 엄격히 제어한다. |
Interview Answer Version (면접 답변식 요약)
"접근 제어자는 클래스 멤버의 가시성 범위를 private, default, protected, public 네 가지로 조절하는 키워드입니다.
저는 주로 '최소 권한의 원칙'에 따라 기본적으로 private을 사용하여 내부 데이터를 보호(캡슐화)하고, 외부와의 소통이 반드시 필요한 메서드에 한해 public을 열어주는 방식으로 설계합니다. 이를 통해 객체의 무결성을 보장하고, 내부 로직 변경이 외부에 영향을 주지 않도록 결합도를 낮출 수 있습니다."
Practical Tip (사용시 주의할 점 or 활용 예)
1. 실무 코딩 원칙 (Rule of Thumb)
- "일단 private으로 막고 시작하라."
- 필요할 때만 범위를 하나씩 넓히는 것이 안전하다. 처음부터 public으로 열면 나중에 줄이는 것은 불가능하다(이미 다른 곳에서 쓰고 있을 수 있으므로).
2. DTO/Entity에서의 활용 (Lombok 주의)
- 잘못된 예: 필드를 public으로 선언.
- Java
public class Member { public String name; // ❌ 외부에서 member.name = "" 등으로 오염 가능 } - 올바른 예: 필드는 private, 접근은 Getter/Setter로 제한.
-
Java
@Getter // Lombok 사용 시 public class Member { private String name; // ✅ 외부 접근 차단 private int age; // Setter를 무분별하게 쓰지 말고, 의미 있는 비즈니스 메서드 제공 public void changeInfo(String name, int age) { ... } }
3. 생성자의 접근 제어자 (Singleton & Factory)
- 싱글톤 패턴(Singleton): 외부에서 new를 못 하게 막아야 하므로 생성자를 **private**으로 선언한다.
- 팩토리 메서드: 생성자는 private이나 protected로 막고, public static 메서드로만 객체 생성을 허용하여 생성 로직을 통제한다.
4. protected의 미묘한 범위
- protected는 같은 패키지는 물론, '다른 패키지라도 상속받은 자식 클래스'에서는 접근 가능하다. 하지만 자식 클래스 내부에서 super.field로는 접근되지만, 자식 클래스에서 부모 객체를 new로 생성해서 접근하는 것은 불가능하다는 점을 주의해야 한다.
예상 꼬리질문 정리
- Q: default와 protected의 정확한 차이는 무엇인가요?
- A: 둘 다 같은 패키지 내 접근을 허용하지만, protected는 '다른 패키지여도 상속 관계'라면 접근을 허용한다는 점이 다릅니다. 즉, protected가 default보다 조금 더 넓은 범위를 가집니다.
- Q: 왜 필드(변수)는 주로 private으로 하고 Getter/Setter를 쓰나요? (불변성 관련)
- A: 메서드를 통하면 값을 넣을 때 유효성 검사(Validation)를 할 수 있고, 필요시 Setter를 만들지 않음으로써 객체를 **불변(Immutable)**으로 만들 수 있기 때문입니다. 필드를 바로 노출하면 이런 통제권을 잃게 됩니다.
- Q: 인터페이스(Interface)의 멤버들은 어떤 접근 제어자를 가지나요?
- A: Java 8 이전까지는 모든 메서드가 암시적으로 public abstract였고, 변수는 public static final이었습니다. Java 9부터는 인터페이스 내부 로직 정리를 위해 private 메서드도 허용됩니다.
'Archive > Daily Dev Q&A' 카테고리의 다른 글
| Daily Dev Q&A: 자바의 빌더 패턴(Builder Pattern) (0) | 2025.12.11 |
|---|---|
| Daily Dev Q&A: 자바 제네릭 (0) | 2025.12.10 |
| Daily Dev Q&A: 자바의 Collections Framework (0) | 2025.12.08 |
| Deily Dev Q&A: SOLID원칙 (0) | 2025.12.08 |
| Daily Dev Q&A: 오버로딩과 오버라이딩 (0) | 2025.12.05 |