[SpringBoot] API ์ž‘์„ฑ

Coastbyยท2022๋…„ 10์›” 27์ผ
0

LIKELION Back-End School

๋ชฉ๋ก ๋ณด๊ธฐ
46/61

5. API๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•

๐Ÿ’ก API ๋ฌธ์„œ: API ์“ฐ๋Š” ๋ฒ•์„ ๊ธฐ์ˆ ํ•ด๋†“์€ ๋ฌธ์„œ, ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•๊ณผ ๊ทœ๊ฒฉ์„ ์ œ๊ณตํ•˜๋Š” ๋ฌธ์„œ.

๐Ÿ“’ย GitHub API ๋ฌธ์„œ๋ณด๊ธฐ

๊นƒํ—™์˜ API ๋ฌธ์„œ

#URL sample
[GET] /repos/{owner}/{repo}/commits
https://api.github.com/repos/OWNER/REPO/commits
//๋‚˜์˜ ๊นƒํ—™ commits API URL
https://api.github.com/repos/coastby/java-project2/commits

โ—‹ Path Parameter

  • ์ฃผ์†Œ๋ฅผ ํ†ตํ•ด ๊ฐ’์„ ๋„˜๊ธธ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.
  • ์ฃผ๋กœ id ๋“ฑ ๊ผญ ๋„ฃ์–ด์ค˜์•ผํ•˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ

owner stringRequired : The account owner of the repository. The name is not case sensitive.

repo stringRequired : The name of the repository. The name is not case sensitive.

โ—‹ Query parameter

  • ? ๋’ค๋กœ ์ „๋‹ฌํ•˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ
  • ์„ ํƒ์ ์œผ๋กœ ์žˆ์–ด๋„ ๋˜๊ณ  ์—†์–ด๋„ ๋˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ

sha string : SHA or branch to start listing commits from. Default: the repositoryโ€™s default branch (usuallyย master).

path string : Only commits containing this file path will be returned.

author string : GitHub login or email address by which to filter by commit author.

since string : Only show notifications updated after the given time. This is a timestamp inย ISO 8601ย format:ย YYYY-MM-DDTHH:MM:SSZ.

until string : Only commits before this date will be returned. This is a timestamp inย ISO 8601ย format:ย YYYY-MM-DDTHH:MM:SSZ.

per_page integer : The number of results per page (max 100).
Default:ย 30

page integer : Page number of the results to fetch.
Default:ย 1

โ—‹ HTTP response status codes

Status codeDescription
200OK
400Bad Request
404Resource not found
409Conflict
500Internal Error



5.2.4 @RequestParam์„ ์ด์šฉํ•œ GET ๊ตฌํ˜„


  • Query Parameter : GET ์š”์ฒญ์—์„œ ? ๋’ค์˜ ์ฟผ๋ฆฌ์ŠคํŠธ๋ง(query string)์€ โ€˜{key}={value}โ€™ ํ˜•ํƒœ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค.
  • @RequestParam : ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์˜ ํ‚ค๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๋งคํ•‘ํ•˜๋ฉด ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค. key๊ฐ’๊ณผ ๋งค๊ฐœ๋ณ€์ˆ˜๋ช…์ด ๊ฐ™์•„์•ผ ํ•˜๋Š”๋ฐ, ๊ทธ๋Ÿด ์ˆ˜ ์—†๋‹ค๋ฉด @RequestParam(โ€keyโ€)๋กœ ๋งคํ•‘ํ•œ๋‹ค.
    ์ฐธ๊ณ ) @PathVariable : URL ์ž์ฒด์— ๋‹ด๊ธด ๋ณ€์ˆ˜ (Path Parameter)๋ฅผ ๋ฐ›์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.
//๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด value๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
@RequestParam String name

//์–ด๋–ค ๊ฐ’์ด ๋“ค์–ด์˜ฌ ์ง€ ๋ชจ๋ฅด๋ฉด Map์„ ์ด์šฉํ•œ๋‹ค.
@RequestParam Map<String, String> param

[์‹ค์Šต1] @RequestParam์„ ์ด์šฉํ•œ GET ๊ตฌํ˜„

