스파르타 15일차

임선구·약 6시간 전

스파르타

목록 보기
14/14

객체지향 설계에서 무분별한 Setter를 지양해야 하는 이유

오늘은 자바 객체지향 과제를 진행하면서 Setter를 무조건 만드는 것이 꼭 좋은 것은 아니라는 점을 다시 정리하게 되었다.
처음에는 클래스 필드를 만들면 자연스럽게 Getter, Setter를 전부 작성하는 습관이 있었는데, 과제를 진행하고 피드백을 들으면서 중요한 값은 함부로 바뀌지 않도록 설계하는 것이 더 객체지향적이라는 점을 이해하게 되었다.


1. 처음에는 왜 Setter를 다 만들게 될까?

자바를 처음 배우면 보통 이렇게 배운다.

  • 필드는 private으로 숨긴다
  • Getter로 값을 조회한다
  • Setter로 값을 수정한다

그래서 자연스럽게 모든 필드에 대해 Getter, Setter를 전부 만드는 습관이 생긴다.

예를 들어 Product 클래스가 있으면 이렇게 작성하기 쉽다.

public class Product {

    private String productName;
    private long productPrice;
    private String productDescription;
    private int productStock;

    public Product(String productName, long productPrice, String productDescription, int productStock) {
        this.productName = productName;
        this.productPrice = productPrice;
        this.productDescription = productDescription;
        this.productStock = productStock;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public long getProductPrice() {
        return productPrice;
    }

    public void setProductPrice(long productPrice) {
        this.productPrice = productPrice;
    }

    public String getProductDescription() {
        return productDescription;
    }

    public void setProductDescription(String productDescription) {
        this.productDescription = productDescription;
    }

    public int getProductStock() {
        return productStock;
    }

    public void setProductStock(int productStock) {
        this.productStock = productStock;
    }
}

처음에는 이 방식이 정석처럼 보인다.
하지만 이렇게 하면 객체의 중요한 정보가 외부에서 너무 쉽게 변경될 수 있다.


2. 무분별한 Setter가 왜 문제일까?

예를 들어 상품 가격, 상품명, 재고는 중요한 데이터다.
그런데 Setter를 전부 열어두면 밖에서 이렇게 바꿀 수 있다.

product.setProductPrice(-10000);
product.setProductName("이상한 상품명");
product.setProductStock(-5);

이렇게 되면 객체가 스스로 자신의 상태를 지키지 못한다.
즉, 객체가 안전하지 않다.

객체지향에서는 단순히 필드를 숨기는 것만 중요한 것이 아니라,
그 값을 누가, 언제, 어떤 방식으로 바꿀 수 있는지까지 통제하는 것이 중요하다.


3. Getter는 조회, Setter는 수정이다

오늘 다시 정리한 중요한 포인트는 이것이다.

  • Getter는 객체의 값을 읽기 위해 사용한다
  • Setter는 객체의 값을 바꾸기 위해 사용한다

문제는 “조회”보다 “수정”이 훨씬 위험하다는 점이다.

값을 읽는 것은 비교적 안전하지만,
값을 수정하는 순간 객체 상태가 달라진다.
그래서 수정 메서드는 정말 필요한 경우에만 열어두는 것이 좋다.


4. 현재 단계에서는 Setter가 꼭 필요하지 않았다

이번 커머스 과제에서 만든 클래스들은 대략 이런 역할을 가진다.

  • Product : 상품 1개 정보
  • Category : 카테고리 이름 + 상품 목록
  • Customer : 고객 정보
  • CommerceSystem : 프로그램 흐름 제어

이 단계에서 대부분의 객체는 조회가 중심이었다.

예를 들면:

  • 상품명을 출력한다
  • 가격을 출력한다
  • 설명을 출력한다
  • 카테고리 이름을 출력한다
  • 고객 정보를 확인한다

즉, 값을 읽는 것은 많이 하지만
중간에 값을 계속 수정할 필요는 거의 없었다.

그래서 Setter를 모두 둘 필요가 없다고 판단했다.


5. 불필요한 Setter를 제거한 방향

예를 들어 Category는 생성될 때 이름과 상품 목록이 정해지면,
실행 중에 굳이 계속 이름을 바꿀 필요가 없다.

그래서 이런 식으로 최소한의 구조로 가져가는 것이 더 자연스럽다.

public class Category {

