[Spring] MVC 연습 - Controller 작성

kai6666·2022년 6월 30일
0

TIL. Spring

목록 보기
5/11

Spring MVC를 연습해보기 위해 책 주문 애플리케이션을 간단히 작성해보는 시리즈입니다. 수업 코드와 거의 유사하지만 추후 기능을 다르게 확장해보는 등 개인적으로 연습 삼아 꾸준히 코드를 덧붙이고 수정할 것이며, MVC 연습이라는 이름으로 그 과정을 기록하고자 합니다.


책 주문 애플리케이션 기능 요구 사항


위에서부터 순차적으로 구현할 것이며, 하단의 + 표시 기능은 수업 외적으로 구현해보고자 한다. 진도에 따라 기능을 더 추가하거나 뺄 수도 있다!

책 주문 애플리케이션에 필요한 리소스

  • 회원 (Member)
  • 책 (Book)
  • 주문 (Order)

이 세 가지 리소스에 대해 패키지를 생성하고, 그에 맞는 MVC를 작성해나간다.

Day1 - Controller v1 작성


book, member, order에 대한 패키지 생성 후 MemberController 클래스와 엔티티 클래스 Member 클래스를 생성했다.

Member

public class Member {
    private long memberId;
    private String name;
    private String phone;
    private String email;
    private String grade;
}

회원 정보에 어떤 것들이 있으면 좋을까 고민하다가, 가장 기본이 되는 id, 이름, 전화번호, 이메일을 만들었다. 추후에 회원 등급에 따라 주문시 할인 등 다르게 적용해보고 싶어서 욕심으로 grade라는 멤버변수도 넣었다. 엔티티 클래스의 멤버변수로 있는 게 좋은지 별도의 Grade 클래스를 작성하는 게 좋은지는 더 고려해봐야 할 것 같다.

MemberController

@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과 매핑 애너테이션의 변수값이 같아야 하는 이유

수업 시간에 배운 바로는, "@PathVariable과 매핑 애너테이션의 변수값이 같아야 한다"였다. 정말 그런 것인지, 그 이유는 무엇인지 찾아보니 이런 글이 있다.

  1. 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 값이 같기 때문)
  • 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가 엔티티 클래스의 기본키와 이름이 동일해서 생략하는 게 아닌 이상 두 변수명은 맞춰줘야 한다.

profile
성장 아카이브

0개의 댓글