์ฟผ๋ฆฌ์ŠคํŠธ๋ง์— ์–ด๋–ค ๊ฐ’์ด ๋“ค์–ด์˜ฌ์ง€ ๋ชจ๋ฅธ๋‹ค๋ฉด Map์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  1. Map์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๋Š” RequestParam ์ž‘์„ฑ
@GetMapping(value = "/request2")
public String getRequestParam2 (@RequestParam Map<String, String> param){
    param.entrySet().forEach((map) -> {
        System.out.printf("key : %s, value : %s", map.getKey(), map.getValue());
    });
    return "ํ˜ธ์ถœ์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.";
}
  1. API tester
http://localhost:8080/api/v1/get-api/request2?name=hoon&weight=7.6
  1. ๊ฒฐ๊ณผ
    a. client ํ™”๋ฉด

    b. console

    key : name, value : hoon
    key : weight, value : 7.6

    ๐Ÿšซ Error 400: ์„œ๋ฒ„ ๋‚ด๋ ธ๋‹ค๊ฐ€ ๋‹ค์‹œ ์˜ฌ๋ ค์•ผ ํ•˜๋Š”๋ฐ ๋ฐ”๋กœ ํ•จ


5.2.5 DTO ๊ฐ์ฒด ์ด์šฉํ•œ GET ๊ตฌํ˜„


DAO (data access object)

  • ๋ฐ์ดํ„ฐ๋ฅผ insert, findById, getCount, deleteAll (Create, Read, Update, Delete)

DTO (Data Transfer Object)

  • ๋‹ค๋ฅธ ๋ ˆ์ด์–ด ๊ฐ„์˜ ๋ฐ์ดํ„ฐ ๊ตํ™˜์— ํ™œ์šฉ, ๋ฐ์ดํ„ฐ ์ปจํ…Œ์ด๋„ˆ ๊ฐœ๋…
  • ๋กœ์ง์ด ํฌํ•จ๋˜์ง€ ์•Š๋Š”๋‹ค.
  • ex) User

VO (Value Object)

  • ๊ฐ’์ด ์žˆ๋Š” ํด๋ž˜์Šค
  • DTO์™€ ํ˜ผ์šฉํ•˜์ง€๋งŒ, ์—„๋ฐ€ํžˆ๋Š” ๋‹ค๋ฅด๋‹ค
  • ์ฝ๊ธฐ์ „์šฉ (Read-Only)๋กœ ์„ค๊ณ„ํ•˜๋ฉฐ, ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๊ฒŒ ๋งŒ๋“ค์–ด ์‹ ๋ขฐ์„ฑ์„ ์œ ์ง€ํ•œ๋‹ค.
  • ex) Node : key์™€ value๊ฐ€ ์žˆ๋‹ค.

๐Ÿ’ก VO ๊ฐ์ฒด

  • ์ปค๋งจ๋“œ ๊ฐ์ฒด: HttpServletRequest๋ฅผ ํ†ตํ•ด ๋“ค์–ด์˜จ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค์„ setter ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฐ์ฒด์— ์ •์˜๋˜์–ด์žˆ๋Š” ์†์„ฑ์— ๋ฐ”์ธ๋”ฉ์ด ๋˜๋Š” ๊ฐ์ฒด
  • ์ปจํŠธ๋กค๋Ÿฌ๋Š” ์ž๋ฐ”์˜ ๋ชจ๋“  ์ž๋ฃŒํ˜•์„ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ์Œ. VO ๊ฐ์ฒด ๋˜ํ•œ ๊ฐ€๋Šฅ!
  • VO ๊ฐ์ฒด๋Š” ํ•„๋“œ๋ช…์ด ์ค‘์š”! ํด๋ž˜์Šค์— ๊ฐ๊ฐ์˜ ํ•„๋“œ๋ช…์ด ์กด์žฌํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ํ•„๋“œ๋ช…์„ ์ด์šฉํ•ด์„œ ์ž๋ฃŒ๋ฅผ ์ž…๋ ฅ๋ฐ›์Œ (๊ฐ์ฒด๋ช…๊ณผ ๋ฌด๊ด€)
  • ๋ฉ”์„œ๋“œ์—์„œ ํด๋ž˜์Šค๋‚˜ VO๊ฐ€ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋“ค์–ด์˜ค๋ฉด ํผ์—์„œ ํด๋ž˜์Šค ํ˜น์€ VO๊ฐ€ ์—†๋„ค~๊ทธ๋ƒฅ ๋ฌด์‹œํ•˜์ž~๊ฐ€ ์•„๋‹ˆ๋ผ
  • VO๋ฅผ ๋งŒ๋‚˜๋Š” ์ˆœ๊ฐ„ ์–ด! VO ๊ฐ์ฒด๋„ค? ๊ทธ๋Ÿผ ๋ณ€์ˆ˜๋ช…์„ ๋“ค์—ฌ๋‹ค๋ณผ๊นŒ? ํ•ด์„œ ๋ณ€์ˆ˜๋ช…์œผ๋กœ ๋งค์นญํ•ด์คŒ

