spring

자바 접근제어자 개념과 JPA @Embeddable에서 기본생성자에 proteced를 사용하는 이유

devJK93 2024. 11. 24.

 

자바 접근 제어자

자바에서 접근 제어자(Access Modifier)는 클래스, 메서드, 변수 등의 접근 범위를 결정하여 객체 지향 프로그래밍의 캡슐화(encapsulation)를 구현하는 데 사용됩니다. 자바는 네 가지 접근 제어자를 제공합니다: public, private, protected, 그리고 default(접근 제어자를 명시하지 않을 때).


1. public

  • 설명: 모든 클래스에서 접근 가능합니다. 패키지 내부 또는 외부 어디서든 해당 멤버에 접근할 수 있습니다.
  • 접근 범위:
    • 같은 클래스: O
    • 같은 패키지: O
    • 하위 클래스(다른 패키지): O
    • 전체 외부 클래스: O
  • 예시:
    public class MyClass {
        public int myVariable;
        public void myMethod() {
            // 구현 코드
        }
    }
  • 사용 시기: 클래스의 인터페이스를 공개하여 다른 클래스나 패키지에서 자유롭게 사용할 수 있도록 할 때 사용합니다.

2. private

  • 설명: 선언된 클래스 내에서만 접근 가능합니다. 다른 클래스에서는 접근할 수 없습니다.
  • 접근 범위:
    • 같은 클래스: O
    • 같은 패키지: X
    • 하위 클래스(다른 패키지): X
    • 전체 외부 클래스: X
  • 예시:
    public class MyClass {
        private int myVariable;
        private void myMethod() {
            // 구현 코드
        }
    }
  • 사용 시기: 클래스 내부의 구현을 감추고 외부에서의 직접적인 접근을 막아 데이터의 무결성을 유지하고 싶을 때 사용합니다.

3. protected

  • 설명: 동일한 패키지 내의 클래스 또는 다른 패키지에 있는 하위 클래스에서 접근 가능합니다.
  • 접근 범위:
    • 같은 클래스: O
    • 같은 패키지: O
    • 하위 클래스(다른 패키지): O
    • 전체 외부 클래스: X
  • 예시:
    public class MyClass {
        protected int myVariable;
        protected void myMethod() {
            // 구현 코드
        }
    }
  • 사용 시기: 상속 관계에서 부모 클래스의 멤버를 하위 클래스에서 사용할 수 있도록 하면서도 외부 접근은 제한하고 싶을 때 사용합니다.

4. default (패키지 전용 접근 제어자)

  • 설명: 접근 제어자를 명시하지 않을 때 적용되며, 동일한 패키지 내에서만 접근 가능합니다.
  • 접근 범위:
    • 같은 클래스: O
    • 같은 패키지: O
    • 하위 클래스(다른 패키지): X
    • 전체 외부 클래스: X
  • 예시:
    public class MyClass {
        int myVariable; // 접근 제어자 없음
        void myMethod() {
            // 구현 코드
        }
    }
  • 사용 시기: 패키지 내부에서만 사용되는 멤버를 정의할 때 사용합니다.

접근 제어자 선택 시 고려사항

  • 캡슐화: 데이터의 무결성을 유지하기 위해 필드는 보통 private으로 선언하고, 필요한 경우 public 메서드를 통해 접근합니다.
  • 상속과 재사용성:
    • protected는 상속 관계에서 하위 클래스가 부모 클래스의 멤버에 접근할 수 있도록 합니다.
    • 외부 패키지에서 클래스의 일부 기능만 노출하고 싶을 때 유용합니다.
  • 패키지 구조: default 접근 제어자는 같은 패키지 내에서만 접근이 가능하므로, 패키지 단위로 클래스를 묶어 관리할 때 유용합니다.
  • 보안과 유지보수:
    • 불필요한 외부 접근을 막음으로써 코드의 보안을 높이고, 유지보수를 용이하게 합니다.
    • 너무 많은 멤버를 public으로 선언하면 오히려 코드의 복잡성이 증가하고 오류가 발생할 가능성이 높아집니다.

