
스프링 부트 라이브러리를 사용하면 스프링 부트 로깅 라이브러리
spring-boot-stater-logging이 함께 포함 된다. 스프링 부트 로깅 라이브러리는 다음 로깅 라이브러리를 사용한다
@Slf4j
Logback
로그 라이브러리는
LogbackLog4J등 여러가지가 있는데 통합해 제공하는 인터페이스가 바로SLF4J라이브러리다.
SLF4J는 인터페이스 -> 구현체 Logback
@RestController
public class LogTestController {
private final Logger logger = LoggerFactory.getLogger(LogTestController.class);
@RequestMapping("/log-test")
public String logtest() {
String name = "Spring";
System.out.println("name = " + name);
logger.info("info log={}", name);
return "ok";
}
}
@RestContoller : RestAPI 의 Rest 이며 반환값이 HttpMessageBody에 담아서 그대로 return 된다.
- 위의 예제에서는 ok 가 그대로 반환된다.
- 반환 값이 뷰가 아닌 바디에 바로 입력한다
@Controller 는 반환 값이 String 이면 뷰 이름으로 인식된다. 그래서 뷰를 찾고 뷰가 랜더링 된다.
뷰를 찾는 것이 아니라, HTTP 메시지 바디에 바로 입력한다. 따라서 실행 결과로 ok 메세지를 받을 수 있다
name = Spring //일반적인 sout
2024-02-27T11:42:13.112+09:00 INFO 43119 --- [nio-8080-exec-2] h.springmvc.basic.LogTestController
로거를 찍은 부분은 시간, INFO 프로세스ID --- [현재실행한 쓰레드] 컨트롤러 이름: 메세지 전부 출력 된다
logger.info("info log={}", name);
logger.trace("trace log={}", name);
logger.debug("debug log={}", name);
logger.info("info log={}", name);
logger.warn("warn log={}", name);
logger.error("error log={}", name);

