자바 10. 접근제어자·정보은닉·클래스다이어그램 UML (public, protected, default, private), this 예약어, 싱글톤 패턴

Bluewiz_YSH·2022년 8월 7일
1

1.접근제어자·정보은닉·클래스다이어그램 UML (public, protected, default, private)

자, 여태까지 보았듯이 자바 프로그램을 포함해 다른 언어 프로그램이더라도 프로그램은 실제에 있는 혹은 실제 있을법한 데이터를 기반으로 하기에 다소 개인정보가 들어갈수 있다. 그래서 보안적인 측면에서 클래스를 설계하고 구현할때 클래스 안에 있는 데이터·정보들에 대한 접근을 누구까지만 허용하고 나머지는 제한할지 생각을 해야한다.

그래서 나온 개념이 Information Hiding, 즉 정보 은닉이고 이는 대부분 클래스 안 개인정보를 담는 멤버 변수에 대해 직접 접근을 막는 처리를 뜻한다. (숨긴다는 의미이며 캡슐화라고도 한다 encapsule)

그런 정보 은닉에는 보통 접근 제어자 access modifier를 쓰는데 이는 우리가 여태까지 잘 써왔지만 잘 모르는, 잘 설명하지 않았던 public-protected-default-private을 뜻한다.

하나 하나씩 보면 다음과 같다 (접근 범위가 큰 것부터 작은 순서로 설명했다):

public: 같은 클래스는 물론 같은 패키지안에서라도, 다른 패키지더라도, 다른 패키지의 상속받은 하위 클래스더라도 이 접근 제어자로 선언되어 있으면 같은 프로젝트 폴더로 묶여만 있다면 누구든지 사용이 가능하다. 말 뜻처럼 한 마디로 접근 제한이 아예 없는 축에 속한다.

protected: public보다는 작은 접근 범위를 가진 접근 제어자로 같은 패키지, 같은 클래스, 다른 패키지에 있는 상속 받은 하위 클래스여도 접근이 가능하지만 이 이외의 클래스에게는 접근을 허용하지 않는다. 보통 이 접근 제어자는 상속 받은 하위 클래스에게만 접근을 허용하기 위해 쓰인다. (그래서 앞선 장에서 마트 사례 할때 고객의 이름 아이디 등급 정보를 담은 변수들을 protected로 선언한것이다.)

default: 같은 패키지, 같은 클래스 안이라면 접근이 가능하다. default라는 의미처럼 이 접근 제어자만 유일하게 생략이 가능하다.

private: 오로지 같은 클래스 안일때만 접근이 가능하다. 그래서 보통 이름, 연락처, 주소 등 개인정보를 담는 변수의 경우 이 접근 제어자를 많이 쓰고 그렇지만 외부에서 접근을 간접적으로 허용하기 위해 보통 public으로 선언된 메소드를 쓰는데 이 변수를 가져와 리턴하는 메소드는 게터(getter)메소드, 이 변수를 초기화/세팅하는데 쓰이는 메소드는 세터(setter) 메소드라고 한다.

이렇게 접근 제어자에는 4개를 쓰며 보통 클래스 선언부에는 public과 default 선언을 주로 쓴다. (접근에 대폭 제한을 거는 protected나 private은 잘 쓰이지 않는다)

하지만 멤버 변수나 지역 변수 혹은 메소드 선언부에는 public/protected/default/private 4개 모두 종종 쓰인다.

여기에 덧붙여 후일 프로젝트할때 쓰일 클래스 다이어그램 (소프트웨어에서 개체 혹은 객체간의 관계를 그린 모델을 다루는 언어인 UML, Unified Modeling Language의 한 종류로 클래스 내부와 클래스들 서로의 관계를 그린 그림이라고 보면 된다)에 대해 알아보겠다.

일단, 앞서 본 public/protected/default/private 이 4개는 각각 클래스 다이어그램에서 특정 모양을 띄는데

  • public은 초록색 원 혹은 + 표시,

  • protected는 노란색 다이아몬드 혹은 # 표시,

  • default는 파란색 세모 혹은 표시 없음,

  • private는 빨간색 네모 혹은 - 표시로 구분한다.

이렇게 접근 제어자와 클래스 안 멤버 변수/메소드/지역 변수 등 요소들에 대해서 기호를 붙이고 도식화하여 자바 프로그램의 전체적인 그림을 나타낸것이 바로 클래스 다이어그램이라고 보면 된다.

