말하는 컴공감자의 텃밭

Spring - 로깅? 요청 매핑? 본문

백엔드/Spring

Spring - 로깅? 요청 매핑?

현콩 2024. 4. 17. 16:19
728x90

로깅 라이브러리를 사용해 로그를 출력해보자.

스프링 부트에서는 기본적으로 아래 라이브러리를 사용한다.

SLF4J - http://www.slf4j.org 
Logback - http://logback.qos.ch

 

오늘은 SLF4J 를 사용해봅시도

SLF4J를 선택해준다.

 

@RestControllerView를 반환하지 않고 바로 메세지 바디 String을 넣어주게 사용한다.

 

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
package hello.springmvc.basic;
 
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class LogTestController {
    private final Logger log = LoggerFactory.getLogger(getClass());
 
    @RequestMapping("/log-test")
    public String logTest() {
//        System.out.println(" 기존에는 이렇게 찍어봤었죠.. ");
        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";
    }
}
 
 
cs

 


  • application.properties 에 아래 코드를 추가하면 콘솔창 색이 구분되어진다. 
spring.output.ansi.enabled=always

요로코롬

 


로그 범위 ?

-> 로그가 출력되는 포멧 확인

시간, 로그 레벨, 프로세스 ID, 쓰레드 명, 클래스명, 로그 메시지 

 

Level 단계

TRACE > DEBUG > INFO > WARN > ERROR 
개발 서버는 debug 출력

운영 서버는 데이터가 많으므로 Info 출력

 

로그 범위 설정.
Debug 레벨까지 확인되는 모습.

 

근데 엥.. 내가 쓴 코드 로그가 없길래 확인해보니 

이전 프로젝트가 제대로 안닫혔나보다

 

윈도우 cmd로 PID 찾아서 꺼주고 진행해줬다.

 

CMD -> netstat -ano 입력 -> 8080 포트 PID 찾기 -> taskkill /f /pid ["PID"]

 

 

제대로 나와주네오

 

 


요청 매핑

 

@RequestMapping

클라이언트 요청에 정보를 어떤 Controller가 처리할지를 매핑하기 위한 어노테이션이다.

@RequestMapping에 URL을 포함하여 해당 Controller 클래스에 명시하여 사용한다.

요청에 맞는 컨트롤러를 사용한다고 이해하면 편하다.

 

예시로 @Controller에 반환 값이 `String` 이라면 뷰 이름으로 인식된다. 그래서 를 찾고 뷰가 랜더링된다.

 

@RequestMapping을 사용하여 모든 유형의 HTTP 요청을 처리할 수 있다.

  • 요청 처리 세부 정보를 지정하는 여러 속성을 제공한다.
    • method: HTTP 메소드(예: RequestMethod.GET, RequestMethod.POST 등)
    • value: 메소드가 처리할 URL 패턴입니다.
    • params: 요청에 있어야 하는 요청 매개변수.
    • headers: 요청에 있어야 하는 헤더.
    • consumes: 요청 본문의 미디어 유형.
    • produces: 응답의 미디어 유형. 등등

각각 로그를 찍어보면서 올바르게 처리되는지 확인해보자.

 

[기본] 예제 코드

@RestController
public class MappingController {
    private Logger log = LoggerFactory.getLogger(getClass());

    @RequestMapping("/hello-basic")
    public String helloBasic() {
        log.info("helloBasic");
        return "ok";
    }

 

[HTTP 메서드 매핑] 예제 코드

    @RequestMapping(value = "/mapping-get-v1", method = RequestMethod.GET)
    public String mappingGetV1() {
        log.info("mappingGetV1");
        return "ok";
    }

 

[HTTP 메서드 축약] 예제 코드

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

 

[PathVariable] 경로변수, 다중도 가능하다

  • @PathVariable("userId") String userId 를 @PathVariable String userId 로 바꿔도 동작한다.
    @GetMapping("/mapping/users/{userId}/orders/{orderId}")
    public String mappingPath(@PathVariable String userId, @PathVariable Long orderId) {
        log.info("mappingPath userId={}, orderId={}", userId, orderId);
        return "ok";
    }

 

다 잘 나오다가 엥? 오류가 발생했다.

 

 

 

 

넌 뭐야

2024-04-17T18:32:37.015+09:00 ERROR 2944 --- [springmvc] 
[nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : 
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
[Request processing failed: java.lang.IllegalArgumentException: Name for argument of type 
[java.lang.String] not specified, and parameter name information not available via reflection. 
Ensure that the compiler uses the '-parameters' flag.] 
with root cause

 

에러를 읽어보니 스프링에서 파라미터 이름추론하려다 실패해서 IllegalArgumentException가 발생했다.

예제에서는 PathVariable에 명시하지 않았기에 변수이름을 지정해주었다.

 

@GetMapping("/mapping/users/{userId}/orders/{orderId}")
    public String mappingPath(@PathVariable("userId") String userId, @PathVariable("orderId") Long orderId) {
        log.info("mappingPath userId={}, orderId={}", userId, orderId);
        return "변수명 명시 후 -> ok";
    }

 

잘 뜨는구만 ^<^

 

이어서

 

[특정 파라미터 조건 매핑]  : 특정 파라미터가 있는지 없는지 조건 추가

  • 파라미터로 추가 매핑 
  • params="mode"
  • params="!mode"  등등
@GetMapping(value = "/mapping-param", params = "mode=debug") 
public String mappingParam() { 
    log.info("mappingParam"); 
    return "ok"; 
}

파라미터 정보도 매핑되어야 함. 대부분은 경로변수 사용.

 

[특정 헤더조건 매핑] : 헤더도 존재.

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

 

[미디어 타입 조건 매핑] 

 

 HTTP 요청 Content-Type, consume 

    @PostMapping(value = "/mapping-consume", consumes = "application/json")
    public String mappingConsumes() {
        log.info("mappingConsumes");
        return "ok";
    }
  • HTTP 요청의 Content-Type 헤더를 기반으로 미디어 타입으로 매핑한다. 
  • 만약 맞지 않으면 HTTP 415 상태코드(Unsupported Media Type)을 반환한다.

  • postman으로 json을 Post로 테스트 하니 ok로 잘 나왔다.

 

 HTTP 요청 Accept, produce

    @PostMapping(value = "/mapping-produce", produces = "text/html")
    public String mappingProduces() {
        log.info("mappingProduces");
        return "ok";
    }
  • HTTP 요청의 Accept 헤더를 기반으로 미디어 타입으로 매핑한다. 
  • 만약 맞지 않으면 HTTP 406 상태코드(Not Acceptable)을 반환한다.

text/html을 생산하기에 Accept를 설정해주어야 한다.

Accept가 /일경우는 ok
json 인 경우는 406 에러를 뱉는 모오습

 

에러의 원인은 미디어 타입이 안맞기 때문이다.

produces = "text/plain" 
produces = {"text/plain", "application/*"} 
produces = MediaType.TEXT_PLAIN_VALUE 
produces = "text/plain;charset=UTF-8"

 

이처럼 여러 방법으로 가능하다

728x90

'백엔드 > Spring' 카테고리의 다른 글

Spring 포인트 컷? - AOP  (0) 2024.06.24
Spring과 웹 애플리케이션  (1) 2023.10.29
Comments