ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 8. 자바 접근 제어자(Access Modifier)
    자바(Java) 강의 2019. 4. 1. 12:47

    지금가지 포스트를 따라오면서 class앞에 붙은 public이라는 키워드가 무엇인지 궁금했을 것이다. 이번 포스트에서는 public과 같이 어떤 클래스/인터페이스나 변수, 메서드 앞에 붙어서 해당 클래스/인터페이스/변수/메서드가 접근 될 수 있는 범위를 정해주는 접근 제한자(Access Modifier)에 대한 이야기를 하도록 하겠다.

    참고!

    인터페이스는 이후의 포스트에서 설명하도록 하겠다.

    이전 포스트

    목표

    • 접근 제어자(Access Modifier)
    • 프로젝트 구조
    • private
    • default
    • public
    • protected

    접근 제어자(Access Modifier)

    객체 지향 디자인/개발(Object Oriented Design/Development) 방법의 원칙 중에는 캡슐화(Encapsulation)이라는 항목이 있다. 캡슐화는 어떤 변수나 메서드의 접근(Access)을 최대한 제한하는 것이다. 다시말해 공개하면 안되는 클래스/변수/메서드등, 또 공개하지 않는 것이 좋은 클래스/변수/메서드등은 공개하지 않는 것이 캡슐화이다. 자바에서는 캡슐화를 지원하기 위해 접근 제어자(Access Modifier)라는 문법을 제공한다. 접근 제어자 키워드는 다음과 같은 private < protected < default  < public 오른쪽으로 갈 수록 접근될 수 있는 범위가 커진다.

    접근 제어자를 이용하면 보안의 취약점(Security Vulnerability)을 예방 할 수 있다. 여러분이 어떤 코드를 짜고 그 코드를 패키지로 만들어 배포한다고 해보자. 패키지가 제공하는 클래스들의 모든 변수와 메서드가 공개되어 있다면 여러분의 비즈니스 로직의 상당 부분이 공개되는 것과 다름 없다.

    또 어떤 클래스를 사용 할 때 그 클래스의 변수와 메서드를 꼭 다 알 필요는 없다(추상화). 이 클래스의 사용자는 이 클래스를 사용하기 위한 최소의 정보만 알면 된다. 만약 모든 변수와 메서드가 공개되어 있다면 다른 개발자가 해당 패키지를 사용하면서 수정하면 안되는 데이터(변수)를 수정 할 수 있다. 따라서 적절한 접근 제어자를 이용해 사용자에게 반드시 필요한 변수와 메서드만 공개하는 것이 좋다. 

    프로젝트 구조

    이 포스트를 실습하기 위한 기본적인 프로젝트의 구조는 다음과 같다.

    ./JavaTutorial
    ├── JavaTutorial.iml
    └── src
        ├── Cat.java
        ├── Main.java
        └── animal
            └── Dog.java
    
    2 directories, 4 files

    animal은 패키지이다.

    private

    private은 제어자가 붙은 변수와 메서드는 해당 클래스 내에서만 접근이 가능하다. 즉, priavate 접근 제어자의 공개 범위는 같은 클래스내이다. src에 Cat이라는 클래스를 만들고 String형의 변수인 name을 private으로 선언해보자.

    public class Cat {
        private String name;
    
        Cat(String catName) {
            name = catName;
        }
    
    }

    이제 이 클래스의 오브젝트를 main메서드에서 생성 해 보자.

    public class Main {
        public static void main(String[] args) {
            Cat cat = new Cat("Tommy");
            cat.name = "Sally";
        }
    }

    cat.name에서 에러가 날 것이다. 왜? name은 private으로 선언되었고, private으로 선언된 변수는 자기 자신의 클래스 내에서만 접근이 가능하기 때문이다. 메서드도 마찬가지이다. 이번엔 Cat아래에 private으로 메서드를 만들어 보자.

    public class Cat {
        private String name;
    
        Cat(String catName) {
            name = catName;
        }
    
        private void eat(int portion) {
            String behavior = name + "(이)는 " + portion + " 만큼의 밥을 먹었다.";
            System.out.println(behavior);
        }
    }

    eat 메서드를 main메서드에서 실행 해 보자. 메인 메서드에서 찾을 수 있는가? 없을 것이다. 이 메서드를 Cat의 생성자 안에서 부를 수 있는가?

    public class Cat {
        private String name;
    
        Cat(String catName) {
            name = catName;
            eat(10);
        }
    
        private void eat(int portion) {
            String behavior = name + "(이)는 " + portion + " 만큼의 밥을 먹었다.";
            System.out.println(behavior);
        }
    }

    이는 에러 없이 작동하는 것을 확인 할 수 있다.

    default

    default 접근 제어자는 우리가 지금까지 사용 해 왔던 접근 제어자이다. 아무 접근 제어자도 붙어있지 않는 경우가 바로 default인 경우이다. 지난 포스트에서 우리는 animal이라는 패키지에 Dog라는 클래스를 만들었다. 연습문제에서 Dog라는 클래스에 name, weight, gender, color변수를 만들었는데, 메인 메서드에서 이 변수들을 사용 할 수 없었다. 그 이유는 name, weight, gender, color변수는 default 접근 제어자로 선언되었기 때문이다. default접근 제어자는 같은 패키지 내에서만 사용 할 수 있다. 우리가 Cat클래스를 src아래 바로 만들었을 때는 이런 문제가 없었다. 같은 패키지 안에 존재하기 때문이다. Dog는 animal패키지에 Main은 src패키지 안에 존재하므로 메인 메서드에서 생성된 Dog 오브젝트의 변수에 접근 할 수 없다.

    default 접근 제어자는 클래스의 앞에도 사용 될 수 있다. 클래스의 앞에 아무 접근 제어자도 붙이지 않으면 해당 패키지 내에서만 이 클래스의 오브젝트를 생성/사용 할 수 있다.

    default 접근 제어자의 공개범위는 같은 패키지 내이다.

    Dog클래스로 실습을 해 보도록 하겠다. 이 클래스가 없는 독자들은 src아래에 animal패키지를 만든 후 animal 패키지 아래에 Dog 클래스를 생성하면 된다.

    package animal;
    
    class Dog {
        String name;
        int weight;
        String gender;
        String color;
    }

    animal 패키지 안에 있는 Dog 클래스의 public 키워드를 지워보자.

    public class Main {
        public static void main(String[] args) {
            Dog dog  = new Dog();
        }
    }

    위의 코드에 신택스 에러가 날 것이다. 이제 public을 다시 붙여보자. 이젠 에러가 나지 않을 것이다.

    public

    다른 패키지에서도 내 클래스의 변수나 메서드를 사용 할 수 있도록 하기 위해서는 public 접근 제어자를 사용하면 된다. public 접근 제어자의 공개 범위는 같은 프로젝트 내이다.

    package animal;
    
    public class Dog {
        public String name;
        public int weight;
        public String gender;
        public String color;
    }

    이제 메인 메서드에서 이 클래스의 오브젝트를 생성하고, 변수들에 접근 해 보자.

    import animal.Dog;
    
    public class Main {
        public static void main(String[] args) {
            Dog dog  = new Dog();
            dog.color = "오렌지";
            dog.gender = "수컷";
            dog.name = "톰";
            dog.weight = 5;
        }
    }

    위처럼 해당 오브젝트의 변수에 접근 할 수 있는 것을 확인 할 수 있다. 또한 public은 클래스에도 적용 할 수 있다. 그때문에 우리는 항상 class 앞에 public을 보았 던 것이다. public class의 뜻은 이 클래스는 다른 패키지에서도 선언 할 수 있다는 뜻이다.

    protected

    protected 접근 제어자의 범위를 알기 위해서는 추상 클래스와 상속을 알아야 한다. 이미 추상 클래스와 상속을 알고 있는 독자들을 위해 간단히 설명하자면 protected는 자기 자신과 자기를 상속하는 자식 클래스에게만 변수/메서드를 공개한다. 자세한 사항은 추상클래스와 상속을 다룰 때 같이 설명하도록 하겠다.

    이번 포스트를 통해서 접근 제어자에 대해 알아보았다. 객체 지향 프로그래밍(Object Oritented Programming)에서는 보통 클래스의 모든 변수를 private으로 선언하고 Getter/Setter 메서드를 이용해 private 변수들을 조작한다. 이에 대한 이야기는 객체 지향 프로그래밍 기법에서 더 자세하게 다루도록 하겠다. 

    다음 포스트: 9. 자바 static 변수 static 메서드

    댓글

f.software engineer @ All Right Reserved