본문 바로가기
ZB 백엔드 스쿨/블로그 과제

스프링 핵심가이드) 북스터디 2주차 : 04~05장 API를 작성하는 다양한 방법

by son_i 2023. 9. 30.
728x90

04 스프링 부트 애플리케이션 개발하기

4.1 프로젝트 생성

 1. 인텔리제이 IDEA에서 생성 - ultimitate 버전에서만 가능

 2. Spring Initalizr - Community 버전에서 사용.


4.2 pom.xml(Project Object Model)

- pom.xml은 메이븐의 기능을 사용하기 위해 작성하는 파일.

- 프로젝트, 의존성 라이브러리, 빌드 등의 정보 및 해당 프로젝트를 관리하는데 필요한 내용있음.

 

- 빌드관리도구 ? ) JVM이나 WAS가 프로젝트를 인식하고 실행할 수 있게 작성한 소스코드와 프로젝트에 사용된 파일들(.xml, .jar, .properties)를 빌드하는 도구. 개발 규모가 커질수록 라이브러리들, 라이브러리 간 버전 호환성 체크에 용이

 

- 메이븐 : 자바 기반 프로젝트 빌드관리 도구. pom.xml을 사용하여 필요한 라이브러리 추가.

   * 대표기능 : 프로젝트 관리. 빌드 및 패키징, 테스트, 배포

 

- 메이븐의 생명주기 : 기본 생명주기, 클린 생명주기, 사이트 생명주기로 구분

 

- 스프링 부트 기본 웹 애플리케이션 실행 포트 : 8080

포트 변경 시 application.properties에 server.port=바꿀 값 입력

 

- 구글 Talend API Tester 를 이용하면 응답을 확인 할 수 있음. (post man 같은 서비스)

 


05 API를 작성하는 다양한 방법

5.1 프로젝트 설정

groupId : com.springboot, 

name, artifactId : api


5.2 GET API 만들기

- GET API는 웹 애플리케이션 서버에서 값을 가져올 때 사용하는 API

@RestController
@RequestMapping("/api/v1/get-api")
public class GetController {

}

- 클래스 수준에서 @RequestMapping을 설정하면 내부에 선언한 메서드의 URL 리소스 앞에 @RequestMapping의 값이 공통으로 추가됨.

 

- @RequestMapping 어노테이션을 별다른 설정 없이 선언하면 모든 HTTP 요청을 받음. 

  method 요소의 값을 requestMethod.GET으로 설정하면 요청 형식을 GET으로만 설정할 수 있음.

 

@RestController
@RequestMapping("/api/v1/get-api")
public class GetController {

	// http://localhost:8080/api/v1/get-api/hello GET 요청을 받는 메서드
	@RequsetMapping(value="/hello", method = RequsetMethod.GET)
    public String getHello() {
    	return "Hello World";
    }
}

 

- 스프링 4.3 버전 이후로는 축약형 매핑 어노테이션을 사용해서 @RequestMapping은 사용되지 않음.

- 축약형 매핑 어노테이션

 : @GetMapping, @PostMapping, @PutMapping, @DeleteMapping

 

- 매개변수가 없는 GET 메서드 구현

@GetMapping(value="/hello")
public String getName() {
	return "Hello World";
}

 

- @PathVariable을 활용한 메서드 구현 : URL 자체에 값을 담아 요청

@GetMapping(value="/variable1/{variable}")
public String getVariable1(@PathVariable String variable) {
	return variable;
}

{} 안에 표시된 위치의 값을 받아 요청함. {}안의 값과 변수의 값이 동일해서 자동으로 String variable에 값이 받아짐.

변수명이 다를 경우 URL에서 받아오는 변수의 이름을 @PathVariable("variable") 이렇게 작성해주면 됨.

 

- @RequestParam을 활용한 GET메서드 구현 : URL경로에 쿼리 형식으로 값 전달

URI에서 ?를 기준으로 {키}={값} 형태로 구성된 값 전송.

// http://localhost:8080/api/v1/get-api/request1?name=value1&email=value2&organization=value3
@GetMapping(value="/request1")
public String getReqeustParam1(
	@RequestParam String name,
    @RequestParam String email,
    @ReqeustParam String organization) {
	return name + " " + email + " " + organization;
}

동일하게 URL에 명시한 키값과 @RequestParam뒤에 변수값과 동일하면 자동으로 값이 들어감.

