๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ–ฅ๏ธ Backend

๐ŸŒ ์›น์˜ ๊ธฐ๋ณธ ๊ฐœ๋…๊ณผ HTTP ์™„์ „ ์ •๋ณต

by hyebin (Helia) 2025. 5. 27.
๋ฐ˜์‘ํ˜•

 


๋ชฉ์ฐจ

     

     

    ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์„ ์‹œ์ž‘ํ•˜๋ ค๋ฉด ๊ฐ€์žฅ ๋จผ์ € ์ดํ•ดํ•ด์•ผ ํ•  ๊ฒƒ์ด ๋ฐ”๋กœ ์›น์˜ ๋™์ž‘ ์›๋ฆฌ์ž…๋‹ˆ๋‹ค.

    ์šฐ๋ฆฌ๊ฐ€ ๋งค์ผ ์‚ฌ์šฉํ•˜๋Š” ์›น ์„œ๋น„์Šค๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€, ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ ์–ด๋–ป๊ฒŒ ์†Œํ†ตํ•˜๋Š”์ง€ ์•Œ์•„์•ผ ๊ฒฌ๊ณ ํ•œ ๋ฐฑ์—”๋“œ๋ฅผ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ์ฃ .

     

    ์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์›น์˜ ๊ธฐ๋ณธ ๊ฐœ๋…๋ถ€ํ„ฐ HTTP, ๊ทธ๋ฆฌ๊ณ  ํ˜„๋Œ€ ์›น ๊ฐœ๋ฐœ์˜ ํ•ต์‹ฌ์ธ RESTful API๊นŒ์ง€ ์ฐจ๊ทผ์ฐจ๊ทผ ์ •๋ฆฌํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


    ๐ŸŒ ์›น์€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ• ๊นŒ?

    ์›น(Web)์€ World Wide Web์˜ ์ค„์ž„๋ง๋กœ, ์ธํ„ฐ๋„ท์ƒ์—์„œ ์ •๋ณด๋ฅผ ๊ณต์œ ํ•˜๊ธฐ ์œ„ํ•œ ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค.

    ์›น์˜ ํ•ต์‹ฌ์€ HTTP(HyperText Transfer Protocol)๋ผ๋Š” ํ†ต์‹  ๊ทœ์•ฝ์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š”๋‹ค๋Š” ์ ์ด์—์š”.

     

    ์ฆ‰, ์šฐ๋ฆฌ๊ฐ€ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์›น์‚ฌ์ดํŠธ๋ฅผ ๋ณผ ๋•Œ๋งˆ๋‹ค HTTP ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ๋ฐ›๋Š” ๊ณผ์ •์„ ๋ฐ˜๋ณตํ•˜๊ณ  ์žˆ๋Š” ์…ˆ์ž…๋‹ˆ๋‹ค.


    ๐Ÿ”„ ํด๋ผ์ด์–ธํŠธ-์„œ๋ฒ„ ๋ชจ๋ธ์ด๋ž€?

    ์›น์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ํด๋ผ์ด์–ธํŠธ-์„œ๋ฒ„ ๊ตฌ์กฐ(Client-Server Model)๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

    • ํด๋ผ์ด์–ธํŠธ(Client): ์›น ๋ธŒ๋ผ์šฐ์ €๋‚˜ ๋ชจ๋ฐ”์ผ ์•ฑ์ฒ˜๋Ÿผ ์„œ๋น„์Šค๋ฅผ ์š”์ฒญํ•˜๋Š” ์ชฝ
    • ์„œ๋ฒ„(Server): ์š”์ฒญ์„ ๋ฐ›๊ณ , ์ฒ˜๋ฆฌํ•œ ํ›„ ์‘๋‹ต์„ ๋Œ๋ ค์ฃผ๋Š” ์ชฝ
    ์‚ฌ์šฉ์ž๊ฐ€ ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ URL์„ ์ž…๋ ฅํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ๋Š” HTTP ์š”์ฒญ์„ ์„œ๋ฒ„์— ๋ณด๋‚ด๊ณ , ์„œ๋ฒ„๋Š” ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ(HTML, JSON ๋“ฑ)๋ฅผ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค.

     

    ๐Ÿ“ฆ ๋น„์œ ํ•˜์ž๋ฉด?

    • ํด๋ผ์ด์–ธํŠธ๋Š” ๋ ˆ์Šคํ† ๋ž‘์˜ ์†๋‹˜
    • ์„œ๋ฒ„๋Š” ์ฃผ๋ฐฉ์— ์ฃผ๋ฌธ์„ ๋„ฃ๊ณ  ์š”๋ฆฌ๋ฅผ ๋‚ด์–ด์ฃผ๋Š” ์ข…์—…์›
    • DB๋Š” ์žฌ๋ฃŒ๋ฅผ ๋ณด๊ด€ํ•˜๋Š” ์ฐฝ๊ณ  

    ํด๋ผ์ด์–ธํŠธ - ์„œ๋ฒ„ ๊ตฌ์กฐ


    ๐Ÿ“ก HTTP ์š”์ฒญ/์‘๋‹ต ๊ตฌ์กฐ์™€ ๋ฉ”์„œ๋“œ

    HTTP๋Š” ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›๊ธฐ ์œ„ํ•œ ๊ทœ์น™์ž…๋‹ˆ๋‹ค.

    ๋ชจ๋“  HTTP ํ†ต์‹ ์€ ์š”์ฒญ(Request)๊ณผ ์‘๋‹ต(Response) ์Œ์œผ๋กœ ์ด๋ฃจ์–ด์ ธ์š”.

     

    HTTP ์š”์ฒญ ์˜ˆ์‹œ

    POST /api/users HTTP/1.1
    Host: example.com
    Content-Type: application/json
    Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
    
    {
      "name": "๊น€๊ฐœ๋ฐœ",
      "email": "dev@example.com"
    }

    ์š”์ฒญ ๊ตฌ์„ฑ ์š”์†Œ

    • ์š”์ฒญ ๋ผ์ธ: HTTP ๋ฉ”์„œ๋“œ + URL ๊ฒฝ๋กœ + HTTP ๋ฒ„์ „
    • ํ—ค๋”: ์š”์ฒญ์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ •๋ณด
    • ๋ฐ”๋””: ์„œ๋ฒ„์— ์ „์†กํ•  ๋ฐ์ดํ„ฐ (GET ์š”์ฒญ์—๋Š” ๋ณดํ†ต ์—†์Œ)

    HTTP ์‘๋‹ต ๊ตฌ์กฐ

    HTTP/1.1 201 Created
    Content-Type: application/json
    Location: /api/users/123
    
    {
      "id": 123,
      "name": "๊น€๊ฐœ๋ฐœ",
      "email": "dev@example.com",  
      "created_at": "2025-01-15T10:00:00Z"
    }

    ์ฃผ์š” HTTP ๋ฉ”์„œ๋“œ

    ๋ฉ”์„œ๋“œ ์„ค๋ช…
    GET ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ๋•Œ ์‚ฌ์šฉ
    POST ๋ฐ์ดํ„ฐ๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•  ๋•Œ ์‚ฌ์šฉ
    PUT ์ „์ฒด ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ ์‚ฌ์šฉ
    PATCH ์ผ๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ ์‚ฌ์šฉ
    DELETE ๋ฐ์ดํ„ฐ๋ฅผ ์‚ญ์ œํ•  ๋•Œ ์‚ฌ์šฉ

    ๐Ÿ“Š HTTP ์ƒํƒœ์ฝ”๋“œ

    ์„œ๋ฒ„๋Š” ์‘๋‹ต๊ณผ ํ•จ๊ป˜ HTTP ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋ณด๋‚ด ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๊ฒฐ๊ณผ๋ฅผ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

    200๋ฒˆ ๋Œ€๋Š” ์„ฑ๊ณต, 400๋ฒˆ๋Œ€๋Š” ํด๋ผ์ด์–ธํŠธ ์˜ค๋ฅ˜, 500๋ฒˆ๋Œ€๋Š” ์„œ๋ฒ„ ์˜ค๋ฅ˜๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

    ์ฃผ์š” ์ƒํƒœ ์ฝ”๋“œ

    ์ƒํƒœ ์ฝ”๋“œ
    ์˜๋ฏธ
    200 OK ์š”์ฒญ์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋จ
    201 Created ๋ฆฌ์†Œ์Šค ์ƒ์„ฑ ์„ฑ๊ณต
    204 No Content ์‘๋‹ต ๋ณธ๋ฌธ ์—†์Œ (์˜ˆ: ์‚ญ์ œ ์„ฑ๊ณต)
    400 Bad Request ์ž˜๋ชป๋œ ์š”์ฒญ
    401 Unauthorized ์ธ์ฆ ์‹คํŒจ
    403 Forbidden ๊ถŒํ•œ ์—†์Œ
    404 Not Found ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฆฌ์†Œ์Šค
    500 Internal Server Error ์„œ๋ฒ„ ๋‚ด๋ถ€ ์˜ค๋ฅ˜
    ์ƒํƒœ ์ฝ”๋“œ๋งŒ ์ž˜ ์ฝ์–ด๋„ ๋ฌธ์ œ๋ฅผ ๋น ๋ฅด๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์–ด์š”!

    ๐ŸŽฏ RESTful API๋ž€?

    REST(Representational State Transfer)๋Š” ์›น์˜ ๊ธฐ๋ณธ ์›์น™์— ๋”ฐ๋ผ API๋ฅผ ์„ค๊ณ„ํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

    REST ์Šคํƒ€์ผ์„ ๋”ฐ๋ฅด๋Š” API๋ฅผ RESTful API๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

     

    REST ์„ค๊ณ„์˜ ํ•ต์‹ฌ ์›์น™

    1. ์ž์›(Resource) ๊ธฐ๋ฐ˜

    • URL์€ ์ž์›์„ ํ‘œํ˜„ํ•ด์•ผ ํ•จ
    • ์˜ˆ: /users, /products/1, /posts/12/comments

    2. HTTP ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•œ ํ–‰์œ„ ํ‘œํ˜„

    • GET /users → ์‚ฌ์šฉ์ž ๋ชฉ๋ก ์กฐํšŒ
    • POST /users → ์‚ฌ์šฉ์ž ์ƒ์„ฑ
    • DELETE /users/1 → ์‚ฌ์šฉ์ž ์‚ญ์ œ

    3. ๋ฌด์ƒํƒœ์„ฑ(Stateless)

    • ์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ์˜ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜์ง€ ์•Š์Œ
    • ๊ฐ ์š”์ฒญ์€ ๋…๋ฆฝ์ ์ด์–ด์•ผ ํ•จ

    4. ํ‘œ์ค€ ์‘๋‹ต ํ˜•์‹(JSON)

    • ์‘๋‹ต์€ ์ผ๊ด€๋œ ๊ตฌ์กฐ(JSON)๋ฅผ ๊ฐ–๋„๋ก ์„ค๊ณ„

    ๐Ÿ’ก RESTfulํ•˜์ง€ ์•Š์€ ์˜ˆ

    โŒ GET /createUser?id=1
    โŒ POST /getUserList  
    โŒ GET /deleteUser?id=123
    
    โญ• POST /users
    โญ• GET /users
    โญ• DELETE /users/123

    ๐Ÿ“š API ๋ฌธ์„œํ™” ๋ฐฉ๋ฒ•

    ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๊ฐœ๋ฐœ์ž ๊ฐ„์˜ ํ˜‘์—…์„ ์œ„ํ•ด API๋ฅผ ๋ฌธ์„œํ™”ํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

    API ๋ช…์„ธ๊ฐ€ ๋ช…ํ™•ํ•˜๋ฉด, ๊ฐœ๋ฐœ์ž๋ฟ ์•„๋‹ˆ๋ผ QA, ํ”„๋ก ํŠธ์—”๋“œ, ๊ธฐํš์ž๋„ ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์›Œ์š”.

    Swagger (OpenAPI)

    • ๊ฐ€์žฅ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ๋ฌธ์„œํ™” ๋„๊ตฌ
    • ์ฝ”๋“œ์— ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฌธ์„œ๊ฐ€ ์ž๋™ ์ƒ์„ฑ๋จ
    • YAML ๋˜๋Š” JSON ๊ธฐ๋ฐ˜
    paths:
      /users:
        get:
          summary: Get user list
          responses:
            '200':
              description: Success

     

    Spring Rest Docs

    • ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๊ธฐ๋ฐ˜์œผ๋กœ API ๋ฌธ์„œ๋ฅผ ์ƒ์„ฑ
    • ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•ด์•ผ๋งŒ ๋ฌธ์„œ๊ฐ€ ๋งŒ๋“ค์–ด์ ธ ์‹ ๋ขฐ๋„๊ฐ€ ๋†’์Œ
    • Spring ๊ธฐ๋ฐ˜ ํ”„๋กœ์ ํŠธ์—์„œ ๋งŽ์ด ์‚ฌ์šฉ๋จ
    mockMvc.perform(get("/users"))
      .andDo(document("get-users",
        responseFields(
          fieldWithPath("[].id").description("์‚ฌ์šฉ์ž ID"),
          fieldWithPath("[].name").description("์‚ฌ์šฉ์ž ์ด๋ฆ„")
        )
      ));

    ๐Ÿงก ๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ

    ์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์˜ ๊ธฐ์ดˆ ์ค‘ ๊ธฐ์ดˆ์ธ ์›น์˜ ๊ตฌ์กฐ์™€ HTTP์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค.

     

    โœ๏ธ  ํ•ต์‹ฌ ํฌ์ธํŠธ ์ •๋ฆฌ

    • ํด๋ผ์ด์–ธํŠธ-์„œ๋ฒ„ ๋ชจ๋ธ: ์š”์ฒญ๊ณผ ์‘๋‹ต์˜ ๊ธฐ๋ณธ ๊ตฌ์กฐ
    • HTTP ๋ฉ”์„œ๋“œ: ๊ฐ ๋ฉ”์„œ๋“œ์˜ ๋ชฉ์ ์— ๋งž๋Š” ์‚ฌ์šฉ๋ฒ•
    • ์ƒํƒœ์ฝ”๋“œ: ์ ์ ˆํ•œ ์ƒํƒœ์ฝ”๋“œ๋กœ ๋ช…ํ™•ํ•œ ์‘๋‹ต ์ „๋‹ฌ
    • RESTful API: ์ผ๊ด€๋˜๊ณ  ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ API ์„ค๊ณ„ ์›์น™
    • API ๋ฌธ์„œํ™”: ๊ฐœ๋ฐœ์ž ์นœํ™”์ ์ธ ๋ฌธ์„œ ์ž‘์„ฑ์˜ ์ค‘์š”์„ฑ

     

    ์ด ๊ฐœ๋…๋“ค์„ ์ •ํ™•ํžˆ ์ดํ•ดํ•˜๋ฉด, ์‹ค์ œ API๋ฅผ ์„ค๊ณ„ํ•˜๊ฑฐ๋‚˜ ๋””๋ฒ„๊น…ํ•  ๋•Œ ํฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

    ๋‹ค์Œ ๊ธ€์—์„œ๋Š” ์‹ค์ œ API๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉฐ ์ด ๊ฐœ๋…๋“ค์ด ์–ด๋–ป๊ฒŒ ํ™œ์šฉ๋˜๋Š”์ง€ ๊ตฌ์ฒด์ ์œผ๋กœ ์‚ดํŽด๋ณผ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

     

    ๊ถ๊ธˆํ•œ ์ ์ด๋‚˜ ์˜๊ฒฌ์€ ๋Œ“๊ธ€๋กœ ๋‚จ๊ฒจ์ฃผ์„ธ์š”! ๐Ÿš€

    ๋ฐ˜์‘ํ˜•