API 작성 방법 - 컨트롤러 구성

김하영·2023년 5월 28일
0

출처: 스프링 부트 핵심 가이드 - 장정우 지음
https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=296591989

@RequestMapping

컨트롤러에 @RestController와 @RequestMapping("/어쩌구")를 붙여 내부에 선언되는 메서드에서 사용할 공통 URL을 설정할 수 있다. 클래스 수준에서 @RequestMapping()을 설정하면 내무에 선언한 메서드의 URL리소스 앞에 공통으로 값이 추가된다.
@RequestMapping 을 별다른 설정없이 선언하면 HTTP의 모든 요청을 받는다. method 속성을 추가하면 요청 형식을 지정해줄 수 있다.

GET API 만들기

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

1. @RequestMapping 활용

@RequestMapping(value = "/어쩌구", method = RequestMethod.GET)으로 메소드 속성을 정해주면 요청형식을 GET으로만 설정할 수 있다.

2. 매개변수가 없는 GET 메소드 구현

@GetMapping(value= "/hello")를 메소드앞에 붙여준다.

3. @PathVariable 활용

URL 자체에 값을 담아 요청하는 방법이다. 중괄호 부분에 요청인자로 받은 variable이 들어간다.
@GetMapping어노테이션과 @PathVariable에 지정된 변수의 이름을 동일하게 맞춰야한다!

// http://localhost:8080/vaiable1/{String 값}
@GetMapping(value = "/variable1/{variable}")
public String getVar(@PathVariable String variable){
	return variable;
}

만약 동이랗게 맞추기 어렵다면 @PathVariable 뒤에 괄호를 열어 @GetMapping어노테이션의 변수명을 지정해 준다.

// http://localhost:8080/vaiable1/{String 값}
@GetMapping(value = "/variable1/{variable}")
public String getVar(@PathVariable("variable") String var){
	return var;
}

4. @RequestParam을 활용

이 방법은 url경로에 값을 담아 요청을 보내는 방법이 아닌 쿼리형식으로 값을 전달한다. uri에서 '?'를 기준으로 {키}-{값}형태로 구성된 요청을 전송한다.

// http://localhost:8080/request1?name=value1&email=value2
@GetMapping(value = "/request1/")
public String getVar(
	@RequestParam String name, 
	@RequestParam String email){
	return name +" " + email;
}
  • 쿼리스트링에 어떤값이 들어올지 모를때 Map객체를 이용할 수 있다
  • 매개변수의 항목이 일정하지 않을때 Map객체로 받으면 효율적이다.
  • 다음과 같이 코드를 작성하면 값에 상관없이 요청받기 가능
// http://localhost:8080/request?name=value1&email=value2
@GetMapping(value = "/request1/")
public String getVar(
	@RequestParam Map<String, String> param){
	StringBuilder sb = new StringBuilder();
    param.entrySet().forEach(map-> sb.append(map.getKey+":"+map.getValue()+"\n"));
    return sb.toString();
}

5. DTO객체를 활용

DTO는 다른 레이거간의 데이터 교환에 활용된다. 즉 전달하는 매개변수로 사용되는 데이터 객체이다. 그래서 DTO에는 별도의 로직이 포함되지 않는다(필드 변수와 getter(), setter(), toString() 정도만 포함).
DTO클래스에 선언된 필드는 컨트롤러의 메서드에서 쿼리파라미터의 키와 매핑된다. 즉, 쿼리스트링의 키가 정해져 있지만 받아야할 파라미터라 많을 경우에 DTO객체를 활용해 코드의 가독성을 높일 수 있다.

// http://localhost:8080/request1?name=value1&email=value2
@GetMapping(value = "/request1/")
public String getVar(MemberDto memberDto){
	return memberDto.toString();
}

POST API 만들기

POST API는 웹 어플리케이션을 통해 데이터베이스 등의 저장소에 리소스를 저장할 때 사용된다. GET API에서는 url의 경로나 파라미터에 변수를 넣어 요청을 보냈지만 POST API에스는 저장하고자 하는 리소스나 값을 HTTP Body에 담아 서버에 전달한다. 그래서 URI가 GET API에 비해 간단하다.

1. @RequestMapping 활용

@RequestMapping(value="/hello", method = RequestMethod.POST) 처럼 method 요소를 RequestMethod.POST로 설정해준다.

