침범된 Layered architecher

웹 자동차 경주 미션을 진행하면서 웹 컨트롤러를 작성했다.

웹 컨트롤러는 자동차의 이름을 입력받고, 게임 진행을 위한 서비스를 초기화하고, 게임을 진행한다.

@PostMapping("/plays")  
@ResponseBody  
public ResponseEntity<ResultResponseDto> play(@RequestBody RacingGameRequestDto racingGameRequestDto) {  
    List<String> names = Arrays.stream(racingGameRequestDto.getNames().split(","))  
            .map(String::trim)  
            .collect(Collectors.toList());  // 이름 입력

    RacingCarService racingCarService = new RacingCarService(  
            Cars.of(names),  
            new RandomNumberGenerator(),  
            new RacingCarRepository(new RacingCarGameDao(jdbcTemplate))  
    );  // 서비스 초기화
    racingCarService.play(racingGameRequestDto.getCount()); // 게임 진행
    ...
}

컨트롤러에서 도메인 객체인 Cars 를 생성해서 서비스를 생성하고 있다. 보통은 서비스를 빈으로 등록하여 컨테이너에서 관리하도록 하는데, 지금의 방식은 비즈니스 로직에 집중하기 어렵다. 그럼 어떤 구조로 만들어야 할까?

WebController는 Layered architecher 상에서 프레젠테이션 레이어에 속한다. 요청에 따라 서비스를 이용하여 적절한 응답을 반환해준다. 어떤 도메인 객체를 사용하는지 WebController 가 알게된다면 서비스레이어가 어떤 구조로 작동하는지 안다는 것이다.

이렇게 레이어를 침범한 구조이기 때문에 원하는 방식으로 Cars직접 생성해서 Service에 직접 주입해줄 수 밖에 없는 구조가 되어버렸다. 따라서 IoC 컨테이너가 의존성을 자동으로 주입해줄 수 없게 되어버렸다.

각 Layer의 역할이 무엇인지 영역을 침범하지 않았는지 고민하면서 다시 리팩토링을 진행해서 IoC컨테이너가 의존성을 알아서 컨트롤하도록 리팩토링 하는 것이 목표다.

DAO와 Repository

DAO나 Repository나 현업에서는 비슷하게 사용한다는 얘기를 들었다. (굳이 구분하지 않는다고 한다.)

dao는 db를 통해 데이터를 가져오고자 하는 목적이다.
db로부터 가져오겠다는 것을 숨기지 않기 때문에 영속적을 보장하겠다는 것이다.

Repository는 도메인을 가져오고자 하는 목적이다.
dao의 추상적인 개념이다 라고 하기도 하는데 잘 와닿지가 않는다.
Repository는 도메인만 가져오면 되기 때문에 Repository.get() 과 같이 도메인을 가져와 주면 되고, 내부적으로 dao를 사용해서 도메인을 반환해주든, 식별자 맵을 통해서 반환해주든, 다른 datasource를 사용해서 반환해주든 상관 없는 것이다. 이러한 특성때문에 영속성을 보장하지 않는다고 한다.
그저 도메인을 add,get과 같이 저장하고 꺼내기 때문에 객체의 컬렉션이라고 부르기도 한다.

식별자 맵

DB에 접근하는 비용은 비싸기 때문에 한 번 꺼낸 데이터는 식별자 맵에 저장해놓고 같은 요청이 들어왔을 때 이를 반환해줄 수 있다.

'회고 > 우아한테크코스' 카테고리의 다른 글

2023.04.18 일일 회고  (0) 2023.04.19
2023.04.17 일일 회고  (0) 2023.04.18
2023.04.12 일일 회고  (0) 2023.04.13
2023.04.11 일일 회고  (0) 2023.04.12
[레벨 1] 체스 미션 회고  (0) 2023.04.10

+ Recent posts