공부내용공유

java package private (feat : default 접근 제어자) 본문

Server/Java

java package private (feat : default 접근 제어자)

forfun 2024. 6. 9. 21:40

서론


 

계층형 아키텍쳐이든 클린 아키텍쳐를 지향하는 어떠한 아키텍쳐이든 보통 패키지를 도메인 별로 분리하는 경우를 많이 보았고, 현재 진행중인 프로젝트도 도메인 별로 패키지가 나눠져 있는 형태이다.  

 

 

다른 레이어에서의 구현에서는 큰 문제가 없었으나 도메인 레이어를 구현할 때 참 많이 고민된 부분이 있다, 이전 글에서 언급했듯이 value object를 적극적으로 활용하여 코드를 작성중인데 "value object들의 접근 제어자를 어떻게 설정할 것인가" 이다.

 

 

(이번 글도 정답이 없는 문제를 제 고민과 주변에서의 조언을 글로 정리한 것으로 반박, 의견 제시 해주시면 감사하겠습니다!)

 

 

본론


 

  • domain 별로 나눴을 때의 장점
  • public 장점
  • package private의 장점

본론은 위 항목으로 구성되어져 있다, 그리고 해당 글은 value object의 장단점, 사용하는 이유에 대해 이해하고 있고 자바의 접근 제어자를 알고 있다는 가정하에 작성된 글로 잘 알지 못한다면 해당 내용을 공부하고 읽는 것을 추천한다.

 

 

domain 별로 나눴을 때의 장점

 

서론에서 언급했듯이 프로젝트를 패키지 구조를 domain 별로 나누는 케이스가 많은데 이렇게 나누는 이유가 무엇일까? 만약 1인 프로젝트이고 규모가 작은 편이라면 굳이 domain 별로 나누지 않아도 될 것이다.

 

계층형 구조로 예시를 들면

- presentation
    - userApi
    - itemApi
    - accountApi
- service
    - userService
    - itemService
    - accountService
- persistence
    - userRepo
    - itemRepo
    - accountRepo

이런식으로 구성되도 큰 문제가 없을 것이다.

 

 

그런데 프로젝트의 규모가 점점 커져서 user, item, account등의 도메인을 별로의 프로젝트로 분리해야하는 상황이 온다면 어떨까?

 

물론 이러한 구조라도 의존성이 깔끔하게 정리될 수 있는 규칙과 함께 개발되었으면 문제가 없을 수 있으나 serivce들 끼리 얽혀있을 수 있고 상위 계층이 다른 도메인의 하위 계층을 의존 하는등의 이유로 분리하기 굉장히 힘든 구조가 되기 쉽다.

 

 

domain 별로 나눴을 때도 당연히 의존성을 개판으로 개발하여 각 도메인을 분리하는 작업이 힘들 수 있다, 하지만 위 예시와 같은 구조가 올바른 구조로 개발할 수 있게 강제하기 쉽다고 생각한다.

 

 

이외에도 규모가 커지게 되면 필요한 클래스들이 워낙 많아지기에 도메인을 기준으로 나눠야 좀 더 파악하기 쉽고, 같이 개발하기 쉬운 등의여러 장점이 있지만 일단 이 글의 주제와 연관이 큰 "도메인 별로 분리하기 쉬운 구조(의존 관계가 깔끔한)를 강제할 수 있다" 를 기준으로 접근 제어자 사용에 대해 생각해보자.

 

 

public의 장점

 

자 이제 프로젝트 구조가 domain으로 나누어져 있다고 가정을 하고 root가 되는 도메인 클래스를 제외한 서브 클래스들, value object 들을 public으로 했을 때 어떤 장점이 있을까?

 

 

내가 느낀 제일 큰 장점은 package private으로 했을 때에 비한 압도적인 편의성이다.

public class User {
    private final long id;
    private final Email email;
    private final Address address;
    private final Coupons coupons;
    private final WishList wishList;
}

class Email {
    private final String email;
}
class Address {
    private final String country;
    private final String city;
}
class Coupons {
    private final List<Coupon> coupons;
}
class Coupon {
    private final String couponCode;
    private final LocalDateTime expiredTime;
}
...

 