[์‹ค์Šต2] DTO ๊ฐ์ฒด๋ฅผ ํ™œ์šฉํ•œ GET ๋ฉ”์„œ๋“œ ๊ตฌํ˜„

  1. ๐Ÿ“„ย MemberDto : ํ•„๋“œ๋ณ€์ˆ˜, constructor, getter, toString()๋งŒ ๊ตฌํ˜„

    • โŒจ๏ธย ์ฝ”๋“œ
      public class MemberDto {
          private String name;
          private String email;
          private String organization;
      
          public MemberDto(String name, String email, String organization) {
              this.name = name;
              this.email = email;
              this.organization = organization;
          }
      
          public String getName() {
              return name;
          }
      
          public String getEmail() {
              return email;
          }
      
          public String getOrganization() {
              return organization;
          }
      
          @Override
          public String toString() {
              return "MemberDto{" +
                      "name='" + name + '\'' +
                      ", email='" + email + '\'' +
                      ", organization='" + organization + '\'' +
                      '}';
          }
      }
  2. ๐Ÿ“„ย Controller : ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ DTO๋ฅผ ๋ฐ›์Œ
    a. DTO ํด๋ž˜์Šค์— ์„ ์–ธ๋œ ํ•„๋“œ๋Š” ์ปจํŠธ๋กค๋Ÿฌ์˜ ๋ฉ”์„œ๋“œ์—์„œ ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ํ‚ค์™€ ๋งคํ•‘๋œ๋‹ค.
    b. ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์˜ ํ‚ค๊ฐ€ ์ •ํ•ด์ ธ ์žˆ์ง€๋งŒ ๋ฐ›์•„์•ผ ํ•  ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ๋งŽ์„ ๊ฒฝ์šฐ DTO ๊ฐ์ฒด๋ฅผ ํ™œ์šฉํ•ด ์ฝ”๋“œ ๊ฐ€๋…์„ฑ์„ ๋†’์„ ์ˆ˜ ์žˆ๋‹ค.

    @GetMapping(value="/request3")
    public String getRequestParam3(MemberDto memberDto){
        return memberDto.toString();
    }
  3. API tester

http://localhost:8080/api/v1/get-api/request3?name=hoon&email=bob@gmai.com&organization=yeji
  1. ๊ฒฐ๊ณผ ํ™”๋ฉด

5.3 POST API ๋งŒ๋“ค๊ธฐ


โญ๏ธ POST API

  • ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ†ตํ•ด DB์— ๋ฆฌ์†Œ์Šค๋ฅผ ์ €์žฅํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” API๋‹ค.
  • GET API๋Š” URL ๋˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด์ง€๋งŒ, POST API๋Š” ๋ฆฌ์†Œ์Šค๋‚˜ ๊ฐ’์„ HTTP Body์— ๋‹ด์•„ ์ „๋‹ฌํ•œ๋‹ค.(์ผ๋ฐ˜์ ์œผ๋กœ JSON ํ˜•์‹)
  • URI๋Š” GET API์— ๋น„ํ•ด ๊ฐ„๋‹จํ•˜๋‹ค.

โญ๏ธ ๋ฉด์ ‘ ์งˆ๋ฌธ - GET๊ณผ Post ์ฐจ์ด

  1. ๊ฐ€์žฅ ํฐ ์ฐจ์ด์ ์€ HTTP ์š”์ฒญ์„ ํ•  ๋•Œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ path๋‚˜ ์ฟผ๋ฆฌํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์“ฐ์ง€ ์•Š๊ณ  Request Body์— ๋ณด๋‚ธ๋‹ค.
  2. ์ฃผ๋กœ ํšŒ์›๊ฐ€์ž… ๋“ฑ Http์ „์†ก ์ค‘ ๋…ธ์ถœ๋˜๋ฉด ์•ˆ๋˜๋Š” ์ •๋ณด๋ฅผ ๋ณด๋‚ผ ๋•Œ Post๋ฅผ ์”๋‹ˆ๋‹ค.

