[JAVA] Getter/Setter 이중성 & 문제점 Refactoring

2025. 12. 12. 19:37·Language/Java
☕
Java Study: Refactoring Getter/Setter
이 포스팅은 Getter/Setter의 남용을 막고, 객체지향적인 설계를 하는 방법을 정리한 글입니다.

자바를 처음 배울 때, 우리는 클래스를 만들고 습관적으로 모든 필드에 대해

Getter와 Setter를 생성하곤 합니다. IDE가 단축키 한 번이면 만들어주니 너무나 자연스럽죠.

하지만 "이게 정말 객체지향적인가?"라는 의문을 가져본 적 있으신가요?

단순히 값을 넣고 빼기만 한다면 그건 객체가 아니라 데이터 주머니에 불과할지도 모릅니다.

 

오늘은 무분별한 Getter/Setter 사용이 왜 문제인지, 그리고 이를 해결하기 위한 진짜 객체지향 설계 방법(Rich Domain Model, VO 등)에 대해 정리해보겠습니다.


 

1. Getter/Setter의 이중성과 문제점

빈약한 도메인 모델 (Anemic Domain Model)

우리는 '정보 은닉'을 위해 필드를 private으로 막습니다. 그런데 바로 public Getter/Setter를 열어버린다면? 사실상 정보 은닉은 깨진 것과 다름없습니다.

// ❌ 상태와 행위가 분리된 절차지향적 코드
public class Order {
    private int totalAmount;
    // 단순히 값만 꺼내주고 넣어주는 역할
    public int getTotalAmount() { return totalAmount; }
    public void setTotalAmount(int amount) { this.totalAmount = amount; }
}

// 서비스 로직 (객체의 데이터를 꺼내서 외부에서 처리함)
public void discount(Order order) {
    int amount = order.getTotalAmount();
    if (amount > 10000) {
        order.setTotalAmount(amount - 1000);
    }
}

 

이렇게 되면 객체는 자신의 데이터에 대한 통제권을 잃고, 단순히 데이터 보관소(주머니) 역할만 하게 됩니다.

이것을 빈약한 도메인 모델이라고 합니다.