    private String categoryName;
    private List<Product> products;

    public Category(String categoryName, List<Product> products) {
        this.categoryName = categoryName;
        this.products = products;
    }

    public String getCategoryName() {
        return categoryName;
    }

    public List<Product> getProducts() {
        return products;
    }
}

Customer도 마찬가지다.

public class Customer {

    private String customerName;
    private String email;
    private String grade;

    public Customer(String customerName, String email, String grade) {
        this.customerName = customerName;
        this.email = email;
        this.grade = grade;
    }

    public String getCustomerName() {
        return customerName;
    }

    public String getEmail() {
        return email;
    }

    public String getGrade() {
        return grade;
    }
}

이렇게 하면 객체를 만들 때 필요한 값을 넣고,
그 이후에는 필요한 정보만 조회하는 구조가 된다.


6. Setter 대신 더 의미 있는 메서드를 만드는 것이 좋다

오늘 공부하면서 가장 인상 깊었던 부분은
무조건 setXXX()를 만드는 것보다, 의도가 드러나는 메서드를 만드는 것이 더 좋다는 점이다.

예를 들어 상품 재고는 나중에 주문 기능이 생기면 바뀔 수 있다.
그런데 이렇게 작성하는 것보다:

product.setProductStock(29);

이렇게 작성하는 것이 훨씬 자연스럽다.

product.decreaseStock(1);

왜냐하면 setProductStock(29)
그 값이 왜 29가 되었는지 문맥이 잘 드러나지 않는다.

반면 decreaseStock(1)
“재고를 1개 줄인다”는 의도가 명확하다.

즉, Setter는 단순 수정이고
의미 있는 메서드는 행동 중심 설계에 더 가깝다.


7. 캡슐화와도 연결된다

이번 과제 Step 4가 캡슐화였는데,
Setter를 줄이는 방향은 캡슐화와도 연결된다.

캡슐화는 단순히 private을 붙이는 것만이 아니라
객체 내부 상태를 안전하게 관리하는 것이다.

즉:

  • 필드는 private으로 숨기고
  • 필요한 값은 Getter로 조회하고
  • 수정은 꼭 필요한 경우에만 허용하고
  • 가능하면 의미 있는 행동 메서드로 표현한다

이런 방식이 더 좋은 캡슐화라고 느꼈다.


8. 오늘 정리한 기준

앞으로는 필드를 만들 때 무조건 Setter를 만들지 않고,
아래 기준으로 생각해보려고 한다.

Setter가 필요 없는 경우

  • 생성 시 값이 정해지고 이후 잘 바뀌지 않는 경우
  • 외부에서 함부로 수정되면 안 되는 중요한 정보
  • 현재 단계에서 조회만 필요한 경우

Setter 대신 다른 메서드가 더 좋은 경우

  • 값 수정에 명확한 의도가 있는 경우
  • 단순 대입이 아니라 “행동”을 표현해야 하는 경우

예:

  • setProductStock() 보다 decreaseStock()
  • setOrderStatus() 보다 completeOrder()

9. 오늘 느낀 점

예전에는 Getter, Setter를 모두 만드는 것이 좋은 습관이라고만 생각했다.
하지만 오늘은 “모든 Setter가 좋은 것은 아니다”라는 점을 분명히 이해하게 되었다.

객체지향에서 중요한 것은 단순히 클래스를 나누는 것이 아니라,
객체가 자신의 데이터를 어떻게 지키는지 설계하는 것이었다.

특히 이번 커머스 과제를 하면서
Product, Category, Customer 같은 클래스는 지금 단계에서 조회가 중심이기 때문에
불필요한 Setter를 열어두지 않는 것이 더 적절하다고 느꼈다.


10. 한 줄 요약

Setter는 무조건 만드는 것이 아니라, 정말 필요한 경우에만 열어두고, 가능하면 객체의 의도가 드러나는 메서드로 설계하는 것이 더 객체지향적이다.


profile
끝까지 가면 내가 다 이겨

0개의 댓글