[TIL] #6. 스프링 MVC - 기본 기능 ①

kiteB·2021년 9월 15일
0

TIL-Spring3

목록 보기
4/7
post-thumbnail

프로젝트 생성

🔗 전체 코드 확인하기

새로운 Welcome 페이지 완성!


로깅 간단히 알아보기

지금까지 실행 결과를 확인하거나 테스트를 하기 위해서 System.out.println()을 이용해왔다.

하지만 이 명령어는 IO 리소스를 많이 사용해서 시스템이 느려질 수 있는 등 여러 단점이 있어서, 실무에서는 로깅 라이브러리를 이용해서 로그를 출력한다!

지금부터 로깅에 대해 더 자세히 알아보자!

✔ 로깅 라이브러리

스프링 부트 로깅 라이브러리(spring-boot-starter-loggin)는 기본적으로 SLF4J, Logback을 사용한다.

SLF4JLogback, Log4J, Log4J2 등 수많은 라이브러리를 통합해서 인터페이스를 제공하는 것으로, 이 인터페이스의 구현체Logback을 대부분 사용한다.

✔ 로그 선언

1. 클래스 참조변수 선언

//getClass() 메서드를 통해 사용되는 클래스 타입 반환하여 삽입한다.
private Logger log = LoggerFactory.getLogger(getClass());

//직접적으로 해당 클래스 타입을 입력해줘도 된다.
private static final Logger log = LoggerFactory.getLogger(Xxx.class);

2. 롬복 사용

간단하게 @Slf4j 애노테이션을 사용해도 된다.


LogTestController

package hello.springmvc.basic;

import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

//@Slf4j
@RestController
public class LogTestController {

    private final Logger log = LoggerFactory.getLogger(getClass());

    @RequestMapping("/log-test")
    public String logTest() {
        String name = "Spring";

        log.trace("trace log={}", name);
        log.debug("debug log={}", name);
        log.info(" info log={}", name);
        log.warn(" warn log={}", name);
        log.error("error log={}", name);

        //로그를 사용하지 않아도 a+b 계산 로직이 먼저 실행됨, 이런 방식으로 사용하면 X
        log.debug("String concat log=" + name);
        return "ok";
    }
}

💡 @RestController를 사용하는 이유!

  • @Controller반환값이 String일 때, 뷰 이름으로 인식하기 때문에 뷰를 찾고 뷰가 렌더링된다.
  • @RestController는 반환값으로 뷰를 찾지 않고, HTTP 메세지 바디에 바로 입력한다.

실행 결과

시간, 로그 레벨, 프로세스 ID, 쓰레드 명, 클래스명, 로그 메시지가 출력된다.