동일하게 해주기 어렵다면 @RequestParam("name") 형식으로 어떤 키의 값을 가져올지 지정해주면 됨.

 

  - 쿼리 스트링에 어떤 값이 들어올지 모른다면 Map 객체를 활용할 수도 있음.

// http://localhost:8080/api/v1/get-api/request2?key1=value1&key2=value2
@GetMapping(value="/request2")
public String getReqeustParam2(
	@RequestParam Map<String, String> param) {
    StringBuilder sb = new StringBuilder();
    param.entrySet().forEach(map ->
    	sb.append(map.getKey() + " : " + map.getValue() + "\n");
    });
	return sb.toString();
}

위와 같이 작성하면 값에 상관없이 요청을 받을 수 있음. 예를들어 회원가입 관련 API에서 사용자는 회원가입을 하면서 ID같은 필수가 아닌 취미 같은 선택항목을 기입하지 않으면 매개변수의 항목이 일정하지 않을 수 있어 Map 객체로 받는 것이 효율적.

 

*URL과 URI의 차이 

 : URL은 흔히 말하는 웹주소 의미. 리소스가 어디있는지 알려주기 위한 경로

 : URI는 특정 리소스를 식별할 수 있는 식별자를 의미

웹에서는 URL을 통해 리소스가 어느 서버에 위치해 있는지 알 수 있으며, 그 서버에 접근해서 리소스에 접근하기 위해서는 대부분 URI가 필요하다.

 

- DTO 객체를 활용한 GET메서드 구현

 * DTO란 ? ) 다른 레이어간의 데이터 교환에 활용.

나같은 경우는 프로젝트에서 클라이언트와 컨트롤러간의 요청과 응답, 컨트롤러와 서비스간의 요청과 응답을 처리하기 위해 DTO객체를 만들어서 처리해봤음.

 

- DTO 객체 생성

@Getter
@Setter
@ToString
public class MemberDto{
	private String name;
    private String email;
    private String organization;
 }

 

DTO 클래스에 선언된 필드는 컨트롤러의 메서드에서 쿼리 파라미터의 키와 매핑.

쿼리스트링의 키가 정해져있지만 받아야 할 파라미터가 많을 경우 DTO객체를 활용해 코드의 가독성을 높일 수 있음.

// http://localhost:8080/api/v1/get-api/request3?name=value1&email=value2&organization=value3
@GetMapping(value="/request3")
public String getReqeustParam3(MemberDto memberDto) {
    return memberDto.toString();
}

5.3 POST API 만들기

- POST API는 웹 어플리케이션을 통해 데이터베이스 등의 저장소에 리소스를 저장할 때 사용되는 API

POST API에서는 저장하고자 하는 리소스나 값을 URL이 아닌 HTTP 바디에 담아 서버에 전달.

(물론 URL에 담아도 됨) 따라서 URI가 GET API에 비해 간단.

 

@RestController
@RequestMapping("/api/v1/post-api")
public class PostController {

	// http://localhost:8080/api/v1/post-api/domain POST 요청을 받는 메서드
	@RequsetMapping(value="/domain", method = RequsetMethod.POST)
    public String postExample() {
    	return "Hello World";
    }
}

Http Body영역에 데이터를 넣어서 전송. Body영역에 작성되는 값은 일반적으로 JSON형태로 구성

 

// http://localhost:8080/api/v1/post-api/member
@PostMapping(value="/member")
public String postMember(@RequestBody Map<String, Object> postData) {
    StringBuilder sb = new StringBuilder();
    
    postData.entrySet().forEach(map ->
    	sb.append(map.getKey() + " : " + map.getValue() + "\n");
    });
	return sb.toString();
}

@RequestBody는 HTTP Body의 내용을 해당 어노테이션이 지정된 객체에 매핑.

Map은 요청을 통해 어떤 값이 들어오게 될지 특정하기 어려울 때 주로 사용.

요청 메세지에 들어갈 값이 정해져 있따면 DTO객체를 매개변수로 삼아 작성할 수 있음.

 

// http://localhost:8080/api/v1/post-api/member2
@PostMapping(value="/request3")
public String postMemberDto(@RequestBody MemberDto memberDto) {
    return memberDto.toString();
}

MemberDto의 멤버 변수를 요청메세지의 키와 매핑해 값을 가져옴.

 