2. @RequestBody를 활용

@RequestBody는 http body내용을 해당 어노테이션이 지정된 객체에 매핑하는 역할을 한다.
Map객체는 요청을 통해 어떤 값이 들어오게 될 지 특장하기 어려울 때 주로 사용한다.

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

요청 메세지에 들어갈 값이 정해져 있다면 DTO객체를 매개변수로 삼아 작성할 수 있다. 아래와 같이 작성하면 MemberDto의 멤버변수를 요청메세지의 키와 매핑해 값을 가져온다.

// http://localhost:8080/postrequest
@PostMapping(value = "/postrequest")
public String postVar(@RequestBody MemberDto memberDto){
	return memberDto.toString();
}

PUT API 만들기

PUT API는 웹어플리케이션 서버를 통해 데이터베이스 같은 저장소에 존재하는 리소스값을 업데이트하는데 사용한다. POST API와 비교하면 요청을 받아 실제 데이터베이스에 만영하는 과정(서비스로직)에 차이가 있지만 컨트롤러 클래스를 구현하는 방법은 POST API와 거의 동일하다. PUT API도 HTTP Body를 활용한다.

1. @RequestBody 활용

전달할 값을 HTTP Body에 담아 전달한다.
Map 사용 : 서버에 어떤 값이 들어올지 모르는 경우 map을 사용하여 값을 받을 수 있음.

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

DTO 사용: 서버에 들어오는 요청에 담겨있는 값이 정해져 있는경우 사용

// http://localhost:8080/putrequest
@PutMapping(value = "/putrequest")
public MemberDto putVar(@RequestBody MemberDto memberDto){
	return memberDto;
}

2. ResponseEntity를 활용

스프링 프래임워크의 HttpEntity클래스는 헤더와 바디로 구성된 HTTP 요청과 응답을 구성하는 역할을 수행한다. 이 클래스를 사용하면 헤더와 바디를 더욱 쉽게 구성할 수 있다. 또한 put메소드가 아니라 get, post 등 다른 메소드에서도 모두 사용할 수 있는 클래스이다!

