인프런 커뮤니티 질문&답변

lect님의 프로필 이미지
lect

작성한 질문수

객체 지향 프로그래밍 입문

캡슐화 예제

캡슐화 예제 질문드립니다

작성

·

445

0

안녕하세요

Member, Rental, Movie 등의 클래스에서 캡슐화하는 방법에 대해서 말씀해주셨는데

이것은 VO(불변) 나 entity 클래스의 경우에만 가능한건가요?

 

JPA 환경이 아닌 mybatis 를 사용하면 많은 경우 단순 setter, getter 형태의 dto 만을 사용하여

개발을 진행하게 되는데 이런 경우 dto 에 getFrequentRenterPoints() 와 같은 메소드를 만들어서 사용하는 것은 별로 좋지 않은 방법일까요?

dto 는 단순 setter, getter 외에는 로직이 들어가서는 안된다라는 글을 어디선가 본 것 같아서요

 

답변 4

1

최범균님의 프로필 이미지
최범균
지식공유자

DTO(Data Transfer Object)는 뒤에 Object라는 단어가 붙어서 객체라고 혼동할 수 있지만 객체가 아니라 데이터만 갖고 있는 값입니다. 이름 그대로 데이터를 이곳에서 저곳으로 보낼 때 사용합니다. 그래서 DTO는 주로 데이터 접근에 필요한 메서드만(getter, setter) 제공하게 됩니다.

DTO에 대표적인 예가 스프링의 커맨드(모델) 객체 일겁니다. 커맨드 객체라고 부르긴 하지만 실제로는 커맨드 데이터이고, 이 커맨드 객체는 브라우저나 클라이언트가 전송한 데이터를 담게 되죠.

DTO에 기능을 캡슐화해서 넣기 시작하면 객체의 특징을 보이게 되죠. Member를 MyBatis를 이용해서 조회했더라도 단순히 getter만 존재하면 데이터에 가깝고, changePassword()나 updateAddress() 같은 메서드(기능)을 제공하면 객체에 가깝게 되는 거죠.

 

0

lect님의 프로필 이미지
lect
질문자

답변 감사드립니다 많은 도움이 되었습니다

좋은 강의도 감사합니다^^

0

최범균님의 프로필 이미지
최범균
지식공유자

먼저 JPA에서 Entity가 "setter가 없기 때문에 객체의 값이 변하는 경우가 없다"는 것은 잘못된 내용입니다. 함수형 프로그래밍을 하지 않는 이상 엔티티는 값(상태)을 변경하는 기능(메서드)을 제공하죠. 캡슐화를 하지 않으면 setter로 엔티티의 값을 변경할 거고 캡슐화를 하면 알맞은 메서드를 이용해서 값을 변경할 겁니다.

DTO/VO에 isEmailVerified()와 같은 메서드를 만들어도 무방합니다.

DTO나 VO는 가능한 값이 바뀌지 않도록 구현하는 것을 선호합니다. 즉 값을 바꾸는 setter나 다른 메서드를 제거하는 것을 선호합니다. 물론, 사용하는 기술의 요구 때문에 setter 메서드가 필요하면 어쩔 수 없지만요. DTO나 VO의 값을 변경해야 하는 상황이 발생하기도 하는데, 이런 경우에도 최대한 DTO/VO 객체를 실제로 사용하기 전에 변경을 하도록 구현합니다.

(함수형 프로그래밍을 사용하지 않는 상황에서) 엔티티는 자연스럽게 상태가 바뀝니다. 예를 들어 아래 코드를 보시죠. member.isEmailVerified() 결과는 인증 기능 실행 전과 후에 달라질 수 있죠.

member.isEmailVerified(); // false
member.verifyEmail(); // 이메일 인증 기능
member.isEmailVerified(); // true

객체의 주 역할은 기능을 제공하는 것이기에 단순 데이터 구조에 기능을 넣게 되면 객체가 된다고 볼 수 있습니다.

 

0

lect님의 프로필 이미지
lect
질문자

캡슐화 예제 중에 

 

if(mem.getVerificationEmailStatus() != 2) {

    return AuthResult.NO_EMAIL_VERIFIED;

}

 

위의 코드를 아래와 같이 바꾸는 예제가 있습니다

 

if(!mem.isEmailVerified()) {

    return AuthResult.NO_EMAIL_VERIFIED;

}

 

vo와 jpa의 entity 같은 경우 한번 값이 세팅이 되면  setter가 없기때문에 그 객체의 값이 변하는 경우가 없다고 알고 있습니다 (맞는 개념인지 확실히 모르겠습니다)

 

그런데 vo, entity 를 쓰지 않고 단순 setter, getter 로 구성된 dto 를 이용하여 모든 레이어에서 사용하는 그런 형태의 개발환경에서

 

dto 에 isEmailVerified() 와 같은 메소드를 만들어서 캡슐화를 하는 것도 괜찮은 것인지 질문을 드렸습니다

 

이런 생각이 든 이유는 vo, entity 같은 경우는 값이 변하지 않지만

 

dto 같은 경우 아래와 같이 검증을 한번 한 후에 setter 를 이용해서 값을 바꿔버릴 수가 있고 다시 mem.isEmailVerified() 를 호출했을때

 

결과에 대한 일관성이 깨질수도(?) 있다는 느낌을 받았습니다 물론 이것은 당연한 결과이고 값을 바꾸지 않으면 될 문제인 것 같기도 합니다

 

하지만 그럴 소지가 있는 환경 혹은 클래스에도 이런 것들을 적용해도 무방한 것인가 라는 생각이 들었고 질문을 드리게 되었습니다

 

if(!mem.isEmailVerified()) {  //return true

    return AuthResult.NO_EMAIL_VERIFIED;

}

 

mem.setVerificationEmailStatus(3);

 

if(!mem.isEmailVerified()) {  //return false

    return AuthResult.NO_EMAIL_VERIFIED;

}

 

이런 리팩토링 관련 강의를 듣다보면 이런것들을 적용할 수 있는 환경(jpa 를 사용하는 프로젝트) 혹은 클래스(setter 가 없는 불변성 클래스) 여야만 하는가?

라는 질문이 머리속에 있었는데

최범균님께서 달아주신 답변을 보면 dto, vo, entity, 불변, jpa , setter/getter 여부 등과 관계없이 사용해도 상관이 없으며

오히려 사용하면 단순 dto (수업 중 구조체에 가깝다고 말씀하신) 에서 진정한 객체에 되려 가깝게 되는 것이다 라는 의미로 해석되는데 맞는 것인지 궁금합니다

 

처음 질문 드린 내용과 중복된 내용이지만 질문을 자세하게 말씀드리지 못한 것 같아 다시 질문을 드리게 되었습니다

이미 좋은 답변을 해주셨지만 번거로우시더라도 한번 더 말씀해주시면 정말 많은 도움이 될 것 같습니다

 

좋은 강의 감사드립니다

lect님의 프로필 이미지
lect

작성한 질문수

질문하기