이걸 이클립스에서 보는게 가능한데, 보는 방법은 이클립스 Package Explorer에서 해당 클래스 파일 왼쪽에 있는 > carrot 아이콘을 클릭하면 아래 상세 목록이 뜨면서 클래스 안에서 지정했던 멤버 변수나 메소드들에 대한 접근 제어자 아이콘들이 주르륵 뜬다, 바로 아래처럼 말이다:

(위의 사진은 우리가 저번 챕터에서 했던 Customer_EndYear의 내용이다. 보면 private + static 선언을 했던 c_List는 빨간 네모에 s 표시, public 선언을 했던 대부분의 요소들은 초록색 원표시, 따로 접근 제어자 표시를 안했던 것들은 default로 파란색 세모 표시로 되어있다.)

그런데, 이게 완전한 클래스 다이어 그램은 아니다. 위 사진은 단순히 클래스 내부에 있는 요소들을 클래스 다이어그램 표기 방법으로 표시를 한것이므로 서로 다른 클래스와의 관계가 포함되어있지가 않다.

그 부분까지 포함하면은 완전한 클래스 다이어그램이라고 볼수 있는데, 더욱 더 자세한 내용은 아주 잘 설명된, 다음 링크로 가서 확인하길 바란다.

2. this 예약어

this 예약어는 우리가 앞서 배웠던 super와 동일하게 자바에서 미리 지정한 키워드 단어, 예약어에 속한다.

다만, super와는 다르게 this는 상속한 부모 클래스를 말하는게 아니라 this 단어 자체 의미와 동일하게 this가 선언되는 부분을 감싼 클래스 전체를 의미한다. 즉, this가 있는 위치의 '이' 클래스 전체, 정확히는 인스턴스 객체를 의미한다.

그렇기에 이 this라는 키워드와 우리가 여태까지 배웠고 써왔던 개념들을 조합하면 this가 언급된 클래스의 다양한 요소들을 끌어올수 있다.

