본문 바로가기
Java

객체지향 캡슐화 이해하기

by 옹알이옹 2023. 9. 15.
목차

1. 캡슐화의 정의

2. 예시를 통해 캡슐화 이해하기

2-1. 캡슐화를 하지 않을 때의 문제점

2-2. 캡슐화를 통해 위의 문제 해결하기


 1. 캡슐화의 정의

한마디로 객체의 내부 정보(필드)를 은닉하고 데이터와 메서드를 하나의 단위로 묶는 것이다.
단순히 class가 가지고 있는 필드의 접근 제어자를 private 한다고 캡슐화를 한것이 아니다.
캡슐화는 객체간의 결합도를 낮추는 가장 기본적인 개념으로 꼭 이해해야 할 개념이다.
아래 예시를 통해 캡슐화가 무엇인지 이해해보자.

 2. 예시를 통해 캡슐화 이해하기

아래와 같이 Bank 클래스와 Customer, Company 클래스가 있다.

 

Bank 클래스

public class Bank {

    private int balance; // 잔액
    private double interestRate; // 이자율

    public Bank(int balance, double interestRate) {
        this.balance = balance;
        this.interestRate = interestRate;
    }

    public int getBalance() {
        return balance;
    }

    public double getInterestRate() {
        return interestRate;
    }
}

 

Customer 클래스

public class Customer {

    public void exMethod1(Bank bank){

        double interest = bank.getBalance() * bank.getInterestRate();

        System.out.println(interest + bank.getBalance());
    }
}

 

Company 클래스

public class Company {

    public void exMethod2(Bank bank){

        double interest = bank.getBalance() * bank.getInterestRate();

        System.out.println(bank.getBalance());
    }
}

 

2-1. 캡슐화를 하지 않을 때의 문제점

상황

Customer 클래스와 Company 클래스는 둘 다 Bank의 getter 메서드를 통해 Bank의 잔액과, 이자율을 꺼내온 뒤
두 값을 곱하여 이자를 계산한다.
계산을 하여 얻은 이자를 각자 목적에 따라 사용하고 있다.

여기서 가정을 하나 해보자 Bank 클래스에서 이자율을 의미하는 필드인 interestRate를 percent라는 이름으로 바꾸었다.

그에 따라 당연히 이자율을에 대한 getter 메서드인 getInterestRate도 getPercent로 바뀌어야 할 것이다.

그러면 getInterestRate()를 사용하던 Customer, Company 클래스도 당연히 변경을 해야 한다.

 

Bank의 필드명만 하나 바꿨을 뿐인데 본인을 제외한 두 객체 모두 바꿔줘야 할 상황이 되어버렸다.

만약 Bank의 getInterestRate() 를 사용하던 객체가 2개가 아니라 100개라면 100개의 코드를 다 수정해야 할 것이다.

 

이런 불행이 일어난 원인은 getter에 존재한다. getter를 통해 현재 Bank가 가지고 있는 필드를 노출하였고,

결과적으로 다른 객체들도 Bank의 값을 이용하여 원하는 데로 사용할 수 있게 된다.

이러한 행위 자체가 위에서 보는 것과 같이 추후 수정에 대해 엄청난 파급 효과를 불러오게 된다.

 

2-2. 캡슐화를 통해 위의 문제 해결하기

 

그러면 Bank 객체에 대한 캡슐화를 진행하여 위의 문제를 해결해보자.

public class Bank {

    private int balance; // 잔액
    private double interestRate; // 이자율

    public Bank(int balance, double interestRate) {
        this.balance = balance;
        this.interestRate = interestRate;
    }

    public double calcInterest(){
        return balance * interestRate;
    }
}
public class Customer {

    public void exMethod1(Bank bank){

        double interest = bank.calcInterest();

        System.out.println("내가 받을 이자 = "+interest);
    }
}
public class Company {

    public void exMethod2(Bank bank){

        double interest = bank.calcInterest();

        System.out.println("회사가 받을 이자 = "+ interest);
    }
}
  • 먼저 외부에 필드를 노출하던 getter 메서드를 지워버렸다.
  • calcInterest 메서드를 생성하여 그 안에서 잔액과 이자율을 곱해 이자를 구한 뒤 리턴한다.
  • Customer와 Company 클래스는 이제 직접 이자를 계산하지 않고 Bank객체에게 계산을 부탁한다.
  • 이제 Bank의  interest 필드의 이름이 percent로 바뀌어도 Bank안에서의 수정만 발생하고 Customer와 Compony는 영향을 받지 않게 된다.
  • 최종적으로 Bank의 변경에 대한 파급 효과 낮아져(결합도가 낮아져) 더 유연한 수정이 가능해졌다.

캡슐화가 왜 결합도를 낮추는 가장 기본적인 방법인지 이해가 되길 바란다. 

반응형

'Java' 카테고리의 다른 글

(Java) 패키지 양방향 의존 문제점과 해결 방안  (0) 2024.05.11
Session과 JSESSIONID  (2) 2023.11.20
[Java] 입출력(I/O) 정리  (0) 2023.08.24
[Java] Generic 사용법  (0) 2023.08.06