@PutMapping(value="/putrequest")
public ResponseEntity<MemberDto> putMemberDto(@RequestBody MemberDto memberDto) {
	return ResponseEntity.status(HttpStatus.ACCEPTED).body(memberDto);

DELETE API 만들기

DELETE API는 웹어플리케이션 서브를 거쳐 데이터 베이스 드으이 저장소에 있는 리소스를 삭제할 때 사용한다. 서버에서는 클라언트로 부어 리소스를 식별할 수 있는 값을 받아 데이터베이스나 캐시에 있는 리소스를 조회하고 삭제하는 역할을 한다.
이때, 컨트롤러를 통해 값을 받는 단계에서는 간단한 값을 받기 때매 GET메소드처럼 URI에 값을 넣어 요청을 받는 형식으로 구현한다.

1. @PathVariable과 @RequestParam을 활용

@PathVariable 사용

// http://localhost:8080/{String 값}
@DeleteMapping(value = "/{variable}")
public String deleteVar(@PathVariable String variable){
	return variable;
}

@RequestParam 사용

// http://localhost:8080/delete-var?email=value
@DeleteMapping(value = "/delete-var")
public String deleteVar(@PathParam String email){
	return "email: "+email;
}

@RestController 어노테이션이 지정된 클래스는 @ResponseBody를 생략할 수 있는데, 이 @ResponseBody 어노테이션은 자동으로 값을 JSON과 같은 형식로 변환해서 전달하는 역할을 수행한다.

@RequestBody사용시 매개변수로
Map 사용 : 서버에 어떤 값이 들어올지 모르는 경우 map을 사용하여 값을 받을 수 있음.
DTO 사용: 서버에 들어오는 요청에 담겨있는 값이 정해져 있는경우 사용

REST API 명세를 문서화 하는 방법 - Swagger

API를 개발하면 명세를 관리해야한다. 명세는 API가 어떤 로직을 수행하느닞 설명하고 이 로직의 수행을위해 어떤 값을 요청하고, 그에따른 응답값으로 무엇을 받을 수 있는지를 정리한 자료이다. 이러한 명세작업을 편리하게 해주는 오픈소스가 Swagger이다.

Swagger 사용하기

  1. pom.xml에 swagger2, swagger-ui의존성을 추가한다.
  2. swagger관련 설정코드를 작성한다. (스웨거 설정코드는 검색하면 많이 나온다!)
    • 이 클래스는 configuration에 관한 클래스이므로 config 패키지를 생성하고 그안에 작성하는게 좋다.
    • 클래스 상단에 @Configuration, @EnableSwagger2어노테이션을 붙인다.
    • RequestHandlerSelectors.basePackage() 메서드로 스캔할 패키지 범위를 정할 수 있다.
  3. 어플리케이션을 실행한 후, 웹브라우저에 http://localhost:8080/swagger-ui.html로 접속하면 swagger 페이지에서 api 명세를 확인할 수 있다.
  4. @ApiOperation(value="Get 메소드 입니다", notes="@RequestParam을활용한 get method") 어노테이션을 GET메소드 위에 추가하면 해당 API의 설명을 붙일 수 있다.
  5. @ApiParam(value="이름", required=true)를 메소드의 매개변수앞에 붙이면 메개변수에 대한 설명을 추가할 수 있다. 메소드의 매개변수 뿐만아니라 DTO 객체를 매개변수로 사용할 경우 DTO클래스 내의 매개변수에도 정의할 수 있다.
  6. swagger는 API 명세 관리 뿐만 아니라 직접 통신도 시도할 수 있다!

로깅 라이브러리 - LogBack

로깅은 어플리케이션이 동작하는 동안 사스템의 상태나 동작 정보를 시간순으로 기록하는 것을 의미한다. 로깅은 비기능 요구사항으로 디버깅하거나 개발이후 발생한 문제를 해결할때 원인을 분석하는데 꼭 필요한 요소이다.

자바 진영헤서 가장 많이 사용되는 로깅 프레임워크는 LogBack이다. LogBack은 스프링 부트의 spring-boot-starter-web 라이브러리내부에 내장되어 있어 의존성을 추가하지 않아도 사용가능하다.

LogBack의 특징

  • TRACE, DEBUG,INFO,WARN, ERROR 5가지 로그레벨을 갖는다.
  • 실제 운영환경과 개발환경에서 각각 다른 출력레벨을 설정해서 로그 확인 가능
  • LogBack의 설정파일을 일정시간마다 스캔해서 어플리케이션을 재가동하지 않아도 설정변경가능
  • 별도의 프로그램 지원 없이도 자체적으로 로그파일 압축 가능
  • 저장된 로그파일에 대한 보관기간 등을 설정해서 관리가능

LogBack 설정

일반적으로 class path에 있는 설정파일을 자동으로 참조하므로 LogBack 설정파일은 resources폴더 안에 생성한다.
일반적인 자바나 스프링프로젝트에서는 logback.xml이름의 파일을 참조하지만 스프링부트에서는 logback-spring.xml파일을 참조한다.

로그백 설정파일은 몇가지 정해준 규칙을 따라 내용을 추가하면 된다. 설정은 검색하면 많이 나온다!

LogBack 설정 영역

  • Property
  • Appender : 로그 형태 설정, 어떤방법으로 출력할지
  • Pattern : Appender를 참조해서 로깅레발 설정
  • Root
  • Appender를 지우려면 따로 설정한 Root나 Logger영역에서도 레퍼런스로 잡혀있지 않은지 확인후 제거!

LogBack 적용

  • LogBack은 출력할 메세지를 Appender에게 전달할 Logger객체를 각 클래스에 정의해서 사용
  • 따라서 로그를 남길 클래스의 전역변수로 Logger객체를 생성해야 한다.
private final Logger LOGGER = LoggerFactory.getLogger(클래스이름.class);
  • 그리고 로그를 남길 메소드에 로그 내용을 작성한다.
LOGGER.info("어쩌구 메소드가 호출되었습니다");
  • 컨트롤러에 들어오는 값을 로그로 찍어보고 싶다면 {}를 이용한다.
// http://localhost:8080/vaiable1/{String 값}
@GetMapping(value = "/variable1/{variable}")
public String getVar(@PathVariable("variable") String var){
	LOGGER.info("@PathVariable을 통해 들어온 값: {}", var);
	return var;
}
profile
백엔드 개발자로 일하고 싶어요 제발

0개의 댓글