728x90

목차

     

    서론

    인프런에서 김영한님의 JPA 강의를 수강하는 중에 "Setter 사용을 지양해야 한다"는 말을 하였다. 이유가 궁금하여 검색하였더니 구글님께서 Getter도 사용을 지양해야 한다고 하는 것이다. Getter, Setter 학습은 객체를 작성할 때 필수로 입력하고 시작한 나의 지난 날을 반성하는 시간이 되었다...

     

    Getter와 Setter 사용을 지양해야 하는 이유 그리고 대안

    Java를 배우면 객체도 배우게 된다. 객체는 그만큼 중요하다는 것이기 때문에 모르시는 분들은 학습하고 읽기를 권장한다.

     

    "정보 은닉이 무색해진다."

    객체의 대표적인 특징중 캡슐화가 있는데 캡슐화의 목적은 외부로 부터 내부를 감싸 숨겨 은닉하는 것에 있다. 즉 '정보 은닉'을 말하는 것이다. Java에서는 protected, private, public 등 접근 제어자를 통해 구현 가능하다.

    Person 클래스를 통해 예시를 보자.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    public class Person {
        
        private String name;
        private Long age;
        private String grade;
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
     
        public Long getAge() {
            return age;
        }
        public void setAge(Long age) {
            this.age= age;
        }
     
        public String getGrade() {
            return grade;
        }
        public void setGrade(String grade) {
            this.grade= grade;
        }
    }
    cs
     

    객체(Person)에서 이름(name)과 나이(age)는 접근 제어자(private)를 통해 외부에서 필드에 직접 접근할 수 없게 정보 은닉되어 있다. 하지만 Getter와 Setter는 public이기 때문에 사용하게 된다면 private으로 선언한 것이 무색하게 외부에서 접근이 가능해진다.

     

    객체 지향 프로그래밍의 장점은 외부에서 객체의 세부 정보에 접근 없이 요청으로 동작하는 것이다. 반면에 객체의 세부 정보를 조회하고 변경하여 비즈니스 로직을 구현한다면 그것이 객체 지향이라고 볼 수 있을까?

     

    " 값을 조회하거나 변경하는 목적을 알 수 없다. "

    하나의 Person 객체의 나이를 조회하거나 변경하기 위해 Getter와 Setter는 getAge(), setAge() 메서드를 사용할 수 있다. 하지만 무슨 목적인지 메서드 이름만으로는 유추조차 할 수 없다.

     

    목적을 분명하게 할 수 있는 '인스턴스 메서드' 혹은 '정적 팩토리 메서드 패턴'을 사용해야한다.(포스팅 예정)

     

    "비즈니스 로직이 복잡해진다."

    다음 예제 코드는 나이대 기준에 따라 명칭을 출력하는 로직이다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    @Service
    public class YouthStandardByAgeService {
        ...
        public void AgeGradeCalculation(long id) {
            Person person = ageGradeCalRepository.findById(id).orElseThrow();
            long age = person.getAge();
     
            String grade = "";
            if (age < 20) {
                grade = "미성년자";
            } 
            else if (20 <= age < 70) {
                grade = "성인";
            } 
            else if (70 <= age) {
                grade = "노인";
            }
     
            System.out.println(grade);
        }
        ...
    }
    cs
     

    간단한 예시기 때문에 단순해보이지만 실무에서 Service 로직은 더 복잡하다. Getter, Setter를 사용하지 않는 다면 비즈니스 로직은 훨씬 단순해진다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    public class Person {
        
        private String name;
        private Long age;
        
        // 인스턴스 메서드
        public String ageGradeCalculation() {
            if (age < 20) {
                return "미성년자";
            } 
            else if (20 <= age < 70) {
                return "성인";
            } 
            else if (70 <= age) {
                return "노인";
            } 
        }
    }
     
    @Service
    public class YouthStandardByAgeService {
        ...
        // 비즈니스 로직
        public void ageGradeCalculation(long id) {
            Person person = ageGradeCalRepository.findById(id).orElseThrow();
            System.out.println(person.ageGradeCalculation());
        }
        ...
    }
    cs

     

    결론

    객체를 모든 경우에 사용하지 않아야 하는 것은 아니다. DTO와 같이 데이터를 주고 받는 것에 목적이 있는 객체는 Getter, Setter를 사용해야 된다.

     

    결론은 Getter, Setter 사용은 지양하고 대안이 되는 '인스턴스 메서드' 또는 '정적 팩토리 메서드'를 사용해야 한다. 두 가지에 대해서는 더 깊이있게 학습한 후 포스팅해보겠다.

    728x90
    TOP