예를 들면, 매개변수가 있는 생성자 A 안에 this() 혹은 this(매개변수(들))을 입력하고 해당 클래스의 객채를 만들때 생성자 A로 만들면 그 생성자 A는 자기 대신에 디폴트 생성자 혹은 매개 변수가 있는 다른 생성자를 호출한다. (ex: Test(){this(int a);)

(다만, 이럴때는 this 생성자가 제일 먼저 첫 줄에 와야하며 메소드안에서는 호출이 불가능하다.)

또한, this.멤버 변수 혹은 this.메소드명으로 인스턴스의 클래스만이 가진 멤버 변수 및 메소드를 끌어올수 있다.

즉, 첫번째는 생성자 안에서 다른 생성자를 호출할때 this()를 쓸수 있고 특정 상황에서 변수나 메서드가 서로 중복되서 구분을 해야할때 this.으로 이 클래스 자체 (인스턴스 객체 자체)의 멤버 변수 혹은 메서드를 구분해서 사용이 가능하다는것이다.

그럼 이 this는 어디서 주로 쓰냐면, 우리가 앞서 봤던 상속에서 마트 사례, 거기서 Customer 클래스에서 protected로 선언했던 customerID, customerName, customerGrade 멤버 변수들의 '값을 설정할때' setter 메소드를 사용했는데 그때 이 this 예약어를 사용했다.

아래 코드문을 다시 한번 보자:

public class Customer {
	protected int customerID;
	protected String customerName;
	protected String customerGrade;
	int bonusPoint;
	double bonusRatio;
    
    public int getCustomerID() {
		return CustomerID;
        }
        
	public void setCustomerID(int customerID) {
		this.customerID = customerID;
        }
        
	public String getCustomerName() {
		return CustomerName;
        }
        
	public void setCustomerName(String customerName) {
		this.customerName = customerName;
        }
        
	public String getCustomerGrade() {
		return CustomerGrade;
        }

	public void setCustomerGrade(String customerGrade) {
		this.customerGrade = customerGrade;
        }

이 구조가 바로 앞서 private 부분에서 설명했던 setter 메소드(setCustomerID(int customerID), setCustomerName(String customerName), setCustomerGrade(String customerGrade))와 getter 메소드 (getCustomerID(), getCustomerName(), getCustomerGrade())이며

setter 메소드에서는 this.클래스의 멤버변수 이름 = 메소드에 주어진 매개변수 이름으로 구성되어있음을 알 수 있다. 즉, 클래스 인스턴스 객체의 멤버변수 이름과 매개변수 이름이 동일하기에 이를 서로 구분하기 위해서 오른쪽 값에서 왼쪽 변수로 대입되는 = 식에서 왼쪽 변수 앞에 this.을 달아준것이다.

보통은 이렇게 this 예약어를 주로 쓰고 앞서 이야기한것처럼 this()를 통해 다른 생성자를 호출하거나 또 가끔은 this 자체를 반환하는 식을 만들어 메소드로 사용하기도 한다.

3. 싱글톤 패턴

이렇게 우리는 여기까지 해서 접근제어자와 this 예약어를 배웠다. 이것들과 우리가 앞선 장들에서 배웠던 걸 활용해서 자바에서 자주 쓰이는 코드 패턴인 싱글톤 패턴을 할수 있는데 한번 설명해보겠다.

싱글톤 패턴(singleton pattern)은 말그대로 싱글, 객체를 하나만 생성하여 그 객체를 계속 쓰게하는 코드 구조 패턴을 뜻한다.

이게 무슨 말이냐면 클래스의 객체를 생성할때 이미 그 객체가 있다면 원래 생성되어있었던 객체를 반환하고, 객체가 없다면 새로 객체를 딱 하나만 생성한다는것이다.

그렇다면 이렇게 해서 무슨 장점이 있냐면, 우리가 클래스를 만들고 객체를 생성해서 프로그램을 돌릴때 프로그램은 메모리에 올라간다. 그런데 컴퓨터 사양 및 프로그램 설정에 따라 메모리 용량이 정해져 있는데 이 용량을 넘어가도록 똑같은 내용의 객체가 쓸모없이 동시에 마구잡이로 생긴다면 최악의 경우 메모리 오버로 프로그램에 문제가 생길 가능성이 높다.

그래서 이런 경우 똑같은, 아예 동일한 내용으로 객체가 많은 곳에서 사용되어야 할 경우 추가 객체 생성을 제한하는 싱글톤 패턴으로 코드를 짜는것이 유효하다.

그런 싱글톤 패턴은 다음과 같은 규칙을 따라 만들어져야 한다:

  1. 디폴트 생성자를 private로 언급해야한다. (왜? 최초 객체 생성 이후 추가 객체 생성을 막아야 하기에
  1. 클래스 내부에 private + static으로 사용할 유일한 객체 미리 만들어 두어야 한다. (왜? 많은 곳에서 사용해야하면서 유일하게 하나여야만 하므로 private이면서 공유가 가능한 static으로 객체를 미리 만들어둬야 하기 때문에)
  1. 외부에서 접근 가능하도록 참조할수 있도록 하는 public static getter 메소드 만들어 두어야 한다. (왜? private으로 선언된 객체를 외부에서 따로 끌고 올수 있는 메소드가 하나 필요하기도 하고 또 이걸 static으로 선언해야 객체가 생성되어있지 않더라도 클래스명.메소드명으로 호출할수 있기 때문)

이런 모든 규칙을 종합해 만들어보면 아래 코드문과 같다:

class Singleton {

	private Singleton() {} // ① 디폴트 생성자를 private로 언급해야한다.

	private static Singleton s; // ② 클래스 내부에 private + static으로 사용할 유일한 객체 미리 만들어 두어야 한다.

	public static Singleton getS() { // ③ 외부에서 접근 가능하도록 참조할수 있도록 하는 public static getter 메소드 만들어 두어야 한다.

	if (s == null) 
		
		s = new Singleton();
	
	return s;

	}

}

이 상태에서 객체를 두개 만들고 각자 클래스 자료형의 다른 변수 (a와 b)에 담아서 이것이 같은지 구하는 식을 콘솔에 출력하는 방식으로 하면 (System.out.println(a==b);) true가 콘솔에 출력된다.

즉, 객체가 꼭 하나만 생성되어야 하고 이것을 많은 곳에서 사용하며 항상 동일하게 혹은 일정한 값을 지니는 패턴이 있다고 할때 그때 사용해야하는 코드 구조는 싱글톤 패턴을 써야한다는것이다.

이렇게 접근제어자,this 예약어, 싱글톤 패턴까지 나갔으니 다음장에서는 제네릭과 제네릭을 기반으로 작동하는, 자바에서 많이 쓰이는 프레임워크인 컬렉션 프레임워크 그리고 이너 클래스 inner class 및 람다식에 대해 설명하겠다.

0개의 댓글