Spring Api역할 분리에대해

2023. 11. 8. 10:03카테고리 없음

지난주에 아프기도해서 오랜만에 til을 작성하게 되버렸다. 얼른 진도를 따라가야지 영차...

 

API역할 분리

 

 

지난 주차에 만들었던 메모장 프로그렘의 가장큰 문제점은 모든 API가 단 한개의 class(Controller) 부분에서

구현되어 사용되고있다는 것이다!

이전 Java를 배울때 역시 기능분리야말로 현대 개발 환경에서 가장 중요한 요소중 하나일것이다.

좀더 다양한 기능이 추가되서 API수가 증가한다면 아마 코드를 직접 써내려간 나역시도 못알아보기 쉽상이니까.

특히 이전프로젝트에서 몇일 지나니까 이걸 왜 이렇게했지 저건 뭐였지... 찾게 되더라.

 

 

 

Spring의 3 Layer Architecture

 

Three Tier Architecture

 

지금 내 프로젝트에는 이들중 단 한개 Controller Classes밖에 없다.

이제 컨트롤러에 있는 API들을 기능에 따라서 Controller, Service, Repository Class로 옮겨주는 작업을 해야한다.

 

그럼 어떤 기준으로 각 API를 옮겨야되는거지?? 라는 의문이 이 시점에 들었다.

그건 생각보다 단순히 컨트롤러는 지금과 같이 주저리 기능이 구현되어있는 Class가 아니라, 클라이언트와 서비스의 요청에 따라서 단순히 데이터와 요청을 넘기는 기능만을 하면 되는것이다.

public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
        // 해당 메모가 DB에 존재하는지 확인
        Memo memo = findById(id);
        if(memo != null) {
            // memo 내용 수정
            String sql = "UPDATE memo SET username = ?, contents = ? WHERE id = ?";
            jdbcTemplate.update(sql, requestDto.getUsername(), requestDto.getContents(), id);

            return id;
        } else {
            throw new IllegalArgumentException("선택한 메모는 존재하지 않습니다.");
        }
    }

 

현재 이 Controller Class의 updateMemo api에서는 컨트롤러기능만을 하는게아닌 Service가 담당해야할 업데이트 기능까지 주먹구구식으로 구현이되어있다. 이걸 분리해주기 위해서 우리는 다음과 같이 할 수있다.

public Long updateMemo(Long id, MemoRequestDto requestDto) {
        MemoRepository memoRepository=new MemoRepository(jdbcTemplate);
        // 해당 메모가 DB에 존재하는지 확인
        Memo memo = memoRepository.findById(id);
        if(memo != null) {
            // memo 내용 수정
            memoRepository.update(id,requestDto);
            return id;
        } else {
            throw new IllegalArgumentException("선택한 메모는 존재하지 않습니다.");
        }
    }

 

두가지 큰변화가 발생했다.

 

1. Repository 기능분리

Memo memo = findById(id);

 

가 사라진거다.

findByID 함수는 당연하게도 데이터베이스에서 ID로 정보를 검색해서 존재할 경우 객체를 전달하는 기능을 한다.

근데 위 기능은 Contoller나 Service 어느쪽도 아닌 Repository에서 가져야할 기능이다.

Repository에서는 DB에대한 관리 및 CRUD기능을 가지고 있어야한다.

 

새 updateMemo에서는 분리된 Repository 객체를 생성해 findByID 메서드를 호출하고 있다. 

 

2. Controller의 기능구현 Service로 분리

 

여기서는 별로 해준게 없다!

왜냐면 그냥 Controller에 구현되어있는 기능을 Service로 분리만 해준것이기 때문이다.

 

대신 우리는 Controller에서 이제 Service로의 요청을 확인할수있다.

@PutMapping("/memos/{id}")
public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
    MemoService memoService = new MemoService(jdbcTemplate);
    return memoService.updateMemo(id,requestDto);
}

 

이제 Controller에는 깔끔하게 기능 구현이아닌 Service로의 요청만을 데이터와함께 Return 주는 모습을 볼수있다.

마치며...

 

처음 Java를 공부할때도 그랬지만 당시에도 각 객체를 분리하고 상속하고 어쩌구 저쩌구 기능의 분리만큼 어려운게 없는거같다. 하지만 하고나면 훨씬 코드를 유지보수하기도 쉽고, 만약 협업을 진행한다면 내 코드를 전혀 알아보지 못하는 일은 생기지 않을것이다.