5.4 PUT API 만들기

- PUT API는 웹 애플리케이션 서버를 통해 DB같은 저장소에 있는 값을 업데이트하는데 사용.

리소스를 서버에 전달하기 위해 HTTP Body 활용

 

// http://localhost:8080/api/v1/put-api/member
@PutMapping(value="/member")
public String putMember(@RequestBody Map<String, Object> putData) {
    StringBuilder sb = new StringBuilder();
    
    postData.entrySet().forEach(map ->
    	sb.append(map.getKey() + " : " + map.getValue() + "\n");
    });
	return sb.toString();
}

 

@RestController 어노테이션은 자동으로 값을 JSON과 같은 형식으로 변환해서 전달하는 역할 수행.

 

- ResponseEntity를 활용한 PUT 메서드 구현

 스프링 프레임워크의 HttpEntity는 헤더와 바디로 구성된 HTTP 요청과 응답을 구성하는역할을 수행.

 

public class HttpEntity<T> {
	private final HttpHeaders headers;
    
    @Nullable
    private final T body;
}

 

RequestEntity와 ResponseEntity는 HttpEntity를 상속받아 구현한 클래스.

ResponseEntity는 서버에 들어온 요청에 대해 응답데이터를 구성해서 전달 할 수 있게 함.

public class ResponseEntity<T> extends HttpEntity<T>{
	private final Object status;
    
    ....
}

 

// http://localhost:8080/api/v1/put-api/member3
@PutMapping(value="/member3")
public ResponseEntity<MemberDto> putMemberDto3(@RequestBody MemberDto memberDto) {
	return ResponseEntity
    	.status(HttpStatus.ACCEPTED)
        .body(memberDto);
}

HttpStatus.ACCEPTED는 응답코드 202를 가짐.


5.5 DELETE API 만들기

- DELETE API는 웹 애플리케이션 서버를 거쳐 DB의 저장소에 있는 리소스 삭제할 때 사용.

GET과 같이 URI에 값을 넣어 요청을 받는 형식으로 구현.

 

- @PathVariable과 @RequestParam을 활용한 DELETE 메서드 구현

@RestController
@RequestMapping("/api/v1/delete-api")
public class DeleteController {
	// http://localhost:8080/api/v1/delete-api/{String값}
	@DeleteMapping(value="/{variable}")
	public String deleteVariable(@PathVariable String variable) {
		return variable;
	}
}

@DeleteMapping 어노테이션의 value값과 메서드 매개변수 이름 동일해야 삭제할 값이 주입.

 

- @RequestParam 사용해 쿼리스트링의 값을 받을 수 있음.

// http://localhost:8080/api/v1/delete-api/request1?email=value
@DeleteMapping(value="/request1")
public String getRequestParam1(@RequestParam String email) {
	return "e-mail : " + email;
}

5.6 Swagger : REST API 명세 문서화

pom.xml파일에 의존성 추가

config/SwaggerConfiguration에 swagger관련 코드 작성.

 

@ApiOperation : 대상 API의 설명을 작성하기 위한 어노테이션

@ApiParam : 매개변수에 대한 설명 및 설정을 위한 어노테이션. 메서드의 매개변수 뿐 아니라 DTO객체를 매개변수로 사용할 경우 DTO클래스 내의 매개변수에도 정의할 수 있다.


5.7 로깅 라이브러리 - Logback

로깅이란 애플리케이션이 동작하는 동안 시스템의 상태나 동작 정보를 시간순으로 기록하는 것.

 

- 자바에서 가장 많이 사용되는 로깅 프레임워크는 Logback

- 로그레벨 : ERROR, WARN, INFO, DEBUG, TRACE

 

logback-spring.xml에 로그 관련 설정을 넣음.

 

- Appender영역

 : 로그의 형태를 설정하고 어떤 방법으로 출력할지를 설정함. Appender자체는 하나의 인터페이스를 의미하고 하위에 여러 구현체가 존재.

 

  - 대표적 구현체 : ConsoleAppender, FileAppender, RollingFileAppender, SMTPAppender, DBAppender

 

  - encoder요소를 통해 로그의 표현 형식을 패턴으로 정의.

 

- Root 영역

 : 설정파일에 정의된 Appender를 활용하려면 Root 영역에서 Appender를 참조해서 로깅 레벨을 설정