DTO 분리

Su hwan Choi·2022년 10월 31일
0

DTO와 모델 구분에 관해 다시한번 생각해본다.

무엇이 문제였나?

Controller, Service, Persistent 레이어에서 모두 참조하는 Dto 클래스

  • 참조하는 영역의 변경속도가 달라서 영역간 사이드 이펙트가 발생할 수 있다.

해당 프로젝트가 정확히 3개 영역으로 나눈것은 아니고, 3개의 영역으로 나누는게 정답이라는것도 아니지만, 설명을 위해 3개 영역으로 나눈것으로 하겠다.

모든 코드의 구조가 아래와 같지는 않았지만, 상당히 많은 곳에서 아래와 같은 구조를 쓰고 있었다.

public class StudentDto
{
    private Long id;
    private String name;
}

@RestController
public class ExampleController
{
    @Autowired
    private final ExampleService exampleService;

    @PostMapping
	  public void saveStudent(StudentDto student)
    {
        //...
        exampleService.save(student);
        //...
    }
}

@Service
public class ExampleService
{
    private final ExampleMapper exampleMapper;

    @Transactional
    public void saveStudent(StudentDto studentDto)
    {
        //...
        exampleMapper.save(studentDto);
        //...
    }
}

@Mapper
public interface ExampleMapper
{
    public void save(StudentDto student);
}

당시 대부분의 기능들이 단순 CRUD 수준이었고, 프로젝트 초반이라 화면구성이 복잡하지 않고 비교적 단순해서 가능했다고 생각한다.
물론 시간이 갈수록 위와같은 구조는 제거되었다.

당연한 말이지만 이런 구조는 좋지 않다.
다들 아는 내용이지만 기록을 위해 내 생각을 적어보자면
시간이 갈수록 코드수정이 어려워진다.
코드를 만들때는 좋다. 클래스 수도 많이 없고, 동작도 이상없이 잘 된다. 개발도 아주 빠르게 진행될 것이다.

문제는 세 영역의 변경 속도가 다르다 는데 있다.

  • Controller영역은 화면과 관계있는 부분이라 자주 바뀐다. 오늘 만들어진 텍스트박스가 내일은 라디오버튼일수 있다.
  • Persistent 영역은 DB와 관계있는 부분이라 거의 안바뀐다. 테이블의 컬럼명이나 컬럼속성은 거의 바뀔일이 없다.
  • Service 영역은 요구사항에 따라 빈도수가 달라진다.

위와 같은 구조라면 같은 클래스를 사용하기 때문에 한곳에서 변경될 경우, 문제가 다른곳에서 발생할 여지가 있다.

다른 영역에 참조가 되면 수정은 더 어려워진다.

구체클래스(추상이나 인터페이스가아닌)에다가 DTO 를 참조하는 댓가를 치뤄야 한다.(물론 대부분은 참조하려는 쪽에서 문제를 제기하고 구조변경에 들어갈 것이다)

그렇게 되면 결국 수정을 덜하거나, 최대한 수정을 안하는 쪽으로 개발이 진행될 가능성이 있다.(물론 대부분은 여기까지 오지 않고 대부분 구조변경으로 해결된다.)
테스트코드가 있더라도 처음에는 있었는데 주석처리되거나, 동작을 안하거나, 무의미하거나 셋중 하나가 될 가능성이 있다.

그래도 어떻게든 개발은 된다. 역설적으로 그래서 더 좋지않다.

비슷한 속성의 클래스들

  • 클래스 파일이 줄어드는 것은 좋지만, 클래스가 늘어나는것을 인지하지 못할 수 있다.

dto를 inner static 클래스를 사용하면서 나온 현상이었다.
본문에 들어가기 전에 하고 싶은 얘기는 inner static class 로 dto를 관리하는게 잘못됬다는 것이 아니라.
내가 경험한 프로젝트에서 inner static class 로 하더라도 프로젝트 규모가 커지면서 발생했던 내 경험을 얘기하는데 있다.

Student 를 각각 저장, 삭제, 검색 3가지 API 가 있고 각각 dto를 만든다고 하면
일반적으로 3개의 dto를 만든다고 할 수 있다.
물론 API 구성에 따라 pathvariable을 쓰는 식으로 dto를 안만들수도 있지만
요점은 클래스가 많아진다는 것이다.