로그를 찍을때 레벨을 정할 수 있다. 가령 현재 정보는 운영시스템에서 봐야하는 중요한 정보야, 경고 메세지야, 상세야.
레벨
1. TRACE
2. DEBUG
3. INFO
4. WARN
5. ERROR
application.prorperties
#전체 로그 레벨 설정 (기본 info)
logging.level.root=info
#hello.springmvc 패키지와 그 하위 로그 레벨 설정
logging.level.hello.springmvc=trace
이미 스프링은 기본 logging level이
info로 설정되어 있는데 임의로debug로 바꿀 시에 수많은 log가 출력되는 것을 볼수 있다.
위와 같은 식으로 각 패키지 별로 log가 출력되는 레벨을 각기 따로 설정할 수 있다.
System.print.out 은 로그가 전부 남아서 실무에서는 절대 쓰지 않는다. 실무에서 적용시 수만건의 로그 폭탄을 맞을 수 있다.
log.debug("data="+dataa)log.debug("data={}",data)lombok 어노테이션
private final Logger logger = LoggerFactory.getLogger(LogTestController.class);
위의 코드를 어노테이션 하나로 축약할 수 있다. 바로 로그를 쓰면 된다.
Syste.out.println() 보다 우수하다.@RequestMapping(method = RequestMethod.GET)
public String mappingGetV1() {
log.info("mappingGetV1");
return "ok";
}
@GetMapping({"/hello-basic", "hello-go"})
public String helloBasic() {
log.info("helloBasic");
return "ok";
}
@PostMapping@PutMapping@DeleteMapping@PatchMapping@RequestMapping 은 URL 경로를 템플릿화 할 수 있는데, @PathVariable 을 사용하면 매칭 되는 부분을 편리하게 조회할 수 있다.
@PathVariable 의 이름과 파라미터 이름이 같으면 생략할 수 있다.
@GetMapping("/mapping/users/{userId}/orders/{orderId}")
public String mappingPath(@PathVariable String userId, @PathVariable Long orderId) {
log.info("mappingPath userId={}, orderId={}", userId, orderId);
return "ok";
}
### GET request with a header
GET http://localhost:8080/mapping/DAEHUN
2024-02-27T12:38:46.039+09:00 INFO 43442 --- [nio-8080-exec-1] h.s.b.requestmapping.MappingController : mappingPath userId=DAEHUN
http://localhost:8080/mapping/userA
http://localhost:8080/mapping/users/userA/orders/100
* 파라미터로 추가 매핑
* params="mode",
* params="!mode"
* params="mode=debug"
* params="mode!=debug" (! = )
* params = {"mode=debug","data=good"} */
@GetMapping(value = "/mapping-param", params = "mode=debug")
public String mappingParam() {
log.info("mappingParam");
return "ok";
}
실행
http://localhost:8080/mapping-param?mode=debug
* 특정 헤더로 추가 매핑
* headers="mode",
* headers="!mode"
* headers="mode=debug"
* headers="mode!=debug" (! = ) */
@GetMapping(value = "/mapping-header", headers = "mode=debug")
public String mappingHeader() {
log.info("mappingHeader");
return "ok";
}
/**
* Content-Type 헤더 기반 추가 매핑 Media Type * consumes="application/json"
* consumes="!application/json"
* consumes="application/*"
* consumes="*\/*"
* MediaType.APPLICATION_JSON_VALUE
*/
@PostMapping(value = "/mapping-consume", consumes = "application/json")
public String mappingConsumes() {
log.info("mappingConsumes");
return "ok";
}
Postman으로 테스트 해야 한다.
HTTP 요청의 Content-Type 헤더를 기반으로 미디어 타입으로 매핑한다.
만약 맞지 않으면 HTTP 415 상태코드(Unsupported Media Type)을 반환한다. 예시) consumes
consumes = "text/plain"
consumes = {"text/plain", "application/*"}
consumes = MediaType.TEXT_PLAIN_VALUE
@PostMapping(value = "/mapping-produce", produces = "text/html")
public String mappingProduces() {
log.info("mappingProduces");
return "ok";
}
HTTP 요청의 Accept 헤더를 기반으로 미디어 타입으로 매핑한다. 만약 맞지 않으면 HTTP 406 상태코드(Not Acceptable)을 반환한다.
예시)
produces = "text/plain"
produces = {"text/plain", "application/*"}
produces = MediaType.TEXT_PLAIN_VALUE
produces = "text/plain;charset=UTF-8"
회원 관리를 HTTP API로 만드는 예시
GET /usersPOST /usersGET /users/{userId}PATCH `/users/{userId}'DELEETE /users/{userId}@RestController
@RequestMapping("/mapping/users")
public class MappingClassControllrr {
@GetMapping
public String user() {
return "get users";
}
@PostMapping
public String addUSer() {
return "post user";
}
@GetMapping("/{userId}")
public String findUser(@PathVariable String id ) {
return "get userId=" + id;
}
@PatchMapping("/{userId}")
public String updateUser(@PathVariable String userId) {
return "get userId=" + userId;
}
@DeleteMapping("/{userId}")
public String deleteUser(@PathVariable String userId) {
return "delete userId=" + userId;
}
}
어노테이션 기반의 스프링 컨트롤러는 다양한 파라메터를 지원한다.
@GetMapping("/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";
}
### GET request with a header
GET http://localhost:8080/headers

HttpServletRequest HttpServletResponse HttpMethod : HTTP 메서드를 조회한다. org.springframework.http.HttpMethod Locale : Locale 정보를 조회한다. @RequestHeader MultiValueMap<String, String> headerMap@RequestHeader("host") String hostrequireddefaultValue @CookieValue(value = "myCookie", required = false) String cookierequired 기본 값: defaultValueMultiValueMap<String,String> map = new LinkedMultiValueMap();
map.add("keyA","value1");
map.add("keyA","value2");
//[value1,value2]
List<String>value = map.get("keyA");
HTTP 요청 메세지를 통해 클라이언트에서 서버로 데이터를 전달하는 방법 3가지
GET 쿼리 파라미터
/url**?username=hello&age=20
@RequestMapping("/request-param-v1")
public void requestParamV1(HttpServlet request, HttpServletResponse response) throws IOException{
String username= request.getParameter("username");
int age= Integer.parseInt(request.getParameter("age"));
log.info("username={}, name={}",username, name);
response.getWriter().wirte("ok");
}
}
http://localhost:8080/request-param-v1?username=hello&age=20
Post Form 페이지 생성
먼저 테스트용 HTML Form을 만들어야 한다.
리소스는 /resources/static 아래에 두면 스프링 부트가 자동으로 인식한다. main/resources/static/basic/hello-form.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/request-param-v1" method="post">
username: <input type="text" name="username" /> age: <input type="text" name="age" /> <button type="submit">전송</button>
</form>
</body>
</html>
Post Form 실행 http://localhost:8080/basic/hello-form.html
참고
Jar 를 사용하면 webapp 경로를 사용할 수 없다. 이제부터 정적 리소스도 클래스 경로에 함께 포함해야 한다.
spring-boot-starter-logging을 포함하며, 이는 Logback을 사용한다. 로깅 라이브러리는 주로 SLF4J를 통해 통합되며, 로그 레벨에는 TRACE, DEBUG, INFO, WARN, ERROR가 있다.