2. 해결책 - 묻지 말고 시켜라 (Tell, Don't Ask)

객체지향의 핵심은 데이터와 그 데이터를 조작하는 행위(로직)를 한곳에 묶는 것입니다.

데이터를 달라고(Ask) 하지 말고, 원하는 작업을 하라고 시켜야(Tell) 합니다.

풍부한 도메인 모델 (Rich Domain Model)

// ✅ 스스로의 상태를 관리하는 객체
public class Order {
    private int totalAmount;

    // 객체가 스스로 판단하고 상태를 변경함
    public void applyDiscount() {
        if (this.totalAmount > 10000) {
            this.totalAmount -= 1000;
        }
    }
}

// 서비스 로직
public void process(Order order) {
    order.applyDiscount(); // "할인해!" 라고 명령만 하면 됨
}

 

이제 외부에서는 Order의 내부 구현을 몰라도 됩니다. 변경 사항이 생겨도 Order 객체 내부만 수정하면 되므로 유지보수성이 대폭 향상됩니다.


3. 더 나은 설계 1: Value Object (VO)

int, long 같은 원시 타입은 값이 무엇을 의미하는지, 유효한 값인지 스스로 증명하지 못합니다.

이를 해결하기 위해 값을 감싸는 객체(VO)를 사용합니다.

 

   Value Object의 특징

  • 불변성 (Immutable): 생성 후 값이 변하지 않음 (Setter 없음).
  • 유효성 검증: 생성자에서 값의 유효성을 체크함 (예: 금액은 음수 불가).
  • 동등성: 값이 같으면 같은 객체로 취급 (equals & hashCode 재정의).
public class Money {
    private final int amount; // 불변

    public Money(int amount) {
        if (amount < 0) {
            throw new IllegalArgumentException("돈은 음수가 될 수 없습니다.");
        }
        this.amount = amount;
    }

    public Money plus(Money other) {
        return new Money(this.amount + other.amount); // 새로운 객체 반환
    }
}

 

이제 int price = -1000; 같은 끔찍한 실수를 원천 차단할 수 있습니다.


4. 더 나은 설계 2: Aggregate Root와 캡슐화

객체들이 복잡하게 얽혀 있을 때, 외부에서 내부의 작은 객체들을 마음대로 조작하게 두면 안 됩니다.

Aggregate Root(대표 객체)를 통해서만 내부에 접근하도록 제약해야 합니다.

잘못된 설계 vs 올바른 설계

구분 방식 문제점/장점
Bad order.getItems().add(item); 주문(Order) 몰래 아이템을 추가함. 총액 계산 누락 등 버그 발생 위험.
Good order.addItem(item); 주문 객체가 아이템 추가와 동시에 총액 갱신 등 규칙을 수행함.

5. 결론: 객체를 객체답게 쓰는 법

  • Getter/Setter는 최소한으로: 무조건 만들지 말고, 꼭 필요한 경우(DTO, 조회용)에만 만들자.
  • 상태 변경은 명확하게: setStatus("CANCEL") 대신 cancelOrder() 처럼 의도가 드러나는 메서드를 사용하자.
  • 검증은 생성 시점에: 생성자에서 유효성을 검사하여, 태어날 때부터 온전한 객체(VO)만 존재하게 하자.

 

핵심 요약:
"값을 꺼내서(Get) 내가 계산하고 다시 넣지(Set) 말자."
"객체에게 계산하라고 시키고(Tell), 결과만 받아오자."
이것이 객체지향 프로그래밍의 시작입니다.

'Language > Java' 카테고리의 다른 글

[JAVA] Stack 구현 & Stack Class의 문제점 (feat. Deque)  (0) 2025.12.19
[JAVA] Collection Framework & Collections Class _ Part 1  (0) 2025.12.16
[JAVA] 접근제한자 & 캡슐화  (0) 2025.12.12
[JAVA] 객체 지향 프로그래밍 4대 원칙  (0) 2025.12.12
[JAVA] String vs StringBuilder vs StringBuffer 비교 정리 (왜 문자열을 다루는 클래스가 3개나 있을까?)  (1) 2025.12.04
'Language/Java' 카테고리의 다른 글
  • [JAVA] Stack 구현 & Stack Class의 문제점 (feat. Deque)
  • [JAVA] Collection Framework & Collections Class _ Part 1
  • [JAVA] 접근제한자 & 캡슐화
  • [JAVA] 객체 지향 프로그래밍 4대 원칙
hlxecz
hlxecz
1인분 개발자가 되고 싶은 개발 기록
  • hlxecz
    H.Dev Log
    hlxecz
  • 전체
    오늘
    어제
    • 분류 전체보기 (12)
      • Language (7)
        • Java (7)
        • C (0)
        • PHP (0)
        • Python (0)
      • Framewrok (0)
        • Spring (0)
      • Data (0)
        • DBMS (0)
      • Cloud (0)
        • Amazon Cloud (0)
      • Knowledge (3)
        • 자료구조 (0)
        • 알고리즘 (1)
        • 디자인 패턴 (2)
      • DevOps (0)
      • Dev Kit (0)
        • InteliJ (0)
        • VSCode (0)
      • TEST (2)
        • Testing (2)
        • Error (0)
      • ETC (0)
        • 일상 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    GOF
    알고리즘
    캡슐화
    collections
    바밀로니아
    getter
    OOP
    BIG-O
    재귀함수
    setter
    디자인 패턴
    인터페이스
    Solid
    string
    문제점
    생각정리
    Java
    Collection
    Interface
    Stack
    피드백
    시간복잡도
    Abstract
    문제풀이
    빅오표기법
    인터페이스 vs 추상클래스
    자바
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
hlxecz
[JAVA] Getter/Setter 이중성 & 문제점 Refactoring
GitHub 상단으로

티스토리툴바