Java객체지향

접근 제한자

Java의 네 가지 접근 제한자가 어떤 범위를 열고 닫는지, `package-private`이 왜 중요한지, 캡슐화 설계 기준을 정리합니다.

마지막 수정 2026년 3월 27일

기본 패턴

java
public class BankAccount {
    private double balance;        // 외부 직접 접근 차단
    private String ownerId;

    public void deposit(double amount) {   // 공개 API
        if (amount > 0) balance += amount;
    }

    public double getBalance() {
        return balance;
    }

    private boolean isValid(double amount) { // 내부 구현
        return amount > 0 && amount <= balance;
    }
}

설명

네 가지 접근 제한자와 적용 범위

Java에는 키워드가 세 개(public, protected, private)이고 아무것도 안 쓰면 package-private이 됩니다.

제한자같은 클래스같은 패키지서브클래스어디서든
private
package-private
protected
public
java
package com.example;

public class Foo {
    private int a;         // Foo 내부에서만
    int b;                 // com.example 패키지 안에서만 (package-private)
    protected int c;       // 패키지 + 서브클래스에서
    public int d;          // 어디서든
}

package-private — 모듈 내부 API의 기본 선택

키워드 없이 선언된 package-private은 Java에서 과소평가되는 접근 제한자입니다. 같은 패키지 안에서만 접근 가능하므로 패키지를 하나의 모듈로 설계할 때 내부 구현을 숨기는 데 씁니다. 외부에 노출할 이유가 없는 클래스나 메서드의 기본 선택입니다.

java
// 외부 노출이 필요 없는 유틸리티 클래스
class InternalParser {       // package-private — public 아님
    String parse(String raw) { ... }
}

// 같은 패키지 내에서만 사용
public class DataService {
    private final InternalParser parser = new InternalParser(); // ✅
}

캡슐화 설계 원칙 — 가능한 한 좁게

접근 제한자 선택의 원칙은 필요한 최소 범위만 열기입니다. 처음부터 public으로 만들면 나중에 좁히기 어렵습니다(다른 코드가 이미 의존하고 있으므로). 좁게 시작하고 필요할 때 넓히는 것이 안전합니다.

java
public class OrderService {
    // ✅ 필드는 private — 직접 접근 차단
    private final OrderRepository repository;
    private double discountRate;

    // ✅ 핵심 API만 public
    public Order placeOrder(Cart cart) { ... }

    // ✅ 내부 로직은 private
    private double calculateTotal(Cart cart) { ... }

    // ✅ 서브클래스에서 재정의해야 한다면 protected
    protected void sendConfirmation(Order order) { ... }
}

빠른 정리

상황선택
클래스 내부 구현private
패키지 내부 공유package-private (키워드 없음)
상속 계층에서 재정의 허용protected
라이브러리 공개 APIpublic
기본 시작점private부터 시작, 필요 시 넓힘

주의할 점

public 필드는 캡슐화를 무너뜨립니다. 외부에서 직접 수정하면 클래스 내부의 불변식을 보장할 수 없습니다. 필드는 항상 private으로, 접근이 필요하면 메서드로 노출하세요.

java
// ❌ public 필드 — 외부에서 직접 수정 가능
public class Circle {
    public double radius; // 음수 값도 막을 수 없음
}
Circle c = new Circle();
c.radius = -5; // 잘못된 상태지만 막을 수 없음

// ✅ private 필드 + 검증 메서드
public class Circle {
    private double radius;
    public void setRadius(double r) {
        if (r < 0) throw new IllegalArgumentException("반지름은 0 이상");
        this.radius = r;
    }
    public double getRadius() { return radius; }
}

참고 링크

1 sources