[MSA스터디] 3. 3계층 스프링부트 애플리케이션

vector13·2022년 9월 13일
0

chap 3. 3계층 스프링부트 애플리케이션

🎠1. 3계층 구조

3계층 구조 :

  • 클라이언트 계층
  • 애플리케이션 계층
    - 비즈니스 레이어
    - 프레젠테이션 레이어
    - 데이터 레이어
  • 데이터 저장 계층
  • 애플리케이션 계층

위 그림의 소프트웨어 아키텍처는 레이어 분리, 결합도를 낮춘다.
장점 : 도메인과 솔루션이 분리되어있음 + presentation과 data layer는 다른 layer로 교체 가능 + 각 layer의 역할이 명확히 구분된다.

@SpringBootTest 작은 테스트에서 남용 X 🎃
: SpringRunner는 애플리케이션 컨텍스트 초기화하고 필요 객체 주입한다. 지금처럼 '단순히 클래스 하나의 기능 테스트'를 위해서라면 종속성 주입이나 애플리케이션 컨텍스트 불필요. @SpringBootTest 없이 그냥 클래스 구현체 테스트 하는 게 나음. (b/c 자원과 시간 낭비, 트랝잭션 롤백과 부작용 발생하지 않도록 스프링 컨텍스트 정리 필요)
그러면 언제 사용? 여러 클래스 간 상호작용 확인하는 통합 테스트에서 사용

위 사항을 참고해서 단위 테스트 클래스들을 만든다.

오늘 사용한 코드는 저자의 깃허브 v2에서 사용한 코드와 동일함
https://github.com/wikibook/springboot-microservices/tree/master/microservices-v2/social-multiplication

🎍2. 도메인 설계

시스템에서 식별할 수 있는 다양한 개체와 개체 간의 관계를 명확하게 파악하는 것이 중요

이 프로젝트의 비즈니스 로직에서 사용하는 객체를 요구사항에 따라 다음과 같이 정의

  • Multiplication : 곱셈의 인수와 연산 포함
  • User : 문제 푸는 사용자 식별
  • MultiplicationResultAttempt : 위 두 객체 참조 포함하고, 사용자 제출 값과 채점 결과 포함

불변성

클래스를 final로 만들면 해당 클래스의 모든 필드는 getter로만 접근이 가능하고 해당 클래스는 불변 상태가 된다. 불변성은 다중 스레드 환경에서 일어날 수있는 여러 문제에서 안전하게 해줌.

코드는
https://github.com/wikibook/springboot-microservices/tree/master/microservices-v3/social-multiplication

@RequiredArgsConstructor : 모든 상수 필드갖는 생성자 만듦
@Getter : 모든 필드 getter만듦
@ToString : 해당 클래스의 toString() 메서드를 읽기 쉽게 만듦
@EqualsAndHashCode : equals()와 hashCode() 메서드를 만든다.

👓3. 비즈니스 로직 레이어

새 비즈니스 로직을 서비스 레이어에 추가

🧦4. 프레젠테이션 레이어 (REST API)

엄밀히 따지면 REST 레이어가 꼭 필요한건 아니다.
스프링 MVC에서 화면 이름 반환하면 HTML같은 뷰 레이어 구현체로 렌더링 가능하지만 코드 기반 뷰 설계 필요함.
REST 사용하면 UI 필요없이 HTTP만을 사용해 인터페이스를 제공
하나의 api로 여러가지 백앤드 서비스에 기능을 제공할 수 있음.

api 설계

  • GET /multiplications/random : 무작위 생성 곱셈 반환
  • POST /results/ : 결과 전송하는 엔드포인트
  • GET /results?user=[user_alias] : 특정 사용자의 계산 결과를 검색

@WebMvcTest는 스프링 웹 애플리케이션 컨텍스트 초기화. SpringbootTest처럼 모든 설정 불러오는 것이 아니라 MVC 레이어(컨트롤러)와 관련된 설정만 불러옴. 즉 컨트롤러를 테스트하는 어노테이션. HTTP요청과 응답은 mock이용해 가짜로 이뤄지고 실제 연결은 생성X
@MockBean : 스프링이 진짜 bean이 아니라 목 객체 주입할때 사용. 목 객체는 given() 메서드에서 지정한 대로 값 반환한다. 테스트가 컨트롤러만 테스트하는 것이라서 사용
@JacksonTester : JSON내용 쉽게 확인가능. @JsonTest 이용해 자동 주입할 수 있다.

