티스토리 뷰

728x90
반응형

 

 

 

지난 글에서 스프링 MVC의 실제적인 구현을 위해 패키지 구조와 컨트롤러 클래스를 설계했다.

 

컨트롤러 클래스를 다시 불러오면 아래와 같다.

 

  • MemberController
package com.gnidinger.member;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;

@RestController
@RequestMapping("/v1/members")
public class MemberController {
}
  • CoffeeController
package com.gnidinger.coffee;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;

@RestController
@RequestMapping("/v1/coffees")
public class CoffeeController {
}
  • OrderController
package com.gnidinger.order;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;

@RestController
@RequestMapping("/v1/orders")
public class OrderController {
}

각 애너테이션과 패키지 구조에 관한 내용은 지난 글에 정리되어 있다.

 

https://gnidinger.tistory.com/466

 

[Spring]Spring MVC - Controller 클래스 구조 생성 및 설계

지난 글에서 스프링 MVC(Model - View - Controller)의 구성요소와 작동방식에 대해 알아봤다. https://gnidinger.tistory.com/464 [Spring]Spring MVC 이전 글에서 스프링의 모듈 구조에 대해 본 적이 있다. 출처..

gnidinger.tistory.com

위와 같이 컨트롤러 구조만 작성한 상태에서 실행 후 Postman을 통해 요청을 전송하면 아래와 같은 화면이 나온다.

 

응답 메시지의 status는 '404', 즉, 요청 페이지 또는 리소스를 찾을 수 없다는 의미이다.

 

이는 컨트롤러 클래스에 핸들러 메서드(요청 처리 메서드)가 아직 정의되지 않았기 때문인데,

 

지금부터 컨트롤러 클래스에 핸들러 메서드를 하나씩 추가해보자.

 

 

MemberController의 핸들러 메서드(Handler Method)

 

핸들러 메서드@RequestMapping과 그 하위 애너테이션이 붙은 메서드의 정보를 추상화한 객체이다.

 

그 자체로 실행하기 위한 메서드가 아닌, 비즈니스 로직을 실행하기 위한 참조정보를 담고 있는 메서드라고 보면 된다.

 

핸들러 메서드는 작성에 앞서 클라이언트의 요청과 그에 대한 응답에 필요한 정보를 특정해야 한다.

 

예를 들어 MemberController 클래스에 필요한 정보는 아래와 같다.

 

  • 회원 이메일 주소 - email
  • 회원 이름 - name
  • 회원 전화번호 - phoneNumber

이를 바탕으로, 코드 실행 시 정보를 사용하는 방법에 대해 알아보자.

 

MemberController 클래스에 핸들러 메서드를 추가하면 아래와 같이 된다.

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

@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) {
        System.out.println("# email: " + email);
        System.out.println("# name: " + name);
        System.out.println("# phone: " + phone);
        
        String response =
                "{\"" + 
                   "email\":\""+email+"\"," + 
                   "\"name\":\""+name+"\",\"" + 
                   "phone\":\"" + phone+ 
                "\"}";
        return response;
    }

    @GetMapping("/{member-id}")
    public String getMember(@PathVariable("member-id")long memberId) {
        System.out.println("# memberId: " + memberId);

        // not implementation
        return null;
    }

    @GetMapping
    public String getMembers() {
        System.out.println("# get Members");

        // not implementation
        return null;
    }
}

 

  • @RequestMapping(value = "", produces = {})

    • value 속성은 클래스 공통 URL 지정
    • produces속성은 응답 데이터의 미디어 타입을 설정
    • JSON 형식의 데이터를 전송하겠다는 의미로 MediaType.APPLICATION_JSON_VALUE 값 설정

  • @PostMapping

    • 클라이언트의 요청 데이터(Request Body)를 서버에 생성할 때 사용
    • URL을 생략하면 클래스 레벨의 URL 경로만으로 요청 URL 구성(”/v1/members)
    • 클라이언트 쪽에서 요청 전송 시, HTTP Method 타입을 동일하게 맞춰주어야 함

 

  • @RequestParam

    • 클라이언트 쪽에서 요청 데이터를 쿼리 파라미터, 폼 데이터, x-www-form-urlencoded 형식으로 전송하면 이를 서버 쪽에서 전달받을 때 사용
    • 쿼리 파라미터(Query Parameter 또는 QueryString) - URL에서 ‘?’를 기준으로 붙는 key/value 쌍의 데이터
      ex)http://localhost:8080/coffees/1?page=1&size=10

  • @GetMapping

    • 클라이언트가 서버 리소스를 조회할 때 사용
    • 괄호 안에는 가지 속성을 사용할 있지만 여기서는 전체 HTTP URL 일부(리소스 ID) 지정

      • 이때 최종 URL은 ”/v1/members/{member-id}”
      • @RequestMapping에 설정된 URL과 @GetMapping에 설정한 URL이 합쳐진 형태
      • member-id는 클라이언트의 요청에 따라 동적으로 바뀌는 값
    • 괄호 안에 URL 없을 경우 상위 주소("/v1/members") 모든 정보를 가져온다.
  • @PathVariable

    • 괄호 안의 문자열은 반드시 @GetMapping("/{member-id}")  중괄호({ }) 안의 문자열과 동일
    • 요청 URL에 패턴 형식으로 지정된 변수의 값을 파라미터로 전달받을 수 있음
  • postMember() 메서드

    • 회원 정보를 등록해주는 핸들러 메서드
    • 현재 리턴 타입은 String
    • 클라이언트 쪽에서 JSON 형식의 데이터를 전송받아야 하기 때문에 응답 문자열을 JSON 형식에 맞게 작성
    • POST Method를 처리하는 핸들러 메서드는 데이터를 생성한 후에 클라이언트 쪽에 생성한 데이터를 리턴해주는 것이 관례
    • 요청과 응답 - POST Method와 요청 URL을 입력, JSON 형식의 응답 데이터를 전달(‘200 OK’)

  • getMember() 메서드

    • 특정 회원의 정보를 클라이언트 쪽에 제공하는 핸들러 메서드
    • 아직 구체적인 로직을 작성하지 않았으므로 응답 데이터 없음
    • getMember() 요청

  • getMembers() 메서드

    • 전체 회원 목록을 클라이언트에게 제공하는 핸들러 메서드
    • getMember()와 마찬가지로 아직 전달받는 별도의 응답 데이터는 없음
    • getMembers() 요청

 