📌 참고

  • 로그 레벨을 설정하면 해당 로그보다 우선순위가 높은 것만 출력된다.
    • LEVEL: TRACE < DEBUG < INFO < WARN < ERROR
  • 스프링 부트에서 default값은 info!
    info보다 낮은 trace, debug는 출력되지 않는다.
    (로그 레벨을 바꾸고 싶다면 application.propertires에서 변경하면 된다.
  • 개발 서버는 debug 출력
  • 운영 서버는 info 출력

요청 매핑

💡 요청 매핑

요청에 대해 어떤 컨트롤러에서 처리할지 매핑을 진행하는 것.

🔗 전체 코드 확인하기


1. 기본 요청

@RestController
public class MappingController {
    private Logger log = LoggerFactory.getLogger(getClass());
 	
    @RequestMapping("/hello-basic")
    public String helloBasic() {
        log.info("helloBasic");
        return "ok";
    }
}

@RequestMapping("/hello-basic")

  • /hello-basic URL 호출이 오면 이 메서드가 실행되도록 매핑한다.
  • 대부분의 속성을 배열[ ]로 제공하기 때문에 URL을 여러 개 설정할 수 있다. (Ex. {"/hello-basic", "/hello-go"})


2. HTTP 메서드 매핑

@RequestMapping(value = "/mapping-get-v1", method = RequestMethod.GET)
public String mappingGetV1() {
    log.info("mappingGetV1");
    return "ok";
}
  • @RequestMappingmethod 속성으로 HTTP 메서드를 지정하지 않으면 메서드와 무관하게 호출된다.
  • 위의 코드는 GET으로만 호출 가능하다.


3. HTTP 메서드 매핑 축약

@GetMapping(value = "/mapping-get-v2")
public String mappingGetV2() {
    log.info("mapping-get-v2");
    return "ok";
}

@RequestMappingmethod 속성을 지정하지 않고 HTTP 메서드를 축약한 메서드도 있다. 훨씬 간편하고 직관적이다!
@GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping


4. PathVariable(경로 변수) 사용

@GetMapping("/mapping/{userId}")
public String mappingPath(@PathVariable("userId") String data) {
   log.info("mappingPath userId={}", data);
   return "ok";
}
  • 최근 HTTP API는 이렇게 리소스 경로에 식별자를 넣는 방식을 선호한다!
  • @RequestMapping은 URL 경로를 템플릿화 할 수 있는데, @PathVariable을 사용하면 매칭되는 부분을 편리하게 조회할 수 있다.
  • @PathVariable의 이름과 파라미터 이름이 같으면 생략할 수 있다.
    • @PathVariable("username") String usernamePathVariable String username


5. 특정 파라미터 조건 매핑

@GetMapping(value = "/mapping-param", params = "mode=debug")
public String mappingParam() {
    log.info("mappingParam");
    return "ok";
}
  • 잘 사용하지 않는다.


6. 특정 헤더 조건 매핑

@GetMapping(value = "/mapping-header", headers = "mode=debug")
public String mappingHeader() {
    log.info("mappingHeader");
    return "ok";
}


7. 미디어 타입 조건 매핑 - HTTP 요청 Content-Type, consume

@PostMapping(value = "/mapping-consume", consumes = "application/json")
public String mappingConsumes() {
    log.info("mappingConsumes");
    return "ok";
}


8. 미디어 타입 조건 매핑 - HTTP 요청 Accept, produce

@PostMapping(value = "/mapping-produce", produces = "text/html")
public String mappingProduces() {
    log.info("mappingProduces");
    return "ok";
}


요청 매핑 - API 예시

지금부터 회원 관리 웹 애플리케이션에 필요한 HTTP API 구조를 만들어보자!

package hello.springmvc.basic.requestmapping;

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

@RestController
@RequestMapping("/mapping/users")
public class MappingClassController {

    /**
     * - 회원 목록 조회  : GET       `/mapping/users`
     * - 회원 등록      : POST      `/mapping/users`
     * - 회원 조회      : GET       `/mapping/users/{userId}`
     * - 회원 수정      : PATCH     `/mapping/users/{userId}`
     * - 회원 삭제      : DELETE    `/mapping/users/{userId}`
     * */

    @GetMapping
    public String user() {
        return "get users";
    }

    @PostMapping
    public String addUser() {
        return "post user";
    }

    @GetMapping("/{userId}")
    public String findUser(@PathVariable String userId) {
        return "get userId=" + userId;
    }

    @PatchMapping("/{userId}")
    public String updateUser(@PathVariable String userId) {
        return "update userId=" + userId;
    }

    @DeleteMapping("/{userId}")
    public String deleteUser(@PathVariable String userId) {
        return "delete userId=" + userId;
    }
}

모두 다 잘 된다~


HTTP 요청 - 기본, 헤더 조회

package hello.springmvc.basic.requestmapping.request;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;

@Slf4j
@RestController
public class RequestHeaderController {

    @RequestMapping("/headers")
    public String headers(HttpServletRequest request,
                          HttpServletResponse response,
                          HttpMethod httpMethod,
                          Locale locale,
                          @RequestHeader MultiValueMap<String, String> headerMap,
                          @RequestHeader("host") String host,
                          @CookieValue(value = "myCookie", required = false) String cookie) {

        log.info("request={}", request);
        log.info("response={}", response);
        log.info("httpMethod={}", httpMethod);
        log.info("locale={}", locale);
        log.info("headerMap={}", headerMap);
        log.info("header host={}", host);
        log.info("myCookie={}", cookie);

        return "ok";
    }
}
  • HttpMethod: HTTP 메서드를 조회한다.
  • Locale: Locale 정보를 조회한다.
  • @RequestHeader MultiValueMap<String, String> headerMap: 모든 HTTP 헤더를 MultiValueMap 형식으로 조회한다.
  • RequestHeader("host") String host: 특정 HTTP 헤더를 조회한다.
  • @CookieValue(value = "myCookie", required = false) String cookie: 특정 쿠키를 조회한다.

profile
🚧 https://coji.tistory.com/ 🏠

0개의 댓글