본문 바로가기

Spring Boot

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

728x90

5.1 프로젝트 설정

 

5.2 GET API 만들기

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

1
2
3
4
5
6
7
8
9
10
11
package com.springboot.api.controller;
 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
@RequestMapping("/api/v1/get-api")
public class GetController {
    
}
cs

내부에 선언되는 메서드에서 사용할 공통 URL 설정

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

더보기

5.2.1 @RequestMapping으로 구현하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.springboot.api.controller;
 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
 
// RequestMethod.GET 으로 설정하여 요쳥 형식을 GET 으로만 함
// 스프링 4.3 버전 이후로는 @RequestMapping 안 씀
@RestController
@RequestMapping("/api/v1/get-api")
public class GetController {
    
    // http://localhost:8080/api/v1/get-api/hello
    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String getHello(){
        return "Hello World";
    }
}
cs

RequestMethod.GET으로 요청 형식을 GET으로만 설정함

스프링 4.3 이후로는 안 씀

더보기

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.springboot.api.controller;
 
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
 
 
@RestController
@RequestMapping("/api/v1/get-api")
public class GetController {
 
    // http://localhost:8080/api/v1/get-api/name
    @GetMapping(value = "/name")
    public String getName(){
        return "Flature";
    }
}
cs

실무에서는 거의 안 쓰임

 

5.2.3 @PathVariable을 활용한 GET 메서드 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.springboot.api.controller;
 
import org.springframework.web.bind.annotation.*;
 
@RestController
@RequestMapping("/api/v1/get-api")
public class GetController {
 
    // http://localhost:8080/api/v1/get-api/variable1/{String 값}
    @GetMapping(value = "/variable1/{variable}")
    public String getVariable1(@PathVariable String variable){
        return variable;
    }
}
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.springboot.api.controller;
 
import org.springframework.web.bind.annotation.*;
 
@RestController
@RequestMapping("/api/v1/get-api")
public class GetController {
 
    // http://localhost:8080/api/v1/get-api/variable2/{String 값}
    @GetMapping(value = "/variable2/{variable}")
    public String getVariable2(@PathVariable("variable"String var){
        return var;
    }
}
cs

URL에 값을 담아 전달되는 요청을 처리하는 방법

5.2.4 @RequestParam을 활용한 GET 메서드 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.springboot.api.controller;
 
import org.springframework.web.bind.annotation.*;
 
@RestController
@RequestMapping("/api/v1/get-api")
public class GetController {
 
    // http://localhost:8080/api/v1/get-api/request1?name=value1&email=value2&organization=value3
    @GetMapping(value = "/request1")
    public String getRequestParam1(
            @RequestParam String name,
            @RequestParam String email,
            @RequestParam String organization) {
        return name + " " + email + " " + organization;
    }
}
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.springboot.api.controller;
 
import org.springframework.web.bind.annotation.*;
 
import java.util.Map;
 
@RestController
@RequestMapping("/api/v1/get-api")
public class GetController {
 
    // http://localhost:8080/api/v1/get-api/request2?key1=vlaue1&key2=value2
    @GetMapping(value = "/request2")
    public String getRequestParam2(@RequestParam Map<StringString> param) {
        StringBuilder sb = new StringBuilder();
        param.entrySet().forEach(map -> {
            sb.append(map.getKey() + " : " + map.getValue() + "\n");
        });
        
        return sb.toString();
    }
}
cs

쿼리 형식으로 값 전달 가능

'?'를 기준으로 우측에 '{키}={값}' 형태(쿼리 스트링)로 구성된 요청 전송

쿼리 스트링에 어떤 값이 들어올지 모를 때 Map 객체 활용

 

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.springboot.api.dto;
 
public class MemberDto {
 
    private String name;
    private String email;
    private String organization;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getEmail() {
        return email;
    }
 
    public void setEmail(String email) {
        this.email = email;
    }
 
    public String getOrganization() {
        return organization;
    }
 