โญ๏ธ JSON (JavaScript Object Notation)

  • ์ž๋ฐ” ์Šคํฌ๋ฆฝํŠธ์—์„œ Object (Class) ํ‘œํ˜„๋ฒ•
  • ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›์„ ๋•Œ ์ž๋ฃŒ ํ˜•์‹
  • JSON์€ Key:Value ํ˜•์‹์œผ๋กœ ์ž๋ฃŒํ˜• Dictionary์™€ ์œ ์‚ฌํ•˜๋‹ค

โญ๏ธ @RequestBody

  • HTTP Body ๋‚ด์šฉ์„ ๊ฐ์ฒด์— ๋งคํ•‘ํ•˜๋Š” ์—ญํ• 
  • Map ๊ฐ์ฒด๋Š” ์š”์ฒญ์„ ํ†ตํ•ด ์–ด๋–ค ๊ฐ’์ด ๋“ค์–ด์˜ค๊ฒŒ ๋ ์ง€ ํŠน์ •ํ•˜๊ธฐ ์–ด๋ ค์šธ ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉ
  • JSON ํ˜•์‹์—์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋–ค ํ˜•์‹์œผ๋กœ ๋“ค์–ด์˜ฌ ์ง€ ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— Value๋ฅผ Object๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค.

[์‹ค์Šต 3] @RequestBody๋กœ POST ๋ฉ”์„œ๋“œ ๊ตฌํ˜„

  1. โŒจ๏ธย Controller ์ž‘์„ฑ
@PostMapping(value = "/member")
public String postMember(@RequestBody Map<String, Object> postData) {
    StringBuilder sb = new StringBuilder();         //Builder Pattern

    postData.entrySet().forEach(map -> {
        sb.append(map.getKey()+" : "+map.getValue() + "\n");
    });
    return sb.toString();
}
  1. API Tester
    a. URI
    http://localhost:8080/api/v1/post-api/member
    b. BODY
    {
      "name" : "hoon",
      "email" : "sleeping@gmail.com",
      "organization" : "yeji"
    }
  2. ๊ฒฐ๊ณผ
    name : hoon
    email : sleeping@gmail.com
    organization : yeji

๐Ÿšซย ์—๋Ÿฌ

2022-10-27 14:09:03.978  WARN 34200 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character (''' (code 39)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character (''' (code 39)): was expecting double-quote to start field name<EOL> at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 2, column: 4]]

JSON ํ˜•์‹์ด ๋ฌธ์ œ์˜€๋‹ค. ๋”ฐ์˜ดํ‘œ๋กœ ์ผ๋Š”๋ฐ ์Œ๋”ฐ์˜ดํ‘œ๋กœ ์จ์•ผํ•œ๋‹ค.


[์‹ค์Šต 4] DTO ๊ฐ์ฒด๋ฅผ ํ™œ์šฉํ•œ POST API ๊ตฌํ˜„

  1. Controller

    @PostMapping(value = "/member2")
    public String postMemberDto(@RequestBody MemberDto memberDto) {
        return memberDto.toString();
    }
  2. API tester

    1. URI
    http://localhost:8080/api/v1/post-api/member2
    1. BODY
    {
      "name" : "hoon",
      "email" : "sleeping@gmail.com",
      "organization" : "yeji"
    }
  3. ๊ฒฐ๊ณผ BODY

    {
      "name" : "hoon",
      "email" : "sleeping@gmail.com",
      "organization" : "yeji"
    }

5.4 PUT API ๋งŒ๋“ค๊ธฐ


โญ๏ธ PUT API

  • POST์™€ ๋น„์Šทํ•˜์ง€๋งŒ ์ฃผ๋กœ Update ํ•˜๋Š” ๋ฐ์— ์‚ฌ์šฉํ•œ๋‹ค.
  • POST API์™€ ๋น„๊ตํ•˜๋ฉด ์„œ๋น„์Šค ๋กœ์ง์—๋Š” ์ฐจ์ด๊ฐ€ ์žˆ์ง€๋งŒ ์ปจํŠธ๋กค๋Ÿฌ ๊ตฌํ˜„์€ ๊ฑฐ์˜ ๋™์ผํ•˜๋‹ค.