이런식으로 클래스가 구성되어져 있다고 생각해보자.

 

user 라는 도메인을 사용하는 클라이언트들이 email, address 등의 값을을 조회하려면 어떻게 해야할까? 각 value object들은 package private이기에 user를 통해서만 접근이 가능하고 그러면 user 클래스는 각 value object들의 값을 반환해주는 메서드를 전부 갖고 있어야 한다.

 

 

이때 접근 제어자가 public 이라면 gettet 메서드를 2번 만들 필요 없이 user.email.getEmail(); 이런식으로 값 조회가 바로 가능하다. (이렇게 사용하는게 객체지향적이지 못하다라는 의견도 알지만 해당 부분은 다른 주제이니 넘어가자)

 

 

package private의 장점

 

그렇다면 이러한 공수 작업을 감수하면서까지 package private의 사용을 할 필요가 있을까?

 

개발자를 위한 라이브러리를 만드는게 아닌 한 대부분의 프로젝트에서 package private의 장점을 살리기 쉽지 않고 비즈니스 로직이나 규모가 급변하는 어플리케이션 프로젝트에서는 오히려 확장을 할 때 걸림돌이 된다는 의견도 있었다.

 

 

분명 상황마다 다르겠지만 나는 가능한 package private을 적극적으로 사용하는 방향을 지향하는게 좋다는 결론을 내렸다. 이러한 결론에 굉장히 큰 영향을 준 이 있는데 글 내용도 정말 좋지만 해당 글의 댓글에서의 의견이 설득되었다.

 

 

댓글 내용을 간단히 설명을 하면 package private으로 구현함으로 꼭 노출해야하는 부분만 public으로 열어서 해당 도메인을 사용하는 클라이언트와의 의존성을 최소화 시킬 수 있고 이러한 이점을 통해 도메인 내부를 리팩토링하는 경우나 분리하는 작업을 손쉽게 할 수 있다라는 주장이었다. (다른 좋은 내용도 많으니 꼭 글과 댓글을 읽었으면 좋겠다.)  

  

즉 같은 user 도메인이라 하더라도 Store에서 user와 Coustomer의 user는 다른 도메인 로직을 가질 수 있기에 public으로 열었다가 여러군데서 사용되는 것보다 pacakge private으로 닫아서 각 도메인에서 역할을 충실하게 하고,

다른 클라이언트에서 직접 접근해서 나중에 user 로직을 변경할 때 각 클라이언트를 다 수정하는 것보다 루트 클래스만 수정할 수 있게 만들 수 있다는 큰 장점이 있다는 것이다.

 

 

물론 위에서 언급했듯이 상황에 따라 유연하게 결정해야 한다고 생각한다. 이를테면 Email 같은 클래스는 여러군데서 사용이 가능하고 사용되는 메서드나 검증 로직이 거의 같을거기 때문에 public으로 열고 common 패키지 등에 넣어서 사용할 수 있다.

 

(각기 다른 domain의 로직들이 조금씩 섞여 들어오면 골치 아파지니 수십번 생각하고 common에 빼라는 사수님의 조언이 있었다.)

 

 

또 공수작업이 많이 들어가는거에 비해 package private으로 철처한 분리를 하는 이점을 많이 못얻을 같을 경우 (타 클라이언트에서 사용되지 않는등의?) public으로 여는 것도 괜찮다고 생각한다.

 

 

이러한 상황을 제외하면 package private을 적극적으로 활용함으로 유지보수, 확장성등을 얻을 수 있기에 pacakge private 사용을 지향하겠다는 생각을 하게 되었다.

 

 

결론


 

코드를 작성할 때 참 많은 고민을 했었는데 정리하고 보니 별거 없는 것 같다, 팀 컨벤션에 따라 달라지겠지만 개인적으로는 package private을 지향하되 우연하게 public도 사용하는게 좋을 것 같다라는 결론을 내렸다.

 

 

이러한 사소한 부분들을 고민하는 것 때문에 업무를 빠르게 쳐내지 못하고 있는데 얼른 나의 기준들을 확립해서 상황에 맞는 적절한 수준의 코드를 빠르게 짤 수 있는 개발자가 되고싶다..!