정리

  • public: 어디서든 접근 가능 (전역 공개).
  • private: 해당 클래스 내에서만 접근 가능 (완전 은닉).
  • protected: 같은 패키지 또는 다른 패키지의 하위 클래스에서 접근 가능 (상속 관계에서 공개).
  • default: 같은 패키지 내에서만 접근 가능 (패키지 공개).

접근 제어자는 객체 지향 프로그래밍에서 매우 중요한 개념으로, 올바른 사용을 통해 코드의 안정성과 재사용성을 높일 수 있습니다. 각 접근 제어자의 특성과 용도를 잘 이해하고 상황에 맞게 적용하는 것이 중요합니다.

 


@Embeddable와 protected 기본 생성자

1. @Embeddable와 기본 생성자

@Embeddable은 JPA에서 값 타입(Value Type)을 정의할 때 사용하는 어노테이션입니다. 값 타입 객체는 데이터베이스의 컬럼으로 매핑되며, 엔티티의 일부로 사용됩니다. 이때 JPA는 리플렉션(Reflection) 기술을 사용해 객체를 생성합니다.

리플렉션과 기본 생성자

  • JPA는 리플렉션을 사용해 객체를 생성하고 데이터베이스에서 조회한 값을 객체에 주입합니다.
  • 리플렉션은 기본 생성자가 반드시 필요합니다. JPA가 new Address()처럼 기본 생성자를 호출해서 객체를 생성하기 때문입니다.
  • 기본 생성자는 직접 호출되지 않더라도, JPA의 내부 동작을 위해 꼭 필요합니다.

2. 왜 protected 접근제어자를 사용하는가?

JPA의 요구사항

  • JPA에서는 기본 생성자를 반드시 제공해야 하지만, 이 생성자는 프레임워크 내부에서만 사용됩니다.
  • 즉, 외부 코드에서 직접 호출하지 않도록 캡슐화해야 합니다.

protected vs public

  • public: 외부에서도 기본 생성자를 호출할 수 있게 됩니다. 이는 값 타입 객체의 불변성을 해칠 가능성을 열어줍니다.
  • protected: JPA와 같은 프레임워크에서만 사용할 수 있도록 제한되며, 외부에서 호출할 수 없으므로 값 타입 객체의 불변성을 유지할 수 있습니다.

3. 객체지향 설계 관점

값 타입 객체는 불변 객체(Immutable Object)로 설계하는 것이 일반적입니다. 불변 객체는 객체 생성 이후 상태가 변하지 않도록 설계된 객체로, 다음과 같은 장점을 제공합니다:

  • 안전성: 객체 상태가 변하지 않아 동시성 문제가 발생하지 않습니다.
  • 신뢰성: 상태가 변하지 않으므로 데이터의 무결성을 유지할 수 있습니다.

Address 클래스의 불변성

private final로 필드를 선언하고, setter를 제거하면 완벽한 불변 객체가 됩니다. 기본 생성자를 protected로 제한하면 JPA 외부에서 호출할 수 없으므로 외부 코드로 인해 불변성이 깨지는 것을 방지합니다.

@Embeddable
@Getter
public class Address {

  private final String city;
  private final String street;
  private final String zipcode;

  protected Address() {
    // JPA가 리플렉션을 통해 사용
    this.city = null;
    this.street = null;
    this.zipcode = null;
  }

  public Address(String city, String street, String zipcode) {
    this.city = city;
    this.street = street;
    this.zipcode = zipcode;
  }
}

4. 결론

  • 기본 생성자: JPA가 리플렉션 기술로 객체를 생성하기 위해 반드시 필요합니다.
  • protected 접근제어자: 외부에서 기본 생성자의 사용을 제한하여 불변성을 유지하고, JPA 프레임워크의 동작만 허용합니다.
  • 설계 원칙: 값 타입 객체는 불변 객체로 설계하는 것이 바람직하며, 이를 위해 protected 접근제어자를 사용합니다.

이러한 설계는 JPA의 동작 방식과 객체지향 원칙을 조화롭게 결합한 결과입니다.

댓글