    public void setOrganization(String organization) {
        this.organization = organization;
    }
 
    @Override
    public String toString() {
        return "MemberDto{" +
                "name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", organization='" + organization + '\'' +
                '}';
    }
}
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.springboot.api.controller;
 
import com.springboot.api.dto.MemberDto;
import org.springframework.web.bind.annotation.*;
 
import java.util.Map;
 
@RestController
@RequestMapping("/api/v1/get-api")
public class GetController {
 
    // http://localhost:8080/api/v1/get-api/request3name=value1&email=value2&organization=value3
    @GetMapping(value = "/request3")
    public String getRequestParam3(MemberDto memberDto) {
        return memberDto.toString();
    }
}
cs

DTO(Data Transfer Object)는 다른 레이어 간의 데이터 교환에 활용된다.

 

5.3 POST API 만들기

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

1
2
3
4
5
6
7
8
9
10
package com.springboot.api.controller;
 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
@RequestMapping("/api/v1/post-api")
public class PostController {
    
}
cs

 

5.3.1 @RequestMapping으로 구현하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.springboot.api.controller;
 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
@RequestMapping("/api/v1/post-api")
public class PostController {
    
    @RequestMapping(value = "/domain", method = RequestMethod.POST)
    public String postExample(){
        return "Hello Post API";
    }
}
cs

 

5.3.2 @RequestBody를 활용한 POST 메소드 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.springboot.api.controller;
 
import org.springframework.web.bind.annotation.*;
 
import java.util.Map;
 
@RestController
@RequestMapping("/api/v1/post-api")
public class PostController {
 
    // 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();
    }
}
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.springboot.api.controller;
 
import com.springboot.api.dto.MemberDto;
import org.springframework.web.bind.annotation.*;
 
import java.lang.reflect.Member;
import java.util.Map;
 
@RestController
@RequestMapping("/api/v1/post-api")
public class PostController {
 
    // http://localhost:8080/api/v1/post-api/member2
    @PostMapping(value = "/member2")
    public String postMemberDto(@RequestBody MemberDto memberDto) {
        return memberDto.toString();
    }
}
cs

POST 요청에서는 리소스를 담기 위해 HTTP Body에 값을 넣어 전송한다.

Talend API Test로 Body 영역에 값을 입력했다. 이때 JSON 형식으로 전송된다.

DTO 객체를 매개변수로 작성할 수도 있다. 

 

5.4 PUT API 만들기

PUT API는 웹 애플리케이션 서버를 통해 데이터베이스 같은 저장소에 존재하는 리소스 값을 업데이트하는 데 사용한다.

리소스를 서버에 전달하기 위해 HTTP Body를 활용해야 하기 때문에 컨트롤러 클래스 구현 방법은 POST API와 거의 동일하다.

1
2
3
4
5
6
7
8
9
10
package com.springboot.api.controller;
 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
@RequestMapping("/api/v1/put-api")
public class PutController {
 
}
cs

 

5.4.1 @RequestBody를 활용한 PUT 메서드 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.springboot.api.controller;
 
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import java.util.Map;
 
@RestController
@RequestMapping("/api/v1/put-api")
public class PutController {
 
    //http://localhost:8080/api/v1/put-api/member
    @PutMapping(value = "/member")
    public String postMember(@RequestBody Map<String, Object> putData) {
        StringBuilder sb = new StringBuilder();
 
        putData.entrySet().forEach(map -> {
            sb.append(map.getKey() + " : " + map.getValue() + "\n");
        });
 
        return sb.toString();
    }
}
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.springboot.api.controller;
 
import com.springboot.api.dto.MemberDto;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import java.util.Map;
 
@RestController
@RequestMapping("/api/v1/put-api")
public class PutController {
 
    //http://localhost:8080/api/v1/put-api/member1
    @PutMapping(value = "/member1")
    public String postMemberDto1(@RequestBody MemberDto memberDto) {
        return memberDto.toString();
    }
 
