일단 씻고 나가자
[스프링 부트 핵심 가이드] 05. API를 작성하는 다양한 방법 본문
(본 포스팅은 해당 도서의 정리 및 개인 공부의 목적 포스팅임을 밝힙니다.)
장정우, 『스프링 부트 핵심 가이드 : 스프링 부트를 활용한 애플리케이션 개발 실무』, 위키북스, 2022
05. API를 작성하는 다양한 방법
본격적인 애플리케이션 개발에 필요한 내용을 소개한다.
각 HTTP 메서드에 해당하는 API 개발 및 그 과정에서 필요한 내용을 살펴보고, 외부의 요청에 대해 컨트롤러가 어떻게 구성되는지 알아본다.
5.1 프로젝트 설정
4장의 기억을 되살려 다시 프로젝트를 생성해보자.
Maven, Java, Spring Boot 버전(적당한 버전으로 설정)을 설정하고
groupId : 'com.springboot' / name, artifact : 'api' 로 설정하여 springboot를 생성한다.
[ADD DEPENDENCIES] 에는 기본적인 Lombok, Spring Configuration Processor, Spring Web 세 가지를 추가한다.
프로젝트 open 방법은 동일하게 [GENERATE] 후 다운 받아진 압축 파일을 압축 해제 후에
IntelliJ 실행 후 Open Project를 통하여 압축 해제한 폴더가 있는 경로로 open 하면 된다. (상세한 사항은 4장 참고)
5.2 GET API 만들기
GET API는 웹 어플리케이션에서 값을 가져올 때 사용하는 API이다.
실무에서는 HTTP 메서드에 따라 컨트롤러 클래스를 구분하지 않지만, 해당 예제에서는 메서드별로 클래스를 생성해본다.
다음과 같이 클래스를 만든다.
5.2.1 @RequestMapping으로 구현하기
별다른 설정 없이 @RequestMapping 어노테이션을 사용하면 HTTP의 모든 요청을 받으므로, 다음과 같이 옵션을 걸어야 @RequestMapping는 HTTP 개별 요청을 받을 수 있다.
단, @RequestMapping 방식은 스프링 4.3 이후로는 사용되지 않는다.
따라서 이후 실습에는 아래와 같이 어노테이션을 사용한다.
5.2.2 매개변수가 없는 GET 메서드 구현
@Get/Post/Put/DeleteMapping 4가지 대체 어노테이션을 통해 요청 타입에 맞게 메서드를 설정한다.
대체 어노테이션을 활용하여 GET 방식으로 요청을 받는 메서드 작성 방법은 다음과 같다.
5.2.3 @PathVariable을 활용한 GET 메서드 구현
실무 환경에서는 매개변수를 활용하여 데이터를 주고받는 웹 통신을 구현하여야 하기 때문에 대부분 매개변수를 활용하는 메서드를 작성하게 된다. 매개변수를 받을 때 자주 쓰이는 방법 중 하나인 url 자체에 값을 담아 요청하는 방식을 알아보자.
사진과 같이 중괄호 내부에 사용할 변수명을 담으며, 그것을 매개변수의 @PathVariable 방식으로 연결한다.
해당 방식을 사용할 때는 몇가지 규칙을 지켜야 한다.
- 중괄호( {} )를 통해 어느 위치에서 값을 받을지 지정한다. (이때 중괄호는 표기일 뿐 요청에는 들어가지 않는다.)
- 매개변수 내에서 @PathVariable 어노테이션을 활용하여 매개변수와 요청 값을 연결한다.
- 요청 값과 @PathVariable로 연결한 매개변수의 이름은 동일해야 한다.
이때, 3의 규칙에서 요청 값과 매개변수의 이름을 동일하게 맞출 수 없는 상황이라면 다음과 같이 작성할 수 있다.
5.2.4 @RequestParam을 활용한 GET 메서드 구현
url 자체에 값을 담는 방식 외에도 쿼리로 값을 담아 요청을 보내는 방식도 존재한다.
해당 방식은 uri에 '요청 url?{키}={값}&{키}={값}...'의 형태로 구성되며,
애플리케이션에선 해당 값을 @RequestParam 어노테이션으로 받는다.
이 방식 또한 마찬가지로, 키와 변수명을 맞출 수 없을 때 @RequestParam의 매개변수를 활용하여 작성할 수 있다.
만약 쿼리스트링에 어떤 값이 들어올지 모른다면 다음과 같은 방식으로 코드를 작성한다.
5.2.5 DTO 객체를 활용한 GET 메서드 구현
DTO란?
Data Transfer Object.
다른 레이어 간의 데이터 교환에 활용됨. 간략하게 각 클래스 및 인터페이스를 호출하며 전달하는 매개변수로 사용되는 데이터 객체이다. DTO는 애플리케이션 내부의 사용이 아닌 다른 서버(시스템, 레이어)와의 데이터의 교환 용도로만 사용되며 이를 '데이터 컨테이너'라고 한다.
VO는 Value Object으로 DTO와 유사하여 엄밀히 구분하지 않을 때가 많지만 정확하게는 의미 차이가 있는데,
VO는 Read-Only으로 설계하여 값을 변경하지 못하게끔 데이터의 신뢰성을 유지한다.
이런 DTO는 로직을 갖지 않는 특수한 용도의 클래스이므로, controller와 구분하여 따로 DTO 관련 클래스만 모아두는 패키지가 필요하다.
DTO는 각 데이터를 받아 하나의 객체를 생성하여 개별 데이터를 관리하는 것이 목적이기 때문에, 객체를 이루는 변수들과 관련 메서드들만으로 이루어져 있다. 보안성의 문제로 개별 변수들은 직접 접근을 허용하지 않고 private 처리하는 자바 빈 규약에 따라, 개별 변수를 가져오고 값을 바꾸는 getter/setter 메서드와, 해당 객체의 정보를 한 번에 볼 수 있는 toString을 구현하는 것이 일반적이다.
직접 모든 메서드를 수기로 작성하는 방법도 있지만, IDE에서 지원하는 generate를 사용하면 편리하다.
작성하고자 하는 코드 라인에서 마우스 우클릭 -> [Generate(Alt+Insert)] -> [Getter and Setter] (따로 필요한 부분만 선택해도 됨) / [toString()] -> 만들고자 하는 변수 모두 선택 -> [OK]
generate는 편리한 기능이지만, 해당 방식으로 매번 작성하는 것은 역시 비효율적이다.
이를 더 쉽게 작성하기 위하여 우리가 stringboot 생성 때 추가했던 Lombok 의존성을 사용해보자.
코드 상에서는 보이지 않지만 Lombok의 어노테이션에 의해 자동으로 [get/set + 변수명()]의 함수가 생겨 활용할 수 있다.
toString 역시 추가되는데, 이는 ["클래스명(변수명1 = 내용1, 변수명2 = 내용2..)"] 와 같은 내용의 String을 반환해준다.
DTO를 통하여 쿼리 방식으로 객체를 생성해보자. 쿼리 방식의 uri에서 해당 클래스의 변수명을 key로, 그 변수에 담을 값을 value로 요청하고 매개변수를 해당 DTO 클래스로 담으면 객체를 자동으로 생성할 수 있다. 예시 코드는 이렇다.
5.3 POST API 만들기
POST API는 웹 애플리케이션에서 데이터 베이스 등의 저장소에 리소스를 저장할 때 사용하는 API이다.
GET에서는 url의 경로나 파라미터에 변수를 넣어 요청을 보냈지만,
POST에서는 저장하고자 하는 값들을 HTTP 바디에 담아 서버에 전달한다. 따라서 URI가 상대적으로 간단하다.
마찬가지로 실습을 위해 controller 패키지 내에 PostController 클래스를 만든다.
클래스 상단의 @RestController 어노테이션은 @Controller와 @ResponseBody 두 어노테이션의 기능을 합친 어노테이션이다. 즉, 컨트롤러의 역할과, json 형태를 return하는 기능을 갖추게 해준다.
5.3.1 @RequestMapping으로 구현하기
우선 @RequestMapping을 통해 post 방식의 메서드를 구현해본다. POST 방식이기 때문에 @RequestMapping 어노테이션의 매개변수 method를 RequestMethod.POST로 선언해주어야 한다.
POST 방식 역시 @RequestMapping(method = RequestMethod.POST) 부분을 @PostMapping 어노테이션을 통하여 줄일 수 있다.
POST 방식의 실습을 Talented API에서 확인하려면 [METHOD]를 POST 방식으로 바꾸어야 한다. POST는 기본적으로 클라이언트가 서버쪽으로 데이터를 보내어 서버에 저장하는 동작이기 때문에, 데이터에 대한 정보 즉 리소스를 담을 수 있는 [BODY] 공간을 제공한다.
5.3.2 @RequestBody를 활용한 POST 메서드 구현
POST 방식에서는 HTTP Body에 값을 넣어 리소스를 전송하고, 이는 앞서 보았던 Talented API의 상단의 [BODY] 부에 작성하여 확인 해볼 수 있다. 이 리소스는 일정한 형태(규약)를 지켜 데이터를 전송해야 하는데, 그래야만 받는 쪽에서도 해당 데이터를 해당 규칙에 맞게 처리할 수 있기 때문이다. 앞으로의 실습은 가장 대중적인 형식인 JSON (Java Script Object Nonation) 방식으로 처리한다. JSON은 자바스크립트 객체 문법을 따르는 데이터 포맷 형태이며, 네트워크 환경의 데이터 전송에 주로 활용되고 파싱하기 쉬운 특징이 있다.
실습으로 POST 방식에서 들어온 JSON 데이터를 받는 코드를 작성해보자. POST 방식은 Body에서 들어온 JSON 데이터를 받아 처리하므로 GET에서 쿼리 형태로 값을 받아 처리하는 @RequestParam 어노테이션 대신 @RequestBody 어노테이션을 사용해야 한다. 동일하게 어떤 값이 얼마나 들어올지 모르는 상황을 대비하여 Map으로 JSON의 키와 값을 동시에 출력해본다. 클라이언트의 요청 값은 위에서 [BODY]에 작성했던 데이터로 실습한다.
마찬가지로 해당 데이터를 바로 객체에 담을 수도 있다. 일전에 GET에서 만들었던 MemberDto 객체를 매개변수로 받아 출력해보자.
5.4 PUT API 만들기
PUT API는 웹 애플리케이션에서 서버를 통해 데이터 베이스와 같은 저장소의 리소스 값을 업데이트 하는 데 사용하는 API이다. POST와 유사하나, POST는 리소스의 생성, PUT은 리소스의 생성과 수정을 담당한다. 즉, 같은 데이터를 POST 반복하면 같은 리소스의 데이터가 반복만큼 생성되지만, PUT은 해당 리소스만을 가져온다. 이때 PUT과 PATCH의 차이는 PUT은 전체 리소스 수정, PATCH는 리소스의 일부만 수정한다는 점에서 차이가 있다.
5.4.1 @RequestBody를 활용한 PUT 메서드 구현
이전 실습과 동일하게 controller 패키지 내부에 PutController 클래스를 만들고 @RestController, @RequestMapping 어노테이션을 통해 url을 연결한다. 마찬가지로 내부 메서드 또한 @RequestMapping을 통해 value와 method를 따로 지정할 수 있지만 생략하고 @PutMapping 어노테이션을 통해 생성한다. 작동방식은 PUT과 유사하기 때문에 역시 @RequestBody와 Map을 통한 매개변수로 실습을 진행한다.
Talented API Tester에서의 실습도 PUT과 동일하게 진행하며, [METHOD] 부만 PUT으로 바꾸고 [BODY]에 동일한 JSON 정보를 적고 [Send] 한다.
PUT 역시 객체에 바로 데이터를 넣을 수 있다. 실습 과정은 같다.
이때 return을 memberDto.toString()으로 하는 것과, memberDto 객체 자체로 하는 것에 대한 차이를 알아보자.
(반환 타입 : String / return : toString() 예시)
(반환 타입 : MemberDto(클래스) / return : memberDto(객체) 예시)
위의 예시처럼 String 형식은 말 그대로 String을 반환하여 [Content-Type]이 [text/plain] 인 것을 볼 수 있고.
클래스 형식은 객체를 반환하여 [Content-Type]이 [application/json] 인 것을 확인할 수 있다.
이는 앞서 얘기했듯 클래스에 선언한 @RestController 어노테이션이 @RequestBody의 역할을 수행하여, 반환값이 객체일 땐 자동으로 JSON 형태로 반환함을 알 수 있다.
5.4.2 ResponseEntity를 활용한 PUT 메서드 구현
응답 방식에는 이전 실습처럼 바로 객체를 JSON 형식으로 보내어 body 부에 출력하는 방식도 있지만,
ResponseEntity<T> 클래스를 활용하여 응답하는 방법도 있다.
스프링 프레임워크에는 HttpEntity<T> 클래스와 그것을 상속받는 Response/RequestEntity<T> 클래스를 지원한다.
HttpEntity<T>는 내부에 HttpHeaders headers 객체와 T body 객체를 가지고 있어서 응답과 요청에 대해 header 부분과 body 부분 각각 분리하여 구성할 수 있는데, 이를 상속받는 ResponseEntity<T> 클래스는 내부에 Object status 객체를 추가하여 header와 body를 손쉽게 구현함은 물론 응답 코드 변경 또한 가능하다.
ResponseEntity를 이용하여 return하는 실습을 진행해보자.
return 타입을 ResponseEntity로 설정해주고 각 설정값을 해당 클래스 객체에 붙여서 return한다.
status 부에는 HttpStatus가 상수로 가지고 있는 http 상태 정보를 반영하여 응답시킬 수 있으며, BAD_GATEWAY, NOT_FOUND 등으로도 설정할 수 있다. body 부에는 실제 반영하는 값을 담아 반영시키면 된다.
이전엔 200으로 반환되던 http status 값이 HttpStatus.ACCEPTED으로 설정한대로 202로 반영된 모습을 확인할 수 있다.
5.5 DELETE API 만들기
DELETE API는 웹 애플리케이션에서 서버를 통해 데이터 베이스와 같은 저장소의 리소스 값을 삭제하는 데 사용하는 API이다. 클라이언트로부터 PK 즉 식별자를 받아 데이터 베이스 혹은 캐시 내부의 리소스를 조회하고 삭제하는 역할을 수행한다. 삭제의 기능은 service에서 따로 메서드를 구현해주어야 하며, 삭제할 리소스에 대하여 DeleteMapping된 메서드 내에서 구현한 삭제 메서드를 수행한다. DELETE API가 컨트롤러에서 값을 받는 단계에선 간단한 값을 받기 때문에 GET 실습 시에 활용했었던 PathVariable, 혹은 @RequestParam을 활용한다.
5.5.1 @PathVariable과 @RequestParam을 활용한 DELETE 메서드 구현
Get 방식에서 활용했던 방식에 service에서 구현할 삭제 메서드를 내부에 추가하기만 하면 되므로
이번 장에선 간단히 @DeleteMapping 어노테이션을 활용하여 두 가지 방법을 구현하는 예제를 작성해본다.
5.6 [ 한걸음 더 ] REST API 명세를 문서화하는 방법 - Swagger
API의 개발 시에는 해당 API의 로직과 요청, 응답 값에 대한 설명을 자료로 정리한 '명세'의 관리가 중요해진다.
이러한 API와 명세는 주기적인 업데이트가 이루어지는데, 이런 잦은 수정과 변화에 대한 문제를 해결해주기 위한 오픈소스 프로젝트가 Swagger이다.
Swagger에 대해 직접 실습해보자. 우선 프로젝트 안의 pom.xml 이라는 파일로 가서, <dependencies> 내부에 새로운 <dependency>를 추가해주고 swagger의 의존성을 넣어준다.
이후 프로젝트 내부에 config라는 패키지를 생성 후, SwaggerConfiguration 클래스를 만든 후 다음과 같이 작성해주자.
(+) Exception
org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException: Cannot invoke "org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.toString()" because the return value of "springfox.documentation.spi.service.contexts.Orderings.patternsCondition(springfox.documentation.RequestHandler)" is null
이때 이런 류의 오류가 나며 서버 자체도 실행이 안 된다면 Springboot와 Swagger의 version 호환 문제가 생긴 것이므로,
같은 pom.xml 파일의 상단에서 Springboot의 <version>을 다음과 같이 수정해주면 된다.
(해당 Swagger의 버전과 호환하는 Springboot의 버전은 실습을 위한 예시일 뿐이다.)
만약 잘 실행됐다면 http://localhost:8080/swagger-ui.html 으로 접속해보자. 다음과 같은 명세 화면이 보인다.
해당 화면에선 프로젝트 내부에서 작성했던 클래스와 내부의 응답, 요청 url 및 model의 클래스도 확인이 가능하다.
간단하게 명세의 세부 내용을 작성하는 코드를 작성해보자.
주요 어노테이션으로 @ApiOperation, @ApiParam이 있으며 각각 API의 설명, 매개변수의 설명을 도와준다.
다음과 같이 작성하고 swagger에 다시 접속하게 되면
이처럼 제목과 상단부엔 @ApiOperation에 적었던 내용을, [Parameters]에는 @ApiParam에 적었던 내용이 출력된다.
뿐만 아니라 우측 상단의 [Try it out]을 누르고 예시 파라미터를 적은 후 [Execute] 하면 완성 url, 응답 status, 반환값 등 다양한 정보를 보여준다. 사진은 해당 기능을 활용하여 실행한 예시이다.
5.7 [ 한걸음 더 ] 로깅 라이브러리 - Logback
로깅(logging)이란 애플리케이션의 동작 중에 일어난 시스템의 상태, 동작 정보 등을 시간순으로 기록하는 활동.
로깅은 사용자(고객)에게 필요한 기능은 아니므로 '비기능 요구사항'에 해당하지만, 디버깅이나 문제 해결 시의 원인 분석에 꼭 필요한 요소.
자바에서의 로깅 프레임워크는 'Logback'이 가장 유명하며, 'slf4j(Simple Logging Facade 4(for) Java' 기반으로 동작한다. 이는 스프링부트의 spring-boot-starter-web에 내장되어 있어 별도의 의존성을 요구하지 않는다.
Logback 의 특징은 다음과 같다.
- 크게 5단계의 로그 레벨 설정 가능.
1. ERROR - 심각한 문제로 애플리케이션 작동 불가능
2. WARN - 경고 레벨
3. INFO - 상태 변경과 같은 정보 전달을 위해 사용
4. DEBUG - 디버깅을 위한 메세지 표시
5. TRACE - DEBUG 레벨보다 더 상세한 정보 표현 - 실제 운영 환경, 개발 환경 별 다른 출력 레벨을 설정하여 로그 확인 가능.
- Logback의 설정 파일을 일정 시간마다 스캔하여 애플리케이션 재가동 없이 설정 변경 가능.
- 별도의 지원 프로그램 없이 자체적으로 로그 파일 압축 가능.
- 저장된 로그 파일의 보관 기간 등의 설정 및 관리 가능.
5.7.1 Logback 설정
Logback의 실습을 위해 설정 파일 생성부터 시작해보자.
일반적으로 class path의 설정 파일을 자동 참조하므로 resorce 폴더 안에 생성한다.
파일명의 경우 자바/스프링에선 'logback.xml'의 이름, 스프링 부트에선 'logback-spring.xml'의 이름으로 참조한다.
사진처럼 resorce 폴더 내부에 'logback-spring.xml' 파일을 만들고 다음과 같이 코드를 작성한다.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- Property 영역 -->
<property name="LOG_PATH" value="./logs"/>
<!-- Appender 영역 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<!-- Encoder 영역 -->
<encoder>
<!-- Pattern 영역 -->
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] %logger %msg%n</pattern>
</encoder>
</appender>
<!-- Appender 영역 -->
<appender name="INFO_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<file>${LOG_PATH}/info.log</file>
<append>true</append>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern> ${LOG_PATH}/info_${type}.%d{yyyy-MM-dd}.gz </fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<!-- Encoder 영역 -->
<encoder>
<!-- Pattern 영역 -->
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] %logger %msg%n</pattern>
</encoder>
</appender>
<!-- TRACE > DEBUG > INFO > WARN > ERROR > OFF -->
<!-- Root 영역 -->
<root level="INFO">
<appender-ref ref="console"/>
<appender-ref ref="INFO_LOG"/>
</root>
</configuration>
코드의 주석 처리한 부분처럼 설정 파일은 크게 Property, Appender, Encoder, Pattern, Root 영역으로 나뉜다.
가장 핵심적이고 중요한 Appender과 Root 영역에 대해 조금 더 알아보자.
Appender 영역
로그의 형태 설정과 출력의 방법을 설정하는 영역이다.
Appender는 하나의 인터페이스이며, 하위에 여러 구현체가 존재한다.
Appender의 대표적인 구현체는 5가지가 있으며, 로그의 출력 부는 괄호의 내용과 같다.
- ConsoleAppender (콘솔)
- FileAppender (파일 저장)
- RollingFileAppender (여러 파일을 순회하며 로그 저장)
- SMTPAppender (메일 전송)
- DBAppender (데이터 베이스)
<!-- Appender 영역 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!-- Appender 영역 -->
<appender name="INFO_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
또한 appender 하위에 filter로 로그 기록의 레벨을 설정하고, encoder로 로그 표현 형식을 pattern으로 정의한다.
pattern은 대표적으로 다음과 같은 문법을 통해 설정할 수 있다.
패턴 | 의미 |
%Logger{length} | 로거의 이름 |
%-5level | 로그 레벨. -5는 출력 고정폭의 값 |
%msg(%message) | 로그 메세지 |
%d | 로그 기록 시간 |
%p | 로깅 레벨 |
%F | 로깅이 발생한 애플리케이션 파일명 |
%M | 로깅이 발생한 메서드 이름 |
%I | 로깅이 발생한 호출지의 정보 |
%thread | 현재 스레드명 |
%t | 로깅이 발생한 스레드명 |
%c | 로깅이 발생한 카테고리 |
%C | 로깅이 발생한 클래스명 |
%m | 로그 메세지 |
%n | 줄바꿈 |
%r | 애플리케이션 실행부터 로깅 발생 시점까지 시간 |
%L | 로깅 발생 호출 지점의 라인수 |
<fileNamePattern> ${LOG_PATH}/info_${type}.%d{yyyy-MM-dd}.gz </fileNamePattern>
참고 사이트
https://velog.io/@myway00/Java-Spring-Boot-005-2-Logging
Root 영역
정의된 Appender을 활용하기 위해, Root 영역에서 Appender를 참조 후 로깅 레벨을 설정한다.
특정 패키지에 대해 다른 로깅 레벨을 설정하고 싶다면 root 대신 logger를 사용하여 지정 가능하다.
<!-- Root 영역 -->
<root level="INFO">
<appender-ref ref="console"/>
<appender-ref ref="INFO_LOG"/>
</root>
<logger name="com.springboot.api.controller" level="DEBUG" additivity="false">
<appender-ref ref="console"/>
<appender-ref ref="INFO_LOG"/>
</logger>
name은 패키지, level은 로그 레벨, additivity는 지정 패키지에 하위 패키지를 포함할지 여부에 대한 설정 부이다.
5.7.2 Logback 적용하기
Logback의 실습을 진행해본다.
우선 위의 코드에서 RollingFileAppender 부를 지워 파일 저장을 제외시키고 실습은 진행한다.
이때, root 부에서 file 부를 참조하는 부분도 마찬가지로 지워주어야 한다.
즉, 최종 src/resources/logback-spring.xml 코드는 이렇다.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- Property 영역 -->
<property name="LOG_PATH" value="./logs"/>
<!-- Appender 영역 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<!-- Encoder 영역 -->
<encoder>
<!-- Pattern 영역 -->
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] %logger %msg%n</pattern>
</encoder>
</appender>
<!-- TRACE > DEBUG > INFO > WARN > ERROR > OFF -->
<!-- Root 영역 -->
<root level="INFO">
<appender-ref ref="console"/>
</root>
</configuration>
이후 Logger 클래스를 활용하여 활용할 클래스 내에서 사용하면 된다.
실습으로 이전에 만들어두었던 GetController 클래스에서, Swagger을 구현한 메서드 내에 구현해보자.
작성 방식은 다음과 같으며, import 할 Logger 클래스는 org.slf4j의 Logger 클래스이다.
이제 spring 서버를 실행하고 swagger 페이지 (http://localhost:8080/swagger-ui.html) 에 접속하여,
방금 Logger 코드를 작성한 메서드에 대해 임의의 매개변수를 넣고 [Try it out] -> [Execute] 해보자.
그럼 다음과 같이 execute 시마다 IDE의 콘솔창에 작성했던 코드처럼 log가 출력되는 것을 볼 수 있다.
코드를 수정한다면 로그를 통해 사용자가 입력한 매개변수를 기록할 수도 있고, 호출 시간을 기록할 수도 있다.
따라서 애플리케이션의 주요 사항이나 로그의 사용 목적에 따라 작성 방식을 바꾸어가며 원하는 방식으로 로그를 기록해야 할 것이다.
5.8 정리
5장에서는 컨트롤러로 요청 값 받기, Swagger를 통한 명세 작성, Logback을 통한 로그 기록 방식에 대해 알아보았다.
'Backend > Spring' 카테고리의 다른 글
[스프링 부트 핵심 가이드] 07. 테스트 코드 작성하기 (0) | 2023.06.08 |
---|---|
[스프링 부트 핵심 가이드] 06. 데이터베이스 연동 (0) | 2023.06.01 |
[스프링 부트 핵심 가이드] 04. 스프링 부트 애플리케이션 개발하기 (0) | 2023.05.23 |
[스프링 부트 핵심 가이드] 03. 개발 환경 구성 (0) | 2023.05.19 |
[스프링 부트 핵심 가이드] 02. 개발에 앞서 알면 좋은 기초 지식 (0) | 2023.05.18 |