CoffeeController의 핸들러 메서드(Handler Method)

 

CoffeeController 클래스에 필요한 정보는 아래와 같다.

 

  • 커피 영문명 - engName
  • 커피 한글명 - korName
  • 커피 가격 - price
package com.gnidinger.coffee;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping(value = "/v1/coffees", produces = {MediaType.APPLICATION_JSON_VALUE})
public class CoffeeController {
    @PostMapping
    public String postCoffee(@RequestParam("engName") String engName,
                             @RequestParam("korName") String korName,
                             @RequestParam("price") String price) {
        System.out.println("# engName: " + engName);
        System.out.println("# korName: " + korName);
        System.out.println("# price: " + price);

        String response =
                "{\"" +
                        "engName\":\""+engName+"\"," +
                        "\"korName\":\""+korName+"\",\"" +
                        "price\":\"" + price+
                        "\"}";
        return response;
    }

    @GetMapping("/{coffee-id}")
    public String getCoffee(@PathVariable("coffee-id")long coffeeId) {
        System.out.println("# coffeeId: " + coffeeId);

        // not implementation
        return null;
    }

    @GetMapping
    public String getCoffees() {
        System.out.println("# get Coffees");

        // not implementation
        return null;
    }
}

 

OrderController의 핸들러 메서드(Handler Method)

 

OrderController 클래스에 필요한 정보는 아래와 같다.

 

  • 회원 식별자 - memberId
  • 커피 식별자 - coffeeId

여기(API 계층)서 식별자란 데이터베이스의 테이블에 저장되는 로우의 식별자인 기본키(Primary key)라고 생각하면 된다.

package com.gnidinger.order;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping(value = "/v1/orders", produces = MediaType.APPLICATION_JSON_VALUE)
public class OrderController {
    @PostMapping
    public String postOrder(@RequestParam("memberId") long memberId,
                            @RequestParam("coffeeId") long coffeeId) {
        System.out.println("# memberId: " + memberId);
        System.out.println("# coffeeId: " + coffeeId);

        String response =
                "{\"" +
                        "memberId\":\""+memberId+"\"," +
                        "\"coffeeId\":\""+coffeeId+"\"" +
                        "}";
        return response;
    }

    @GetMapping("/{order-id}")
    public String getOrder(@PathVariable("order-id") long orderId) {
        System.out.println("# orderId: " + orderId);

        // not implementation
        return null;
    }

    @GetMapping
    public String getOrders() {
        System.out.println("# get Orders");

        // not implementation
        return null;
    }
}
  • postOrder() 메서드

    • 회원이 주문한 커피 주문 정보를 등록해주는 핸들러 메서드
    • 이때 필요한 주문 정보는 어떤 고객이 어떤 커피를 주문했느냐 하는 것
    • ‘어떤 고객’은 회원 식별자(memberId)에, ‘어떤 커피’는 커피 식별자(coffeeId)에 해당함

 


이런 식으로 각 컨트롤러 클래스에 핸들러 메서드를 구현했다.

 

하지만 지금 작성한 코드에도 개선해야 할 부분이 남아있는데, 대략 아래와 같다.

 

  • 수작업으로 JSON 문자열을 만들어 주는 부분 - 오타가 나기 쉽고 코드와 그 작성 시간이 길어진다.
  • @RequestParam 애너테이션을 사용한 요청 파라미터 수신 - 파라미터가 많아질수록 코드와 그 작성 시간이 길어진다.

이어지는 글에서 하나씩 고쳐나가 보자.

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함