@RequestMapping을 클래스에 붙이면 클래스 내 모든 메서드에 최상위 경로 지정
@GetMapping 은 @RequestMapping(method = RequestMethod.GET)을 줄여쓴 것

단위 테스트를 컨트롤러 단위로 있으면 변경사항 적용 시 테스트 오류를 통해 이중으로 확인. API 사용하는 쪽에서 알아채기 전에 미리 오류 감지

프론트엔드 (웹 클라이언트)

HTML과 jQuery 로 REST 웹 서비스와 통신

http://localhost:8080/index.html 접속 시

엇 .. 문제 꽤 어렵네
일부러 틀려봤다! ^^


정답을 맞췄을 땐

새로운 요구사항 (데이터 저장)

사용자 스토리2 : 최근에 제출한 답안을 보고싶다.
(애자일 방식으로 진행되고있음)

요구사항 달성할 step

  • MultiplicationResultAttempt 클래스의 인스턴스 모두 저장
  • 특성 사용자 최근 답안 가져오는 REST 엔드포인트 생성
  • 답안 검색 새로운 서비스 생성
  • 사용자 답안 제출 시 답안 내역 보여주는 페이지 생성

코드는

https://github.com/wikibook/springboot-microservices/tree/master/microservices-v4/social-multiplication

MultiplicationResultAttemptControllerTest.java의 genericParameterizedTest 테스트 코드를 짜는 과정에서

에러
cannot resolve method 'any'를 만나서 고생좀 했는데
아래 블로그의 글처럼 intelliJ의 캐시를 지우고 재실행 했더니 잘 작동하였다.
https://ottl-seo.tistory.com/entry/IntelliJ-Cannot-resolve-symbol-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0

데이터 레이어

하이버네이트 같은 ORM 프레임워크
ORM 프레임워크 활용하면 자바 객체에 매핑할 수 있는 모델에 따라 데이터를 데이터베이스에 저장할 수 있다.

dependencies 에 jpa와 h2 추가

데이터 모델

영속화 레이어 완성 위해 데이터 모델 설계가 중요하다.
데이터 모델이 도메인 모델과 일치하지 않을 수 있음. (이 애플리케이션에서는 도메인 개체와 데이터 개체가 바로 매핑)
어노테이션으로 jpa로 모델링 @Entity @Id @GeneratedValue @Column 등 ..

repository

jpa repository로 java 객체 저장하고 읽는다.
스프링 데이터 jpa의 인터페이스 상속받아 인터페이스를 만들면 그 안에 필요한 기능 모두 들어있음. (개체 CRUD)

import org.springframework.data.repository.CrudRepository; 의
CrudRepository 는 자바 제너릭 사용하기 때문에 저장 클래스(@Entity) 와 식별자 타입을 인자로 넘김. PagingAndSoringRepository는 CRUD기능에 페이지와 정렬기능 까지 있는 유용한 인터페이스!

쿼리 메소드인 findTop5ByUserAliasOrderByIdDesc도 스프링 데이터 jap의 기능임.

repository는 TDD 안하는데 새로운 코드가 아니라 스프링 제공 코드라서 단위테스트 생성x

사용자 스토리2 를 만족시킨 결과물

중간에 user table을 생성 못하는 에러가 있었음 -> @table 어노테이션으로 다른 이름으로 지정해줌

의도한 대로 테이블이 나오지 않아서 코드를 다시수정해줌

api요청은 잘 오는데 표가 안나옴

혹시나 해서 다른 브라우저로 시도
잘 나와서 킹받음 ......
캐시때문인 것으로 예상 .. .킹 ....👑👑

profile
HelloWorld! 같은 실수를 반복하지 말기위해 적어두자..

0개의 댓글