Spring MVC를 연습해보기 위해 책 주문 애플리케이션을 간단히 작성해보는 시리즈입니다. 수업 코드와 거의 유사하지만 추후 기능을 다르게 확장해보는 등 개인적으로 연습 삼아 꾸준히 코드를 덧붙이고 수정할 것이며, MVC 연습이라는 이름으로 그 과정을 기록하고자 합니다.
위에서부터 순차적으로 구현할 것이며, 하단의 + 표시 기능은 수업 외적으로 구현해보고자 한다. 진도에 따라 기능을 더 추가하거나 뺄 수도 있다!
이 세 가지 리소스에 대해 패키지를 생성하고, 그에 맞는 MVC를 작성해나간다.
book, member, order에 대한 패키지 생성 후 MemberController
클래스와 엔티티 클래스 Member
클래스를 생성했다.
public class Member {
private long memberId;
private String name;
private String phone;
private String email;
private String grade;
}
회원 정보에 어떤 것들이 있으면 좋을까 고민하다가, 가장 기본이 되는 id, 이름, 전화번호, 이메일을 만들었다. 추후에 회원 등급에 따라 주문시 할인 등 다르게 적용해보고 싶어서 욕심으로 grade
라는 멤버변수도 넣었다. 엔티티 클래스의 멤버변수로 있는 게 좋은지 별도의 Grade 클래스를 작성하는 게 좋은지는 더 고려해봐야 할 것 같다.
@RestController
@RequestMapping("/v1/member")
public class MemberController {
@PostMapping
public ResponseEntity postMember(@RequestParam("name") String name,
@RequestParam("phone") String phone,
@RequestParam("email") String email,
@RequestParam("grade") String grade) {
Map<String, String> map = new HashMap<>();
map.put("name", name);
map.put("phone", phone);
map.put("email", email);
map.put("grade", grade);
return new ResponseEntity<>(map, HttpStatus.CREATED);
}
@PatchMapping("/{member-id}")
public ResponseEntity patchMember(@PathVariable("member-id") long memberId,
@RequestParam("name") String name,
@RequestParam("phone") String phone,
@RequestParam("email") String email,
@RequestParam("grade") String grade) {
Map<String, Object> map = new HashMap<>();
map.put("memberId", memberId);
map.put("name", "강동원");
map.put("phone", phone);
map.put("email", email);
map.put("grade", "VIP");
return new ResponseEntity<>(map, HttpStatus.OK);
}
@DeleteMapping("/{member-id}")
public ResponseEntity deleteMember(@PathVariable("member-id") long memberId) {
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
회원 정보 등록, 회원 정보 수정, 회원 정보 삭제의 기능을 구현했다. v2에서 DTO를 적용할 거기 때문에 우선은 HashMap으로 값을 지정하고, 받을 수 있게 구현해두었다.
포스트맨으로 POST
를 날리면 입력한 정보대로 회원 정보가 생성되는 것을 확인할 수 있었다. HTTP 상태코드도 원하는대로 201 CREATED
가 떴다. (memberId는 값으로 넘길 필요가 없는데 실험하는 과정에서 빼는 걸 까먹었다..)
PATCH
는 전화번호, 이메일만 수정할 수 있게 코드로 설정해놓아서 grade값은 바뀌지 않았다. (캡처에 잘렸는데 상태 코드도 200번으로 잘 나왔다.)
수업 시간에 배운 바로는, "@PathVariable과 매핑 애너테이션의 변수값이 같아야 한다"였다. 정말 그런 것인지, 그 이유는 무엇인지 찾아보니 이런 글이 있다.
- Overview
In this quick tutorial, we'll explore Spring's @PathVariable annotation.
Simply put, the @PathVariable annotation can be used to handle template variables in the request URI mapping, and set them as method parameters.
Let's see how to use @PathVariable and its various attributes.
(중략)
원문 링크
내가 이해한 바로는,
@PathVariable
애너테이션에 URI에 대한 값은 생략해도 된다. (어차피 파라미터와 Path Variable 값이 같기 때문)@PathVariable
에 URI를 추가해줘야 한다.
Member
클래스에 private long familyId
를 추가하고,
@PatchMapping("/{member-id}")
public ResponseEntity patchMember(@PathVariable("member-id") long familyId,
@RequestParam("name") String name,
@RequestParam("phone") String phone,
@RequestParam("email") String email,
@RequestParam("grade") String grade) {
Map<String, Object> map = new HashMap<>();
map.put("familyId", "패밀리아이디");
(이하생략...)
매핑 애너테이션과 @PathVariable의 URI를 맞춰주고 familyId 변수를 가져오니 위와 같이 PATCH가 성공적으로 되었다.
@PatchMapping("/{member-id}")
public ResponseEntity patchMember(@PathVariable long familyId,
@RequestParam("name") String name,
@RequestParam("phone") String phone,
@RequestParam("email") String email,
@RequestParam("grade") String grade) {
Map<String, Object> map = new HashMap<>();
map.put("familyId", "패밀리아이디");
(이하생략...)
위 코드에서 @PathVariable URI를 지우면, 매핑 애너테이션이 아이디를 읽어와도 @PathVariable과 매치가 안 되어 500 Internal Server Error
가 발생한다. 결론적으로, URI가 엔티티 클래스의 기본키와 이름이 동일해서 생략하는 게 아닌 이상 두 변수명은 맞춰줘야 한다.