개발/개발 일상

BeanCopy는 편한데 왜 불안할까? 실무에서 setter로 바꾸게 된 이유

댕주 2025. 3. 22. 23:44

BeanCopy, 처음엔 정말 편했는데 ..

서비스에서 DTO <-> Entity 변환을 할 때,

처음에는 BeanUtils.copyProperties(source, target) 같은 방식이 너무 편하게 느껴졌다.

코드도 짧고, 작성도 빠르고, 당장은 문제 없어 보였다.


하지만 점점 마음 한구석이 불편해진다?

처음엔 편했지만, 시간이 지날 수록 이런 문제가 생기기 시작했다.

  • 어떤 값이 복사되는지 명확하지 않다.
  • 필드를 추가/삭제해도 에러가 안 나서 눈치 못 채고 버그 발생
  • 디버깅할 때 이 값 왜 들어가 있지? 같은 현상도 발생

결국 복사되는 흐름이 코드에 드러나지 않다 보니,

읽는 나도 헷갈리는데, 나중에 유지보수하는 사람은 더 헷갈리지 않을까? 하는 생각을 하게됐다.


그래서 setter 방식으로

결국 명시적으로 하나하나 설정하는 방식으로 바꿨다.

OrderDto dto = new OrderDto();
dto.setOrderId(entity.getOrderId());
dto.setProductName(entity.getProductName());
// ... 나머지 필드들

이렇게 하면 무슨 값을 어디서 복사하는지 한눈에 보이고,

리팩토링이나 디버깅할 때도 훨씬 안정적이었다.


필드가 많아질 수록 장황해지는 코드 ...

setter 방식은 안전하지만,

  • 필드가 10개만 넘어가도 코드가 너무 길어지고
  • 수정할 부분이 많아져서 유지보수가 부담

코드가 "안전하긴 한데, 너무 보기 싫다"는 느낌이 들기 시작했다.

특히 팀원들이랑 협업할 땐 가독성도 중요하니까 고민이 더 깊어졌다.


그럼 어떻게 하는게 좋을까?

내가 내린 결론은 이거다:

  • 간단한 구조면 setter 직접 할당
  • 복잡한 구조면 ModelMapper, MapStruct 같은 라이브러리 고려
  • 아니면 toDto() / toEntity() 같은 매핑 전용 유틸 클래스를 따로 만들어서 관리
public OrderDto toDto(Order entity) {
    return new OrderDto(
        entity.getOrderId(),
        entity.getProductName(),
        ...
    );
}

이런 식으로 만들면 명시성과 유지보수성 둘 다 챙길 수 있다.


마무리

BeanCopy는 처음에 정말 편한 도구지만,

실무에서 "내가 뭘 하고 있는지 보이는 코드"가 훨씬 더 중요하다는 걸 깨달았다.

가끔은 "귀찮아도 명시적으로 작성하는 것"이

결국은 나중의 나를 도와주는 일이더라.