on
[Java] Setter 사용을 지양하자!!
[Java] Setter 사용을 지양하자!!
들어가며
안녕하십니까 백엔드 개발자 지망생 BLoo 입니다. 이번 시간에는 제가 Entity와 DTO등에 Setter를 지양하고 있는데 그 이유를 한 번 정리하고자 포스팅하게 되었습니다.
보통 자바 클래스는 자바빈 규약을 지키기 위해서 Getter/Setter를 명시하는 경우가 많습니다. 하지만 Setter를 무분별하게 사용하는 것은 문제가 발생할 여지가 있기 때문에 최근에는 Setter 사용을 지양하는 경우가 많습니다. 이제 그 이유를 자세히 알아보겠습니다.
1. Setter 메소드는 의도를 갖기 힘들다.
public Person updatePersonInfo(Long id, PersonUpdateDto updateDto) { final Person person = findById(id); person.setName(updateDto.getName); person.setAddress(updateDto.getAddress); person.setPhoneNumber(updateDto.getPhoneNumber); return person; }
위의 코드가 대표적인 Setter 사용 예시라고 할 수 있습니다. 위의 Setter만 보고 여기서 Setter가 어떤 의도를 가지고 사용되는지 명확히 알 수 있나요??? 보통은 No입니다. 그냥 값을 Setting 한다는 것만 알 수 있지 Person의 정보를 수정하기 위해 값을 다시 Setting 한다고 단번에 생각하기에는 힘듭니다.
따라서 도메인 클래스에서 회원정보 수정이라는 update 메소드를 만들어 내부 로직으로 사용하고 Service와 같은 다른 Layer에서 update 메소드를 호출하는 방식이 훨씬 가독성이 올라가고 어떤 행위를 하고자 하는지 의도를 파악하기 쉽습니다.
Refactoring Ex)
public class Person { private String name; private String address; private String phoneNumber; public void updatePersonInfo(PersonUpdateDto updateDto) { this.name = updateDto.getName; this.address = updateDto.getAddress; this.phoneNumber = updateDto.getPhoneNumber; } }
이렇게 해서 Service 단에서는 단순히 updatePersonInfo() 메서드를 호출하기만 하면 됩니다.
Service Ex)
public Person updatePersonInfo(Long id, PersonUpdateDto updateDto) { final Person person = findById(id); // update 메소드 호출로 명확히 의도를 들어내고 가독성을 높임 person.updatePersonInfo(updateDto); return person; }
2. 객체의 일관성을 유지하기 어렵다.
두 번째 이유는 객체의 일관성을 유지하기 어렵기 때문 입니다. 자바 빈 규약을 따르는 Setter는 public으로 어떤 곳에서도 접근이 가능합니다. 이렇게 되면 개발자도 결국엔 사람이기 때문에 의도치 않은 변경을 할 수도 있게 됩니다.
불변 값에 대해서는 final 키워드를 추가해서 Setter 사용을 막거나, Setter를 해당 필드에는 사용하지 않는 것으로 막을 수 있으나, Setter 사용을 지양하면 처음부터 이러한 걱정을 할 필요가 없기 때문에 실수가 줄어들어 개발의 생산성이 훨씬 높아진다고 필자는 생각합니다.
3. Builder 패턴을 사용하자
지금까지 Setter를 지양해야 하는 이유를 작성해보았습니다. 이렇게 되면 다음과 같은 의문이 생길 수 있습니다. setter를 사용하지 않는다면, 클래스의 멤버 변수가 많을 때 꽤나 불편합니다.
setter 없이 개발자의 입맛에 맞게 클래스를 생성하기 위해서는 필요한 생성자들을 여러번 오버 로딩해야 하는데 이렇게 되면 클래스의 가독성이 매우 떨어지며 유지보수성 또한 매우 떨어진다고 생각합니다.
따라서 이렇게 멤버변수가 많고 다양한 생성자를 가져야 하는 경우가 있다면 Builder 패턴을 도입해서 Setter를 지양하며 입맛에 맞는 여러 클래스를 생성할 수 있으며, 동시에 코드의 유지보수성도 높일 수 있습니다.
다양한 클래스를 생성하기 위해서 생성자 오버로딩을 많이 사용하는 케이스
public class Person { private String name; private String phoneNumber; private String address; private String hobby; public Person ( String name, String phoneNumber ) { this.name = name; this.phoneNumber = phoneNumber; } public Person ( String name, String phoneNumber, String address ) { this.name = name; this.phoneNumber = phoneNumber; this.address = address; } public Person ( String name, String phoneNumber, String address, String hobby ) { this.name = name; this.phoneNumber = phoneNumber; this.address = address; this.hobby = hobby; } }
Builder 패턴
public class Person { private String name; private String phoneNumber; private String address; private String hobby; @Builder public Person ( String name, String phoneNumber, String address, String hobby ) { this.name = name; this.phoneNumber = phoneNumber; this.address = address; this.hobby = hobby; } }
다양한 생성자들이 사라지고 전체 생성자 하나만을 가지고 있는 형태로 변경되어 유지보수 및 가독성이 매우 향상되었다.
마무리
이번 포스팅에서는 Setter를 지양해야 하는 이유와 Setter가 없을 때 어떻게 효율적으로 Class를 생성할 수 있는지 알아보았습니다.
여기서 Builder가 무슨 의미인지 잘모르는 분들이 있을 것이라 생각하기 때문에 다음에는 Builder 패턴에 대해서 포스팅하도록 하겠습니다.
from http://bloowhale.tistory.com/97 by ccl(A) rewrite - 2021-09-22 11:27:49