//StudentSaveDto.java
public class StudentSaveDto
{
    private Long id;
    private String name;
}

//StudentDeleteDto.java
public class StudentDeleteDto
{
    private Long id;
    private String name;
}

//StudentSearchDto.java
public class StudentSearchDto
{
    private Long id;
    private String name;
}

그래서 나온 방안이 java 파일은 하나만 만들되, inner static class 로 dto를 작성하자는 것이었다.
예를들면..

public class Student
{
    public static class StudentSaveDto
    {
        private Long id;
        private String name;
    }

    public static class StudentDeleteDto
    {
        private Long id;
        private String name;
    }

    public static class StudentSearchDto
    {
        private Long id;
        private String name;
    }
}

위와 inner static class 를 사용하면 class파일은 하나지만 class 는 여러개 사용할 수 있다.
class파일의 이름과 inner static class 이름을 조합해서 좀더 상세히 쓰는것이 가능하다.

처음에는 좋았는데, 문제는 시간이 가면서 참여하는 개발자가 늘어나면서 발생했다.

클래스의 속성은 같은데, inner static class로 다른 파일에 만들어지거나, 더이상 반대로 사용되지 않아서 지워야 하지만 그렇지 않고 계속 남아있는 클래스들이 생기기 시작했다.

클래스는 늘어났지만, 파일이 늘어나지 않기 때문에 그 변화를 알기 어려웠다.

그리고 파일이 하나로 되면서 소스수정시 충돌도 생각보다 자주 일어났다.

사실 이 문제의 원인은 위에도 적었듯이 inner static class 문제가 아니라. 이런 문제를 코드리뷰로 잡아내지 못했다고 볼수도 있다.

내 생각은 inner static class 로 DTO를 설정하는 방식은 모든 영역에 일괄적으로 하는 것이 아닌. DTO 가 몇개 없다고 판단될때 하면 좋은 방식이라고 생각한다.

그래서 우선 위 내용을 팀원들에게 공유하고 하나씩 해체하는 작업을 하면서 불필요한 DTO를 제거 했다.

변경후에 무엇이 좋아졌는가?

미사용 코드 제거

간혹 프로젝트를 진행하다보면 코드를 주석처리하고(아마 대부분 지우기 아까워서) 넘어가는 경우가 종종 있다. 프로젝트가 개발되는 과정에서 클래스가 사용되지 않는 경우가 많지 않지만 미사용 클래스는 나올때마다 제거해주는 것이 좋다.

FE변경으로부터 코드변경 자유로움

위에도 써놨지만 UI 변경으로 API 상세를 변경할때 관련된 코드만 변경하는것에 장점이 있다.

주의점

변경되는 코딩컨벤션의 관리

위와 같은 변경점은 일관성을 위해 다른 개발자도 숙지해야 하는데, 그 방법을 어떻게 할지가 어렵다. 가장 최악의 방법은 다른 개발자가 만든 클래스 도 모두 수정하고, 후에 알리는 것이다.

특히 이번 이슈처럼 어찌보면 '당연히 수정해야 하는 문제'더라도 임의로 진행하면 안된다.
만약 강제로 변경할 경우, 내 주장을 일방적으로 강요하는 꼴이 된다.

그렇다고 팀원들과 충분한 얘기 없이 규칙을 만들고 강제로 변경하게 할경우, 기계적으로 규칙을 실행만 할뿐 그 규칙을 만든 목적을 고려하지 않기 때문에 응용하거나 주의해야되는 상황을 인지하지 못한다.

모든 규칙을 팀내의 위키페이지에 적어가면서 진행하는것도 바람직 하지 않다. 경험상 텍스트로 적은 규칙이 디테일하고 자세할수록 추적 변경이 어렵고, 시간이 지나면 작성자도 이해하기 어려운 경우가 많다. 그리고 처음 문서를 보는 사람들을 위해서도 좋지 않다.

이것에 관한 개인적인 생각은, 정답은 없고 중간에 합류하는 사람 들을 대상으로 하는 수준의 내용으로 적되, 변경되지 않을만한 내용과 어떤 이유로 이런규칙을 만들었는지 를 포함하고, 코드리뷰때 자주 인용하는것이 바람직하다고 본다.

0개의 댓글