/////
Search

221115

작성자
김지영
김희정
이현주
날짜
2022/11/15
학습 내용
텍스트

@RestController

UI를 통해 제공하는 것이 아닌 백엔드에서 REST API를 통해 json(or XML)형태로 데이터만 전달하기 위해 @RestController를 사용해 컨트롤러 다시 정의

실습코드

결과

@Controller와 @RestController 차이

@Controller : 주로 View 반환할 때 사용 @RestController : 주로 데이터 반환 시 사용
@Controller
전통적인 스프링 MVC의 컨트롤러
주로 View를 반환하기 위해 사용
@ResponseBody 어노테이션을 활용해 데이터 반환도 가능
@RestController
@Controller에 @ResponseBody가 추가된 것
주로 Json 형태로 객체 데이터를 반환할 때 사용
ResponseEntity로 객체를 감싸서 반환

API

Json형식으로 데이터를 어플리케이션끼리 주고 받으면서 서로 대화가 가능하게 하는 매커니즘!
Application Programming Interface로 컴퓨터나 소프트웨어를 서로 연결
Json형식으로 데이터를 리턴해주는 서버 프로그램
>> Json형식으로 데이터를 어플리케이션끼리 주고 받으면서 서로 대화가 가능하게 하는 매커니즘!
ex) 기상청의 소프트웨어 시스템에는 일일 기상 데이터 존재. 휴대폰의 날씨 앱은 API를 통해 이 시스템과 ‘대화’하여 휴대폰에 매일 최신 날씨 정보를 표시함.

Json

JavaScript Object Notation으로 "키-값 쌍"으로 이루어진 데이터 오브젝트를 표현하는 파일 포맷
Example
위 데이터를 Json형식으로 표현하면, (GET /api/v1/hospitals/2321 호출)
{id:"", roadNameAddress:"", hospitalName:"",patientRoomCount:"", totalNumberOfBeds:"", businessTypeName:"",totalAreaSize:""}

Service

목표 : business_status_code에서 숫자로 표기된 값(13)을 매핑된 텍스트(영업중)로 변환하여 데이터 전달
문제점 : 해당 비즈니스 로직 어디로? Controller에? HospitalResponse에?
→ 레이어드 아키텍쳐에 맞게 비즈니스 계층인 Service에 구현

실습 코드

레이어드 아키텍쳐

어플리케이션 컴포넌트를 유사 관심사 기준으로 레이어로 묶어 수평적으로 구성한 구조
특징
각 레이어는 가장 가까운 하위 레이어의 의존성 주입받음
각 레이어는 관심사 따라 묶여 있고, 다른 레이어 역할 침범 X
장점 : 코드 가독성, 기능 구현에 유리, 코드 확장성’
각 레이어가 독립적이면 단위테스트에 용이
Presentation계층 – Controller GET /api/v1/hospitals/{id}  
비즈니스(Business) 계층 — Service
데이터 접근 계층— Dao(Repository)
이전 코드 문제점
@RestController @RequestMapping("/api/v1/hospitals") public class HospitalRestController { private final HospitalRepository hospitalRepository;
Java
복사
레이어드 아키텍처에 맞게 설계 x
Presentation 계층인 HospitalRestController 가 비즈니스 계층에게 의존성 갖는 것이 아닌 데이터 접근 계층인 HospitalRepository 를 의존하고 있음.

WebMvcTest

WebMvcTest와 Mock을 이용해 Controller를 테스트

문제점

1.
Contoller 테스트 시 Service에 의존성
Mock 객체 사용
2.
많은 Controller 테스팅 단계 수
1. SpringBoot 실행
b.
웹브라우저 or Api 호출 App
c.
/api/v1/hospitals/111
d.
눈으로 확인
@WebMvcTest 이용

어노테이션

@WebMvcTest(테스트 대상 클래스.class)
웹에서 사용되는 요청과 응답 테스트 수행
테스트 대상 클래스 선언안하면 @Controller, @RestController, @ControllerAdvice 등 컨트롤러 관련 빈 객체 모두 로드
@MockBean
가짜 객체 생성해서 주입
@MockBean이 선언된 객체는 실제 객체가 아니기 때문에 개발자가 given()메소드 통해 동작 정의해야함.

테스트 과정

@MockBean // HospitalService는 테스트를 위해 가짜 객체를 쓰겠다는 뜻 HospitalService hospitalService;
Java
복사
@MockBean을 통해 HospitalController가 의존하는 HospitalService 객체에 Mock객체를 주입한다.
HospitalResponse hospitalResponse = HospitalResponse.builder() .id(2321) .roadNameAddress("서울특별시 서초구 서초중앙로 230, 202호 (반포동, 동화반포프라자빌딩)") .hospitalName("노소아청소년과의원") .patientRoomCount(0) .totalNumberOfBeds(0) .businessTypeName("의원") .totalAreaSize(0.0f) .businessStatusName("영업중") .build(); given(hospitalService.getHospital(2321)) .willReturn(hospitalResponse);
Java
복사
Builder 어노테이션 이용해 HospitalResponse 객체를 생성한다.
필요한 파라미터만 넣고 빌드 가능
given() 메소드를 통해 Mock객체 동작 정의
Mock객체인 hospitalServicegetHospital(2321) 호출
willReturn() 통해 어떤 결과 리턴할 지 정의
hospitalServicegetHospital(2321)결과로 id가 2321인 HospitalResponse 객체 리턴
Builder로 정의한 hospitalResponse 객체 넣기
int hospitalId = 2321; String url = String.format("/api/v1/hospitals/%d", hospitalId); mockMvc.perform(get(url)) .andExpect(status().isOk()) .andExpect(jsonPath("$.hospitalName").exists()) // $는 루트 $아래에 hospitalName이 있어야 함 .andExpect(jsonPath("$.hospitalName").value("노소아청소년과의원")) .andDo(print()); // http request, response내역을 출력 해라 verify(hospitalService).getHospital(hospitalId);// getHospital()메소드의 호출이 있었는지 확인
Java
복사
perform()메소드를 통해 서버로 URL 요청하는 것처럼 테스트
get(), post(), put(), delete()를 인자로 넣어 HTTP 메소드로 URL 정의 가능
결과값 : ResultActions 객체
ResultActions의 andExpect()통해 결과값 검증
MockMvcResultMatchers 클래스에 정의되어 있는 메서드 활용
status() : HTTP 상태 코드 검증
andDo() : 요청과 응답 전체 내용 확인
print() : 콘솔에 http request, response 내용 출력
verify() :지정된 메소드가 실행됐는지 검증

전체실습코드