    //http://localhost:8080/api/v1/put-api/member2
    @PutMapping(value = "/member2")
    public MemberDto postMemberDto2(@RequestBody MemberDto memberDto) {
        return memberDto;
    }
}
cs

postMemberDto1 : 일반 문자열 

postMemberDto2 : JSON

 

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.springboot.api.controller;
 
import com.springboot.api.dto.MemberDto;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import java.util.Map;
 
@RestController
@RequestMapping("/api/v1/put-api")
public class PutController {
 
    //http://localhost:8080/api/v1/put-api/member3
    @PutMapping(value = "/member3")
    public ResponseEntity<MemberDto> postMemberDto3(@RequestBody MemberDto memberDto) {
        return ResponseEntity
                .status(HttpStatus.ACCEPTED)
                .body(memberDto);
    }
}
cs

스프링 프레임워크에는 HttpEntity라는 클래스가 있다. 이는 헤더와 바디로 구성된 HTTP 요청과 응답을 구성하는 역할을 수행한다.

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

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

 

5.5 DELETE API 만들기

DELETE API는 웹 애플리케이션 서버를 거쳐 데이터베이스 등의 저장소에 있는 리소스를 삭제할 때 사용한다.

서버에서는 클라이언트로부터 리소스를 식별할 수 있는 값을 받아 데이터베이스나 캐시에 있는 리소스를 조회하고 삭제한다.

1
2
3
4
5
6
7
8
9
10
package com.springboot.api.controller;
 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
@RequestMapping("/api/v1/delete-api")
public class DeleteController {
    
}
cs

 

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.springboot.api.controller;
 
import org.springframework.web.bind.annotation.*;
 
@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;
    }
 
    // http://localhost:8080/api/v1/delete-api/request1?email=value
    @DeleteMapping(value = "/request1")
    public String getRequestParam1(@RequestParam String email) {
        return "e-mail : " + email;
    }
}
cs

 

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

명세란 해당 API가 어떤 로직을 수행하는지 설명하고 어떤 값을 요청하며 무엇을 받을 수 있는지 정리한 자료이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.springboot.api.controller;
 
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;
 
import java.util.Map;
 
@RestController
@RequestMapping("/api/v1/get-api")
public class GetController {
 
    @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;
    }
}
cs

기존 코드에 Swagger 명세를 추가하였다.

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

@ApiParam : 매개변수에 대한 설명 및 설정을 위한 어노테이션. DTO 클래스 내의 매개변수에도 정의 가능하다.

 

⚠️http://localhost:/swagger-ui.html 접속이 안 될 때⚠️

https://velog.io/@gillog/Error-Swagger-2.9.2-swagger-ui.html-열리지-않을때-해결

 

5.7 로깅 라이브러리 - Logback

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

개발 영역 중 '비기능 요구사항'에 속하여 사용자나 고객에게 필요한 기능은 아니다.

하지만 로깅은 디버깅하거나 개발 이후 발생한 문제를 해결할 때 원인을 분석하는 데 꼭 필요한 요소이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.springboot.api.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
 
import java.util.Map;
 
@RestController
@RequestMapping("/api/v1/get-api")
public class GetController {
 
    private final Logger LOGGER = LoggerFactory.getLogger(GetController.class);
 
    // http://localhost:8080/api/v1/get-api/hello
    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String getHello() {
        LOGGER.info("getHello 메서드가 호출되었습니다.");
        return "Hello World";
    }
 
    // http://localhost:8080/api/v1/get-api/variable1/{String 값}
    @GetMapping(value = "/variable1/{variable}")
    public String getVariable1(@PathVariable String variable){
        LOGGER.info("@PathVariable을 통해 들어온 값 : {}", variable);
        return variable;
    }
}
 
cs

 

 

 

 

 

from 스프링 부트 핵심 가이드: 스프링 부트를 활용한 애플리케이션 개발 실무 (장정우, 위키북스)