Srping의 모듈에는 웹 계층을 담당하는 몇가지의 모듈이 있다. 특히 서블릿 API를 기반으로 요청을 처리하는 모듈을 spring-mvc라고 한다.
서블릿이란?
클라이언트의 요청을 처리하도록 특정 규약에 맞춰 Java 코드로 작성하는 클래스 파일
또한 Tomcat은 이런 서블릿들이 웹 애플리케이션으로 실행 되도록 도와주는 서블릿 컨테이너 중 하나이다.
클라이언트의 요청을 전달 받으면 요청 사항을 정리하기 위한 작업을 한다. 이 작업의 결과데이터를 응답으로 돌려줘야 하는데, 이 작업의 처리 결과 데이터를 Model이라고 한다.
View는 Model 데이터를 이용해 웹브라우저같은 클라이언트 애플리케이션의 화면에 보여지는 리소스를 제공하는 역할을 한다.
주로 우리가 쓰는 View 형태는 Model 데이터를 JSON 프로토콜 데이터로 변환하는 것이다. JSON은 {"속성" : "값"} 의 형태로 나타내어진다.
Controller는 클라이언트 측의 요청을 직접 전달받는 엔드포인트로써 Model과 View의 중간에서 상호작용을 한다.
클라이언트의 요청을 전달 받아 비즈니스 로직을 거친 후 Model 데이터가 만들어지는데, 이것을 View로 전달하는 역할을 하는 것이다.
@RestController
@RequestMapping(value = "/v1/members", produces = {MediaType.APPLICATION_JSON_VALUE})
public class MemberController {
@PostMapping
public String postMember(@RequestParam("email") String email,
@RequestParam("name") String name,
@RequestParam("phone") String phone) {
String response =
"{\"" +
"email\":\""+email+"\"," +
"\"name\":\""+name+"\",\"" +
"phone\":\"" + phone+
"\"}";
return response;
}
@GetMapping("/{member-id}")
public String getMember(@PathVariable("member-id")long memberId) {
return null;
}
@GetMapping
public String getMembers() {
return null;
}
}
public String postMember( ~ )
Map<String, String> map = new HashMap<>();
map.put("email", email);
map.put("name", name);
map.put("phone", phone);
return new ResponseEntity<>(map, HttpStatus.CREATED);
위와 같이 return값을 ResponseEntity 형태로 바꾸었다. Map 객체를 리턴하게 되면 내부적으로 JSON 형식으로 자동 변환해준다. 따라서 직접 써줄 필요가 없어진다.
또한 이렇게 쓸 시에 @RequestMapping에서 JSON type으로 설정을 안해주어도 된다.
DTO는 Data Transfer Object의 약자이다. 클라이언트에서 서버로 전송하는 요청 데이터, 서버에서 클라이언트로 전송하는 응답 데이터의 형식으로 클라이언트와 서버간에 데이터 전송이 이루어지는데 이 구간에서 DTO를 사용하게 된다.
RequestParam을 이용하여 많은 파라미터들을 받아오게 되면 Controller에서 너무 많은 것을 담당하게 됨. 이에 따라 요청 데이터를 하나의 객체로 모두 전달받기 위해 DTO 클래스를 사용한다.
또한 DTO 클래스에서 유효성 검사 또한 할 수 있다. (@Valid와 함께)
@RestController
@RequestMapping("/v1/members")
public class MemberController {
// 회원 정보 등록
@PostMapping
public ResponseEntity postMember(@RequestBody MemberPostDto memberPostDto) {
return new ResponseEntity<>(memberPostDto, HttpStatus.CREATED);
}
// 회원 정보 수정
@PatchMapping("/{member-id}")
public ResponseEntity patchMember(@PathVariable("member-id") long memberId,
@RequestBody MemberPatchDto memberPatchDto) {
memberPatchDto.setMemberId(memberId);
memberPatchDto.setName("홍길동");
return new ResponseEntity<>(memberPatchDto, HttpStatus.OK);
}
// 한명의 회원 정보 조회
@GetMapping("/{member-id}")
public ResponseEntity getMember(@PathVariable("member-id") long memberId) {
System.out.println("# memberId: " + memberId);
return new ResponseEntity<>(HttpStatus.OK);
}
// 모든 회원 정보 조회
@GetMapping
public ResponseEntity getMembers() {
System.out.println("# get Members");
return new ResponseEntity<>(HttpStatus.OK);
}
// 회원 정보 삭제
@DeleteMapping("/{member-id}")
public ResponseEntity deleteMember(@PathVariable("member-id") long memberId) {
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
}
@RequestBody
JSON 형식의 Request Body를 뒤에 선언된 클래스의 객체로 변환 시켜주는 역할을 한다. 즉 이는 클라이언트에서 전송하는 Request Body가 JSON 형태여야 한다는 말이 된다.
따라서 이전에는 parameter를 통해 전송했다면 이제는 JSON 형태로 제대로 전송해야한다.
@ResponseBody
핸들러 메서드의 리턴값이 ResponseEntity 클래스의 객체라면 내부적으로 HttpMessageConverter가 작동하여 응답 객체를 JSON 형식으로 바꿔준다.
Java 객체 -> JSON : JSON 직렬화
JSON -> Java 객체 : JSON 역직렬화