정보 은닉
접근 제어자 살펴보기
객체 지향 프로그램에서는 예약어를 사용해 클래스 내부의 변수나 메서드, 생성자에 대한 접근 권한을 지정할 수 있다. 이러한 예약어를 '접근 제어자(access modifier)'라고 한다. Student.java 코드의 모든 변수에는 public 예약어가 있다. public이라고 선언한 변수나 메서드는 외부 클래스에서 접근이 가능하며 외부 클래스가 사용할 수 있다는 뜻이다. 반대로 접근 제어자를 private으로 선언한 변수나 메서드는 외부 클래스에서 사용할 수 없다.
다음 예제에서 변수를 private으로 선언하면 결과 값이 어떻게 바뀌는지 알아보자.
package hiding;
public class Student {
int studentID;
//studentName 변수를 private으로 선언
private String studentName;
int grade;
String address;
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
}
앞 예제에서 studentName 변수를 private으로 바꿔보았다. 그리고 파일을 저장한다.
코드를 수정한 후 저장하고 나서 Student.java 파일의 실행 클래스인 SrudentTest.java 파일을 보니 오류가 발생한다. 그 이유는 무엇일까? studentName 변수의 접근 제어자가 public일때는 외부 클래스인 StudentTest.java 클래스에서 이 변수에 접근할 수 있었지만, private으로 바뀌면거 외부 클래스의 접근이 허용되지 않기 때문이다.
get(), set() 메서드
그러면 private으로 선언한 studentName 변수를 외부 코드에서 사용하려면 어떻게 해야 할까? studentName 변수를 사용할 수 있도록 public 메서드를 제공해야 한다. public 메서드가 제공되지 않는다면 studentName 변수에 접근할 수 있는 방법은 없다. 이때 사용할 수 있는 것이 바로 get(), set() 메서드이다.
* 값을 얻는 get() 메서드를 getter, 값을 지정하는 set() 메서드를 setter라고도 부른다.
package hiding;
public class Student {
int studentID;
//studentName 변수를 private으로 선언
private String studentName;
int grade;
String address;
//private 변수인 studentName에 접근해 값을 가져오는 public get() 메서드
public String getStudentName() {
return studentName;
}
////private 변수인 studentName에 접근해 값을 지정하는 public set() 메서드
public void setStudentName(String studentName) {
this.studentName = studentName;
}
}
학생 이름을 받아오거나 지정할 수 있도록 getStudentName() 메서드와 setStudentName() 메서드를 추가하였다.
이클립스에서는 모든 멤버 변수에 대해 get 메서드와 set 메서드를 자동으로 만들 수 있는 기능을 제공한다. 이클립스 편집기 창의 멤버 변수를 선언한 클래스 내부에서 오른쪽 마우스를 클릭하고 [Source -> Generate Getters and Setters...] 메뉴를 클릭하면 아래와 같은 창이 뜬다. 이 중 get(), set() 메서드를 추가하고 싶은 멤버 변수를 선택하고 아래쪽의 [OK]를 누르면 해당 변수의 get(), set() 메서드가 생성된다.
다음과 같이 studentTest.java 파일을 수정한다.
package hiding;
public class StudentTest {
public static void main(String[] args) {
Student studentLee = new Student();
//studentLee.studentName = "이건희"; //오류 발생
//setStudentName() 메서드를 활용해 private 변수에 접근 가능
studentLee.setStudentName("이건희");
System.out.println(studentLee.getStudentName());
}
}
studentName 멤버 변수에 이름 값을 직접 대입하는 것이 아니고 setStudentName() 메서드를 활용하여 값을 대입할 수 있다. 즉 외부 클래스에서 private 변수에 직접 접근할 수는 없지만, public 메서드를 통하면 private 변수에 접근할 수 있다.
정보 은닉이란?
변수를 public으로 선언하는 것과 변수를 private으로 선언하고 나서 그 변수를 사용할 수 있도록 public 메서드를 제공하는 것의 차이는 무엇일까? 어차피 변수에 접근하는 것은 마찬가지인데 말이다. 다음 예제를 생각해보자.
public class MyDate {
public int day;
public int month;
public int year;
}
앞 코드에서 MyDate 클래스를 보면 MyDate 클래스의 day, month, year를 모두 public으로 선언했다. 따라서 외부 클래스에서 MyDate를 사용할 때 값을 마음대로 넣을 수 있다. 그리고 이 클래스를 사용한 다음 코드를 보면 2월은 28이나 29일까지인데 31일로 대입되었다.
package test;
public class MyDateTest {
public static void main(String[] args) {
MyDate date = new MyDate();
date.month = 2;
date.day = 31;
date.year = 2023;
}
}
즉 클래스의 멤버 변수를 public으로 선언하면 접근이 제한되지 않으므로 정보의 오류가 발생할 수 있다. 이런 경우에는 오류가 나더라도 그 값이 해당 변수에 대입되지 못하도록 다음과 같이 변수를 private으로 바꾸고 public 메서드를 별도로 제공해야 한다.
public class MyDate {
private int day;
private int month;
private int year;
public void setDay(int day) {
if(month == 2) {
if(day < 1 || day > 28) {
System.out.println("오류입니다");
} else {
this.day = day;
}
}
}
}
이처럼 클래스 내부에서 사용할 변수나 매서드는 private으로 선언해서 외부에서 접근하지 못하도록 하는 것을 객체 지향에서는 '정보 은닉(information hiding)'이라고 한다. 정보 은닉은 객체 지향 프로그래밍의 특징 중 하나이며 자바에서는 접근 제어자를 사용하여 정보 은닉을 구현한다. 모든 변수를 private으로 선언해야 하는 것은 아니지만, 필요한 경우에는 private으로 선언하여 오류를 막을 수 있다.
자바에서 사용하는 접근 제어자를 정리하면 다음과 같다.
접근 제어자 | 설명 |
public | 외부 클래스 어디에서나 접근할 수 있다. |
protected | 같은 패키지 내부와 상속 관계의 클래스에서만 접근할 수 있고 그 외 클래스에서는 접근할 수 없다. |
아무것도 없는 경우 | default이며 같은 패키지 내부에서만 접근할 수 있다. |
private | 같은 클래스 내부에서만 접근할 수 있다. |