2. 3 계층 스프링 부트 애플리케이션 2 by happyprogfrog · Pull Request #3 · happyprogfrog/mallang
작업 내용 새로운 요구사항 구현 데이터 모델 생성, 엔티티 구현 리포지토리를 만들어 데이터 저장 특정 사용자의 최근 5개의 답안을 조회하여 제공하는 작업 진행 새로운 엔드포인트 노출 js 파
github.com
사용자 스토리 2
최근에 제출한 답안을 보고 싶어요! 그러면 시간이 지나면서 제 두뇌가 얼마나 말랑해졌는지 알 수 있겠죠?
요구사항을 보니, 사용자의 답안을 유지하기 위한 데이터 스토리지가 필요함을 알 수 있다. 다음 단계에 따라 요구사항을 달성해 보자!
- MultiplicationResultAttempt 클래스의 인스턴스를 모두 저장한다. 그렇게 하면 나중에 추출해서 사용할 수 있다.
- 특정 사용자의 최근 답안을 가져오는 새로운 REST 엔드포인트를 만든다.
- 답안을 검색하는 새로운 서비스(비즈니스 로직)를 만든다.
- 사용자가 답안을 제출하면 답안 내역을 보여주는 웹 페이지를 만든다.
이 사용자 스토리는 우리 코드에 다른 방식으로 영향을 미친다. 지금은 사용자가 제출한 답안을 바로 채점하기 때문에 MultiplicationResultAttempt 클래스가 채점 결과를 나타내는 플래그를 따로 가지고 있지 않다. 기존에는 요구사항에 대처하기 충분했지만 지금은 아니다! 리팩터링 작업을 정리해 보자.
- 사용자가 제출한 답안(MultiplicationResultAttempt)에 정답인지 오답인지를 나타내는 boolean 값을 추가한다. 클래스에 값을 담았다가 나중에 데이터베이스에 저장한다.
- 서비스(MultiplicationServiceImpl)에서는 해당 결과를 바로 반환하는 대신 답안 내에 저장해야 한다.
- 클라이언트가 답안을 채점해서는 안된다! 따라서 해당 필드는 REST API에서 읽는 대신 내부적으로 계산한다.
- 새로운 환경을 반영하기 위해 테스트를 수정해야 한다.
그럼 리팩터링과 데이터 저장 작업으로 나눠서 진행해 보자.
리팩터링
답안에 boolean 값을 저장하며 로직 및 테스트 코드 수정
데이터 저장 작업
사용자가 곱셈 문제를 풀어 답안을 제출했을 때 개체들은 각 테이블에서 다음과 같이 보인다.
users 테이블
user_id | alias |
123 | Flog |
multiplication 테이블
multiplication_id | factor_a | factor_b |
8 | 41 | 54 |
multiplication_result_attempt 테이블
id | correct | result_attempt | multiplication_id | user_id |
11 | true | 2214 | 8 | 123 |
사용자 스토리 2 완성하기: 레이어 연결
특정 사용자의 최근 5개의 답안을 조회하여 제공하는 REST API 엔드포인트를 만들기 위해 MultiplicationResultAttemptRepository에 작업한 findTop5ByUserAliasOrderByIdDesc() 메서드를 호출하는 서비스 로직을 작성, 테스트 코드 수정 후 컨트롤러 작업 진행. 이 REST API를 호출하고 결과를 화면에 출력하도록 수정하기 위해 js 파일과 뷰 파일에 코드 추가.
+ 같은 곱셈 문제가 있더라도 새로운 것처럼 저장하는 문제 수정
+ 사용자가 이미 푼 문제라면 예외를 발생시키도록 했으나, 같은 문제를 또 푸는 것이 가능하도록 관련 로직은 작업했지만 삭제
참고) 리포지토리는 스프링에서 제공하는 코드이므로 따로 단위 테스트를 작성하지 않는다.
정리
- 이후 여러 애플리케이션으로 분산된 기능을 배울 때 이 애플리케이션은 하나의 마이크로서비스가 된다.
- 테스트 주도 개발은 코드를 작성하기 전에 유스 케이스와 단위 테스트를 먼저 작성한다. 이런 접근 방식에 익숙해진다면, 장점이 꽤 많은 데 그중 하나는 기능 요구사항의 정의를 개선하는 일이다.
- 도메인, 애플리케이션, 프레젠테이션 및 데이터로 계층화하는 3단계 계층 설계는 책임을 명확히 분리하고 결합도를 낮추는 방법으로 잘 알려진 패턴이다.
- 그럼 애플리케이션을 확장할 때 어떻게 다른 인스턴스를 찾아 연결할 수 있을까? 다음장부터 마이크로서비스를 시작해 보자!