GET/member โ€“ select * from member between , limit 100 โ€“ list(๋ชฉ๋ก)
GET/member/{id} โ€“ select * from member where id = ?
POST/member โ€” insert RequestBody
PUT/member โ€” update RequestBody
DELETE/member
PATCH/member โ€” put๊ณผ ๋น„์Šท

๐Ÿ’ก ์ถ”๊ฐ€ ๋‚ด์šฉ
API ๋ฉ”์„œ๋“œ์—์„œ return์„ ๊ฐ์ฒด๋กœ ํ•˜๋ฉด Content-Type์ด applicatioin/json ํ˜•์‹์œผ๋กœ ์ „๋‹ฌ๋œ๋‹ค. (@ResponseBody)

โญ๏ธ HttpEntity ํด๋ž˜์Šค

  • ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์˜ ํด๋ž˜์Šค

  • Header์™€ Body๋กœ ๊ตฌ์„ฑ๋œ HTTP ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ๊ตฌ์„ฑํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

  • ResponseEntity๋Š” ์„œ๋ฒ„์— ๋“ค์–ด์˜จ ์š”์ฒญ์— ๋Œ€ํ•ด ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ์„ฑํ•œ๋‹ค.

    • ์ด ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•˜์—ฌ ์‘๋‹ต ์ฝ”๋“œ, Header, Body๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ์—์„œ๋„ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•˜๋‹ค.
    • HttpStatus, HttpHeaders, HttpBody๋ฅผ ํฌํ•จํ•œ๋‹ค.
    • ๐Ÿ’ก ResponseEntity๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ๊ฒฐ๊ณผ๊ฐ’, ์ƒํƒœ์ฝ”๋“œ, ํ—ค๋”๊ฐ’์„ ๋ชจ๋‘ ํ”„๋ก ํŠธ์— ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ๊ณ , ์—๋Ÿฌ์ฝ”๋“œ๋„ ์ƒ์„ธํ•˜๊ฒŒ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.
    • ์‚ฌ์šฉ๋ฐฉ๋ฒ•
      • ์ƒ์„ฑ์ž ์ด์šฉ

        return new ResponseEntity<>("success", HttpStatus.OK);
        // ๋‹จ์ˆœํ•œ ๋ฉ”์„ธ์ง€์™€ ์ƒํƒœ์ฝ”๋“œ ๋ฆฌํ„ด
        HttpHeaders headers = new HttpHeaders();
        headers.add("TOKEN","XXXXXX");
        return new ResponseEntity<>("Custom header set", headers, HttpStatus.OK);
        // header์™€ ์ƒํƒœ์ฝ”๋“œ ๋ฆฌํ„ด
        Message message = Messgae.builder() // Messgae ๊ฐ์ฒด๋Š” ์ง์ ‘ ๋งŒ๋“  ๊ฑฐ.
            .message1("์ฒซ๋ฒˆ์งธ ๋ฉ”์„ธ์ง€")
            .message2("๋‘๋ฒˆ์งธ ๋ฉ”์„ธ์ง€")
            .build();  
        return new ResponseEntity<>(message, HttpStatus.INTERNAL_SERVER_ERROR);
        // ๋ฉ”์„ธ์ง€์™€ ์ƒํƒœ์ฝ”๋“œ ๋ฆฌํ„ด
      • static method ์ด์šฉ

        return ResponseEntity.ok();
        return ResponseEntity.status(HttpStatus.OK)
        				.header("Custom-Header","foo")
        				.body("Custom header set");

[์‹ค์Šต5] ResponseEntity๋ฅผ ํ™œ์šฉํ•œ PUT ๋ฉ”์„œ๋“œ ๊ตฌํ˜„

  1. Controller

    1. PutController ํด๋ž˜์Šค ์ƒ์„ฑ
    @PutMapping("/member3")
    public ResponseEntity<MemberDto> postMemberDto3(@RequestBody MemberDto memberDto){
        return ResponseEntity
                .status(HttpStatus.ACCEPTED)        //์‘๋‹ต ์ฝ”๋“œ 202
                .body(memberDto);
    } 
  2. API tester
    a. URI

    http://localhost:8080/api/v1/put-api/member3

    b. BODY

    {
      "name" : "hoon",
      "email" : "sleeping@gmail.com",
      "organization" : "yeji"
    }
  3. ๊ฒฐ๊ณผ

    • ์ด์ „๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ content type์ด application/json์œผ๋กœ ๋‚˜์˜จ๋‹ค.

