스프링 공식 사이트에는 스프링 부트 프로젝트를 자동으로 만들어주는 서비스가 있다.
위 경로를 접속하면 다음과 같은 화면이 나온다.
이 페이지에서 왼쪽에 각 항목을 선택하면 프로젝트 설정을 할 수 있다. 그리고 오른쪽 [ADD DEPENDENCIES..] 버튼을 클릭하여 Dependencies 항목을 채울 수 있다.
pom.xml 파일은 메이븐의 기능을 사용하기 위해 작성하는 파일이다. 이 파일에는 프로젝트, 의존성 라이브러리, 빌드 등의 정보 및 해당 프로젝트를 관리하는 데 필요한 내용이 기술돼 있다.
아파치 메이븐은 자바 기반의 프로젝트를 빌드하고 관리하는 데 사용되는 도구이다. 메이븐의 가장 큰 특징은 pom.xml 파일에 필요한 라이브러리를 추가하면 해당 라이브러리에 필요한 라이브러리까지 함께 내려받아 관리한다는 점이다. 메이븐의 대표 기능에는 프로젝트 관리, 빌드 및 패키징, 테스트, 배포가 있다.
메이븐의 기능은 생명주기 순서에 따라 관리되고 동작한다. 인텔리제이 IDEA에서 생성한 프로젝트의 경우 인텔리제이 IDEA에서 우측에 있는 'Maven' 탭을 클릭하면 메이븐의 생명주기를 확인할 수 있다. 메이븐의 생명주기는 크게 기본 생명주기(Default Lifecycle), 클린 생명주기(Clean Lifecycle), 사이트 생명주기(Site Lifecycle)의 3가지로 구분한다.
별도의 매개변수 없이 GET API를 구현하는 경우 다음과 같이 코드를 작성할 수 있다.
@GetMapping(value = "/name")
public String getName() {
return "Flature";
}
URL 자체에 값을 담아 전달되는 요청을 처리할 때 @PathVariable을 활용한다.
@GetMapping(value = "/variable1/{variable}")
public String getVariable1(@PathVariable String variable) {
return variable;
}
@GetMapping 어노테이션에 지정한 변수의 이름과 메서드 매개변수의 이름을 동일하게 맞추기 어렵다면 @PathVariable 뒤에 괄호를 열어 @GetMapping 어노테이션의 변수명을 지정한다.
@GetMapping(value = "/variable2/{variable}")
public String getVariable2(@PathVariable("variable") String var) {
return var;
}
URI에서 '?'를 기준으로 우측에 '{키}={값}' 형태로 구성된 요청을 전송할 때는 @RequestParam을 활용하면 된다.
@GetMapping(value = "/request1")
public String getRequestParam1(
@RequestParam String name,
@RequestParam String email,
@RequestParam String organization
) {
return name + " " + email + " " + organization;
}
만약 쿼리스트링에 어떤 값이 들어올지 모른다면 Map 객체를 활용할 수 있다.
@GetMapping(value = "/request2")
public String getRequestParam2(@RequestParam Map<String, String>) param) {
StringBuilder sb = new StringBuilder();
param.entrySet().forEach(map -> {
sb.append(map.getKey() + " : " + map.getValue() + "\n");
});
}
POST API는 웹 애플리케이션을 통해 데이터베이스 등의 저장소에 리소스를 저장할 때 사용되는 API이다. 저장하고자 하는 리소스나 값을 HTTP 바디(body)에 담아 서버에 전달한다. 바디 영역에 작성되는 값은 일정한 형태를 취한다. 일반적으로 JSON 형식으로 전송되며, 이렇게 서버에 들어온 요청은 다음과 같이 @RequestBody를 활용한다.
@PostMapping(value = "/member")
public String postMember(@RequestBody Map<String, Object> postData) {
String Builder sb = new StringBuilder();
postData.entrySet().forEach(map -> {
sb.append(map.getKey() + " : " + map.getValue() + "\n");
});
return sb.toString();
}
Map 객체는 요청을 통해 어떤 값이 들어오게 될지 특정하기 어려울 때 주로 사용한다. 요청 메시지에 들어갈 값이 정해져 있다면 DTO 객체를 매개변수로 삼아 작성할 수 있다.
PUT API는 웹 애플리케이션 서버를 통해 데이터베이스 같은 저장소에 존재하는 리소스 값을 업데이트하는 데 사용한다. 컨트롤러 클래스를 구현하는 방법은 POST API와 거의 동일하다. 마찬가지로 HTTP body로 리소스를 서버에 전달한다.
@PutMapping(value = "/member")
public String postMember(@RequestBody Map<String, Object> putData) {
String Builder sb = new StringBuilder();
postData.entrySet().forEach(map -> {
sb.append(map.getKey() + " : " + map.getValue() + "\n");
});
return sb.toString();
}
DTO 객체를 활용한 PUT 메서드 구현은 다음과 같다.
@PutMapping(value = "/memeber2/")
public MemberDto postMemberDto2(@RequestBody MemberDto memberDto) {
return memberDto;
}
@RestController 어노테이션이 지정된 클래스는 @ResponseBody를 생략할 수 있는데 이 @ResponseBody 어노테이션은 자동으로 값을 JSON과 같은 형식으로 병환해서 전달하는 역할을 수행한다.
스프링 프레임워크에는 HttpEntity라는 클래스가 있다. HttpEntity는 헤더와 바디로 구성된 HTTP 요청과 응답을 구성하는 역할을 수행한다. RequestEntity와 ResponseEntity는 HttpEntity를 상속받아 구현한 클래스이다. 그중 ResponseEntity는 HttpEntity로부터 HttpHeaders와 Body를 가지고 자체적으로 HttpStatus를 구현한다. 이 클래스를 활용하면 응답 코드 변경은 물론 Header와 Body를 더욱 쉽게 구성할 수 있다. 메서드의 리턴타입에 ResponseEntity를 적용한 예시는 다음과 같다.
@PutMapping(value = "/member3")
public ResponseEntity<MemberDto> postMemberDto3(
@RequestBody MemberDto memberDto
) {
return ResponseEntity
.status(HttpStatus.ACCEPTED)
.body(memberDto);
}
DELETE API는 웹 애플리케이션 서버를 거쳐 데이터베이스 등의 저장소에 있는 리소스를 삭제할 때 사용한다. 컨트롤러를 통해 값을 받는 단계에서는 간단한 값을 받기 때문에 GET 메서드와 같이 URI에 값을 넣어 요청을 받는 형식으로 구현된다.
@PathVariable을 이용하면 다음과 같다.
@DeleteMapping(value = "/{variable}")
public String DeleteVariable(@PathVariable String variable) {
return variable;
}
@RequestParam 어노테이션을 통해 쿼리스트링 값도 받을 수 있다.
@DeleteMapping(value = "/reuqest1")
public String DeleteVariable(@RequestParam String email) {
return "email : " + email;
}
API를 개발하면 명세를 관리해야 한다. 명세란 해당 API가 어떤 로직을 수행하는지 설명하고 이 로직을 수행하기 위해 어떤 값을 요청하며, 이에 따른 응답값으로는 무엇을 받을 수 있는지를 정리한 자료이다.
Swagger를 사용하기 위해 pom.xml 파일에 의존성을 추가해야 한다.
<dependencies>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
</dependencies>
그 다음, Swagger와 관련된 설정 코드를 작성한다. 이 클래스는 설정(Configuration)에 관한 클래스로 config라는 패키지를 생성한 후에 그 안에 생성하는 것이 좋다.
@Configuration
@EnableSwagger2
public class SwaggerConfiguration {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.springboot.api"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot Open Api Test with Swagger")
.description("설명 부분")
.version("1.0.0")
.build();
}
}
Swagger를 더 잘 활용하기 위해 Controller 코드에서 @ApiOperation, @ApiParam을 활용할 수 있다.
@ApiOperation(value = "GET 메서드 예제", notes = "@RequestParam을 활용한 GET Method")
@GetMapping(value = "/request1")
public String getRequestParam1(
@ApiParam(value = "이름", required = true) @RequestParam String name,
@ApiParam(value = "이메일", required = true) @RequestParam String email,
@ApiParam(value = "회사", required = true) @RequestParam String organization
) {
return name + " " + email + " " + organization;
}
애플리케이션을 실행한 후 웹 브라우저를 통해 http://localhost:8080/swagger-ui.html 로 속하면 Swagger 페이지가 출력된다.
로깅(logging)이란 애플리케이션이 동작하는 동안 시스템의 상태나 동작 정보를 시간순으로 기록하는 것을 의미한다.
로깅은 개발 영역 중 '비기능 요구사항'에 속한다. 즉, 사용자나 고객에게 필요한 기능은 아니지만 디버깅하거나 개발 이후 발생한 문제를 해결할 때 원인을 분석하는 데 꼭 필요한 요소이다.
자바 진영에서 가장 많이 사용되는 로깅 프레임워크는 Logback이다. Logback이란 log4j 이후에 출시된 로깅 프레임워크로서 slf4j를 기반으로 구현됐으며, 과거에 사용되던 log4j에 비해 월등한 성능을 자랑한다.
Logback의 특징은 다음과 같다.
@RestController
@RequestMapping("/api/v1/get-api")
public class GetController {
private final Logger logger = LoggerFactory.getLogger(GetController.class);
@GetMapping(value = "/name")
public String getName() {
logger.info("getName 메서드가 호출되었습니다.");
return "Flature";
}
}