๐Ÿ’ก Annotation ์ •๋ฆฌ


5.6 Swagger

  • API ๋ฌธ์„œ ์ž๋™ ์ƒ์„ฑ๊ธฐ, OAS(Open Api Specification)
  • ๊ฐœ๋ฐœ์ž๋“ค์˜ ํ•„์ˆ˜ ๊ณผ์ œ์ธ API ๋ฌธ์„œํ™”๋ฅผ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋ฉฐ, ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋„ฃ์–ด์„œ ์‹ค์ œ๋กœ ์–ด๋–ค ์‘๋‹ต์ด ์˜ค๋Š”์ง€ ํ…Œ์ŠคํŠธ๋„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ•˜๋Š”๋ฐ ํ•„์ˆ˜ ๊ณผ์ œ์ธ API ๋ฌธ์„œํ™”๋ฅผ ์‰ฝ๊ฒŒ ์ž๋™ํ™” ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๊ณ , ํŽ˜์ด์ง€์—์„œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋„ฃ์–ด์„œ ์‹ค์ œ ์‘๋‹ต์„ ํ…Œ์ŠคํŠธ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

[์‹ค์Šต 6] Swagger ์ ์šฉํ•˜๊ธฐ

  1. pom.xml - ์•ˆ์— dependency ์ถ”๊ฐ€

    • โŒจ๏ธย ์ฝ”๋“œ
      <dependency>
          <groupId>io.springfox</groupId>
          <artifactId>springfox-swagger-ui</artifactId>
          <version>3.0.0</version>
      </dependency>
      <dependency>
          <groupId>io.springfox</groupId>
          <artifactId>springfox-boot-starter</artifactId>
          <version>3.0.0</version>
      </dependency>
  2. ํ”„๋กœ์ ํŠธ ์•„๋ž˜์— configuration ํŒจํ‚ค์ง€ ์ƒ์„ฑ - SwaggerConfiguration ํด๋ž˜์Šค ์ถ”๊ฐ€

    • โŒจ๏ธย ์ฝ”๋“œ
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import springfox.documentation.builders.PathSelectors;
      import springfox.documentation.builders.RequestHandlerSelectors;
      import springfox.documentation.spi.DocumentationType;
      import springfox.documentation.spring.web.plugins.Docket;
      
      @Configuration
      public class SwaggerConfiguration {
          @Bean
          public Docket api() {
              return new Docket(DocumentationType.OAS_30)
                      .select()
                      .apis(RequestHandlerSelectors.any())
                      .paths(PathSelectors.any())
                      .build();
          }
      }
    • ๐Ÿšซย ์—๋Ÿฌ
            2022-10-27 15:20:55.045  WARN 36418 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
            2022-10-27 15:20:55.064  INFO 36418 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
            2022-10-27 15:20:55.088  INFO 36418 --- [           main] ConditionEvaluationReportLoggingListener : 
    
            Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
            2022-10-27 15:20:55.119 ERROR 36418 --- [           main] o.s.boot.SpringApplication               : Application run failed
    1. application.properties ๋ฅผ application.yml๋กœ ์ด๋ฆ„ ๋ณ€๊ฒฝ
    2. application.yml์— ์•„๋ž˜์™€ ๊ฐ™์ด ์ถ”๊ฐ€
    spring:
    	mvc:
    		pathmatch:
    			matching-strategy: ant_path_matcher
      
  3. http://localhost:8080/swagger-ui/ ๋“ค์–ด๊ฐ€๋ฉด ์•„๋ž˜์˜ ํ™”๋ฉด์ด ๋‚˜์˜จ๋‹ค.

    ์•„๋ž˜์— ๋‚ด๊ฐ€ ๋งŒ๋“  API๋“ค์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

profile
ํ›ˆ์ด์•ผ ํ™”์ดํŒ…

0๊ฐœ์˜ ๋Œ“๊ธ€