Skip to main content Link Menu Expand (external link) Document Search Copy Copied

Table of contents

  1. 1๏ธโƒฃ Learn REST
    1. What is REST?
      1. 1. REST์˜ ๊ธฐ๋ณธ ์›์น™
        1. 1.1. Uniform Interface
        2. 1.2. Client-Server
        3. 1.3. Stateless
        4. 1.4. Cacheable
        5. 1.5. Layerd System
        6. 1.6. Code on Demand (Optional)
      2. 2. What is a Resource?
        1. 2.1. ๋ฆฌ์†Œ์Šค ์‹๋ณ„์ž
        2. 2.2. ํ•˜์ดํผ๋ฏธ๋””์–ด
        3. 2.3. ์ž๊ธฐ ์„ค๋ช… ( Self-Descriptive )
      3. 3. Resource Methods
      4. 4. REST != HTTP
      5. 5. ์š”์•ฝ
    2. REST Constraints
      1. 1. REST ์•„ํ‚คํ…์ฒ˜ ์ œ์•ฝ
        1. 1.1. Uniform interface
        2. 1.2. Client - Server
        3. 1.3. Stateless
        4. 1.4. Cacheable
        5. 1.5. Layered system
        6. 1.6. Code on demand (optional)
    3. Naming REST Resources
      1. 1. What is a Resource?
        1. 1.1. ์‹ฑ๊ธ€ํ†ค ๊ทธ๋ฆฌ๊ณ  ์ฝœ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค
        2. 1.2. ์ปฌ๋ ‰์…˜ ๋ฐ ํ•˜์œ„ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค
        3. 1.3. URI
      2. 2. ๋ชจ๋ฒ” ์‚ฌ๋ก€
        1. 2.1. ๋ฆฌ์†Œ์Šค๋ฅผ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด ๋ช…์‚ฌ๋ฅผ ์‚ฌ์šฉํ•ด๋ผ
          1. 2.1.1. ๋ฌธ์„œ
          2. 2.1.2. ์ปฌ๋ ‰์…˜
          3. 2.1.3. ์ €์žฅ์†Œ(store)
          4. 2.1.4. ์ปจํŠธ๋กค๋Ÿฌ
        2. 2.2. ์ผ๊ด€์„ฑ์ด ํ•ต์‹ฌ
          1. 2.2.1. ์Šฌ๋ž˜์‹œ(/)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ„์ธต์  ๊ด€๊ณ„๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
          2. 2.2.2. URI์— ํ›„ํ–‰ ์Šฌ๋ž˜์‹œ(/)๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.
          3. 2.2.3. ํ•˜์ดํ”ˆ(-)์„ ์‚ฌ์šฉํ•˜์—ฌ URI์˜ ๊ฐ€๋…์„ฑ ํ–ฅ์ƒ
          4. 2.2.4. ๋ฐ‘์ค„( _ )์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.
          5. 2.2.5. URI์— ์†Œ๋ฌธ์ž ์‚ฌ์šฉ
        3. 2.3. ํŒŒ์ผ ํ™•์žฅ์ž๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค
        4. 2.4. URI์— CRUD ํ•จ์ˆ˜ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.
        5. 2.5. URI ์ปฌ๋ ‰์…˜ ํ•„ํ„ฐ๋ง์„ ์œ„ํ•ด ์ฟผ๋ฆฌ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.
  2. 2๏ธโƒฃ Guides
    1. Caching
      1. 1. ์บ์‹ฑ
      2. 2. REST API์˜ ์บ์‹ฑ
      3. 3. ์บ์‹œ ์ œ์–ด ํ—ค๋”
        1. 3.1. Expires
        2. 3.2. Cache-Control
        3. 3.3. ETag
        4. 3.4. Last-Modified
    2. Compression
      1. 1.์••์ถ• ๊ด€๋ จ ์š”์ฒญ/์‘๋‹ต ํ—ค๋”
        1. 1.1. Accept-Encoding (์ธ์ฝ”๋”ฉ ์ˆ˜๋ฝ)
        2. 1.2. Content-Encoding
    3. Content Negotiation
      1. 1. ์ฝ˜ํ…์ธ  ํ˜‘์ƒ
      2. 2. ์„œ๋ฒ„ ๊ธฐ๋ฐ˜ vs ์—์ด์ „ํŠธ ๊ธฐ๋ฐ˜ ์ฝ˜ํ…์ธ  ํ˜‘์ƒ
        1. 2.1. HTTP ํ—ค๋” ์‚ฌ์šฉ
        2. 2.2. URL ํŒจํ„ด ์‚ฌ์šฉ
      3. 3. ๊ธฐ๋ณธ ์„ค์ • ์ •์˜
    4. HATEOAS
      1. 1. HATEOAS ๋ž€?
      2. 2. HATEOAS ๊ตฌํ˜„ ๋ฐฉ๋ฒ•
      3. 3. HATEOAS ์ฐธ์กฐ
        1. 3.1. RFC 5988(์›น ๋งํฌ)
        2. 3.2. JSON ํ•˜์ดํผ๋ฏธ๋””์–ด API ์–ธ์–ด(HAL)
    5. Idempotence
      1. 1. APIs์˜ ๋ฉฑ๋“ฑ
      2. 2. HTTP ๋ฉ”์„œ๋“œ์˜ ๋ฉฑ๋“ฑ์„ฑ
        1. 2.1. HTTP POST
        2. 2.2. HTTP GET, HEAD, OPTIONS ๋ฐ TRACE
        3. 2.4 HTTP DELETE
          1. 2.4.1. ๋ฆฌ์†Œ์Šค ์‹๋ณ„์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ญ์ œ
          2. 2.4.2. ๋ฆฌ์†Œ์Šค ์‹๋ณ„์ž ์—†์ด ์‚ญ์ œ
    6. Security Essentials
      1. 1. REST ๋ณด์•ˆ ์„ค๊ณ„ ์›์น™
      2. 2. REST API ๋ณด์•ˆ์˜ ๋ชจ๋ฒ” ์‚ฌ๋ก€
        1. 2.1. Keep it Simple
        2. 2.2. Always Use HTTPS
        3. 2.3. Use Password Hash
        4. 2.4. Never expose information on URLs
        5. 2.5. Consider OAuth
        6. 2.6. Consider Adding Timestamp in Request
        7. 2.7. Input Parameter Validation
    7. Versioning
      1. 1. When to version?
      2. 2. REST API๋ฅผ ์–ด๋–ป๊ฒŒ ๋ฒ„์ „๊ด€๋ฆฌ ํ•˜๋Š”๊ฐ€?
        1. 2.1. URI Versioning
        2. 2.2. ์‚ฌ์šฉ์ž ์ •์˜ ์š”์ฒญ ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•œ ๋ฒ„์ „ ๊ด€๋ฆฌ
        3. 2.3. โ€œAcceptโ€ ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•œ ๋ฒ„์ „๊ด€๋ฆฌ
    8. Statelessness
      1. 1. ๋ฌด์ƒํƒœ์„ฑ
      2. 2. Application State vs Resource State
      3. 3. ๋ฌด์ƒํƒœ API์˜ ์žฅ์ 
  3. 3๏ธโƒฃ Tech - How To
    1. Designing REST APIs
      1. 1. ๋ฆฌ์†Œ์Šค ์‹๋ณ„ โ€“ ๊ฐ์ฒด ๋ชจ๋ธ๋ง
      2. 2. ๋ชจ๋ธ URI ์ƒ์„ฑ
      3. 3. ๋ฆฌ์†Œ์Šค Representations ๊ฒฐ์ •
        1. 3.1. ์žฅ์น˜์˜ ์ˆ˜์ง‘ ์ž์›
        2. 3.2. ๋‹จ์ผ ์žฅ์น˜ ๋ฆฌ์†Œ์Šค
        3. 3.3. ๊ตฌ์„ฑ์˜ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค
        4. 3.4. ๋‹จ์ผ ๊ตฌ์„ฑ ๋ฆฌ์†Œ์Šค
        5. 3.5. ๋‹จ์ผ ์žฅ์น˜์—์„œ ๊ตฌ์„ฑ ๋ฆฌ์†Œ์Šค ์ˆ˜์ง‘
        6. 3.6. ๋‹จ์ผ ์žฅ์น˜ ์•„๋ž˜์˜ ๋‹จ์ผ ๊ตฌ์„ฑ ๋ฆฌ์†Œ์Šค
      4. 4. HTTP ๋ฉ”์†Œ๋“œ ํ• ๋‹น
        1. 4.1. ๋ชจ๋“  ์žฅ์น˜ ๋˜๋Š” ๊ตฌ์„ฑ ํƒ์ƒ‰(Browse) [๊ธฐ๋ณธ ์ปฌ๋ ‰์…˜]
        2. 4.2. ์žฅ์น˜์˜ ๋ชจ๋“  ๊ตฌ์„ฑ ํƒ์ƒ‰(Browse) [๋ณด์กฐ ์ปฌ๋ ‰์…˜]
        3. 4.3. ๋‹จ์ผ ์žฅ์น˜ ๋˜๋Š” ๊ตฌ์„ฑ ํƒ์ƒ‰(Browse)
        4. 4.4. ์žฅ์น˜์—์„œ ๋‹จ์ผ ๊ตฌ์„ฑ ํƒ์ƒ‰(Browse)
        5. 4.5. ์žฅ์น˜ ๋˜๋Š” ๊ตฌ์„ฑ ๋งŒ๋“ค๊ธฐ(Create)
        6. 4.6. ์žฅ์น˜ ๋˜๋Š” ๊ตฌ์„ฑ ์—…๋ฐ์ดํŠธ
        7. 4.7. ์žฅ์น˜ ๋˜๋Š” ๊ตฌ์„ฑ ์ œ๊ฑฐ
        8. 4.8. ์žฅ์น˜์—์„œ ๊ตฌ์„ฑ ์ ์šฉ ๋˜๋Š” ์ œ๊ฑฐ
      5. 5. ์ถ”๊ฐ€ ์ž‘์—…
    2. REST APIs with JAX-RS
      1. 1. JAX-RS ์‚ฌ์–‘
      2. 2. JAX-RS ์–ด๋…ธํ…Œ์ด์…˜
        1. 2.1. @Path(โ€˜resourcePathโ€™)
        2. 2.2. @POST
        3. 2.3. @PUT
        4. 2.4. @GET
        5. 2.5. @DELETE
        6. 2.6. @PathParam(โ€œ๋งค๊ฐœ๋ณ€์ˆ˜ ์ด๋ฆ„โ€)
        7. 2.7. @Produces
        8. 2.8. @Consumes
        9. 2.9. @Context
    3. 3. Maven ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒ์„ฑ
      1. 4. JAX-RS ์ข…์†์„ฑ ํฌํ•จ
      2. 5. ๋ฆฌ์†Œ์Šค ํ‘œํ˜„ ์ƒ์„ฑ
        1. 5.1. ๊ตฌ์„ฑ์˜ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค
        2. 5.2. ๋‹จ์ผ ๊ตฌ์„ฑ ๋ฆฌ์†Œ์Šค
        3. 5.3. ๋ฉ”์‹œ์ง€ ๋ฆฌ์†Œ์Šค [๋ฆฌ์†Œ์Šค ํ‘œํ˜„์ด ํ•„์š”ํ•˜์ง€ ์•Š์„ ๋•Œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์•Œ๋ฆฌ๊ธฐ]
      3. 6. REST ๋ฆฌ์†Œ์Šค ์ƒ์„ฑ
      4. 7. ๋Ÿฐํƒ€์ž„์— ๋ฆฌ์†Œ์Šค ๋“ฑ๋ก
      5. 8. Demo
  4. 4๏ธโƒฃ FAQs
    1. PUT vs POST
      1. 1. PUT ๊ณผ POST ์˜ ์ฐจ์ด
      2. 2. PUT vs POST ์˜ˆ์ œ
    2. N+1 Problem
      1. 1. N+1 ๋ฌธ์ œ
      2. 2. REST API์˜ N+1 ๋ฌธ์ œ
      3. 3. N+1 ๋ฌธ์ œ๋ฅผ ํ‘ธ๋Š” ๋ฐฉ๋ฒ•
    3. โ€˜qโ€™ Parameter
      1. 1. API ํด๋ผ์ด์–ธํŠธ๋Š” ์—ฌ๋Ÿฌ ํ˜•์‹์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
      2. 2. โ€˜qโ€™ ๋งค๊ฐœ๋ณ€์ˆ˜
      3. 3. HTTP ์‚ฌ์–‘์— ๋”ฐ๋ฆ„
  5. 5๏ธโƒฃ Resources
    1. What is an API?
      1. 1. ์‹ค์ƒํ™œ์—์„œ์˜ API ์˜ˆ์‹œ
      2. 2. API ์‚ฌ์šฉ ๋ฐฉ๋ฒ•
      3. 3. API์˜ ๋ชฉ์ ์€?
      4. 4. API ๊ฐœ๋ฐœ ๋ฐฉ๋ฒ•
        1. 4.1. API ์‚ฌ์–‘
        2. 4.2. API ๋ณด์•ˆ
        3. 4.3. ๊ฐ์‚ฌ ๋กœ๊น…
        4. 4.4. ์„ฑ๋Šฅ
    2. SOAP vs REST
      1. SOAP ๋ฐ REST API ๋น„๊ต
        1. 1. ๊ธฐ๋ณธ ํ”„๋กœํ† ์ฝœ
        2. 2. ๋ฐ์ดํ„ฐ ํ˜•์‹
        3. 3. ์ƒํƒœ์œ ์ง€(Statefulness)
        4. 4. ์บ์‹ฑ
        5. 5. HTTP ๋™์‚ฌ ์‚ฌ์šฉ
        6. 6. ๋ณด์•ˆ
        7. 7. ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ
      2. ์š”์•ฝ
    3. HTTP Methods
      1. 1. HTTP GET
        1. 1.1. GET API ์‘๋‹ต ์ฝ”๋“œ
        2. 1.2. ์˜ˆ์‹œ URI
      2. 2. HTTP POST
        1. 2.1. POST API ์‘๋‹ต ์ฝ”๋“œ
        2. 2.2. ์˜ˆ์‹œ URI
      3. 3. HTTP PUT
        1. 3.1. PUT API ์‘๋‹ต ์ฝ”๋“œ
        2. 3.2. ์˜ˆ์‹œ URI
      4. 4. HTTP ์‚ญ์ œ
        1. 4.1. DELETE API ์‘๋‹ต ์ฝ”๋“œ
        2. 4.2. ์˜ˆ์‹œ
      5. 5. HTTP ํŒจ์น˜
      6. 6. HTTP ๋ฉ”์†Œ๋“œ ์š”์•ฝ
      7. 7. ์šฉ์–ด์ง‘
        1. 7.1. ์•ˆ์ „ํ•œ ๋ฐฉ๋ฒ•
        2. 7.2. ๋ฉฑ๋“ฑ์ˆ˜ ๋ฉ”์„œ๋“œ
    4. Richardson Maturity Model
      1. 1. Richardson Maturity Model ์ด๋ž€?
      2. 2. ์„ฑ์ˆ™๋„
        1. 2.1. Level Zero
        2. 2.2. Level One
        3. 2.3. Level Two
        4. 2.4. Level Three
    5. HTTP Response Codes
      1. 1xx Status Codes [Informational]
      2. 2xx Status Codes [Success]
      3. 3xx Status Codes [Redirection]
      4. 4xx Status Codes [Client Error]
      5. 5xx Status Codes [Server Error]
      6. 200 (OK)
        1. 1. ์‘๋‹ต ์—”ํ‹ฐํ‹ฐ
        2. 2. ์ค‘์š”ํ•œ ์‚ฌ์‹ค
      7. 201 (Created)
        1. 1. HTTP ํ—ค๋”
        2. 2. ์—…๋ฐ์ดํŠธ ์œ ์‹ค ๋ฌธ์ œ
      8. 202 (Accepted)
        1. 1. ์‘๋‹ต ์—”ํ‹ฐํ‹ฐ
        2. 2. HTTP ์ƒํƒœ 202 โ€“ ์˜ˆ
          1. 2.1. ์ž‘์—…์ด ์‹œ์ž‘๋˜์ง€ ์•Š์Œ
          2. 2.2. ์ž‘์—… ์‹œ์ž‘๋จ
          3. 2.3. ์ž‘์—… ์™„๋ฃŒ
      9. 204 (No Content)
        1. 1. Cacheable
        2. 2. ์—…๋ฐ์ดํŠธ ์œ ์‹ค ๋ฌธ์ œ
      10. 301 (Moved Permanently)
        1. 1. URL์„ ์˜๊ตฌ์ ์œผ๋กœ ์ด๋™ํ•ด์•ผ ํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?
        2. 2. ์œ„์น˜ ํ—ค๋”
          1. 2.1. ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ
          2. 2.2. ์„œ๋ฒ„ ์‘๋‹ต
        3. 3. Cachable
        4. 4. ์‘๋‹ต ์ฒ˜๋ฆฌ


๋ฉ‹์Ÿ์ด ์‚ฌ์ž์ฒ˜๋Ÿผ ๋ฐฑ์—”๋“œ ์Šคํ„ฐ๋”” ๊ทธ๋ฃน์›์ด ํ•จ๊ป˜ restfulapi.net ๊ธ€์„ ๋ฒˆ์—ญํ•œ ๋ฒˆ์—ญ๋ณธ์ž…๋‹ˆ๋‹ค.


1๏ธโƒฃ Learn REST

What is REST?

REST๋Š” REpresentational State Transfer์˜ ์•ฝ์ž์ด๋ฉฐ ๋ถ„์‚ฐ ํ•˜์ดํผ๋ฏธ๋””์–ด ์‹œ์Šคํ…œ์„ ์œ„ํ•œ ์•„ํ‚คํ…์ฒ˜ ์Šคํƒ€์ผ์ž…๋‹ˆ๋‹ค. Roy Fielding์€ 2000๋…„ ๊ทธ์˜ ์œ ๋ช…ํ•œ ๋…ผ๋ฌธ์—์„œ ์ด๋ฅผ ์ฒ˜์Œ ์ œ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ์•„ํ‚คํ…์ฒ˜ ์Šคํƒ€์ผ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ REST์—๋Š” ๊ธฐ๋ณธ ์›์น™๊ณผ ์ œ์•ฝ ์กฐ๊ฑด์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์„œ๋น„์Šค ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ RESTful๋กœ ์ฐธ์กฐํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์ด๋Ÿฌํ•œ ์›์น™์ด ์ถฉ์กฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

REST ์•„ํ‚คํ…์ฒ˜ ์Šคํƒ€์ผ์„ ๋”ฐ๋ฅด๋Š” Web API(๋˜๋Š” Web Service)๊ฐ€ REST API์ž…๋‹ˆ๋‹ค.

1. REST์˜ ๊ธฐ๋ณธ ์›์น™

RESTful ์•„ํ‚คํ…์ฒ˜์˜ 6๊ฐ€์ง€ ๊ธฐ๋ณธ ์›์น™ ๋˜๋Š” ์ œ์•ฝ ์กฐ๊ฑด์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

1.1. Uniform Interface

๊ตฌ์„ฑ ์š”์†Œ ์ธํ„ฐํŽ˜์ด์Šค์— ์ผ๋ฐ˜์„ฑ์˜ ์›์น™์„ ์ ์šฉํ•˜์—ฌ ์ „์ฒด ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜๋ฅผ ๋‹จ์ˆœํ™”ํ•˜๊ณ  ์ƒํ˜ธ ์ž‘์šฉ์˜ ๊ฐ€์‹œ์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ ์•„ํ‚คํ…์ฒ˜ ์ œ์•ฝ ์กฐ๊ฑด์€ ๊ท ์ผํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™•๋ณดํ•˜๊ณ  ๊ตฌ์„ฑ ์š”์†Œ์˜ ๋™์ž‘์„ ์•ˆ๋‚ดํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ๋„ค ๊ฐ€์ง€ ์ œ์•ฝ ์กฐ๊ฑด์ด ๊ทœ๊ฒฉํ™”๋œ/๊ท ์ผํ•œ (uniform) REST ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฆฌ์†Œ์Šค ์‹๋ณ„: ์ธํ„ฐํŽ˜์ด์Šค๋Š” ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„์˜ ์ƒํ˜ธ ์ž‘์šฉ์— ๊ด€๋ จ๋œ ๊ฐ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ณ ์œ ํ•˜๊ฒŒ ์‹๋ณ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • representations ์„ ํ†ตํ•œ ๋ฆฌ์†Œ์Šค ์กฐ์ž‘: ๋ฆฌ์†Œ์Šค๋Š” ์„œ๋ฒ„ ์‘๋‹ต์—์„œ ๊ท ์ผํ•œ representations ์„ ๊ฐ€์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. API ์†Œ๋น„์ž๋Š” ์ด๋Ÿฌํ•œ ํ‘œํ˜„์„ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋ฒ„์˜ ๋ฆฌ์†Œ์Šค ์ƒํƒœ๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    ( โ€ป โ€œrepresentationโ€์€ ๋ฌด์—‡์ธ๊ฐ€? ์–ด๋–ค ๋ฆฌ์†Œ์Šค์˜ ํŠน์ • ์‹œ์ ์˜ ์ƒํƒœ๋ฅผ ๋ฐ˜์˜ํ•˜๊ณ  ์žˆ๋Š” ์ •๋ณด )

  • ์ž์ฒด ์„ค๋ช… ๋ฉ”์‹œ์ง€: ๊ฐ ๋ฆฌ์†Œ์Šค ํ‘œํ˜„์—๋Š” ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•˜๊ธฐ์— ์ถฉ๋ถ„ํ•œ ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•ด ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ถ”๊ฐ€ ์ž‘์—…์— ๋Œ€ํ•œ ์ •๋ณด๋„ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒํƒœ์˜ ์—”์ง„์œผ๋กœ์„œ์˜ ํ•˜์ดํผ๋ฏธ๋””์–ด: ํด๋ผ์ด์–ธํŠธ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ดˆ๊ธฐ URI๋งŒ ๊ฐ€์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์€ ํ•˜์ดํผ๋งํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค๋ฅธ ๋ชจ๋“  ๋ฆฌ์†Œ์Šค์™€ ์ƒํ˜ธ ์ž‘์šฉ์„ ๋™์ ์œผ๋กœ ๊ตฌ๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

1.2. Client-Server

ํด๋ผ์ด์–ธํŠธ-์„œ๋ฒ„ ๋””์ž์ธ ํŒจํ„ด์€ ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋…๋ฆฝ์ ์œผ๋กœ ๋ฐœ์ „ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค ๋ฌธ์ œ(ํด๋ผ์ด์–ธํŠธ)์™€ ๋ฐ์ดํ„ฐ ์Šคํ† ๋ฆฌ์ง€ ๋ฌธ์ œ(์„œ๋ฒ„)๋ฅผ ๋ถ„๋ฆฌํ•˜์—ฌ ์—ฌ๋Ÿฌ ํ”Œ๋žซํผ์—์„œ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ด์‹์„ฑ์„ ๊ฐœ์„ ํ•˜๊ณ  ์„œ๋ฒ„ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋‹จ์ˆœํ™”ํ•˜์—ฌ ํ™•์žฅ์„ฑ์„ ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ ์ง„ํ™”ํ•˜๋Š” ๋™์•ˆ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„์˜ ์ธํ„ฐํŽ˜์ด์Šค/๊ณ„์•ฝ์ด ๊นจ์ง€์ง€ ์•Š๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

1.3. Stateless

stateless ์ƒํƒœ์—์„œ๋Š” ํด๋ผ์ด์–ธํŠธ์—์„œ ์„œ๋ฒ„๋กœ์˜ ๊ฐ ์š”์ฒญ์— ์š”์ฒญ์„ ์ดํ•ดํ•˜๊ณ  ์™„๋ฃŒํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„๋Š” ์ด์ „์— ์ €์žฅ๋œ ์ปจํ…์ŠคํŠธ ์ •๋ณด๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ด์œ ๋กœ ํด๋ผ์ด์–ธํŠธ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์€ ์„ธ์…˜ ์ƒํƒœ๋ฅผ ์™„์ „ํžˆ ์œ ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

1.4. Cacheable

Cacheable ์กฐ๊ฑด์€ ์‘๋‹ต์ด ์•”์‹œ์  ๋˜๋Š” ๋ช…์‹œ์ ์œผ๋กœ ์บ์‹œ ๊ฐ€๋Šฅ ๋˜๋Š” ์บ์‹œ ๋ถˆ๊ฐ€๋Šฅ์œผ๋กœ ์Šค์Šค๋กœ ๋ ˆ์ด๋ธ”์„ ์ง€์ •ํ•ด์•ผ ํ•จ์„ ์š”๊ตฌํ•ฉ๋‹ˆ๋‹ค.

์‘๋‹ต์ด ์บ์‹œ ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ ํด๋ผ์ด์–ธํŠธ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์€ ๋‚˜์ค‘์— ๋™๋“ฑํ•œ ์š”์ฒญ ๋ฐ ์ง€์ •๋œ ๊ธฐ๊ฐ„ ๋™์•ˆ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ์–ป์Šต๋‹ˆ๋‹ค.

1.5. Layerd System

๊ณ„์ธตํ™”๋œ ์‹œ์Šคํ…œ ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ตฌ์„ฑ ์š”์†Œ ๋™์ž‘์„ ์ œํ•œํ•˜์—ฌ ์•„ํ‚คํ…์ฒ˜๊ฐ€ ๊ณ„์ธต์ ์œผ๋กœ ๊ตฌ์„ฑ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๊ณ„์ธตํ™”๋œ ์‹œ์Šคํ…œ์—์„œ ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š” ์š”์†Œ์™€ ์ง์ ‘ ์—ฐ๊ฒฐ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

1.6. Code on Demand (Optional)

REST๋Š” ๋˜ํ•œ applet ๋˜๋Š” ์Šคํฌ๋ฆฝํŠธ ํ˜•ํƒœ์˜ ์ฝ”๋“œ๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ์‹คํ–‰ํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์šด๋กœ๋“œํ•œ ์ฝ”๋“œ๋Š” ๋ฏธ๋ฆฌ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ๊ธฐ๋Šฅ์˜ ์ˆ˜๋ฅผ ์ค„์—ฌ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋‹จ์ˆœํ™”ํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌ๋˜๋Š” ๊ธฐ๋Šฅ์˜ ์ผ๋ถ€๋ฅผ ์ฝ”๋“œ ํ˜•ํƒœ๋กœ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ํด๋ผ์ด์–ธํŠธ๋Š” ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.


2. What is a Resource?

REST์—์„œ ์ •๋ณด๋ฅผ ์ถ”์ƒํ™”ํ•˜๋Š” ํ‚ค๊ฐ€ ๋ฆฌ์†Œ์Šค์ž…๋‹ˆ๋‹ค. ์ด๋ฆ„์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ์ •๋ณด๋Š” ๋ฆฌ์†Œ์Šค๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด REST ๋ฆฌ์†Œ์Šค๋Š” ๋ฌธ์„œ ๋˜๋Š” ์ด๋ฏธ์ง€, ์ž„์‹œ ์„œ๋น„์Šค, ๋‹ค๋ฅธ ๋ฆฌ์†Œ์Šค ๋ชจ์Œ ๋˜๋Š” ๋น„๊ฐ€์ƒ ๊ฐœ์ฒด(์˜ˆ: ์‚ฌ๋žŒ)์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŠน์ • ์‹œ๊ฐ„์˜ ๋ฆฌ์†Œ์Šค ์ƒํƒœ๋ฅผ ๋ฆฌ์†Œ์Šค ํ‘œํ˜„(resource representation)์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๋ฆฌ์†Œ์Šค ํ‘œํ˜„์€ ๋‹ค์Œ์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

  • ๋ฐ์ดํ„ฐ
  • ๋ฐ์ดํ„ฐ๋ฅผ ์„ค๋ช…ํ•˜๋Š” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ
  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›ํ•˜๋Š” ๋‹ค์Œ ์ƒํƒœ๋กœ ์ „ํ™˜ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ๋Š” ํ•˜์ดํผ๋ฏธ๋””์–ด ๋งํฌ.

REST API๋Š” ์ƒํ˜ธ ์—ฐ๊ฒฐ๋œ ๋ฆฌ์†Œ์Šค์˜ ์กฐํ•ฉ์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์ด ๋ฆฌ์†Œ์Šค ์ง‘ํ•ฉ์„ REST API์˜ ๋ฆฌ์†Œ์Šค ๋ชจ๋ธ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

2.1. ๋ฆฌ์†Œ์Šค ์‹๋ณ„์ž

REST๋Š” ๋ฆฌ์†Œ์Šค ์‹๋ณ„์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ตฌ์„ฑ ์š”์†Œ ๊ฐ„์˜ ์ƒํ˜ธ ์ž‘์šฉ์— ๊ด€๋ จ๋œ ๊ฐ ๋ฆฌ์†Œ์Šค๋ฅผ ์‹๋ณ„ํ•ฉ๋‹ˆ๋‹ค.

2.2. ํ•˜์ดํผ๋ฏธ๋””์–ด

ํ‘œํ˜„( representation)์˜ ๋ฐ์ดํ„ฐ ํ˜•์‹์€ ๋ฏธ๋””์–ด ์œ ํ˜•์œผ๋กœ ์•Œ๋ ค์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฏธ๋””์–ด ์œ ํ˜•์€ ํ‘œํ˜„์ด ์ฒ˜๋ฆฌ๋˜๋Š” ๋ฐฉ๋ฒ•์„ ์ •์˜ํ•˜๋Š” ์‚ฌ์–‘์„ ์‹๋ณ„ํ•ฉ๋‹ˆ๋‹ค.

RESTful API๋Š” ํ•˜์ดํผํ…์ŠคํŠธ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. ์ฃผ์†Œ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ์ •๋ณด ๋‹จ์œ„๋Š” ๋ช…์‹œ์ ์œผ๋กœ(์˜ˆ: ๋งํฌ ๋ฐ id ์†์„ฑ) ๋˜๋Š” ์•”์‹œ์ ์œผ๋กœ(์˜ˆ: ๋ฏธ๋””์–ด ์œ ํ˜• ์ •์˜ ๋ฐ ํ‘œํ˜„ ๊ตฌ์กฐ์—์„œ ํŒŒ์ƒ๋œ) ์ฃผ์†Œ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ดํผํ…์ŠคํŠธ(๋˜๋Š” ํ•˜์ดํผ๋ฏธ๋””์–ด)๋Š” ์ •๋ณด๊ฐ€ ์‚ฌ์šฉ์ž(๋˜๋Š” ์ž๋™ ์žฅ์น˜)๊ฐ€ ์„ ํƒ์„ ์–ป๊ณ  ํ–‰๋™์„ ์„ ํƒํ•˜๋Š” ์œ ๋„ ์žฅ์น˜๊ฐ€ ๋˜๋„๋ก ์ •๋ณด์™€ ์ œ์–ด๋ฅผ ๋™์‹œ์— ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ดํผํ…์ŠคํŠธ๋Š” ๋ธŒ๋ผ์šฐ์ €์—์„œ HTML(๋˜๋Š” XML ๋˜๋Š” JSON)์ผ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๊ธฐ๊ณ„๋Š” ๋ฐ์ดํ„ฐ ํ˜•์‹๊ณผ ๊ด€๊ณ„ ์œ ํ˜•์„ ์ดํ•ดํ•˜๋ฉด ๋งํฌ๋ฅผ ๋”ฐ๋ผ๊ฐˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โ€” ๋กœ์ด ํ•„๋”ฉ

2.3. ์ž๊ธฐ ์„ค๋ช… ( Self-Descriptive )

๋˜ํ•œ ๋ฆฌ์†Œ์Šค ํ‘œํ˜„์€ ์ž์ฒด ์„ค๋ช…์ ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” ๋ฆฌ์†Œ์Šค๊ฐ€ ์ง์›์ธ์ง€ ์žฅ์น˜์ธ์ง€ ์•Œ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋ฆฌ์†Œ์Šค์™€ ์—ฐ๊ฒฐ๋œ ๋ฏธ๋””์–ด ์œ ํ˜•์— ๋”ฐ๋ผ ์ž‘๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

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

๋ชจ๋“  ๋ฏธ๋””์–ด ์œ ํ˜•์€ ๊ธฐ๋ณธ ์ฒ˜๋ฆฌ ๋ชจ๋ธ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, HTML์€ ํ•˜์ดํผํ…์ŠคํŠธ์— ๋Œ€ํ•œ ๋ Œ๋”๋ง ํ”„๋กœ์„ธ์Šค์™€ ๊ฐ ์š”์†Œ ์ฃผ๋ณ€์˜ ๋ธŒ๋ผ์šฐ์ € ๋™์ž‘์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

๋ฏธ๋””์–ด ์œ ํ˜•์€ GET/PUT/POST/DELETE/โ€ฆ ๋“ฑ๋“ฑ์˜ ๋ฆฌ์†Œ์Šค ๋ฉ”์†Œ๋“œ์™€ ๊ด€๋ จ์ด ์—†์Šต๋‹ˆ๋‹ค.

๋‹จ, ์ผ๋ถ€ ๋ฏธ๋””์–ด ์œ ํ˜• ์š”์†Œ๋Š” โ€œhref ์†์„ฑ์ด ์žˆ๋Š” ์•ต์ปค ์š”์†Œ๊ฐ€ ํ•˜์ดํผํ…์ŠคํŠธ ๋งํฌ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ•˜์ดํผํ…์ŠคํŠธ ๋งํฌ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

CDATA๋กœ ์ธ์ฝ”๋”ฉ๋œ href ์†์„ฑ์— ํ•ด๋‹นํ•˜๋Š” URI์—์„œ ๊ฒ€์ƒ‰ ์š”์ฒญ(GET)์„ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.โ€


3. Resource Methods

REST์™€ ๊ด€๋ จ๋œ ๋˜ ๋‹ค๋ฅธ ์ค‘์š”ํ•œ ๊ฒƒ์€ ๋ฆฌ์†Œ์Šค ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฆฌ์†Œ์Šค ๋ฉ”์„œ๋“œ๋Š” ๋ฆฌ์†Œ์Šค์˜ ๋‘ ์ƒํƒœ ๊ฐ„์— ์›ํ•˜๋Š” ์ „ํ™˜์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ๋ฆฌ์†Œ์Šค ๋ฉ”์„œ๋“œ๋ฅผ HTTP ๋ฉ”์„œ๋“œ(์˜ˆ: GET/PUT/POST/DELETE)์™€ ์ž˜๋ชป ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. Roy Fielding์€ ์–ด๋–ค ์กฐ๊ฑด์—์„œ ์–ด๋–ค ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ๊ถŒ์žฅ ์‚ฌํ•ญ์„ ์–ธ๊ธ‰ํ•œ ์ ์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฐ€ ๊ฐ•์กฐํ•˜๋Š” ๊ฒƒ์€ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๊ท ์ผํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์ด HTTP PUT์„ ๊ถŒ์žฅํ•˜๋Š” ๋Œ€์‹  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ API๊ฐ€ ๋ฆฌ์†Œ์Šค ์—…๋ฐ์ดํŠธ์— HTTP POST๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฑด ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•ด๋„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ธํ„ฐํŽ˜์ด์Šค๋Š” RESTful์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ด์ƒ์ ์œผ๋กœ๋Š” ๋ฆฌ์†Œ์Šค ์ƒํƒœ๋ฅผ ์ „ํ™˜ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ๊ฒƒ์ด ๋ฆฌ์†Œ์Šค ํ‘œํ˜„์˜ ์ผ๋ถ€๊ฐ€ ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ์ง€์›๋˜๋Š” ๋ชจ๋“  ๋ฉ”์„œ๋“œ์™€ ํ‘œํ˜„์„ ๋‚ ๋ฆด ํ˜•์‹์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

์ดˆ๊ธฐ URI(์ฑ…๊ฐˆํ”ผ) ๋ฐ ์˜๋„๋œ ์ฒญ์ค‘(์ฆ‰, API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ดํ•ดํ•  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋˜๋Š”)์— ์ ํ•ฉํ•œ ํ‘œ์ค€ํ™”๋œ ๋ฏธ๋””์–ด ์œ ํ˜• ์ง‘ํ•ฉ ์™ธ์—๋Š” ์‚ฌ์ „ ์ง€์‹ ์—†์ด REST API๋ฅผ ์ž…๋ ฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ ์‹œ์ ๋ถ€ํ„ฐ ๋ชจ๋“  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒํƒœ ์ „ํ™˜์€ ์ˆ˜์‹ ๋œ ํ‘œํ˜„์— ์กด์žฌํ•˜๊ฑฐ๋‚˜ ํ•ด๋‹น ํ‘œํ˜„์˜ ์‚ฌ์šฉ์ž ์กฐ์ž‘์— ์˜ํ•ด ์•”์‹œ๋˜๋Š” ์„œ๋ฒ„ ์ œ๊ณต ์„ ํƒ์˜ ํด๋ผ์ด์–ธํŠธ ์„ ํƒ์— ์˜ํ•ด ๊ตฌ๋™๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ „ํ™˜์€ ๋ฏธ๋””์–ด ์œ ํ˜• ๋ฐ ๋ฆฌ์†Œ์Šค ํ†ต์‹  ๋ฉ”์ปค๋‹ˆ์ฆ˜์— ๋Œ€ํ•œ ํด๋ผ์ด์–ธํŠธ์˜ ์ง€์‹์œผ๋กœ ๊ฒฐ์ •(๋˜๋Š” ์ œํ•œ)๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋‘˜ ๋‹ค ์ฆ‰์„์—์„œ ๊ฐœ์„ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ: ์ฃผ๋ฌธํ˜• ์ฝ”๋“œ). [์—ฌ๊ธฐ์„œ ์‹คํŒจ๋Š” ๋Œ€์—ญ ์™ธ ์ •๋ณด๊ฐ€ ํ•˜์ดํผํ…์ŠคํŠธ ๋Œ€์‹  ์ƒํ˜ธ ์ž‘์šฉ์„ ์ฃผ๋„ํ•˜๊ณ  ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.]


4. REST != HTTP

๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด HTTP๋ฅผ REST์™€ ๋น„๊ตํ•˜๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•˜์ง€๋งŒ. REST์™€ HTTP๋Š” ๋™์ผํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

REST๋„ ์›น(์ธํ„ฐ๋„ท)์„ ๋ณด๋‹ค ๊ฐ„์†Œํ™”๋˜๊ณ  ํ‘œ์ค€์œผ๋กœ ๋งŒ๋“ค๋ ค๊ณ  ํ•˜์ง€๋งŒ Roy Fielding์€ REST ์›์น™ ์‚ฌ์šฉ์„ ๋ณด๋‹ค ์—„๊ฒฉํ•˜๊ฒŒ ์˜นํ˜ธํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์€ ์‚ฌ๋žŒ๋“ค์ด REST๋ฅผ ์›น๊ณผ ๋น„๊ตํ•˜๊ธฐ ์‹œ์ž‘ํ•˜๋Š” ์ง€์ ์ž…๋‹ˆ๋‹ค.

Roy Fielding์€ ๊ทธ์˜ ๋…ผ๋ฌธ์—์„œ ํ”„๋กœํ† ์ฝœ ๊ธฐ๋ณธ ์„ค์ •์ด๋‚˜ HTTP๋ฅผ ํฌํ•จํ•˜์—ฌ ๊ตฌํ˜„ ๋ฐฉํ–ฅ์— ๋Œ€ํ•ด ์–ธ๊ธ‰ํ•œ ์ ์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋•Œ๊นŒ์ง€ ์šฐ๋ฆฌ๋Š” ์šฐ๋ฆฌ์˜ ์ธํ„ฐํŽ˜์ด์Šค์ธ RESTful์ด๋ผ๊ณ  ๋ถ€๋ฅผ ์ˆ˜ ์žˆ๋Š” REST์˜ 6๊ฐ€์ง€ ๊ธฐ๋ณธ ์›์น™์„ ์กด์ค‘ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.


5. ์š”์•ฝ

๊ฐ„๋‹จํžˆ ๋งํ•ด์„œ REST ์•„ํ‚คํ…์ฒ˜ ์Šคํƒ€์ผ์—์„œ ๋ฐ์ดํ„ฐ์™€ ๊ธฐ๋Šฅ์€ ๋ฆฌ์†Œ์Šค๋กœ ๊ฐ„์ฃผ๋˜๊ณ  URI(Uniform Resource Identifier)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•ก์„ธ์Šค๋ฉ๋‹ˆ๋‹ค.

๋ฆฌ์†Œ์Šค๋Š” ๊ฐ„๋‹จํ•˜๊ณ  ์ž˜ ์ •์˜๋œ ์ž‘์—… ์ง‘ํ•ฉ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘๋™๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ HTML, XML, ์ผ๋ฐ˜ ํ…์ŠคํŠธ, PDF, JPEG, JSON ๋“ฑ๊ณผ ๊ฐ™์€ ๋‹ค์–‘ํ•œ ํ˜•์‹์˜ ์ฝ˜ํ…์ธ ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ฆฌ์†Œ์Šค๋ฅผ ํ•ด๋‹น ํ‘œํ˜„์—์„œ ๋ถ„๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๋Š” ํ‘œ์ค€ํ™”๋œ ์ธํ„ฐํŽ˜์ด์Šค์™€ ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฆฌ์†Œ์Šค ํ‘œํ˜„์„ ๊ตํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ HTTP๊ฐ€ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ํ”„๋กœํ† ์ฝœ์ด์ง€๋งŒ REST๋Š” ์ด๋ฅผ ์š”๊ตฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ ์ œ๊ณต๋˜์–ด ์บ์‹ฑ์„ ์ œ์–ดํ•˜๊ณ  ์ „์†ก ์˜ค๋ฅ˜๋ฅผ ๊ฐ์ง€ํ•˜๋ฉฐ ์ ์ ˆํ•œ ํ‘œํ˜„ ํ˜•์‹์„ ํ˜‘์ƒํ•˜๊ณ  ์ธ์ฆ ๋˜๋Š” ์•ก์„ธ์Šค ์ œ์–ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ ์„œ๋ฒ„์™€์˜ ๋ชจ๋“  ์ƒํ˜ธ ์ž‘์šฉ์ด ์ƒํƒœ ๋น„์ €์žฅ(stateless)์ด์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ชจ๋“  ์›์น™์€ RESTful ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๊ฐ„๋‹จํ•˜๊ณ  ๊ฐ€๋ณ๊ณ  ๋น ๋ฅด๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.

์ฐธ์กฐ:

REST Constraints

REST๋Š” Representational State Transfer์˜ ์•ฝ์ž๋กœ Roy Fielding์ด 2000๋…„์— ๋งŒ๋“  ์šฉ์–ด์ž…๋‹ˆ๋‹ค. ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ๋Š์Šจํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„ค๊ณ„ํ•˜๊ธฐ ์œ„ํ•œ ์•„ํ‚คํ…์ฒ˜ ์Šคํƒ€์ผ๋กœ ์›น ์„œ๋น„์Šค ๊ฐœ๋ฐœ์— ์ž์ฃผ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

REST๋Š” ํ•˜์œ„ ์ˆ˜์ค€์—์„œ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„๋˜์–ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ์–ด๋– ํ•œ ๊ทœ์น™๋„ ์‹œํ–‰ํ•˜์ง€ ์•Š์œผ๋ฉฐ, ๋‹จ์ง€ ๋†’์€ ์ˆ˜์ค€์˜ ๋””์ž์ธ ์ง€์นจ์„ ์ œ์‹œํ•˜๊ณ  ์šฐ๋ฆฌ๊ฐ€ ์ง์ ‘ ๊ตฌํ˜„์„ ์ƒ๊ฐํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰ ์ง์žฅ์—์„œ ์ €๋Š” 2๋…„ ๋™์•ˆ ์ฃผ์š” ํ†ต์‹  ํšŒ์‚ฌ๋ฅผ ์œ„ํ•ด RESTful API๋ฅผ ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒŒ์‹œ๋ฌผ์—์„œ๋Š” ํ‘œ์ค€ ๋””์ž์ธ ๊ด€ํ–‰๊ณผ ๋ณ„๊ฐœ๋กœ ๋‚ด ์ƒ๊ฐ์„ ๊ณต์œ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹น์‹ ์€ ๋ช‡ ๊ฐ€์ง€ ์ ์—์„œ ๋‚˜์™€ ๋™์˜ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์ง€๋งŒ ๊ทธ๊ฒƒ์€ ๋ญ ์™„์ „ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ์—ด๋ฆฐ ๋งˆ์Œ์œผ๋กœ ๋ฌด์—‡์ด๋“  ์ƒ๋‹ดํ•ด ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

โ€˜Roy Fieldingโ€™์ด ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค๊ณ ์ž ํ•˜๋Š” ๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ํ‘œ์ค€ ๋””์ž์ธ ๊ด€๋ จ ํ•ญ๋ชฉ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ RESTful API๋ฅผ ์„ค๊ณ„ํ•˜๋Š” ๋™์•ˆ ๋Š๋‚€ ์ œ ์ƒ๊ฐ์— ๋Œ€ํ•ด ๋…ผ์˜ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

1. REST ์•„ํ‚คํ…์ฒ˜ ์ œ์•ฝ

REST๋Š” ๋ชจ๋“  ์›น ์„œ๋น„์Šค๋ฅผ ์ง„์ •ํ•œ RESTful API๋กœ ๋งŒ๋“œ๋Š” 6๊ฐ€์ง€ ์•„ํ‚คํ…์ฒ˜ ์ œ์•ฝ ์กฐ๊ฑด์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

1.1. Uniform interface

์ œ์•ฝ ์กฐ๊ฑด ์ด๋ฆ„ ์ž์ฒด๊ฐ€ ์ ์šฉ๋˜๋ฏ€๋กœ API ์†Œ๋น„์ž์—๊ฒŒ ๋…ธ์ถœ๋˜๊ณ  ์–ด๊น€์—†์ด ๋”ฐ๋ฅด๋Š” ์‹œ์Šคํ…œ ๋‚ด๋ถ€ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ API ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ฒฐ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‹œ์Šคํ…œ์˜ ๋ฆฌ์†Œ์Šค์—๋Š” ํ•˜๋‚˜์˜ ๋…ผ๋ฆฌ์  URI๋งŒ ์žˆ์–ด์•ผ ํ•˜๋ฉฐ ๊ด€๋ จ ๋ฐ์ดํ„ฐ๋‚˜ ์ถ”๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฆฌ์†Œ์Šค๋ฅผ ์›น ํŽ˜์ด์ง€์™€ ๋™์˜์–ดํ™”ํ•˜๋Š” ๊ฒƒ์ด ํ•ญ์ƒ ๋” ์ข‹์Šต๋‹ˆ๋‹ค.

๋‹จ์ผ ๋ฆฌ์†Œ์Šค๋Š” ๋„ˆ๋ฌด ์ปค์„œ๋Š” ์•ˆ ๋˜๋ฉฐ ํ‘œํ˜„์— ๊ฐ๊ฐ์˜ ๋ชจ๋“  ๊ฒƒ์„ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ด€๋ จ์ด ์žˆ์„ ๋•Œ๋งˆ๋‹ค ๋ฆฌ์†Œ์Šค๋Š” ๊ด€๋ จ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ์ƒ๋Œ€ URI๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋งํฌ(HATEOAS)๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ ์‹œ์Šคํ…œ ์ „์ฒด์˜ ๋ฆฌ์†Œ์Šค ํ‘œํ˜„์€ ๋ช…๋ช… ๊ทœ์น™, ๋งํฌ ํ˜•์‹ ๋˜๋Š” ๋ฐ์ดํ„ฐ ํ˜•์‹(XML ๋˜๋Š”/๋ฐ JSON)๊ณผ ๊ฐ™์€ ํŠน์ • ์ง€์นจ์„ ๋”ฐ๋ผ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  ๋ฆฌ์†Œ์Šค๋Š” HTTP GET๊ณผ ๊ฐ™์€ ์ผ๋ฐ˜์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์„ ํ†ตํ•ด ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•˜๋ฉฐ ์ผ๊ด€๋œ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ์œ ์‚ฌํ•˜๊ฒŒ ์ˆ˜์ •๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž๊ฐ€ API ์ค‘ ํ•˜๋‚˜์— ์ต์ˆ™ํ•ด์ง€๋ฉด ๋‹ค๋ฅธ API์— ๋Œ€ํ•ด์„œ๋„ ์œ ์‚ฌํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์„ ๋”ฐ๋ฅผ ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

1.2. Client - Server

์ด ์ œ์•ฝ ์กฐ๊ฑด์€ ๋ณธ์งˆ์ ์œผ๋กœ ํด๋ผ์ด์–ธํŠธ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ๊ณผ ์„œ๋ฒ„ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ์„œ๋กœ์— ๋Œ€ํ•œ ์ข…์†์„ฑ ์—†์ด ๊ฐœ๋ณ„์ ์œผ๋กœ ๋ฐœ์ „ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ๋Š” ๋ฆฌ์†Œ์Šค URI๋งŒ ์•Œ์•„์•ผ ํ•˜๋ฉฐ ๊ทธ๊ฒŒ ์ „๋ถ€์ž…๋‹ˆ๋‹ค. ์˜ค๋Š˜๋‚  ์ด๊ฒƒ์€ ์›น ๊ฐœ๋ฐœ์˜ ํ‘œ์ค€ ๊ด€ํ–‰์ด๋ฏ€๋กœ ์‚ฌ์šฉ์ž ์ธก์—์„œ ํ™”๋ คํ•œ ๊ฒƒ์€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•˜๊ฒŒ ์œ ์ง€ํ•˜์‹ญ์‹œ์˜ค.

์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ํ•œ ๋…๋ฆฝ์ ์œผ๋กœ ๊ต์ฒด ๋ฐ ๊ฐœ๋ฐœ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1.3. Stateless

Roy Fielding์€ HTTP์—์„œ ์˜๊ฐ์„ ์–ป์—ˆ์œผ๋ฏ€๋กœ ์ด ์ œ์•ฝ ์กฐ๊ฑด์„ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ-์„œ๋ฒ„ ์ƒํ˜ธ ์ž‘์šฉ์„ stateless(์ƒํƒœ ๋น„์ €์žฅ)์œผ๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋งŒ๋“  ์ตœ์‹  HTTP ์š”์ฒญ์— ๋Œ€ํ•ด ์•„๋ฌด๊ฒƒ๋„ ์ €์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ์š”์ฒญ์„ ์ƒˆ๋กœ์šด ๊ฒƒ์œผ๋กœ ์ทจ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค. ์„ธ์…˜๋„, ํžˆ์Šคํ† ๋ฆฌ๋„ ์—†์Šต๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ์ตœ์ข… ์‚ฌ์šฉ์ž๋ฅผ ์œ„ํ•œ ์ƒํƒœ ์ €์žฅ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด์–ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž๊ฐ€ ํ•œ ๋ฒˆ ๋กœ๊ทธ์ธํ•˜๊ณ  ๊ทธ ํ›„์— ๋‹ค๋ฅธ ์Šน์ธ๋œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๊ณ ๋‚˜์„œ ํด๋ผ์ด์–ธํŠธ์˜ ๊ฐ ์š”์ฒญ์—๋Š” ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด(์ธ์ฆ ๋ฐ ์Šน์ธ ์„ธ๋ถ€ ์ •๋ณด)๋ฅผ ํฌํ•จํ•œ๋‹ค.

ํด๋ผ์ด์–ธํŠธ ์ปจํ…์ŠคํŠธ๋Š” ์š”์ฒญ ์‚ฌ์ด์— ์„œ๋ฒ„์— ์ €์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•  ์ฑ…์ž„์ด ์žˆ์Šต๋‹ˆ๋‹ค.

1.4. Cacheable

์˜ค๋Š˜๋‚ ์˜ ์„ธ๊ณ„์—์„œ ๋ฐ์ดํ„ฐ ๋ฐ ์‘๋‹ต์˜ ์บ์‹ฑ์€ (์ ์šฉ ๊ฐ€๋Šฅํ•˜๊ฑฐ๋‚˜ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ๊ณณ์—์„ ) ๊ฐ€์žฅ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ฝ๊ณ  ์žˆ๋Š” ์›น ํŽ˜์ด์ง€๋Š” HTML ํŽ˜์ด์ง€์˜ ์บ์‹œ๋œ ๋ฒ„์ „์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

์บ์‹ฑ์€ ๋ถ€ํ•˜๊ฐ€ ์ค„์–ด๋“ค์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ํด๋ผ์ด์–ธํŠธ ์ธก์˜ ์„ฑ๋Šฅ ํ–ฅ์ƒ๊ณผ ์„œ๋ฒ„์˜ ํ™•์žฅ์„ฑ ๋ฒ”์œ„๋ฅผ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

REST์—์„œ ์บ์‹ฑ์€ ํ•ด๋‹น๋˜๋Š” ๊ฒฝ์šฐ ๋ฆฌ์†Œ์Šค์— ์ ์šฉ๋˜๋ฉฐ ์ด๋Ÿฌํ•œ ๋ฆฌ์†Œ์Šค๋Š” ์บ์‹œ ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ๋ฐ˜๋“œ์‹œ ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์บ์‹ฑ์€ ์„œ๋ฒ„ ๋˜๋Š” ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž˜ ๊ด€๋ฆฌ๋˜๋Š” ์บ์‹ฑ์€ ์ผ๋ถ€ ํด๋ผ์ด์–ธํŠธ-์„œ๋ฒ„ ์ƒํ˜ธ ์ž‘์šฉ์„ ๋ถ€๋ถ„์ ์œผ๋กœ ๋˜๋Š” ์™„์ „ํžˆ ์ œ๊ฑฐํ•˜์—ฌ ํ™•์žฅ์„ฑ๊ณผ ์„ฑ๋Šฅ์„ ๋”์šฑ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

1.5. Layered system

REST๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์˜ˆ๋ฅผ ๋“ค์–ด ์„œ๋ฒ„ A์— API๋ฅผ ๋ฐฐํฌํ•˜๊ณ  ์„œ๋ฒ„ B์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์„œ๋ฒ„ C์—์„œ ์š”์ฒญ์„ ์ธ์ฆํ•˜๋Š” ๊ณ„์ธตํ™”๋œ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ž์‹ ์ด ์ตœ์ข… ์„œ๋ฒ„์— ์ง์ ‘ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š”์ง€ ์ค‘๊ฐ„ ์ค‘๊ฐ„์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

1.6. Code on demand (optional)

์Œ, ์ด ์ œ์•ฝ ์กฐ๊ฑด์€ ์„ ํƒ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๋ฆฌ์†Œ์Šค์˜ ์ •์  ํ‘œํ˜„์„ XML ๋˜๋Š” JSON ํ˜•์‹์œผ๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ํ•„์š”ํ•  ๋•Œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ผ๋ถ€๋ฅผ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ๋ฅผ ์ž์œ ๋กญ๊ฒŒ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํด๋ผ์ด์–ธํŠธ๋Š” UI ์œ„์ ฏ ๋ Œ๋”๋ง ์ฝ”๋“œ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด API๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค.

์œ„์˜ ๋ชจ๋“  ์ œ์•ฝ ์กฐ๊ฑด์€ ์ง„์ •ํ•œ RESTful API๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋ฏ€๋กœ ์ด๋ฅผ ๋”ฐ๋ผ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ ๋•Œ๋•Œ๋กœ ํ•œ๋‘ ๊ฐ€์ง€ ์ œ์•ฝ ์กฐ๊ฑด์„ ์œ„๋ฐ˜ํ•˜๋Š” ์ž์‹ ์„ ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ฑฑ์ • ํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค. ์—ฌ์ „ํžˆ RESTful API ๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, โ€œ์ง„์ •ํ•œ RESTfulโ€œ์€ ์•„๋‹™๋‹ˆ๋‹ค.


์œ„์˜ ๋ชจ๋“  ์ œ์•ฝ ์กฐ๊ฑด์€ WWW(์›น)์™€ ๊ฐ€์žฅ ๋ฐ€์ ‘ํ•˜๊ฒŒ ๊ด€๋ จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. RESTful API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์›น ํŽ˜์ด์ง€์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ์ž‘์—…์„ ์›น ์„œ๋น„์Šค์—์„œ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Naming REST Resources

1. What is a Resource?

REST์—์„œ ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ ํ‘œํ˜„์„ ๋ฆฌ์†Œ์Šค๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์ผ๊ด€๋˜๊ณ  ๊ฐ•๋ ฅํ•œ REST ๋ฆฌ์†Œ์Šค ๋ช…๋ช… ์ „๋žต์„ ๊ฐ–๋Š” ๊ฒƒ์€ ์žฅ๊ธฐ์ ์œผ๋กœ ์ตœ๊ณ ์˜ ๋””์ž์ธ ๊ฒฐ์ • ์ค‘ ํ•˜๋‚˜์ž„์„ ์ฆ๋ช…ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

REST์—์„œ ํ•ต์‹ฌ์€ ์ •๋ณด๋ฅผ ์ถ”์ƒํ™”ํ•˜๋Š” ์ž์›(๋ฆฌ์†Œ์Šค)์ž…๋‹ˆ๋‹ค. ์ด๋ฆ„์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ์ •๋ณด๋Š” ๋ฆฌ์†Œ์Šค๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์„œ ๋˜๋Š” ์ด๋ฏธ์ง€, ์ž„์‹œ ์„œ๋น„์Šค(์˜ˆ: โ€œ๋กœ์Šค์•ค์ ค๋ ˆ์Šค์˜ ์˜ค๋Š˜ ๋‚ ์”จโ€), ๊ธฐํƒ€ ๋ฆฌ์†Œ์Šค ๋ชจ์Œ, ๋น„๊ฐ€์ƒ ๊ฐ์ฒด(์˜ˆ: ์‚ฌ๋žŒ) ๋“ฑ

์ฆ‰, ์ €์ž์˜ ํ•˜์ดํผํ…์ŠคํŠธ ์ฐธ์กฐ ๋Œ€์ƒ์ด ๋  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๊ฐœ๋…์€ ๋ฆฌ์†Œ์Šค ์ •์˜ ๋‚ด์— ๋งž์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฆฌ์†Œ์Šค๋Š” ํŠน์ • ์‹œ์ ์˜ ๋งคํ•‘์— ํ•ด๋‹นํ•˜๋Š” ์—”ํ„ฐํ‹ฐ๊ฐ€ ์•„๋‹ˆ๋ผ ์—”ํ„ฐํ‹ฐ ์ง‘ํ•ฉ์— ๋Œ€ํ•œ ๊ฐœ๋…์  ๋งคํ•‘์ž…๋‹ˆ๋‹ค.

โ€” ๋กœ์ด ํ•„๋”ฉ์˜ ๋…ผ๋ฌธ

1.1. ์‹ฑ๊ธ€ํ†ค ๊ทธ๋ฆฌ๊ณ  ์ฝœ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค

๋ฆฌ์†Œ์Šค๋Š” ์‹ฑ๊ธ€ํ†ค ๋˜๋Š” ์ปฌ๋ ‰์…˜์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. โ€œcustomersโ€œ์€ ์ˆ˜์ง‘ ๋ฆฌ์†Œ์Šค์ด๊ณ  โ€œcustomerโ€œ์€ ์‹ฑ๊ธ€ํ†ค ๋ฆฌ์†Œ์Šค(๋ฑ…ํ‚น ๋„๋ฉ”์ธ์—์„œ)์ž…๋‹ˆ๋‹ค.

URI โ€œ/customersโ€œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ โ€œcustomersโ€ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

URI โ€œ/customers/{customerId}โ€œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ์ผ โ€œcustomerโ€ ๋ฆฌ์†Œ์Šค๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1.2. ์ปฌ๋ ‰์…˜ ๋ฐ ํ•˜์œ„ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค

๋ฆฌ์†Œ์Šค์—๋Š” ํ•˜์œ„ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค๋„ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํŠน์ • โ€œcustomerโ€œ์˜ ํ•˜์œ„ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค โ€œaccountsโ€œ๋Š” URN โ€œ/customers/{customerId}/accountsโ€œ(์€ํ–‰ ๋„๋ฉ”์ธ์—์„œ)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ•˜์œ„ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค โ€œaccountsโ€ ๋‚ด์˜ ๋‹จ์ผ ๋ฆฌ์†Œ์Šค โ€œaccountโ€œ๋Š” โ€œ/customers/{customerId}/accounts/{accountId}โ€œ์™€ ๊ฐ™์ด ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1.3. URI

REST API๋Š” URI(Uniform Resource Identifier)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฆฌ์†Œ์Šค ์ฃผ์†Œ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. REST API ์„ค๊ณ„์ž๋Š” REST API์˜ ๋ฆฌ์†Œ์Šค ๋ชจ๋ธ์„ API์˜ ์ž ์žฌ์  ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌํ•˜๋Š” URI๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฆฌ์†Œ์Šค ์ด๋ฆ„์ด ์ž˜ ์ง€์ •๋˜๋ฉด API๊ฐ€ ์ง๊ด€์ ์ด๊ณ  ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. ์ œ๋Œ€๋กœ ์ˆ˜ํ–‰๋˜์ง€ ์•Š์œผ๋ฉด ๋™์ผํ•œ API๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ท ์ผํ•œ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ œ์•ฝ์€ URI์™€ HTTP ๋™์‚ฌ์˜ ์กฐํ•ฉ๊ณผ ํ‘œ์ค€ ๋ฐ ๊ทœ์น™์— ๋”ฐ๋ผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ๋ถ€๋ถ„์ ์œผ๋กœ ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ์ƒˆ API์— ๋Œ€ํ•œ ๋ฆฌ์†Œ์Šค URI๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ๋„์›€์ด ๋˜๋Š” ๋ช‡ ๊ฐ€์ง€ ํŒ์ž…๋‹ˆ๋‹ค.


2. ๋ชจ๋ฒ” ์‚ฌ๋ก€

2.1. ๋ฆฌ์†Œ์Šค๋ฅผ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด ๋ช…์‚ฌ๋ฅผ ์‚ฌ์šฉํ•ด๋ผ

RESTful URI๋Š” ๋™์ž‘(๋™์‚ฌ)์„ ์ฐธ์กฐํ•˜๋Š” ๋Œ€์‹  ์‚ฌ๋ฌผ(๋ช…์‚ฌ)์ธ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐธ์กฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ช…์‚ฌ์—๋Š” ๋™์‚ฌ๊ฐ€ ๊ฐ–์ง€ ์•Š๋Š” ์†์„ฑ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋ฆฌ์†Œ์Šค์˜ ๋ช‡ ๊ฐ€์ง€ ์˜ˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • Users of the system

  • User Accounts

  • Network Devices etc.

๋ฆฌ์†Œ์Šค URI๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค :

http://api.example.com/device-management/managed-devices 
http://api.example.com/device-management/managed-devices/{device-id} 
http://api.example.com/user-management/users
http://api.example.com/user-management/users/{id}

๋” ๋ช…ํ™•ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๋ฆฌ์†Œ์Šค ์›ํ˜•์„ ๋„ค ๊ฐ€์ง€ ๋ฒ”์ฃผ(๋ฌธ์„œ, ์ปฌ๋ ‰์…˜, ์ €์žฅ์†Œ ๋ฐ ์ปจํŠธ๋กค๋Ÿฌ)๋กœ ๋‚˜๋ˆ„๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ํ•ญ์ƒ ์ž์›์„ ํ•˜๋‚˜์˜ ์›ํ˜•์— ๋„ฃ์€ ๋‹ค์Œ ๋ช…๋ช… ๊ทœ์น™์„ ์ผ๊ด€๋˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ์‚ผ๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์Šต๋‹ˆ๋‹ค.

๊ท ์ผ์„ฑ์„ ์œ„ํ•ด ๋‘˜ ์ด์ƒ์˜ ์›ํ˜•์ด ํ˜ผํ•ฉ๋œ ๋ฆฌ์†Œ์Šค๋ฅผ ์„ค๊ณ„ํ•˜๋ ค๋Š” ์œ ํ˜น์— ์ €ํ•ญํ•˜์‹ญ์‹œ์˜ค.

2.1.1. ๋ฌธ์„œ

๋ฌธ์„œ ๋ฆฌ์†Œ์Šค๋Š” ๊ฐœ์ฒด ์ธ์Šคํ„ด์Šค ๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ ˆ์ฝ”๋“œ์™€ ์œ ์‚ฌํ•œ ๋‹จ์ผ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค.

REST์—์„œ๋Š” ๋ฆฌ์†Œ์Šค ์ปฌ๋ ‰์…˜ ๋‚ด์˜ ๋‹จ์ผ ๋ฆฌ์†Œ์Šค๋กœ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์„œ์˜ ์ƒํƒœ ํ‘œํ˜„์—๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๊ฐ’์ด ์žˆ๋Š” ํ•„๋“œ์™€ ๋‹ค๋ฅธ ๊ด€๋ จ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ๋งํฌ๊ฐ€ ๋ชจ๋‘ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

โ€œ๋‹จ์ˆ˜โ€ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์„œ ๋ฆฌ์†Œ์Šค ์›ํ˜•์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

http://api.example.com/device-management/managed-devices/{device-id}
http://api.example.com/user-management/users/{id}
http://api.example.com/user-management/users/admin
2.1.2. ์ปฌ๋ ‰์…˜

์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค๋Š” ์„œ๋ฒ„์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ๋ฆฌ์†Œ์Šค ๋””๋ ‰ํ„ฐ๋ฆฌ์ž…๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ๋Š” ์ปฌ๋ ‰์…˜์— ์ถ”๊ฐ€ํ•  ์ƒˆ ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ์•ˆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ƒˆ ๋ฆฌ์†Œ์Šค๋ฅผ ์ƒ์„ฑํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ์„ ํƒํ•˜๋Š” ๊ฒƒ์€ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค์— ๋‹ฌ๋ ค ์žˆ์Šต๋‹ˆ๋‹ค.

์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค๋Š” ํฌํ•จํ•  ํ•ญ๋ชฉ์„ ์„ ํƒํ•˜๊ณ  ํฌํ•จ๋œ ๊ฐ ๋ฆฌ์†Œ์Šค์˜ URI๋„ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

โ€œ๋ณต์ˆ˜โ€ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค ์›ํ˜•์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

http://api.example.com/device-management/managed-devices
http://api.example.com/user-management/users
http://api.example.com/user-management/users/{id}/accounts
2.1.3. ์ €์žฅ์†Œ(store)

์ €์žฅ์†Œ(store)๋Š” ํด๋ผ์ด์–ธํŠธ ๊ด€๋ฆฌ ๋ฆฌ์†Œ์Šค ์ €์žฅ์†Œ์ž…๋‹ˆ๋‹ค.

์ €์žฅ์†Œ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด API ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฆฌ์†Œ์Šค๋ฅผ ๋„ฃ๊ณ  ๋‹ค์‹œ ๊ฐ€์ ธ์˜ค๊ณ  ์‚ญ์ œํ•  ์‹œ๊ธฐ๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ €์žฅ์†Œ๋Š” ์ƒˆ URI๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  ์ €์žฅ๋œ ๊ฐ ๋ฆฌ์†Œ์Šค์—๋Š” URI๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฆฌ์†Œ์Šค๊ฐ€ ์ €์žฅ์†Œ์— ์ฒ˜์Œ ๋„ฃ์„ ๋•Œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ URI๋ฅผ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

์ƒ์  ๋ฆฌ์†Œ์Šค ์›ํ˜•์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด โ€œ๋ณต์ˆ˜ํ˜•โ€ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.

http://api.example.com/song-management/users/{id}/playlists
2.1.4. ์ปจํŠธ๋กค๋Ÿฌ

์ปจํŠธ๋กค๋Ÿฌ ๋ฆฌ์†Œ์Šค๋Š” ์ ˆ์ฐจ์  ๊ฐœ๋…์„ ๋ชจ๋ธ๋งํ•ฉ๋‹ˆ๋‹ค. ์ปจํŠธ๋กค๋Ÿฌ ๋ฆฌ์†Œ์Šค๋Š” ๋งค๊ฐœ ๋ณ€์ˆ˜์™€ ๋ฐ˜ํ™˜ ๊ฐ’, ์ž…๋ ฅ ๋ฐ ์ถœ๋ ฅ์ด ์žˆ๋Š” ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ํ•จ์ˆ˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

โ€œ๋™์‚ฌโ€๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ปจํŠธ๋กค๋Ÿฌ ์›ํ˜•์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

http://api.example.com/cart-management/users/{id}/cart/checkout http://api.example.com/song-management/users/{id}/playlist/play

2.2. ์ผ๊ด€์„ฑ์ด ํ•ต์‹ฌ

๋ชจํ˜ธ์„ฑ์„ ์ตœ์†Œํ™”ํ•˜๊ณ  ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€ ๊ด€๋ฆฌ์„ฑ์„ ๊ทน๋Œ€ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์ผ๊ด€๋œ ๋ฆฌ์†Œ์Šค ๋ช…๋ช… ๊ทœ์น™๊ณผ URI ํ˜•์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์•„๋ž˜ ๋””์ž์ธ ํžŒํŠธ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2.2.1. ์Šฌ๋ž˜์‹œ(/)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ„์ธต์  ๊ด€๊ณ„๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

์Šฌ๋ž˜์‹œ(/) ๋ฌธ์ž๋Š” ๋ฆฌ์†Œ์Šค ๊ฐ„์˜ ๊ณ„์ธต์  ๊ด€๊ณ„๋ฅผ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด URI์˜ ๊ฒฝ๋กœ ๋ถ€๋ถ„์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด

http://api.example.com/device-management
http://api.example.com/device-management/managed-devices
http://api.example.com/device-management/managed-devices/{id}
http://api.example.com/device-management/managed-devices/{id}/scripts
http://api.example.com/device-management/managed-devices/{id}/scripts/{id}
2.2.2. URI์— ํ›„ํ–‰ ์Šฌ๋ž˜์‹œ(/)๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

URI ๊ฒฝ๋กœ ๋‚ด์˜ ๋งˆ์ง€๋ง‰ ๋ฌธ์ž์ธ ์Šฌ๋ž˜์‹œ(/)๋Š” ์˜๋ฏธ๋ก ์  ๊ฐ’์„ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์œผ๋ฉฐ ํ˜ผ๋™์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. URI์—์„œ ์‚ญ์ œํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

http://api.example.com/device-management/managed-devices/
http://api.example.com/device-management/managed-devices 	/*This is much better version*/
2.2.3. ํ•˜์ดํ”ˆ(-)์„ ์‚ฌ์šฉํ•˜์—ฌ URI์˜ ๊ฐ€๋…์„ฑ ํ–ฅ์ƒ

์‚ฌ๋žŒ๋“ค์ด ์‰ฝ๊ฒŒ ์Šค์บ”ํ•˜๊ณ  ํ•ด์„ํ•  ์ˆ˜ ์žˆ๋„๋ก URI๋ฅผ ๋งŒ๋“ค๋ ค๋ฉด ํ•˜์ดํ”ˆ(-) ๋ฌธ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ธด ๊ฒฝ๋กœ ์„ธ๊ทธ๋จผํŠธ์—์„œ ์ด๋ฆ„์˜ ๊ฐ€๋…์„ฑ์„ ๋†’์ด์‹ญ์‹œ์˜ค.

http://api.example.com/device-management/managed-devices/
http://api.example.com/device-management/managed-devices 	/*This is much better version*/
2.2.4. ๋ฐ‘์ค„( _ )์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

ํ•˜์ดํ”ˆ ๋Œ€์‹  ๋ฐ‘์ค„์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌ๋ถ„ ๊ธฐํ˜ธ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ๊ธ€๊ผด์— ๋”ฐ๋ผ ๋ฐ‘์ค„() ๋ฌธ์ž๊ฐ€ ์ผ๋ถ€ ๋ธŒ๋ผ์šฐ์ €๋‚˜ ํ™”๋ฉด์—์„œ ๋ถ€๋ถ„์ ์œผ๋กœ ๊ฐ€๋ ค์ง€๊ฑฐ๋‚˜ ์™„์ „ํžˆ ์ˆจ๊ฒจ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ํ˜ผ๋™์„ ํ”ผํ•˜๋ ค๋ฉด ๋ฐ‘์ค„(_) ๋Œ€์‹  ํ•˜์ดํ”ˆ(-)์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.

2.2.5. URI์— ์†Œ๋ฌธ์ž ์‚ฌ์šฉ
http://api.example.org/my-folder/my-doc       //1
HTTP://API.EXAMPLE.ORG/my-folder/my-doc     //2
http://api.example.org/My-Folder/my-doc       //3

์œ„์˜ ์˜ˆ์—์„œ 1๊ณผ 2๋Š” ๊ฐ™์ง€๋งŒ 3์€ My-Folder๋ฅผ ๋Œ€๋ฌธ์ž๋กœ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

2.3. ํŒŒ์ผ ํ™•์žฅ์ž๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค

ํŒŒ์ผ ํ™•์žฅ์ž๋Š” ๋ณด๊ธฐ์— ์ข‹์ง€ ์•Š์œผ๋ฉฐ ์–ด๋–ค ์ด์ ๋„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์ œ๊ฑฐํ•˜๋ฉด URI ๊ธธ์ด๋„ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ๋„ ์žˆ์„ ์ด์œ ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์œ„์˜ ์ด์œ ์™€๋Š” ๋ณ„๋„๋กœ ํŒŒ์ผ ํ™•์žฅ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ API์˜ ๋ฏธ๋””์–ด ์œ ํ˜•์„ ๊ฐ•์กฐํ•˜๋ ค๋ฉด Content-Type ํ—ค๋”๋ฅผ ํ†ตํ•ด ์ „๋‹ฌ๋˜๋Š” ๋ฏธ๋””์–ด ์œ ํ˜•์— ์˜์กดํ•˜์—ฌ ๋ณธ๋ฌธ์˜ ์ฝ˜ํ…์ธ ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ฒฐ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

http://api.example.com/device-management/managed-devices.xml  /*Do not use it*/
http://api.example.com/device-management/managed-devices 	/*This is correct URI*/

2.4. URI์— CRUD ํ•จ์ˆ˜ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

CRUD ๊ธฐ๋Šฅ์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด URI๋ฅผ ์‚ฌ์šฉํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. URI๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ๊ณ ์œ ํ•˜๊ฒŒ ์‹๋ณ„ํ•˜๋Š” ๋ฐ๋งŒ ์‚ฌ์šฉ๋˜์–ด์•ผ ํ•˜๋ฉฐ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์ž‘์—…์ด ์•„๋‹™๋‹ˆ๋‹ค.

์–ด๋–ค CRUD ๊ธฐ๋Šฅ์ด ์ˆ˜ํ–‰๋˜๋Š”์ง€ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด HTTP ์š”์ฒญ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

HTTP GET http://api.example.com/device-management/managed-devices  //Get all devices
HTTP POST http://api.example.com/device-management/managed-devices  //Create new Device

HTTP GET http://api.example.com/device-management/managed-devices/{id}  //Get device for given Id
HTTP PUT http://api.example.com/device-management/managed-devices/{id}  //Update device for given Id
HTTP DELETE http://api.example.com/device-management/managed-devices/{id}  //Delete device for given Id

2.5. URI ์ปฌ๋ ‰์…˜ ํ•„ํ„ฐ๋ง์„ ์œ„ํ•ด ์ฟผ๋ฆฌ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.

ํŠน์ • ๋ฆฌ์†Œ์Šค ์†์„ฑ์— ๋”ฐ๋ผ ์ •๋ ฌ, ํ•„ํ„ฐ๋ง ๋˜๋Š” ์ œํ•œ๋˜๋Š” ๋ฆฌ์†Œ์Šค ๋ชจ์Œ์ด ํ•„์š”ํ•œ ์š”๊ตฌ ์‚ฌํ•ญ์ด ์ž์ฃผ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์ด ์š”๊ตฌ ์‚ฌํ•ญ์˜ ๊ฒฝ์šฐ ์ƒˆ API๋ฅผ ์ƒ์„ฑํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ๋Œ€์‹  ๋ฆฌ์†Œ์Šค ์ปฌ๋ ‰์…˜ API์—์„œ ์ •๋ ฌ, ํ•„ํ„ฐ๋ง ๋ฐ ํŽ˜์ด์ง€ ๋งค๊น€ ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™”ํ•˜๊ณ  ์ž…๋ ฅ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์ฟผ๋ฆฌ ๋งค๊ฐœ ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌํ•˜์‹ญ์‹œ์˜ค.

http://api.example.com/device-management/managed-devices
http://api.example.com/device-management/managed-devices?region=USA
http://api.example.com/device-management/managed-devices?region=USA&brand=XYZ
http://api.example.com/device-management/managed-devices?region=USA&brand=XYZ&sort=installation-date

2๏ธโƒฃ Guides

Caching

1. ์บ์‹ฑ

์บ์‹ฑ์€ ์š”์ฒญ-์‘๋‹ต ๊ฒฝ๋กœ๋ฅผ ๋”ฐ๋ผ ์—ฌ๋Ÿฌ ์œ„์น˜์— ์ž์ฃผ ์•ก์„ธ์Šคํ•˜๋Š” ๋ฐ์ดํ„ฐ์˜ ๋ณต์‚ฌ๋ณธ์„ ์ €์žฅํ•˜๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

์†Œ๋น„์ž๊ฐ€ ๋ฆฌ์†Œ์Šค ํ‘œํ˜„์„ ์š”์ฒญํ•˜๋ฉด ์š”์ฒญ์€ ์บ์‹œ ๋˜๋Š” ์ผ๋ จ์˜ ์บ์‹œ (๋กœ์ปฌ ์บ์‹œ, ํ”„๋ก์‹œ ์บ์‹œ ๋˜๋Š” ์—ญ๋ฐฉํ–ฅ ํ”„๋ก์‹œ)๋ฅผ ํ†ตํ•ด ๋ฆฌ์†Œ์Šค๋ฅผ ํ˜ธ์ŠคํŒ…ํ•˜๋Š” ์„œ๋น„์Šค๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

์š”์ฒญ ๊ฒฝ๋กœ์— ์žˆ๋Š” ์บ์‹œ์— ์š”์ฒญ๋œ ํ‘œํ˜„์˜ ์ƒˆ ๋ณต์‚ฌ๋ณธ์ด ์žˆ๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น ๋ณต์‚ฌ๋ณธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์š”์ฒญ์„ ์ถฉ์กฑํ•ฉ๋‹ˆ๋‹ค. ์–ด๋–ค ์บ์‹œ๋„ ์š”์ฒญ์„ ๋งŒ์กฑ์‹œํ‚ฌ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ, ์š”์ฒญ์€ ์„œ๋น„์Šค(๋˜๋Š” ๊ณต์‹์ ์œผ๋กœ ์•Œ๋ ค์ง„ ์˜ค๋ฆฌ์ง„ ์„œ๋ฒ„)๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

HTTP ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์˜ค๋ฆฌ์ง„ ์„œ๋ฒ„๋Š” ์‘๋‹ต์„ ์บ์‹œํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€์™€ ์บ์‹œํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ, ์‚ฌ์šฉ์ž ๋ฐ ๊ธฐ๊ฐ„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์‘๋‹ต ๊ฒฝ๋กœ์— ์žˆ๋Š” ์บ์‹œ๋Š” ์‘๋‹ต์˜ ๋ณต์‚ฌ๋ณธ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์ง€๋งŒ, ์ด๋Š” ์บ์‹ฑ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ ํ—ˆ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์บ์‹ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋„คํŠธ์›Œํฌ๋ฅผ ์ตœ์ ํ™”ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์ „๋ฐ˜์ ์ธ ์„œ๋น„์Šค ํ’ˆ์งˆ์ด ํ–ฅ์ƒ๋ฉ๋‹ˆ๋‹ค.

  • ๋Œ€์—ญํญ ์ค„์ด๊ธฐ
  • ๋Œ€๊ธฐ ์‹œ๊ฐ„ ๊ฐ์†Œ
  • ์„œ๋ฒ„์˜ ๋ถ€ํ•˜ ๊ฐ์†Œ
  • ๋„คํŠธ์›Œํฌ ์žฅ์•  ์ˆจ๊ธฐ๊ธฐ

2. REST API์˜ ์บ์‹ฑ

์บ์‹œ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์€ REST์˜ ์•„ํ‚คํ…์ฒ˜ ์ œ์•ฝ ์กฐ๊ฑด ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.

  • GET ์š”์ฒญ์€ ํŠน๋ณ„ํ•œ ์กฐ๊ฑด์ด ๋ฐœ์ƒํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์บ์‹œ ๊ฐ€๋Šฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๋ธŒ๋ผ์šฐ์ €๋Š” ๋ชจ๋“  GET ์š”์ฒญ์„ ์บ์‹œ ๊ฐ€๋Šฅํ•œ ๊ฒƒ์œผ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • POST ์š”์ฒญ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์บ์‹œํ•  ์ˆ˜ ์—†์ง€๋งŒ ๋ช…์‹œ์ ์œผ๋กœ ์บ์‹ฑ์„ ํ—ˆ์šฉํ•˜๋Š” ์ง€์‹œ๋ฌธ์ด ์žˆ๋Š” Expires ํ—ค๋” ๋˜๋Š” Cache-Control ํ—ค๋”๊ฐ€ ์‘๋‹ต์— ์ถ”๊ฐ€๋˜๋Š” ๊ฒฝ์šฐ ์บ์‹œ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • PUT ๊ณผ DELETE ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์€ ์ „ํ˜€ ์บ์‹œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

HTTP ๋‚ ์งœ๋Š” ํ•ญ์ƒ ํ˜„์ง€ ์‹œ๊ฐ„์ด ์•„๋‹Œ GMT๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

3. ์บ์‹œ ์ œ์–ด ํ—ค๋”

๋‹ค์Œ์€ ์บ์‹ฑ ๋™์ž‘์„ ์ œ์–ดํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ฃผ์š” HTTP ์‘๋‹ต ํ—ค๋”์ž…๋‹ˆ๋‹ค.

3.1. Expires

Expires HTTP ํ—ค๋”๋Š” ์บ์‹œ๋œ ํ‘œํ˜„์˜ ์ ˆ๋Œ€ ๋งŒ๋ฃŒ ์‹œ๊ฐ„์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด ์บ์‹œ๋œ ํ‘œํ˜„์€ ์˜ค๋ž˜๋œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋˜๋ฉฐ ์›๋ณธ ์„œ๋ฒ„์—์„œ ๋‹ค์‹œ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ‘œํ˜„์ด ๋งŒ๋ฃŒ๋˜์ง€ ์•Š์Œ์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด ์„œ๋น„์Šค์—๋Š” ํ–ฅํ›„ ์ตœ๋Œ€ 1๋…„๊นŒ์ง€์˜ ์‹œ๊ฐ„์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Expires: Fri, 20 May 2016 19:20:49 GMT

3.2. Cache-Control

ํ—ค๋” ๊ฐ’์€ ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„๋œ ํ•˜๋‚˜ ์ด์ƒ์˜ ์ง€์‹œ์–ด๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ง€์‹œ์–ด๋Š” ์‘๋‹ต์ด ์บ์‹œ ๊ฐ€๋Šฅํ•œ์ง€ ์—ฌ๋ถ€, ์บ์‹œ ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ ์ตœ๋Œ€ ์‚ฌ์šฉ ๊ธฐ๊ฐ„ ๋˜๋Š” ์ตœ๋Œ€ ์‚ฌ์šฉ ๊ธฐ๊ฐ„ ๋“ฑ์„ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

Cache-Control: max-age=3600

3.3. ETag

ETag ๊ฐ’์€ ์„œ๋ฒ„๊ฐ€ ์ˆ˜๋ช… ๋™์•ˆ ๋ฆฌ์†Œ์Šค ์ƒํƒœ๋ฅผ ๊ณ ์œ ํ•˜๊ฒŒ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•ด ๋ฆฌ์†Œ์Šค์™€ ์—ฐ๊ฒฐํ•˜๋Š” ๋ถˆํˆฌ๋ช… ๋ฌธ์ž์—ด ํ† ํฐ์ž…๋‹ˆ๋‹ค.

์ง€์ •๋œ URL์˜ ๋ฆฌ์†Œ์Šค๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ์ƒˆ Etag ๊ฐ’์„ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋‘˜์„ ๋น„๊ตํ•˜์—ฌ ๋ฆฌ์†Œ์Šค์˜ ๋‘ ํ‘œํ˜„์ด ๋™์ผํ•œ์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•˜๋Š” ๋™์•ˆ ํด๋ผ์ด์–ธํŠธ๋Š” If-None-Match ํ—ค๋” ํ•„๋“œ์˜ ETag๋ฅผ ์„œ๋ฒ„๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ๋œ ๋ฆฌ์†Œ์Šค์˜ Etag์™€ If-None-Match ํ—ค๋”๋กœ ์ „์†ก๋œ ๊ฐ’์„ ์ผ์น˜์‹œํ‚ต๋‹ˆ๋‹ค.

๋‘ ๊ฐ’์ด ์ผ์น˜ํ•˜๋Š” ๊ฒฝ์šฐ ์„œ๋ฒ„๋Š” ๋ณธ๋ฌธ ์—†์ด 304 Not Modified ์ƒํƒœ๋ฅผ ๋‹ค์‹œ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ์ด ์ƒํƒœ๋Š” ํด๋ผ์ด์–ธํŠธ์— ์‘๋‹ต์˜ ์บ์‹œ๋œ ๋ฒ„์ „์ด ์—ฌ์ „ํžˆ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ์„ ์•Œ๋ ค์ค๋‹ˆ๋‹ค(์ƒˆ๋กœ ๊ณ ์นจ).

ETag: "abcd1234567n34jv"

3.4. Last-Modified

์‘๋‹ต์˜ Date ํ—ค๋”๋Š” ์‘๋‹ต์ด ์ƒ์„ฑ๋œ ์‹œ๊ฐ„์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐ˜๋ฉด Last-Modified ํ—ค๋”๋Š” ์—ฐ๊ฒฐ๋œ ๋ฆฌ์†Œ์Šค๊ฐ€ ๋งˆ์ง€๋ง‰์œผ๋กœ ๋ณ€๊ฒฝ๋œ ์‹œ๊ฐ„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

์ด ํ—ค๋”๋Š” ๋ฆฌ์†Œ์Šค๊ฐ€ ์ด์ „์— ํด๋ผ์ด์–ธํŠธ ์บ์‹œ์— ์ €์žฅ๋œ ๋ฆฌ์†Œ์Šค์™€ ๋™์ผํ•œ์ง€ ํ™•์ธํ•˜๋Š” ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ธฐ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ETag ํ—ค๋”๋ณด๋‹ค ๋œ ์ •ํ™•ํ•˜์ง€๋งŒ ํด๋ฐฑ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ž…๋‹ˆ๋‹ค.

Last-Modified ๊ฐ’์€ Date ๊ฐ’๋ณด๋‹ค ํด ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. Date ํ—ค๋”๋Š” ๊ธˆ์ง€๋œ ํ—ค๋” ์ด๋ฆ„์— ๋‚˜์—ด๋ฉ๋‹ˆ๋‹ค.

Last-Modified: Fri, 10 May 2016 09:17:49 GMT

Compression

REST API๋Š” XML, JSON, HTML ๋˜๋Š” ์ผ๋ฐ˜ ํ…์ŠคํŠธ์™€ ๊ฐ™์€ ์—ฌ๋Ÿฌ ํ˜•์‹์œผ๋กœ ๋ฆฌ์†Œ์Šค ํ‘œํ˜„์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ชจ๋“  ํ˜•์‹์€ ๋„คํŠธ์›Œํฌ์—์„œ ๋Œ€์—ญํญ์„ ์ ˆ์•ฝํ•˜๊ธฐ ์œ„ํ•ด ๋” ์ ์€ ์ˆ˜์˜ ๋ฐ”์ดํŠธ๋กœ ์••์ถ•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ํ”„๋กœํ† ์ฝœ์€ ๋‹ค๋ฅธ ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜์—ฌ ์••์ถ•์„ ํ™œ์„ฑํ™”ํ•˜๊ณ  ํด๋ผ์ด์–ธํŠธ์— ์••์ถ• ์ฒด๊ณ„์— ๋Œ€ํ•ด ์•Œ๋ ค ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ‘œํ˜„์„ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ์••์ถ•์„ ํ’€ ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

์•”ํ˜ธํ™”์™€ ๊ฐ™์€ ์••์ถ•์€ ์ „์†ก ์ค‘์ธ ๋ฆฌ์†Œ์Šค ํ‘œํ˜„์— ๋ฐœ์ƒํ•˜๋ฉฐ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ‘œํ˜„์„ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ์‹คํ–‰ ์ทจ์†Œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

HTTP๋Š” REST์— ๋Œ€ํ•ด ๊ฐ€์žฅ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ํ”„๋กœํ† ์ฝœ์ด๋ฏ€๋กœ HTTP ๊ด€๋ จ ์‘๋‹ต ์••์ถ•์˜ ์˜ˆ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

1.์••์ถ• ๊ด€๋ จ ์š”์ฒญ/์‘๋‹ต ํ—ค๋”

1.1. Accept-Encoding (์ธ์ฝ”๋”ฉ ์ˆ˜๋ฝ)

๋ฆฌ์†Œ์Šค ํ‘œํ˜„์„ ์š”์ฒญํ•˜๋Š” ๋™์•ˆ - HTTP ์š”์ฒญ๊ณผ ํ•จ๊ป˜ ํด๋ผ์ด์–ธํŠธ๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ดํ•ดํ•˜๋Š” ์••์ถ• ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์ข…๋ฅ˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” Accept-Encoding ํ—ค๋”๋ฅผ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

Accept-Encoding์˜ ๋‘ ๊ฐ€์ง€ ํ‘œ์ค€ ๊ฐ’์€ compress์™€ gzip์ž…๋‹ˆ๋‹ค.

Accept-encoding์˜ ํ—ค๋”๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค :

GET        /employees         HTTP/1.1
Host:     www.domain.com
Accept:     text/html
Accept-Encoding:     gzip,compress

accept-encoding์˜ ๋˜ ๋‹ค๋ฅธ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์šฉ๋„๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค :

Accept-Encoding: compress, gzip
Accept-Encoding:
Accept-Encoding: *
Accept-Encoding: compress;q=0.5, gzip;q=1.0
Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0

Accept-Encoding ํ•„๋“œ๊ฐ€ ์š”์ฒญ์— ์žˆ๊ณ  ์„œ๋ฒ„๊ฐ€ Accept-Encoding ํ—ค๋”์— ๋”ฐ๋ผ ํ—ˆ์šฉ ๊ฐ€๋Šฅํ•œ ์‘๋‹ต์„ ๋ณด๋‚ผ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ, ์„œ๋ฒ„๋Š” 406(Not Acceptable) ์ƒํƒœ ์ฝ”๋“œ๋กœ ์˜ค๋ฅ˜ ์‘๋‹ต์„ ๋ณด๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

1.2. Content-Encoding

์„œ๋ฒ„๊ฐ€ Accept-Encoding์˜ ์••์ถ• ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ์ดํ•ดํ•˜๋ฉด ํ•ด๋‹น ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ํ‘œํ˜„์„ ์ œ๊ณตํ•˜๊ธฐ ์ „์— ์••์ถ•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ฑ๊ณต์ ์œผ๋กœ ์••์ถ•๋˜๋ฉด ์„œ๋ฒ„๋Š” ๋‹ค๋ฅธ HTTP ํ—ค๋”(์˜ˆ: Content-Encoding)๋กœ ์ธ์ฝ”๋”ฉ ์ฒด๊ณ„๋ฅผ ํด๋ผ์ด์–ธํŠธ์— ์•Œ๋ฆฝ๋‹ˆ๋‹ค.

200 OK
Content-Type:     text/html
Content-Encoding:     gzip

์š”์ฒญ ๋ฉ”์‹œ์ง€์˜ ์—”ํ‹ฐํ‹ฐ ๋‚ด์šฉ ์ฝ”๋”ฉ์„ ์›๋ณธ ์„œ๋ฒ„์—์„œ ํ—ˆ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ, ์„œ๋ฒ„๋Š” ์ƒํƒœ ์ฝ”๋“œ 415(์ง€์›๋˜์ง€ ์•Š๋Š” ๋ฏธ๋””์–ด ์œ ํ˜•)๋กœ ์‘๋‹ตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ๋‚ด์šฉ ์ธ์ฝ”๋”ฉ์ด ์—”ํ‹ฐํ‹ฐ์— ์ ์šฉ๋œ ๊ฒฝ์šฐ ๋ชจ๋“  ์ธ์ฝ”๋”ฉ์ด ์‚ฌ์šฉ๋œ ์ˆœ์„œ๋Œ€๋กœ ๋‚˜์—ด๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์••์ถ• ์š”์ฒญ ์—ฌ๋ถ€์— ๊ด€๊ณ„์—†์ด ์š”์ฒญ ๋ฐ ์‘๋‹ต์— ๋Œ€ํ•œ ์›๋ž˜ ๋ฏธ๋””์–ด ์œ ํ˜•์€ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์••์ถ•์€ ์ถ”๊ฐ€ ๋ณต์žก์„ฑ ์—†์ด ์ตœ์†Œํ•œ์˜ ๋น„์šฉ์œผ๋กœ ๋งŽ์€ ๋Œ€์—ญํญ์„ ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋Œ€๋ถ€๋ถ„์˜ ์›น ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์œ„์˜ ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น ์‚ฌ์ดํŠธ ํ˜ธ์ŠคํŠธ ์„œ๋ฒ„์—์„œ ์••์ถ•๋œ ํ‘œํ˜„์„ ์ž๋™์œผ๋กœ ์š”์ฒญํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ๊ณ  ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฐธ์กฐ :

  • https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11
  • https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3

Content Negotiation

1. ์ฝ˜ํ…์ธ  ํ˜‘์ƒ

์ผ๋ฐ˜์ ์œผ๋กœ REST ๋ฆฌ์†Œ์Šค๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ”„๋ ˆ์  ํ…Œ์ด์…˜์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋Š” ๋Œ€๋ถ€๋ถ„ ์„œ๋กœ ๋‹ค๋ฅธ ํ‘œํ˜„์„ ๊ธฐ๋Œ€ํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ ์ ˆํ•œ ํ”„๋ ˆ์  ํ…Œ์ด์…˜์„ ์š”์ฒญํ•˜๋Š” ๊ฒƒ์„ ์ฝ˜ํ…์ธ  ํ˜‘์ƒ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

HTTP๋Š” โ€œ์ปจํ…์ธ  ํ˜‘์ƒโ€์„ ์œ„ํ•œ ๋ช‡ ๊ฐ€์ง€ ๋ฉ”์ปค๋‹ˆ์ฆ˜์— ๋Œ€ํ•œ ๊ทœ์ •์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์—ฌ๋Ÿฌ ํ‘œํ˜„์ด ์žˆ์„ ๋•Œ ์ฃผ์–ด์ง„ ์‘๋‹ต์— ๋Œ€ํ•œ ์ตœ์ƒ์˜ ํ‘œํ˜„์„ ์„ ํƒํ•˜๋Š” ํ”„๋กœ์„ธ์Šค์ž…๋‹ˆ๋‹ค.

2. ์„œ๋ฒ„ ๊ธฐ๋ฐ˜ vs ์—์ด์ „ํŠธ ๊ธฐ๋ฐ˜ ์ฝ˜ํ…์ธ  ํ˜‘์ƒ

์‘๋‹ต์— ๋Œ€ํ•œ ์ตœ์ƒ์˜ ํ‘œํ˜„์ด ์„œ๋ฒ„์— ์žˆ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ์˜ํ•ด ์„ ํƒ๋˜๋Š” ๊ฒฝ์šฐ ์ด๋ฅผ ์„œ๋ฒ„ ์ฃผ๋„ ํ˜‘์ƒ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ ๋˜๋Š” ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์„ ํƒํ•˜๋Š” ๊ฒฝ์šฐ ์—์ด์ „ํŠธ ์ฃผ๋„ ํ˜‘์ƒ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

ํ˜„์‹ค์ ์œผ๋กœ ์„œ๋ฒ„ ์ธก ํ˜‘์ƒ์˜ ์šฉ๋„๋Š” ๋งŽ์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ์‹์œผ๋กœ, ์šฐ๋ฆฌ๋Š” ๊ณ ๊ฐ์˜ ๊ธฐ๋Œ€์— ๋Œ€ํ•ด ๋งŽ์€ ๊ฐ€์ •์„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ ์ปจํ…์ŠคํŠธ ๋˜๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฆฌ์†Œ์Šค ํ‘œํ˜„์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ๊ฐ™์€ ๋ช‡ ๊ฐ€์ง€ ์‚ฌํ•ญ์„ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์ด ๊ฑฐ์˜ ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์„œ๋ฒ„ ์ฃผ๋„ ํ˜‘์ƒ์€ ์„œ๋ฒ„ ์ธก ์ฝ”๋“œ๋ฅผ ๋ถˆํ•„์š”ํ•˜๊ณ  ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋Œ€๋ถ€๋ถ„์˜ REST API ๊ตฌํ˜„์€ ์—์ด์ „ํŠธ ์ฃผ๋„ ์ฝ˜ํ…์ธ  ํ˜‘์ƒ์— ์˜์กดํ•ฉ๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ ๊ธฐ๋ฐ˜ ์ฝ˜ํ…์ธ  ํ˜‘์ƒ์€ HTTP ์š”์ฒญ ํ—ค๋” ๋˜๋Š” ๋ฆฌ์†Œ์Šค URI ํŒจํ„ด์˜ ์‚ฌ์šฉ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

2.1. HTTP ํ—ค๋” ์‚ฌ์šฉ

์„œ๋ฒ„ ์ธก์—์„œ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์—๋Š” ์—ฐ๊ฒฐ๋œ ์—”ํ„ฐํ‹ฐ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์œ ํ˜•์„ ๊ฒฐ์ •ํ•˜๊ธฐ ์œ„ํ•ด ์„œ๋ฒ„๋Š” HTTP ์š”์ฒญ ํ—ค๋” Content-Type์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ฝ˜ํ…์ธ  ์œ ํ˜•์˜ ์ผ๋ฐ˜์ ์ธ ์˜ˆ๋กœ๋Š” โ€œtext/plainโ€, โ€œapplication/xmlโ€, โ€œtext/htmlโ€, โ€œapplication/jsonโ€, โ€œimage/gifโ€ ๋ฐ โ€œimage/jpegโ€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

Content-Type: application/json

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์›ํ•˜๋Š” ํ‘œํ˜„ ์œ ํ˜•์„ ๊ฒฐ์ •ํ•˜๊ธฐ ์œ„ํ•ด HTTP ํ—ค๋” ACCEPT๊ฐ€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์œ„์˜ Content-Type์— ๋Œ€ํ•ด ์–ธ๊ธ‰ํ•œ ๊ฐ’ ์ค‘ ํ•˜๋‚˜๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค.

Accept: application/json

์ผ๋ฐ˜์ ์œผ๋กœ ์š”์ฒญ์— Accept ํ—ค๋”๊ฐ€ ์—†์œผ๋ฉด ์„œ๋ฒ„๋Š” ๋ฏธ๋ฆฌ ๊ตฌ์„ฑ๋œ ๊ธฐ๋ณธ ํ‘œํ˜„ ์œ ํ˜•์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Accept ํ—ค๋” ๊ธฐ๋ฐ˜ ์ฝ˜ํ…์ธ  ํ˜‘์ƒ์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๊ณ  ๊ถŒ์žฅ๋˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

2.2. URL ํŒจํ„ด ์‚ฌ์šฉ

์ฝ˜ํ…์ธ  ์œ ํ˜• ์ •๋ณด๋ฅผ ์„œ๋ฒ„์— ์ „๋‹ฌํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” ๋ฆฌ์†Œ์Šค URI์˜ ํŠน์ • ํ™•์žฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํด๋ผ์ด์–ธํŠธ๋Š” ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

http://rest.api.com/v1/employees/20423.xml
http://rest.api.com/v1/employees/20423.json

์œ„์˜ ๊ฒฝ์šฐ ์ฒซ ๋ฒˆ์งธ ์š”์ฒญ URI๋Š” ๋‘ ๋ฒˆ์งธ ์š”์ฒญ URI๊ฐ€ JSON ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ• ์ง€ ์—ฌ๋ถ€์— ๊ด€๊ณ„์—†์ด XML ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

3. ๊ธฐ๋ณธ ์„ค์ • ์ •์˜

์ƒ๋Œ€ ํ’ˆ์งˆ ์š”์†Œ์ธ โ€˜qโ€™ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Accept ํ—ค๋”์— ์—ฌ๋Ÿฌ ๊ฐ’์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›ํ•˜๋Š” ํ‘œํ˜„์ด ์กด์žฌํ•˜๋Š”์ง€ ๋˜๋Š” ๊ทธ ๋‹น์‹œ ์„œ๋ฒ„์—์„œ ์ง€์›ํ•˜๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์„ ๋•Œ ์ˆ˜๋ฝ ํ—ค๋”์— ์—ฌ๋Ÿฌ ๊ฐ’์„ ์ œ๊ณตํ•˜๊ธฐ๋ฅผ ์›ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ

Accept: application/json,application/xml;q=0.9,*/*;q=0.8

์œ„์˜ Accept ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์„œ๋ฒ„์— JSON ํ˜•์‹(์ฒซ ๋ฒˆ์งธ ์„ ํƒ)์„ ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ XML ํ˜•์‹(๋‘ ๋ฒˆ์งธ ์„ ํƒ)์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ์ „ํžˆ ๊ฐ€๋Šฅํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๊ฐ€๋Šฅํ•œ ๋งŒํผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ์„ค์ • ์ˆœ์„œ๋Š” 0์—์„œ 1 ์‚ฌ์ด์˜ ๊ฐ’์„ ๊ฐ–๋Š” q ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด ์ •์˜๋ฉ๋‹ˆ๋‹ค. ์•„๋ฌด ๊ฒƒ๋„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ๊ฐ’์€ 1์ž…๋‹ˆ๋‹ค.

HATEOAS

1. HATEOAS ๋ž€?

HATEOAS(Hypermedia as Engine as Application State)๋Š” REST ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•„ํ‚คํ…์ฒ˜์˜ ์ œ์•ฝ ์กฐ๊ฑด์ž…๋‹ˆ๋‹ค. HATEOAS๋Š” REST ์Šคํƒ€์ผ ์•„ํ‚คํ…์ฒ˜๋ฅผ ๋Œ€๋ถ€๋ถ„์˜ ๋‹ค๋ฅธ ๋„คํŠธ์›Œํฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•„ํ‚คํ…์ฒ˜์—์„œ ๊ณ ์œ ํ•˜๊ฒŒ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

โ€œํ•˜์ดํผ๋ฏธ๋””์–ดโ€ ๋ผ๋Š” ์šฉ์–ด๋Š” ์ด๋ฏธ์ง€, ์˜ํ™” ๋ฐ ํ…์ŠคํŠธ์™€ ๊ฐ™์€ ๋‹ค๋ฅธ ํ˜•ํƒœ์˜ ๋ฏธ๋””์–ด์— ๋Œ€ํ•œ ๋งํฌ๋ฅผ ํฌํ•จํ•˜๋Š” ๋ชจ๋“  ์ฝ˜ํ…์ธ ๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค.

REST ์•„ํ‚คํ…์ฒ˜ ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•˜๋ฉด API ์‘๋‹ต ์ฝ˜ํ…์ธ ์—์„œ ํ•˜์ดํผ๋ฏธ๋””์–ด ๋งํฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ๋Š” ํ•˜์ดํผ๋ฏธ๋””์–ด ๋งํฌ๋ฅผ ํ†ต๊ณผํ•˜์—ฌ ์ ์ ˆํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ๋™์ ์œผ๋กœ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ดํผ๋ฏธ๋””์–ด ๋งํฌ๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๊ฒƒ์€ ์ตœ์ข… ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ๊ด€๋ จ ํ•˜์ดํผ๋งํฌ๋ฅผ ํด๋ฆญํ•˜์—ฌ ์›น ํŽ˜์ด์ง€๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐœ๋…์ ์œผ๋กœ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ์•„๋ž˜ JSON ์‘๋‹ต์€ HTTP GET http://api.domain.com/management/departments/10๊ณผ ๊ฐ™์€ API์—์„œ ์ œ๊ณต๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

{
    "departmentId": 10,
    "departmentName": "Administration",
    "locationId": 1700,
    "managerId": 200,
    "links": [
        {
            "href": "10/employees",
            "rel": "employees",
            "type" : "GET"
        }
    ]
}

์•ž์˜ ์˜ˆ์—์„œ ์„œ๋ฒ„๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ์‘๋‹ต์—๋Š” ๋ถ€์„œ์— ์†ํ•œ ์ง์›์„ ์ฝ๊ธฐ ์œ„ํ•ด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ง์› ๋ฆฌ์†Œ์Šค 10/employees์— ๋Œ€ํ•œ ํ•˜์ดํผ๋ฏธ๋””์–ด ๋งํฌ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„ ์ ‘๊ทผ ๋ฐฉ์‹์˜ ์žฅ์ ์€ ์„œ๋ฒ„์—์„œ ๋ฐ˜ํ™˜๋œ ํ•˜์ดํผ๋ฏธ๋””์–ด ๋งํฌ๊ฐ€ ๊ทธ ๋ฐ˜๋Œ€๊ฐ€ ์•„๋‹ˆ๋ผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ƒํƒœ๋ฅผ ๊ตฌ๋™ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

JSON์—๋Š” ๋‘ ๋ฆฌ์†Œ์Šค ๊ฐ„์˜ ๋งํฌ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ณดํŽธ์ ์œผ๋กœ ํ—ˆ์šฉ๋˜๋Š” ํ˜•์‹์ด ์—†์Šต๋‹ˆ๋‹ค. ์‘๋‹ต ๋ณธ๋ฌธ์„ ๋ณด๋‚ด๊ฑฐ๋‚˜ HTTP ์‘๋‹ต ํ—ค๋”์— ๋งํฌ๋ฅผ ๋ณด๋‚ด๊ธฐ๋กœ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

HTTP/1.1 200 OK
...
Link: <10/employees>; rel="employees"

๋‘˜ ๋‹ค ์ข‹์€ ํ•ด๊ฒฐ์ฑ…์ž…๋‹ˆ๋‹ค.

2. HATEOAS ๊ตฌํ˜„ ๋ฐฉ๋ฒ•

์šฐ๋ฆฌ๋Š” ์›น์‚ฌ์ดํŠธ๋ฅผ ๋ฐฉ๋ฌธํ•  ๋•Œ ํ™ˆํŽ˜์ด์ง€๋ฅผ ๋ฐฉ๋ฌธํ•ฉ๋‹ˆ๋‹ค. ํ™ˆํŽ˜์ด์ง€๋Š” ์ผ๋ถ€ ์Šค๋ƒ…์ƒท๊ณผ ์›น์‚ฌ์ดํŠธ์˜ ๋‹ค๋ฅธ ์„น์…˜์— ๋Œ€ํ•œ ๋งํฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋งํฌ๋ฅผ ํด๋ฆญํ•˜๊ณ  ์ปจํ…์ŠคํŠธ์™€ ๊ด€๋ จ๋œ ์ถ”๊ฐ€ ์ •๋ณด ๋ฐ ๊ด€๋ จ ๋งํฌ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.

์›น ์‚ฌ์ดํŠธ์™€ ์ธ๊ฐ„์˜ ์ƒํ˜ธ ์ž‘์šฉ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ REST ํด๋ผ์ด์–ธํŠธ๋Š” ์ดˆ๊ธฐ API URI์— ๋„๋‹ฌํ•˜๊ณ  ์„œ๋ฒ„ ์ œ๊ณต ๋งํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•„์š”ํ•œ ๋ฆฌ์†Œ์Šค์— ์•ก์„ธ์Šคํ•˜๊ณ  ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ž‘์—…์„ ๋™์ ์œผ๋กœ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ๋Š” ์„œ๋น„์Šค ๋˜๋Š” ์›Œํฌํ”Œ๋กœ์™€ ๊ด€๋ จ๋œ ๋‹ค์–‘ํ•œ ๋‹จ๊ณ„์— ๋Œ€ํ•œ ์‚ฌ์ „ ์ง€์‹์ด ์—†์–ด๋„ ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ํด๋ผ์ด์–ธํŠธ๋Š” ๋” ์ด์ƒ ๋‹ค์–‘ํ•œ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ URI ๊ตฌ์กฐ๋ฅผ ํ•˜๋“œ์ฝ”๋”ฉํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

HATEOAS๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ค‘๋‹จํ•˜์ง€ ์•Š๊ณ  API๊ฐ€ ๋ฐœ์ „ํ•จ์— ๋”ฐ๋ผ ์„œ๋ฒ„๊ฐ€ URI๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„ API ์ƒํ˜ธ์ž‘์šฉ์€ HATEOAS๋ฅผ ํ†ตํ•ด์„œ๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๊ฐ REST ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ HATEOAS ๋งํฌ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, Spring Boot HATEOAS ํŠœํ† ๋ฆฌ์–ผ์—์„œ ๋งํฌ๋Š” ๋ฆฌ์†Œ์Šค ์ƒํƒœ๋กœ ํด๋ผ์ด์–ธํŠธ์— ์ „์†ก๋˜๋Š” ๋ฆฌ์†Œ์Šค ๋ชจ๋ธ ํด๋ž˜์Šค์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค.

3. HATEOAS ์ฐธ์กฐ

๋‹ค์Œ์€ JSON REST API ํ•˜์ดํผ๋ฏธ๋””์–ด ๋งํฌ๋ฅผ ์ง€์ •ํ•˜๋Š” ๋ฐ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ๋‘ ๊ฐ€์ง€ ํ˜•์‹์ž…๋‹ˆ๋‹ค.

3.1. RFC 5988(์›น ๋งํฌ)

RFC 5988์€ ์›น์ƒ์˜ ๋ฆฌ์†Œ์Šค ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ์ •์˜ํ•˜๋Š” ๋งํฌ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ œ์‹œํ•ฉ๋‹ˆ๋‹ค. RFC 5988์˜ ๊ฐ ๋งํฌ์—๋Š” ๋‹ค์Œ ์†์„ฑ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

  • Target URI(๋Œ€์ƒ URI): ๊ฐ ๋งํฌ์—๋Š” ๋Œ€์ƒ IRI(Internationalized Resource Identifier)๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ href ์†์„ฑ์œผ๋กœ ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค.
  • Link relation type(๋งํฌ ๊ด€๊ณ„ ์œ ํ˜•): ๋งํฌ ๊ด€๊ณ„ ์œ ํ˜•์€ ํ˜„์žฌ ์ปจํ…์ŠคํŠธ(์†Œ์Šค)๊ฐ€ ๋Œ€์ƒ ๋ฆฌ์†Œ์Šค์™€ ์–ด๋–ป๊ฒŒ ๊ด€๋ จ๋˜์–ด ์žˆ๋Š”์ง€ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ rel ์†์„ฑ์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
  • Attributes for target IRI(๋Œ€์ƒ IRI์˜ ์†์„ฑ): ๋งํฌ์˜ ์†์„ฑ์—๋Š” hreflang, media, title, type ๋ฐ ๋ชจ๋“  ํ™•์žฅ ๋งํฌ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

3.2. JSON ํ•˜์ดํผ๋ฏธ๋””์–ด API ์–ธ์–ด(HAL)

JSON HAL์€ ๋งํฌ์™€ ๊ฐ™์€ ํ•˜์ดํผ๋ฏธ๋””์–ด ์ œ์–ด๋ฅผ JSON ๋˜๋Š” XML๋กœ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ๊ทœ์น™์„ ์„ค์ •ํ•˜๋Š” ์œ ๋งํ•œ ์ œ์•ˆ์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ ์ดˆ์•ˆ ๋‹จ๊ณ„์— ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฐ๊ฒฐ๋œ ๋‘ MIME ์œ ํ˜•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

media type: application/hal+xml 
media type: application/hal+json

HAL์˜ ๊ฐ ๋งํฌ์—๋Š” ๋‹ค์Œ ์†์„ฑ์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Target URI(๋Œ€์ƒ URI): ๋Œ€์ƒ ๋ฆฌ์†Œ์Šค URI๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ href ์†์„ฑ์œผ๋กœ ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค.
  • Link relation(๋งํฌ ๊ด€๊ณ„):๋งํฌ ๊ด€๊ณ„ ์œ ํ˜•์€ ํ˜„์žฌ ์ปจํ…์ŠคํŠธ๊ฐ€ ๋Œ€์ƒ ๋ฆฌ์†Œ์Šค์™€ ๊ด€๋ จ๋˜๋Š” ๋ฐฉ์‹์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ rel ์†์„ฑ์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
  • Type(์œ ํ˜•):์˜ˆ์ƒ ๋ฆฌ์†Œ์Šค ๋ฏธ๋””์–ด ์œ ํ˜•์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ type ์†์„ฑ์œผ๋กœ ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์— ๋Œ€ํ•œ ํ•˜์ดํผ ๋ฏธ๋””์–ด ๋งํฌ ํ˜•์‹์„ ์„ ํƒํ•˜๋Š” ๋ฐ ์˜ณ๊ณ  ๊ทธ๋ฆ„์ด ์—†์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ถฉ์กฑํ•˜๋Š” ํ˜•์‹์„ ์„ ํƒํ•˜๊ณ  ๊ณ ์ˆ˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Idempotence

1. APIs์˜ ๋ฉฑ๋“ฑ

REST API์˜ ๋งฅ๋ฝ์—์„œ, ๋™์ผํ•œ ์š”์ฒญ์„ ์—ฌ๋Ÿฌ ๊ฐœ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ๋‹จ์ผ ์š”์ฒญ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ํšจ๊ณผ๋ฅผ ๊ฐ€์ง„๋‹ค๋ฉด, ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์„ ๋ฉฑ๋“ฑํ•˜๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ REST API๋ฅผ ์„ค๊ณ„ํ•  ๋•Œ, ์šฐ๋ฆฌ๋Š” API ์†Œ๋น„์ž๊ฐ€ ์‹ค์ˆ˜๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์—ผ๋‘์— ๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.์†Œ๋น„์ž๋Š” API๋ฅผ ์ค‘๋ณต ์š”์ฒญ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์‹์œผ๋กœ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ค‘๋ณต ์š”์ฒญ์€ ์˜๋„์ ์ผ์ˆ˜๋„ ๊ทธ๋ ‡์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. (์˜ˆ: ์‹œ๊ฐ„ ์ดˆ๊ณผ ๋˜๋Š” ๋„คํŠธ์›Œํฌ ๋ฌธ์ œ).์ค‘๋ณต ์š”์ฒญ์ด ์‹œ์Šคํ…œ์„ ๋ถˆ์•ˆ์ •ํ•˜๊ฒŒ ๋งŒ๋“ค์ง€ ์•Š๋„๋ก API๋ฅผ ๊ฒฐํ•จ ํ—ˆ์šฉ์‹œ์Šคํ…œ์œผ๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฉฑ๋“ฑํ•œ HTTP ๋ฉ”์„œ๋“œ๋Š” ๋‹ค๋ฅธ ๊ฒฐ๊ณผ ์—†์ด ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ๋ฉ”์„œ๋“œ๊ฐ€ ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋˜์—ˆ๋Š”์ง€, ์•„๋‹ˆ๋ฉด ์—ด ๋ฒˆ ํ˜ธ์ถœ๋˜์—ˆ๋Š”์ง€๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ๋Š” ํ•ญ์ƒ ๊ฐ™์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฉฑ๋“ฑ์€ ์„ฑ๊ณต์ ์œผ๋กœ ์ˆ˜ํ–‰๋œ ์š”์ฒญ์˜ ๊ฒฐ๊ณผ๊ฐ€ ์‹คํ–‰๋˜๋Š” ํšŸ์ˆ˜์™€ ๋ฌด๊ด€ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ์‚ฐ์ˆ ์—ฐ์‚ฐ์—์„œ ์ˆซ์ž์— 0์„ ๋”ํ•˜๋Š” ๊ฒƒ์€ ๋ฉฑ๋“ฑ์ด ์„ฑ๋ฆฝํ•˜๋Š” ์—ฐ์‚ฐ์ž…๋‹ˆ๋‹ค.

2. HTTP ๋ฉ”์„œ๋“œ์˜ ๋ฉฑ๋“ฑ์„ฑ

API๋ฅผ ์„ค๊ณ„ํ•  ๋•Œ REST ์›์น™์„ ๋”ฐ๋ฅด๋ฉด GET, PUT, DELETE, HEAD, OPTIONS ๋ฐ TRACE ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•ด ์ž๋™์œผ๋กœ ๋ฉฑ๋“ฑํ•œ REST API๋ฅผ ๊ฐ–๊ฒŒ ๋˜๊ณ , POST API๋งŒ ๋ฉฑ๋“ฑ์ด ์„ฑ๋ฆฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  1. POST๋Š” ๋ฉฑ๋“ฑ์ด ์•„๋‹ˆ๋‹ค.
  2. GET, PUT, DELETE, HEAD, OPTIONS ๋ฐ TRACE๋Š” ๋ฉฑ๋“ฑ์ด๋‹ค.

POST๋ฅผ ์ œ์™ธํ•œ ์œ„์˜ HTTP ๋ฉ”์„œ๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋ฉฑ๋“ฑ์ด ์„ฑ๋ฆฝํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  POST๋Š” ์™œ ๋ฉฑ๋“ฑํ•˜์ง€ ์•Š๋Š”์ง€ ์ด์œ ๋ฅผ ๋ถ„์„ํ•ด๋ณด์ž.

2.1. HTTP POST

์ผ๋ฐ˜์ ์œผ๋กœ, ๊ผญ ๊ทธ๋ ‡์ง€๋Š” ์•Š์ง€๋งŒ, POST API๋Š” ์„œ๋ฒ„์— ์ƒˆ ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋™์ผํ•œ POST ์š”์ฒญ์„ N๋ฒˆ ํ˜ธ์ถœํ•˜๋ฉด ์„œ๋ฒ„์— N๊ฐœ์˜ ์ƒˆ๋กœ์šด ๋ฆฌ์†Œ์Šค๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ POST๋Š” ๋ฉฑ๋“ฑํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

2.2. HTTP GET, HEAD, OPTIONS ๋ฐ TRACE

GET, HEAD, OPTIONS ๋ฐ TRACE ๋ฉ”์„œ๋“œ๋Š” ์„œ๋ฒ„์˜ ๋ฆฌ์†Œ์Šค ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ˆœ์ „ํžˆ ํ•ด๋‹น ์‹œ์ ์˜ ๋ฆฌ์†Œ์Šค ํ‘œํ˜„ ๋˜๋Š” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์—ฌ๋Ÿฌ ์š”์ฒญ์„ ํ˜ธ์ถœํ•˜๋ฉด ์„œ๋ฒ„์—์„œ ์“ฐ๊ธฐ ์ž‘์—…์ด ์ˆ˜ํ–‰๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ GET, HEAD, OPTIONS ๋ฐ TRACE ๋ฉ”์„œ๋“œ๋Š” ๋ฉฑ๋“ฑํ•ฉ๋‹ˆ๋‹ค.

2.4 HTTP DELETE

2.4.1. ๋ฆฌ์†Œ์Šค ์‹๋ณ„์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ญ์ œ

N๊ฐœ์˜ ์œ ์‚ฌํ•œ DELETE ์š”์ฒญ์„ ํ˜ธ์ถœํ•˜๋ฉด ์ฒซ ๋ฒˆ์งธ ์š”์ฒญ์ด ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ญ์ œํ•˜๊ณ  ์‘๋‹ต์€ 200(OK) ๋˜๋Š” 204(๋‚ด์šฉ ์—†์Œ)๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

๋‹ค๋ฅธ N-1 ์š”์ฒญ์€ 404(Not Found)๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ด ๋•Œ์˜ ์‘๋‹ต์€ ์ฒซ ๋ฒˆ์งธ ์š”์ฒญ๊ณผ๋Š” ํ™•์‹คํžˆ ๋‹ค๋ฅด์ง€๋งŒ, ์›๋ณธ ๋ฆฌ์†Œ์Šค๊ฐ€ ์ด๋ฏธ ์‚ญ์ œ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ฒ„ ์ธก ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์ƒํƒœ ๋ณ€๊ฒฝ์€ ์—†์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ DELETE๋Š” ๋ฉฑ๋“ฑํ•ฉ๋‹ˆ๋‹ค.

2.4.2. ๋ฆฌ์†Œ์Šค ์‹๋ณ„์ž ์—†์ด ์‚ญ์ œ

์ผ๋ถ€ ์‹œ์Šคํ…œ์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ DELETE API๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

DELETE/item/last

์œ„์˜ ๊ฒฝ์šฐ ์ž‘์—…์„ N๋ฒˆ ํ˜ธ์ถœํ•˜๋ฉด N๊ฐœ์˜ ๋ฆฌ์†Œ์Šค๊ฐ€ ์‚ญ์ œ๋ฉ๋‹ˆ๋‹ค. DELETE๋Š” ์ด ๊ฒฝ์šฐ ๋ฉฑ๋“ฑํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด ๊ฒฝ์šฐ, POST๋Š” ๋ฉฑ๋“ฑํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์œ„์˜ API๋ฅผ POST๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด ๋‚˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

POST/item/last

์ด์ œ ์ด๊ฒƒ์€ HTTP ์‚ฌ์–‘์— ๋” ๊ฐ€๊น๊ณ , ๋”ฐ๋ผ์„œ REST์™€ ๋” ํ˜ธํ™˜๋ฉ๋‹ˆ๋‹ค.


Security Essentials

REST API ๋ณด์•ˆ์€ ์‚ฌํ›„ ๊ณ ๋ ค ์‚ฌํ•ญ์ด ์•„๋‹™๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ฐœ๋ฐœ ํ”„๋กœ์ ํŠธ์™€ REST API์˜ ํ•„์ˆ˜์ ์ธ ๋ถ€๋ถ„์ด ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ์ธ์ฆ, OAuth ๋“ฑ๊ณผ ๊ฐ™์ด RESTful API๋ฅผ ๋ณดํ˜ธํ•˜๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์ง€๋งŒ, ํ•œ ๊ฐ€์ง€ ํ™•์‹คํ•œ ๊ฒƒ์€ RESTful API๊ฐ€ ๋ฌด์ƒํƒœ ํ”„๋กœํ† ์ฝœ์ด์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์š”์ฒญ ์ธ์ฆ/ํ—ˆ๊ฐ€๋Š” ์„ธ์…˜์— ์˜์กดํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.๋Œ€์‹  ๊ฐ API ์š”์ฒญ์—๋Š” ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด ์„œ๋ฒ„์—์„œ ๊ฒ€์ฆํ•ด์•ผ ํ•˜๋Š” ์ผ์ข…์˜ ์ธ์ฆ ์ž๊ฒฉ ์ฆ๋ช…์ด ํ•จ๊ป˜ ์ œ๊ณต๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

1. REST ๋ณด์•ˆ ์„ค๊ณ„ ์›์น™

Jerome Saltzer์™€ Michael Schroeder์˜ โ€œ์ปดํ“จํ„ฐ ์‹œ์Šคํ…œ์—์„œ์˜ ์ •๋ณด ๋ณดํ˜ธโ€๋ผ๋Š” ๋…ผ๋ฌธ์—์„  ์•„๋ž˜์™€ ๊ฐ™์ด ์ปดํ“จํ„ฐ ์‹œ์Šคํ…œ์˜ ์ •๋ณด ๋ณด์•ˆ์„ ์œ„ํ•œ 8๊ฐ€์ง€ ์„ค๊ณ„ ์›์น™์„ ์ œ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค.

  • Least Privilege(์ตœ์†Œ ๊ถŒํ•œ): ์—”ํ‹ฐํ‹ฐ๋Š” ๊ถŒํ•œ์ด ๋ถ€์—ฌ๋œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์‚ฌ์šฉ ๊ถŒํ•œ ์ง‘ํ•ฉ๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ ๊ถŒํ•œ์€ ํ•„์š”์— ๋”ฐ๋ผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๋•Œ๋Š” ์ทจ์†Œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • Fail-Safe Defaults: ์‹œ์Šคํ…œ ๋‚ด ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์‚ฌ์šฉ์ž์˜ ๊ธฐ๋ณธ ์•ก์„ธ์Šค ์ˆ˜์ค€์€ ๋ช…์‹œ์ ์œผ๋กœ โ€œํ—ˆ๊ฐ€โ€๊ฐ€ ๋ถ€์—ฌ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ โ€œ๊ฑฐ๋ถ€โ€๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • The economy of Mechanism: ๋””์ž์ธ์€ ๊ฐ€๋Šฅํ•œ ํ•œ ๋‹จ์ˆœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ด๋“ค ๊ฐ„์˜ ์ƒํ˜ธ ์ž‘์šฉ์€ ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์›Œ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • Complete Mediation: ์‹œ์Šคํ…œ์€ ๋ชจ๋“  ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์•ก์„ธ์Šค ๊ถŒํ•œ์„ ๊ฒ€์ฆํ•˜์—ฌ ํ•ด๋‹น ๋ฆฌ์†Œ์Šค๊ฐ€ ํ—ˆ์šฉ๋˜๊ณ  ์บ์‹œ๋œ ๊ถŒํ•œ ๋งคํŠธ๋ฆญ์Šค์— ์˜์กดํ•˜์ง€ ์•Š๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฃผ์–ด์ง„ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์•ก์„ธ์Šค ์ˆ˜์ค€์ด ์ทจ์†Œ๋˜๊ณ  ์žˆ๋Š”๋ฐ ํ•ด๋‹น ์ˆ˜์ค€์ด ์‚ฌ์šฉ ๊ถŒํ•œ ๋งคํŠธ๋ฆญ์Šค์— ๋ฐ˜์˜๋˜์ง€ ์•Š์œผ๋ฉด ๋ณด์•ˆ์„ ์œ„๋ฐ˜ํ•˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • open Design(์—ด๋ฆฐ ์„ค๊ณ„): ์ด ์›์น™์€ ์‹ ๋ขฐ์„ฑ์žˆ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์—†์ด ๊ฐœ๋ฐฉ์ ์ธ ๋ฐฉ์‹์œผ๋กœ ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฒƒ์˜ ์ค‘์š”์„ฑ์„ ๊ฐ•์กฐํ•ฉ๋‹ˆ๋‹ค.
  • Separation of Privilege(๊ถŒํ•œ ๋ถ„๋ฆฌ): ์—”ํ‹ฐํ‹ฐ์— ์‚ฌ์šฉ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋Š” ๊ฒƒ์ด ๋‹จ์ˆœํžˆ ๋‹จ์ผ ์กฐ๊ฑด์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๋ฆฌ์†Œ์Šค ์œ ํ˜•์— ๋”ฐ๋ผ ์กฐ๊ฑด์„ ์กฐํ•ฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์Šต๋‹ˆ๋‹ค.
  • Least Common Mechanism: ์ด๋Š” ์—ฌ๋Ÿฌ ๊ตฌ์„ฑ ์š”์†Œ ๊ฐ„์— ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•˜๋Š” ๊ฒƒ์˜ ์œ„ํ—˜์„ฑ์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋งŒ์•ฝ ํ•˜๋‚˜์˜ ์š”์†Œ๊ฐ€ ๊ณต์œ  ์ƒํƒœ๋ฅผ ์†์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ ๊ณต์œ  ์ƒํƒœ์— ์˜์กดํ•˜๋Š” ๋‹ค๋ฅธ ๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์†์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • Psychological Acceptability: ๋ณด์•ˆ ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ ๋ณด์•ˆ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด ์—†๋Š” ๊ฒฝ์šฐ๋ณด๋‹ค ๋ฆฌ์†Œ์Šค ์ ‘๊ทผ์„ ๋” ์–ด๋ ต๊ฒŒ ํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค๊ณ  ๋ช…์‹œ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ„๋‹จํžˆ ๋งํ•ด์„œ, ๋ณด์•ˆ์€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์•…ํ™”์‹œ์ผœ์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

2. REST API ๋ณด์•ˆ์˜ ๋ชจ๋ฒ” ์‚ฌ๋ก€

์•„๋ž˜๋Š” REST API์˜ ๋ณด์•ˆ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์„ค๊ณ„ํ•˜๊ธฐ ์œ„ํ•œ ์ฒดํฌ๋ฆฌ์ŠคํŠธ ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2.1. Keep it Simple

API/์‹œ์Šคํ…œ ๋ณด์•ˆ โ€“ ๋ณด์•ˆ์ด ์–ผ๋งˆ๋‚˜ ํ•„์š”ํ•œ์ง€๋ฅผ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์†”๋ฃจ์…˜์„ โ€œ๋ถˆํ•„์š”ํ•˜๊ฒŒโ€ ๋” ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“ค ๋•Œ๋งˆ๋‹ค ๊ตฌ๋ฉ์„ ๋‚จ๊ธธ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค.

2.2. Always Use HTTPS

ํ•ญ์ƒ SSL์„ ์‚ฌ์šฉํ•˜๋ฉด ์ธ์ฆ ์ž๊ฒฉ ์ฆ๋ช…์„ ์ž„์˜๋กœ ์ƒ์„ฑ๋œ ์•ก์„ธ์Šค ํ† ํฐ์œผ๋กœ ๋‹จ์ˆœํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ† ํฐ์€ HTTP Basic Auth์˜ username ํ•„๋“œ์— ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

๋น„๊ต์  ์‚ฌ์šฉ์ด ๊ฐ„ํŽธํ•˜๊ณ  ๋งŽ์€ ๋ณด์•ˆ ๊ธฐ๋Šฅ์„ ๋ฌด๋ฃŒ๋กœ ์ด์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.HTTP 2๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ์œ„ํ•ด ๋‹จ์ผ ์—ฐ๊ฒฐ์„ ํ†ตํ•ด ์—ฌ๋Ÿฌ ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜๋„ ์žˆ์œผ๋ฏ€๋กœ ์ดํ›„ ์š”์ฒญ์— ๋Œ€ํ•œ ์ „์ฒด TCP ๋ฐ SSL ํ•ธ๋“œ์…ฐ์ดํฌ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2.3. Use Password Hash

์ผ๋ถ€ ํ•ดํ‚น ์‹œ๋„์—์„œ ์•”ํ˜ธ๊ฐ€ ์†์ƒ๋˜๋”๋ผ๋„ ์‹œ์Šคํ…œ์„ ๋ณดํ˜ธํ•˜๊ฑฐ๋‚˜ ์†์ƒ์„ ์ตœ์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์•”ํ˜ธ๋ฅผ ํ•ญ์ƒ ํ•ด์‹œํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

PBKDF2, bcrypt ๋ฐ scrypt ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ๊ฐ™์ด ์•”ํ˜ธ ๋ณด์•ˆ์— ๋งค์šฐ ํšจ๊ณผ์ ์ธ ํ•ด์‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ๋งŽ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

2.4. Never expose information on URLs

์‚ฌ์šฉ์ž ์ด๋ฆ„, ์•”ํ˜ธ, ์„ธ์…˜ ํ† ํฐ ๋ฐ API ํ‚ค๋Š” ์›น ์„œ๋ฒ„ ๋กœ๊ทธ์— ์บก์ฒ˜๋˜์–ด ์‰ฝ๊ฒŒ ์•…์šฉ๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ URL์— ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

https://api.domain.com/user-management/users/{id}/someAction?apiKey=abcd123456789
//๋งค์šฐ ๋‚˜์œ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

์œ„์˜ URL์€ API ํ‚ค๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋Ÿฐ ํ˜•ํƒœ์˜ ๋ณด์•ˆ์€ ์ ˆ๋Œ€ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

2.5. Consider OAuth

๊ธฐ๋ณธ ์ธ์ฆ์€ ๋Œ€๋ถ€๋ถ„์˜ API์— ์ถฉ๋ถ„ํ•˜๊ณ  ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ตฌํ˜„๋  ๊ฒฝ์šฐ ์•ˆ์ „ํ•˜์ง€๋งŒ OAuth๋„ ๊ณ ๋ คํ•ด ๋ณด๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

OAuth 2.0 ์ธ์ฆ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฆฌ์†Œ์Šค ์†Œ์œ ์ž์™€ HTTP ์„œ๋น„์Šค ๊ฐ„์˜ ์Šน์ธ ์ƒํ˜ธ ์ž‘์šฉ์„ ์กฐ์ •ํ•˜๊ฑฐ๋‚˜ ํƒ€์‚ฌ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด HTTP ์„œ๋น„์Šค์— ๋Œ€ํ•œ ์•ก์„ธ์Šค๋ฅผ ๋Œ€์‹ ํ•˜๋„๋ก ํ—ˆ์šฉํ•˜์—ฌ ํƒ€์‚ฌ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด HTTP ์„œ๋น„์Šค์— ๋Œ€ํ•œ ์ œํ•œ๋œ ์•ก์„ธ์Šค ๊ถŒํ•œ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2.6. Consider Adding Timestamp in Request

๋‹ค๋ฅธ ์š”์ฒญ ๋งค๊ฐœ ๋ณ€์ˆ˜์™€ ํ•จ๊ป˜ API ์š”์ฒญ์—์„œ ์š”์ฒญ ํƒ€์ž„์Šคํƒฌํ”„๋ฅผ HTTP ์‚ฌ์šฉ์ž ์ •์˜ ํ—ค๋”๋กœ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„œ๋ฒ„๋Š” ํ˜„์žฌ ํƒ€์ž„์Šคํƒฌํ”„๋ฅผ ์š”์ฒญ ํƒ€์ž„์Šคํƒฌํ”„์™€ ๋น„๊ตํ•˜๊ณ  ์ ์ ˆํ•œ ์‹œ๊ฐ„(30์ดˆ ์ •๋„)์ด ์ง€๋‚œ ๊ฒฝ์šฐ์—๋งŒ ์š”์ฒญ์„ ์ˆ˜๋ฝํ•ฉ๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ด ํƒ€์ž„์Šคํƒฌํ”„๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ์‹œ์Šคํ…œ์„ ๊ฐ•์ œ๋กœ ์žฌ์ƒํ•˜๋ ค๋Š” ์‚ฌ์šฉ์ž์˜ ๋งค์šฐ ๊ธฐ๋ณธ์ ์ธ ์žฌ์ƒ ๊ณต๊ฒฉ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2.7. Input Parameter Validation

์š”์ฒญ ๋งค๊ฐœ ๋ณ€์ˆ˜๊ฐ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง์— ๋„๋‹ฌํ•˜๊ธฐ ์ „์— ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„์—์„œ ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•ฉ๋‹ˆ๋‹ค.

๊ฐ•๋ ฅํ•œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ์— ์‹คํŒจํ•˜๋ฉด ์š”์ฒญ์„ ์ฆ‰์‹œ ๊ฑฐ๋ถ€ํ•ฉ๋‹ˆ๋‹ค.

Versioning

๋ฒ„์ „์— ๋Œ€ํ•œ ์–ด๋ ค์›€์„ ํ•ด๊ฒฐํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๋ฒ„์ „ ๊ด€๋ฆฌ๋ฅผ ํ•˜์‹ญ์‹œ์˜ค.

๋ฒ„์ „ ๊ด€๋ฆฌ๋ฅผ ํ†ตํ•ด API์—์„œ ํ•„์š”ํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์ƒ๊ธฐ๋ฉด ๋” ๋นจ๋ฆฌ ๋ฐ˜๋ณต(๋Œ€์‘)ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‹œ์Šคํ…œ์— ๋Œ€ํ•œ ์ง€์‹๊ณผ ๊ฒฝํ—˜์ด ํ–ฅ์ƒ๋จ์— ๋”ฐ๋ผ API์˜ ๋ณ€ํ™”๋Š” ๋ถˆ๊ฐ€ํ”ผํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด client integration์ด ์ค‘๋‹จ๋  ์œ„ํ—˜์ด ์žˆ๋Š” ๊ฒฝ์šฐ ์ด๋Ÿฌํ•œ ๋ณ€๊ฒฝ์˜ ์˜ํ–ฅ์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1. When to version?

API๋Š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์žˆ์„ ๋•Œ๋งŒ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๋ณ€๊ฒฝ ์‚ฌํ•ญ์—๋Š” ๋‹ค์Œ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

  • ํ•˜๋‚˜ ์ด์ƒ์˜ ํ˜ธ์ถœ์— ๋Œ€ํ•œ ์‘๋‹ต ๋ฐ์ดํ„ฐ ํ˜•์‹์˜ ๋ณ€๊ฒฝ
  • ์š”์ฒญ ๋˜๋Š” ์‘๋‹ต ์œ ํ˜•์˜ ๋ณ€๊ฒฝ(ex. ์ •์ˆ˜๋ฅผ ๋ถ€๋™ ์†Œ์ˆ˜์ ์œผ๋กœ ๋ณ€๊ฒฝ)
  • API์˜ ๋ชจ๋“  ๋ถ€๋ถ„์„ ์ œ๊ฑฐํ•˜๋Š” ๊ฒฝ์šฐ

์—ฐ์†์ ์ธ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์€ ํ•ญ์ƒ API ๋˜๋Š” ์ปจํ…์ธ  ์‘๋‹ต ์œ ํ˜•์˜ major ๋ฒ„์ „ ๋ฒˆํ˜ธ์˜ ๋ณ€๊ฒฝ์„ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

์ƒˆ ์—”๋“œํฌ์ธํŠธ ๋˜๋Š” ์ƒˆ ์‘๋‹ต ๋งค๊ฐœ ๋ณ€์ˆ˜ ์ถ”๊ฐ€์™€ ๊ฐ™์ด ์ค‘๋‹จ๋˜์ง€ ์•Š๋Š” ๋ณ€๊ฒฝ์‚ฌํ•ญ์€ major ๋ฒ„์ „ ๋ฒˆํ˜ธ๋ฅผ ๋ณ€๊ฒฝํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์บ์‹œ๋œ ๋ฒ„์ „์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์‹ , ํ˜น์€ ๋‹ค๋ฅธ API ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์†Œ๋น„์ž๋ฅผ ์œ„ํ•ด ๋ณ€๊ฒฝํ•œ ๊ฒฝ์šฐ, API์˜ minor ๋ฒ„์ „์„ ์ถ”์ ํ•˜๋Š” ๊ฒƒ์€ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. REST API๋ฅผ ์–ด๋–ป๊ฒŒ ๋ฒ„์ „๊ด€๋ฆฌ ํ•˜๋Š”๊ฐ€?

REST๋Š” ํŠน์ • ๋ฒ„์ „ ๊ด€๋ฆฌ ์ง€์นจ์„ ์ œ๊ณตํ•˜์ง€ ์•Š์ง€๋งŒ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์ ‘๊ทผ ๋ฐฉ์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ธ ๊ฐ€์ง€ ๋ฒ”์ฃผ๋กœ ๋‚˜๋‰ฉ๋‹ˆ๋‹ค.

2.1. URI Versioning

URI๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ URI๊ฐ€ ๊ณ ์œ ํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐธ์กฐํ•ด์•ผ ํ•œ๋‹ค๋Š” ์›์น™์— ์œ„๋ฐฐ๋˜์ง€๋งŒ ๊ฐ€์žฅ ์ง์ ‘์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹(๊ทธ๋ฆฌ๊ณ  ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋จ)์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ฒ„์ „์ด ์—…๋ฐ์ดํŠธ๋  ๋•Œ client integration์ด ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค.

http://api.example.com/v1
http://apiv1.example.com

๋ฒ„์ „์€ ์ˆซ์ž์ผ ํ•„์š”๋„ ์—†๊ณ  โ€œv[x]โ€ ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ง€์ •ํ•  ์ˆ˜๋„ ์—†์Šต๋‹ˆ๋‹ค.

๋Œ€์•ˆ์œผ๋กœ๋Š” ๋‚ ์งœ, ํ”„๋กœ์ ํŠธ ๋ช…, ์‹œ์ฆŒ ๋˜๋Š” API๋ฅผ ์ œ์ž‘ํ•˜๋Š” ํŒ€์—๊ฒŒ ์ถฉ๋ถ„ํžˆ ์˜๋ฏธ ์žˆ๊ณ  ๋ฒ„์ „์ด ๋ณ€๊ฒฝ๋จ์— ๋”ฐ๋ผ ์œ ์—ฐํ•˜๊ฒŒ ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐํƒ€ ์‹๋ณ„์ž๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

2.2. ์‚ฌ์šฉ์ž ์ •์˜ ์š”์ฒญ ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•œ ๋ฒ„์ „ ๊ด€๋ฆฌ

์‚ฌ์šฉ์ž ์ •์˜ ํ—ค๋”(์˜ˆ: Accept-version)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ธฐ์กด Accept ํ—ค๋”์— ์˜ํ•ด ๊ตฌํ˜„๋œ content negotiation(ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„ ํ˜ธํ•˜๋Š” ํ‘œํ˜„ ์š”์ฒญ)๊ณผ ์ค‘๋ณต๋˜์ง€๋งŒ ๋ฒ„์ „ ๊ฐ„์˜ URI๋ฅผ ๋ณด์กดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Accept-version: v1
Accept-version: v2

2.3. โ€œAcceptโ€ ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•œ ๋ฒ„์ „๊ด€๋ฆฌ

Content negotiation์„ ํ†ตํ•ด URL์„ ๊น”๋”ํ•˜๊ฒŒ ๋ณด์กดํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋‹ค๋ฅธ ๋ฒ„์ „์˜ content๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•˜๋Š” ์–ด๋ ค์›€์„ ํ•ด๊ฒฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์–ด๋ ค์›€์€ ์ „์†กํ•  ๋ฆฌ์†Œ์Šค ๋ฒ„์ „์„ ๊ฒฐ์ •ํ•˜๋Š” ์—ญํ• ์„ ํ•˜๋Š” API ์ปจํŠธ๋กค๋Ÿฌ์—๊ฒŒ ๊ทธ ์ฑ…์ž„์„ ๊ฐ€์ค‘ํ•˜๋Š” ๊ฒฝํ–ฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๋˜๋ฉด, ํด๋ผ์ด์–ธํŠธ๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•˜๊ธฐ ์ „์— ์–ด๋–ค ํ—ค๋”๋ฅผ ์ง€์ •ํ•ด์•ผ ํ•˜๋Š”์ง€ ์•Œ์•„์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋” ๋ณต์žกํ•œ API๊ฐ€ ๋˜๋Š” ๊ฒฝํ–ฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

Accept: application/vnd.example.v1+json
Accept: application/vnd.example+json;version=1.0

ํ˜„์‹ค ์„ธ๊ณ„์—์„œ API๋Š” ์™„์ „ํ•˜๊ฒŒ ์•ˆ์ •์ ์ด์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ด๋Ÿฌํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์–ด๋–ป๊ฒŒ ๊ด€๋ฆฌํ•˜๋Š”์ง€๊ฐ€ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.์ž˜ ๋ฌธ์„œํ™”๋˜์–ด ์žˆ๊ณ  ์ ์ง„์ ์œผ๋กœ ์‚ฌ์žฅ๋˜๊ณ  ์žˆ๋Š” API๋Š” ๋Œ€๋ถ€๋ถ„์˜ API์—์„œ ํ—ˆ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

Statelessness

1. ๋ฌด์ƒํƒœ์„ฑ

REST(Respresentational โ€œStateโ€ Transfer) ์•„ํ‚คํ…์ฒ˜์— ๋”ฐ๋ฅด๋ฉด ์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ์˜ ์ƒํƒœ๋ฅผ ์„œ๋ฒ„ ์ธก์— ์ €์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ๋ฌด์ƒํƒœ์„ฑ์ด๋ผ ํ•ฉ๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ์—์„œ ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๋Š” ๊ฐ ์š”์ฒญ์—๋Š” ์š”์ฒญ์„ ์ดํ•ดํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ํ•„์ˆ˜ ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„์—์„œ ์„œ๋ฒ„์— ์ €์žฅ๋œ context(ํ™˜๊ฒฝ์„ค์ • ์ •๋ณด)๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์‘์šฉํ”„๋กœ๊ทธ๋žจ์˜ ์„ธ์…˜ ์ƒํƒœ๋Š” ์ „์ ์œผ๋กœ ํด๋ผ์ด์–ธํŠธ์— ์˜ํ•ด ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. **๊ณ ๊ฐ์€ ์„ธ์…˜ ๊ด€๋ จ ์ •๋ณด๋ฅผ ์ž์ฒด์ ์œผ๋กœ ์ €์žฅํ•˜๊ณ  ์ฒ˜๋ฆฌํ•  ์ฑ…์ž„์ด ์žˆ์Šต๋‹ˆ๋‹ค. **

์ด๋Š” ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ์„œ๋ฒ„๋กœ ์ƒํƒœ ์ •๋ณด๋ฅผ ์ „์†กํ•  ์ฑ…์ž„์ด ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ์‚ฌ์ด์— ์„ธ์…˜ ์„ ํ˜ธ๋„ ๋˜๋Š” ๊ณ ์ • ์„ธ์…˜์ด ์—†์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฌด์ƒํƒœ์„ฑ์€ ๋ชจ๋“  HTTP ์š”์ฒญ์€ ์™„์ „ํžˆ ๊ฒฉ๋ฆฌ๋˜์–ด ๋ฐœ์ƒํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๊ฐ€ HTTP ์š”์ฒญ์„ ์ง„ํ–‰ํ•˜๋ฉด, ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ์˜ ์ด์ „ ์š”์ฒญ ์ •๋ณด์— ์˜์กดํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด์ „ ์ •๋ณด๊ฐ€ ์ค‘์š”ํ•œ ๊ฒฝ์šฐ ํด๋ผ์ด์–ธํŠธ๋Š” ํ•ด๋‹น ์ •๋ณด๋ฅผ ํ˜„์žฌ ์š”์ฒญ์˜ ์ผ๋ถ€๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ด๋Ÿฌํ•œ ๋ฌด์ƒํƒœ์„ฑ API์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ ค๋ฉด ์„œ๋ฒ„ ๋˜ํ•œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ƒํƒœ๋ฅผ ์ƒ์„ฑ/์œ ์ง€ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฌด์ƒํƒœ์„ฑ์ด ๋˜๊ธฐ ์œ„ํ•ด ํด๋ผ์ด์–ธํŠธ์˜ ์ธ์ฆ/์Šน์ธ ์„ธ๋ถ€ ์ •๋ณด์กฐ์ฐจ ์ €์žฅํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ๋Œ€์‹  ๊ฐ ์š”์ฒญ์— authentication credentials(์ธ์ฆ ์ž๊ฒฉ ์ฆ๋ช…)์„ ์ œ๊ณตํ•˜์‹ญ์‹œ์˜ค.

๋”ฐ๋ผ์„œ ๊ฐ ์š”์ฒญ์€ ๋…๋ฆฝ์ ์ด์–ด์•ผ ํ•˜๋ฉฐ ์ด์ „์— ๋™์ผํ•œ ํด๋ผ์ด์–ธํŠธ์™€ ์ฃผ๊ณ ๋ฐ›์€ ๊ฒƒ์— ์˜ํ•ด ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

2. Application State vs Resource State

Application state์™€ resource state๋Š” ์™„์ „ํžˆ ๋‹ค๋ฅธ ๋‚ด์šฉ์ด๋ฏ€๋กœ ์ด๋ฅผ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์€ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

Application state๋Š” ์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ, ์ด์ „ ์ƒํ˜ธ ์ž‘์šฉ์˜ ์„ธ๋ถ€ ์ •๋ณด ๋ฐ ํ˜„์žฌ์˜ ํ™˜๊ฒฝ์„ค์ • ์ •๋ณด๋ฅผ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•ด ์ €์žฅํ•˜๋Š” โ€œ์„œ๋ฒ„ ์ธก ๋ฐ์ดํ„ฐโ€์ž…๋‹ˆ๋‹ค.

Resource state๋Š” ์„œ๋ฒ„์— ์žˆ๋Š” ๋ฆฌ์†Œ์Šค์˜ ํ˜„์žฌ ์ƒํƒœ์ด๋ฉฐ, ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„์˜ ์ƒํ˜ธ ์ž‘์šฉ๊ณผ๋Š” ๊ด€๋ จ์ด ์—†์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ API ์‘๋‹ต์œผ๋กœ ๋ฐ›๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์„ resource representation์ด๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

์ฆ‰, REST ๋ฌด์ƒํƒœ์„ฑ์ด๋ž€ application ์ƒํƒœ๋กœ๋ถ€ํ„ฐ์˜ ์ž์œ ๋กœ์šด ์ƒํƒœ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

3. ๋ฌด์ƒํƒœ API์˜ ์žฅ์ 

REST API๊ฐ€ ๋ฌด์ƒํƒœ์„ฑ์ด๋ฉด ๋ช‡ ๊ฐ€์ง€ ๋ˆˆ์— ๋„๋Š” ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๋ฌด์ƒํƒœ์„ฑ์€ API๋ฅผ ์—ฌ๋Ÿฌ ์„œ๋ฒ„์— ๋ฐฐํฌํ•˜์—ฌ ์ˆ˜๋ฐฑ๋งŒ ๋ช…์˜ ๋™์‹œ ์‚ฌ์šฉ์ž๋กœ ํ™•์žฅ(์Šค์ผ€์ผ ์•„์›ƒ)ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. ์„ธ์…˜ ๊ด€๋ จ ์ข…์†์„ฑ์ด ์—†์œผ๋ฏ€๋กœ ์–ด๋–ค ์„œ๋ฒ„๋“  ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ๋ฌด์ƒํƒœ์„ฑ์€ server-side state synchronization logic์„ ๋ชจ๋‘ ์ œ๊ฑฐํ•˜์—ฌ REST API์˜ ๋ณต์žก์„ฑ์„ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  3. ๋ฌด์ƒํƒœ์„ฑ API๋Š” ์บ์‹œํ•˜๊ธฐ๋„ ์‰ฝ์Šต๋‹ˆ๋‹ค. ํŠน์ • ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ์š”์ฒญ ํ•˜๋‚˜๋ฅผ ๋ณด๊ณ  HTTP ์š”์ฒญ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹œํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด, ์ด์ „ ์š”์ฒญ์˜ ์ƒํƒœ๊ฐ€ ์ด ์š”์ฒญ์˜ ์บ์‹œ ๊ฐ€๋Šฅ์„ฑ์— ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ง€์†์ ์ธ ๋ถˆํ™•์‹ค์„ฑ์€ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.
  4. ํด๋ผ์ด์–ธํŠธ๋Š” ์š”์ฒญ๋งˆ๋‹ค ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ๋ณด๋‚ด๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ฒ„๋Š” ์‘์šฉํ”„๋กœ๊ทธ๋žจ์—์„œ ๊ฐ ํด๋ผ์ด์–ธํŠธ๊ฐ€ โ€œ์–ด๋””โ€ ์žˆ๋Š”์ง€ ์ถ”์ ํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.

3๏ธโƒฃ Tech - How To

Designing REST APIs

REST๋ฅผ ๊ฐœ๋ณ„์ ์œผ๋กœ ํ•™์Šตํ•˜๋Š” ๊ฒƒ๊ณผ ์ด๋Ÿฌํ•œ ๋ชจ๋“  ๊ฐœ๋…์„ ์‹ค์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์— ์ ์šฉํ•˜๋Š” ๊ฒƒ์€ ์™„์ „ํžˆ ๋‹ค๋ฅธ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

์ด ํŠœํ† ๋ฆฌ์–ผ ์—์„œ๋Š” ๋„คํŠธ์›Œํฌ ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•œ REST API๋ฅผ ์„ค๊ณ„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ฐ€๋ฅด์ณ์ค„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ์„ค๊ณ„ ํ”„๋กœ์„ธ์Šค์—์„œ REST ์›์น™์„ ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํ•™์Šตํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

1. ๋ฆฌ์†Œ์Šค ์‹๋ณ„ โ€“ ๊ฐ์ฒด ๋ชจ๋ธ๋ง

REST API ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋””์ž์ธํ•˜๋Š” ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„๋Š” ๋ฆฌ์†Œ์Šค ๋กœ ํ‘œ์‹œ๋  ๊ฐœ์ฒด๋ฅผ ์‹๋ณ„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋„คํŠธ์›Œํฌ ๊ธฐ๋ฐ˜ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฒฝ์šฐ ๊ฐœ์ฒด ๋ชจ๋ธ๋ง์ด ํ›จ์”ฌ ๋” ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ์žฅ์น˜, ๊ด€๋ฆฌ๋˜๋Š” ์—”ํ‹ฐํ‹ฐ, ๋ผ์šฐํ„ฐ, ๋ชจ๋Ž€ ๋“ฑ๊ณผ ๊ฐ™์€ ๋งŽ์€ ๊ฒƒ๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹จ์ˆœํ™”๋ฅผ ์œ„ํ•ด ๋‘ ๊ฐ€์ง€ ๋ฆฌ์†Œ์Šค๋งŒ ๊ณ ๋ คํ•ฉ๋‹ˆ๋‹ค.

  • ์žฅ์น˜(Devices)
  • ๊ตฌ์„ฑ(Configurations)

์—ฌ๊ธฐ์„œ ๊ตฌ์„ฑ์€ ์žฅ์น˜์˜ ํ•˜์œ„ ๋ฆฌ์†Œ์Šค์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์žฅ์น˜์—๋Š” ๋งŽ์€ ๊ตฌ์„ฑ ์˜ต์…˜์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„ ๋ชจ๋ธ์˜ ๋‘ ๊ฐ์ฒด/์ž์› ๋ชจ๋‘ ์ •์ˆ˜(Integer)์˜ id ์†์„ฑ์ธ ๊ณ ์œ  ์‹๋ณ„์ž๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

2. ๋ชจ๋ธ URI ์ƒ์„ฑ

์ด์ œ ๊ฐœ์ฒด ๋ชจ๋ธ์ด ์ค€๋น„๋˜๋ฉด, ๋ฆฌ์†Œ์Šค URI๋ฅผ ๊ฒฐ์ •ํ•  ์ฐจ๋ก€์ž…๋‹ˆ๋‹ค. ์ด ๋‹จ๊ณ„์—์„œ ๋ฆฌ์†Œ์Šค URI๋ฅผ ์„ค๊ณ„ํ•˜๋Š” ๋™์•ˆ ๋ฆฌ์†Œ์Šค์™€ ํ•˜์œ„ ๋ฆฌ์†Œ์Šค ๊ฐ„์˜ ๊ด€๊ณ„์— ์ค‘์ ์„ ๋‘ก๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ฆฌ์†Œ์Šค URI๋Š” API์˜ endpoint์ž…๋‹ˆ๋‹ค.์šฐ๋ฆฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋””๋ฐ”์ด์Šค๋Š” ์ตœ์ƒ์œ„ ๋ฆฌ์†Œ์Šค์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ตฌ์„ฑ์€ ์žฅ์น˜ ์•„๋ž˜์˜ ํ•˜์œ„ ๋ฆฌ์†Œ์Šค์ž…๋‹ˆ๋‹ค. ์•„๋ž˜์˜ URI๋ฅผ ์ ์–ด ๋ด…์‹œ๋‹ค.

/devices
/devices/{id}
 
/configurations
/configurations/{id}
 
/devices/{id}/configurations
/devices/{id}/configurations/{configId}

์ด๋Ÿฌํ•œ URI์—๋Š” ๋™์‚ฌ๋‚˜ ์—ฐ์‚ฐ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. URI์— ๋™์‚ฌ๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. URI๋Š” ๋ชจ๋‘ ๋ช…์‚ฌ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

3. ๋ฆฌ์†Œ์Šค Representations ๊ฒฐ์ •

์ด์ œ ๋ฆฌ์†Œ์Šค URI๊ฐ€ ๊ฒฐ์ •๋˜๋ฉด ํ•ด๋‹น representation์— ๋Œ€ํ•ด ์ž‘์—…ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ํ‘œํ˜„์€ XML ๋˜๋Š” JSON ํ˜•์‹์œผ๋กœ ์ •์˜๋ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๊ฐ€ ๊ตฌ์„ฑ๋˜๋Š” ๋ฐฉ์‹์„ ๋” ์ž˜ ํ‘œํ˜„ํ•˜๋Š” XML ์˜ˆ์ œ๋ฅผ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

3.1. ์žฅ์น˜์˜ ์ˆ˜์ง‘ ์ž์›

์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ, ํ•ด๋‹น ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์ •๋ณด๋งŒ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‘๋‹ต ํŽ˜์ด๋กœ๋“œ์˜ ํฌ๊ธฐ๊ฐ€ ์ค„์–ด๋“ค๊ฒŒ๋˜๊ณ , ์ด๊ฑด API์˜ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

<devices size="2">
 
  	<link rel="self" href="/devices"/>
 
  	<device id="12345">
  	  	<link rel="self" href="/devices/12345"/>
  	  	<deviceFamily>apple-es</deviceFamily>
  	  	<OSVersion>10.3R2.11</OSVersion>
  	  	<platform>SRX100B</platform>
  	  	<serialNumber>32423457</serialNumber>
  	  	<connectionStatus>up</connectionStatus>
  	  	<ipAddr>192.168.21.9</ipAddr>
  	  	<name>apple-srx_200</name>
  	  	<status>active</status>
  	</device>
 
  	<device id="556677">
  	  	<link rel="self" href="/devices/556677"/>
  	  	<deviceFamily>apple-es</deviceFamily>
  	  	<OSVersion>10.3R2.11</OSVersion>
  	  	<platform>SRX100B</platform>
  	  	<serialNumber>6453534</serialNumber>
  	  	<connectionStatus>up</connectionStatus>
  	  	<ipAddr>192.168.20.23</ipAddr>
  	  	<name>apple-srx_200</name>
  	  	<status>active</status>
  	</device>
 
</devices>

3.2. ๋‹จ์ผ ์žฅ์น˜ ๋ฆฌ์†Œ์Šค

์ปฌ๋ ‰์…˜ URI์™€ ๋‹ฌ๋ฆฌ, ๋‹จ์ผ ๋ฆฌ์†Œ์Šค URI์—๋Š” ํŠน์ • ์žฅ์น˜์— ๋Œ€ํ•œ ์™„์ „ํ•œ ์ •๋ณด๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ํ•˜์œ„ ๋ฆฌ์†Œ์Šค ๋ฐ ๊ธฐํƒ€ ์ง€์›๋˜๋Š” ์ž‘์—…์— ๋Œ€ํ•œ ๋งํฌ ๋ชฉ๋ก๋„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด REST API HATEOAS ๊ตฌ๋™์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

<device id="12345">
  	<link rel="self" href="/devices/12345"/>
 
  	<id>12345</id>
  	<deviceFamily>apple-es</deviceFamily>
  	<OSVersion>10.0R2.10</OSVersion>
  	<platform>SRX100-LM</platform>
  	<serialNumber>32423457</serialNumber>
  	<name>apple-srx_100_lehar</name>
  	<hostName>apple-srx_100_lehar</hostName>
  	<ipAddr>192.168.21.9</ipAddr>
  	<status>active</status>
 
  	<configurations size="2">
  	  	<link rel="self" href="/configurations" />
 
  	  	<configuration id="42342">
        	  	<link rel="self" href="/configurations/42342" />
  	  	</configuration>
 
  	  	<configuration id="675675">
        	  	<link rel="self" href="/configurations/675675" />
  	  	</configuration>
  	</configurations>
 
  	<method href="/devices/12345/exec-rpc" rel="rpc"/>
  	<method href="/devices/12345/synch-config"rel="synch device configuration"/>
</device>

3.3. ๊ตฌ์„ฑ์˜ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค

์žฅ์น˜ ์ปฌ๋ ‰์…˜์˜ ํ‘œํ˜„๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ตœ์†Œํ•œ์˜ ์ •๋ณด๋งŒ์œผ๋กœ ๊ตฌ์„ฑ ์ปฌ๋ ‰์…˜์˜ representation์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

<configurations size="20">
  	<link rel="self" href="/configurations" />
 
  	<configuration id="42342">
  	  	<link rel="self" href="/configurations/42342" />
  	</configuration>
 
  	<configuration id="675675">
  	  	<link rel="self" href="/configurations/675675" />
  	</configuration>
  	...
  	...
</configurations>

๋‚ด๋ถ€ configurations์ปฌ๋ ‰์…˜ ํ‘œํ˜„ device์€ ์ตœ์ƒ์œ„ configurationsURI์™€ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์œ ์ผํ•œ ์ฐจ์ด์ ์€ ์žฅ์น˜์— ๋Œ€ํ•œ ๊ตฌ์„ฑ์ด ๋‘ ๊ฐœ๋ฟ์ด๋ฏ€๋กœ ๋‘ ๊ฐœ์˜ ๊ตฌ์„ฑ ํ•ญ๋ชฉ๋งŒ ์žฅ์น˜ ์•„๋ž˜์— ํ•˜์œ„ ๋ฆฌ์†Œ์Šค๋กœ ๋‚˜์—ด๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

3.4. ๋‹จ์ผ ๊ตฌ์„ฑ ๋ฆฌ์†Œ์Šค

์ด์ œ ๋‹จ์ผ ๊ตฌ์„ฑ ๋ฆฌ์†Œ์Šค representation์—๋Š” ๊ด€๋ จ ๋งํฌ๋ฅผ ํฌํ•จํ•˜์—ฌ ์ด ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ๋ชจ๋“  ๊ฐ€๋Šฅํ•œ ์ •๋ณด๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

<configuration id="42342">
  	<link rel="self" href="/configurations/42342" />
  	<content><![CDATA[...]]></content>
  	<status>active</status>
  	<link rel="very big raw configuration script" href="/configurations/42342/raw" />
</configuration>

3.5. ๋‹จ์ผ ์žฅ์น˜์—์„œ ๊ตฌ์„ฑ ๋ฆฌ์†Œ์Šค ์ˆ˜์ง‘

์ด ๊ตฌ์„ฑ์˜ ํ•˜์œ„ ์ปฌ๋ ‰์…˜์€ ๊ตฌ์„ฑ์˜ ๊ธฐ๋ณธ ์ปฌ๋ ‰์…˜์˜ ํ•˜์œ„ ์ง‘ํ•ฉ์ด๋ฉฐ ์žฅ์น˜์—๋งŒ ๊ณ ์œ ํ•˜๊ฒŒ ํ•ด๋‹น๋ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ์ปฌ๋ ‰์…˜์˜ ํ•˜์œ„ ์ง‘ํ•ฉ์ด๋ฏ€๋กœ ๊ธฐ๋ณธ ์ปฌ๋ ‰์…˜๊ณผ ๋‹ค๋ฅธ representation ๋ฐ์ดํ„ฐ ํ•„๋“œ๋ฅผ ์ƒ์„ฑํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค . ๊ธฐ๋ณธ ์ปฌ๋ ‰์…˜๊ณผ ๋™์ผํ•œ ํ”„๋ ˆ์  ํ…Œ์ด์…˜ ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

<configurations size="2">
  	<link rel="self" href="/devices/12345/configurations" />
 
  	<configuration id="53324">
  	  	<link rel="self" href="/devices/12345/configurations/53324" />
  	  	<link rel="detail" href="/configurations/53324" />
  	</configuration>
 
  	<configuration id="333443">
  	  	<link rel="self" href="/devices/12345/configurations/333443" />
  	  	<link rel="detail" href="/configurations/333443" />
  	</configuration>
</configurations>

์ด ํ•˜์œ„ ๋ฆฌ์†Œ์Šค ์ปฌ๋ ‰์…˜์—๋Š” ๋‘ ๊ฐœ์˜ ๋งํฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜๋Š” ํ•˜์œ„ ์ปฌ๋ ‰์…˜ ๋‚ด์—์„œ ์ง์ ‘ ํ‘œํ˜„(representation)ํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์ด๊ณ , ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ๊ธฐ๋ณธ ์ปฌ๋ ‰์…˜/devices/12345/configurations/333443 ์—์„œ ์œ„์น˜๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š”, /configurations/333443 ์ž…๋‹ˆ๋‹ค.๋” ํŠน๋ณ„ํ•œ ๋ฐฉ์‹์œผ๋กœ ์žฅ์น˜ ๋ณ„ ๊ตฌ์„ฑ์— ๋Œ€ํ•œ ์•ก์„ธ์Šค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋‘ ๊ฐœ์˜ ๋งํฌ๊ฐ€ ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค.

๋˜ํ•œ ์ผ๋ถ€ ํ•„๋“œ๋ฅผ ๋งˆ์Šคํ‚นํ•˜๋Š” ๊ธฐ๋Šฅ (๋””์ž์ธ์— ํ•„์š”ํ•œ ๊ฒฝ์šฐ)์ด ์žˆ์œผ๋ฉฐ ๋ณด์กฐ ์ปฌ๋ ‰์…˜์—๋Š” ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

3.6. ๋‹จ์ผ ์žฅ์น˜ ์•„๋ž˜์˜ ๋‹จ์ผ ๊ตฌ์„ฑ ๋ฆฌ์†Œ์Šค

์ด representation์€ ๊ธฐ๋ณธ ์ปฌ๋ ‰์…˜์˜ ๊ตฌ์„ฑ ํ‘œํ˜„๊ณผ ๊ฑฐ์˜ ์œ ์‚ฌํ•œ representation์„ ๊ฐ€์ ธ์•ผ ํ•˜๊ฑฐ๋‚˜, ๋ช‡ ๊ฐœ์˜ ํ•„๋“œ๋ฅผ ๋งˆ์Šคํ‚นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ํ•˜์œ„ ๋ฆฌ์†Œ์Šค representation์—๋Š” ๊ธฐ๋ณธ ํ”„๋ ˆ์  ํ…Œ์ด์…˜์— ๋Œ€ํ•œ ์ถ”๊ฐ€์ ์ธ ๋งํฌ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

<configuration id="11223344">
  	<link rel="self" href="/devices/12345/configurations/11223344" />
  	<link rel="detail" href="/configurations/11223344" />
  	<content><![CDATA[...]]></content>
  	<status>active</status>
  	<link rel="raw configuration content" href="/configurations/11223344/raw" />
</configuration>

์ด์ œ ๋‹ค์Œ ์„น์…˜์œผ๋กœ ๋„˜์–ด๊ฐ€๊ธฐ ์ „์— ๋ช‡ ๊ฐ€์ง€ ๊ด€์ฐฐ ์‚ฌํ•ญ์„ ๊ธฐ๋กํ•ด ๋‘ก์‹œ๋‹ค.

  • ๋ฆฌ์†Œ์Šค URI๋Š” ๋ชจ๋‘ ๋ช…์‚ฌ์ž…๋‹ˆ๋‹ค.
  • URI๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฆฌ์†Œ์Šค ๋ชจ์Œ๊ณผ ๋‹จ์ผ ๋ฆฌ์†Œ์Šค์˜ ๋‘ ๊ฐ€์ง€ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค.
  • ์ปฌ๋ ‰์…˜์€ 1์ฐจ ์ปฌ๋ ‰์…˜๊ณผ 2์ฐจ ์ปฌ๋ ‰์…˜์˜ ๋‘ ๊ฐ€์ง€ ํ˜•ํƒœ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณด์กฐ ์ปฌ๋ ‰์…˜์€ ๊ธฐ๋ณธ ์ปฌ๋ ‰์…˜์˜ ํ•˜์œ„ ์ปฌ๋ ‰์…˜์ž…๋‹ˆ๋‹ค.
  • ๊ฐ ๋ฆฌ์†Œ์Šค/์ปฌ๋ ‰์…˜์—๋Š” ์ ์–ด๋„ ํ•˜๋‚˜์˜ ๋งํฌ, ์ฆ‰ ์ž์‹ ์— ๋Œ€ํ•œ ๋งํฌ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ปฌ๋ ‰์…˜์—๋Š” ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์ •๋ณด๋งŒ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์™„์ „ํ•œ ์ •๋ณด๋ฅผ ์–ป์œผ๋ ค๋ฉด ํŠน์ • ๋ฆฌ์†Œ์Šค URI์—๋งŒ ์•ก์„ธ์Šคํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • Representation์—๋Š” ์ถ”๊ฐ€ ๋งํฌ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์ฆ‰, ๋‹จ์ผ ์žฅ์น˜์˜ ๋ฉ”์„œ๋“œ). ์—ฌ๊ธฐ์„œ ๋ฉ”์†Œ๋“œ๋Š” POST ๋ฉ”์†Œ๋“œ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ๋˜ํ•œ ์™„์ „ํžˆ ์ƒˆ๋กœ์šด ๋ฐฉ์‹์œผ๋กœ ๋” ๋งŽ์€ ์†์„ฑ์ด๋‚˜ ์–‘์‹ ๋งํฌ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์šฐ๋ฆฌ๋Š” ์•„์ง ์ด๋Ÿฌํ•œ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์ž‘์—…์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

4. HTTP ๋ฉ”์†Œ๋“œ ํ• ๋‹น

๋”ฐ๋ผ์„œ ๋ฆฌ์†Œ์Šค URI์™€ ํ•ด๋‹น representation์ด ์ด์ œ ์ˆ˜์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฐ€๋Šฅํ•œ ์ž‘์—…์„ ๊ฒฐ์ •ํ•˜๊ณ  ํ•ด๋‹น ์ž‘์—…์„ ๋ฆฌ์†Œ์Šค URI์— ๋งคํ•‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹น์‚ฌ ๋„คํŠธ์›Œํฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์‚ฌ์šฉ์ž๋Š” ๋„คํŠธ์›Œํฌ์—์„œ ์žฅ์น˜๋ฅผ ๊ฒ€์ƒ‰, ์ƒ์„ฑ, ์—…๋ฐ์ดํŠธ ๋˜๋Š” ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๊ณ  ์žฅ์น˜ ๊ตฌ์„ฑ์„ ์ƒ์„ฑ/๋ฐฐํฌ/์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋Ÿฌํ•œ ์ž‘์—…์„ ํ•ด๋‹น ๋ฆฌ์†Œ์Šค์— ํ• ๋‹นํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

4.1. ๋ชจ๋“  ์žฅ์น˜ ๋˜๋Š” ๊ตฌ์„ฑ ํƒ์ƒ‰(Browse) [๊ธฐ๋ณธ ์ปฌ๋ ‰์…˜]

HTTP GET /devices
HTTP GET /configurations

์ปฌ๋ ‰์…˜ ํฌ๊ธฐ๊ฐ€ ํฐ ๊ฒฝ์šฐ ํŽ˜์ด์ง• ๋ฐ ํ•„ํ„ฐ๋ง์„ ์ ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์•„๋ž˜ ์š”์ฒญ์€ ์ปฌ๋ ‰์…˜์—์„œ ์ฒ˜์Œ 20๊ฐœ์˜ ๋ ˆ์ฝ”๋“œ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

HTTP GET /devices?startIndex=0&size=20
HTTP GET /configurations?startIndex=0&size=20

4.2. ์žฅ์น˜์˜ ๋ชจ๋“  ๊ตฌ์„ฑ ํƒ์ƒ‰(Browse) [๋ณด์กฐ ์ปฌ๋ ‰์…˜]

HTTP GET /devices/{id}/configurations

๋Œ€๋ถ€๋ถ„ ์†Œ๊ทœ๋ชจ ์ปฌ๋ ‰์…˜์ด๋ฏ€๋กœ ์—ฌ๊ธฐ์—์„œ ํ•„ํ„ฐ๋ง์ด๋‚˜ ์ •๋ ฌ์„ ํ™œ์„ฑํ™”ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

4.3. ๋‹จ์ผ ์žฅ์น˜ ๋˜๋Š” ๊ตฌ์„ฑ ํƒ์ƒ‰(Browse)

์žฅ์น˜ ๋˜๋Š” ๊ตฌ์„ฑ์˜ ์ „์ฒด ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ์–ป์œผ๋ ค๋ฉด GET๋‹จ์ผ ๋ฆฌ์†Œ์Šค URI์— GET ์ž‘์—…์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

HTTP GET /devices/{id}
HTTP GET /configurations/{id}

4.4. ์žฅ์น˜์—์„œ ๋‹จ์ผ ๊ตฌ์„ฑ ํƒ์ƒ‰(Browse)

HTTP GET /devices/{id}/configurations/{configId}

ํ•˜์œ„ ๋ฆฌ์†Œ์Šค representation์€ ๊ธฐ๋ณธ ํ”„๋ ˆ์  ํ…Œ์ด์…˜๊ณผ ๊ฐ™๊ฑฐ๋‚˜ ํ•˜์œ„ ์ง‘ํ•ฉ์ด ๋ฉ๋‹ˆ๋‹ค.

4.5. ์žฅ์น˜ ๋˜๋Š” ๊ตฌ์„ฑ ๋งŒ๋“ค๊ธฐ(Create)

CREATE๋Š” ๋ฉฑ๋“ฑ์„ฑ(๋‹คํšŒ ์ ์šฉํ•ด๋„ ๊ฒฐ๊ณผ๊ฐ€ ๋ณ€ํ•˜์ง€ ์•Š๋Š”๋‹ค) ์ž‘์—…์ด ์•„๋‹ˆ๋ฉฐ HTTP ํ”„๋กœํ† ์ฝœ POST๋˜ํ•œ ๋ฉฑ๋“ฑ์„ฑ์ด ์•„๋‹™๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ POST๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.

HTTP POST /devices
HTTP POST /configurations

์„œ๋ฒ„๊ฐ€ ๊ฒฐ์ •ํ•  ์ฑ…์ž„์ด ์žˆ์œผ๋ฏ€๋กœ ์š”์ฒญ ํŽ˜์ด๋กœ๋“œ์—๋Š” id ์†์„ฑ์ด ํฌํ•จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. CREATE ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

HTTP/1.1 201 Created
Content-Type: application/xml
Location: http://example.com/network-app/configurations/678678
 
<configuration id="678678">
  	<link rel="self" href="/configurations/678678" />
  	<content><![CDATA[...]]></content>
  	<status>active</status>
  	<link rel="raw configuration content" href="/configurations/678678/raw" />
</configuration>

4.6. ์žฅ์น˜ ๋˜๋Š” ๊ตฌ์„ฑ ์—…๋ฐ์ดํŠธ

์—…๋ฐ์ดํŠธ ์ž‘์—…์€ ๋ฉฑ๋“ฑ ์ž‘์—…์ด๊ณ  HTTP PUT๋„ ๋ฉฑ๋“ฑ ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์—…๋ฐ์ดํŠธ ์ž‘์—…์— PUT ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

HTTP PUT /devices/{id}
HTTP PUT /configurations/{id}

PUT ์‘๋‹ต์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

HTTP/1.1 200 OK
Content-Type: application/xml
 
<configuration id="678678">
  	<link rel="self" href="/configurations/678678" />
  	<content><![CDATA[. updated content here .]]></content>
  	<status>active</status>
  	<link rel="raw configuration content" href="/configurations/678678/raw" />
</configuration>

4.7. ์žฅ์น˜ ๋˜๋Š” ๊ตฌ์„ฑ ์ œ๊ฑฐ

์ œ๊ฑฐ(Removing)๋Š” ํ•ญ์ƒ DELETE์ž‘์—…์ž…๋‹ˆ๋‹ค.

HTTP DELETE /devices/{id}
HTTP DELETE /configurations/{id}

๋ฆฌ์†Œ์Šค๊ฐ€ ์‚ญ์ œ๋ฅผ ์œ„ํ•ด ๋Œ€๊ธฐ์—ด์— ์žˆ์„ ๊ฒฝ์šฐ(๋น„๋™๊ธฐ ์ž‘์—…) ์„ฑ๊ณตํ•œ ์‘๋‹ต์€ 202(Accepted)์—ฌ์•ผ ํ•˜๋ฉฐ, ๋ฆฌ์†Œ์Šค๊ฐ€ ์˜๊ตฌ์ ์œผ๋กœ ์‚ญ์ œ๋œ ๊ฒฝ์šฐ(๋™๊ธฐ ์ž‘์—…)๋Š” 200(OK)/204 (No Content) ์—ฌ์•ผํ•ฉ๋‹ˆ๋‹ค.

๋น„๋™๊ธฐ ์ž‘์—…์˜ ๊ฒฝ์šฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์„ฑ๊ณต/์‹คํŒจ ์ƒํƒœ๋ฅผ ์ถ”์ ํ•  ์ˆ˜ ์žˆ๋Š” ์ž‘์—… ID๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์‹œ์Šคํ…œ์—์„œ ํ•˜์œ„ ๋ฆฌ์†Œ์Šค๊ฐ€ ์‚ญ์ œ๋  ๋•Œ, ๋™์ž‘์„ ๊ฒฐ์ •ํ•˜๋ ค๋ฉด ์ถฉ๋ถ„ํ•œ ๋ถ„์„์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.์ผ๋ฐ˜์ ์œผ๋กœ ์ด๋Ÿฌํ•œ ์š”์ฒญ์—์„œ ๋ฆฌ์†Œ์Šค๋ฅผ SOFT DELETE *ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์ƒํƒœ๋ฅผ INACTIVE๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

์ด ์ ‘๊ทผ ๋ฐฉ์‹์„ ๋”ฐ๋ฅด๋ฉด ๋‹ค๋ฅธ ์œ„์น˜์—์„œ๋„ ํ•ด๋‹น ์ฐธ์กฐ๋ฅผ ์ฐพ์•„ ์ œ๊ฑฐํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

4.8. ์žฅ์น˜์—์„œ ๊ตฌ์„ฑ ์ ์šฉ ๋˜๋Š” ์ œ๊ฑฐ

์‹ค์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ์žฅ์น˜์— ๊ตฌ์„ฑ์„ ์ ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” ๊ธฐ๋ณธ ์ปฌ๋ ‰์…˜์ด ์•„๋‹Œ ์žฅ์น˜์—์„œ ๊ตฌ์„ฑ์„ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๋ฉฑ๋“ฑ์„ฑ ํŠน์„ฑ ๋•Œ๋ฌธ์— PUT ๋ฐ DELETE ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

//Apply Configuration on a device
HTTP PUT /devices/{id}/configurations
 
//Remove Configuration on a device
HTTP DELETE /devices/{id}/configurations/{configId}

5. ์ถ”๊ฐ€ ์ž‘์—…

์ง€๊ธˆ๊นŒ์ง€ ์šฐ๋ฆฌ๋Š” ๊ฐ์ฒด ๋ชจ๋ธ๊ณผ URI๋งŒ์„ ์„ค๊ณ„ํ•˜๊ณ  HTTP ๋ฉ”์†Œ๋“œ ๋˜๋Š” ์ž‘์—…์„ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋‹ค๋ฅธ ์ธก๋ฉด์—์„œ๋„ ์ž‘์—…ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  1. ๋กœ๊น…
  2. ๋ณด์•ˆ
  3. ๊ฒ€์ƒ‰ ๋“ฑ

REST APIs with JAX-RS

REST API ๋””์ž์ธ ํŠœํ† ๋ฆฌ์–ผ ์—์„œ ๋„คํŠธ์›Œํฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋””์ž์ธ ํ”„๋กœ์„ธ์Šค์— REST ์›์น™์„ ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒŒ์‹œ๋ฌผ์—์„œ๋Š” JAX-RS 2.0 (Java APIfor RESTful Services)์„ ์‚ฌ์šฉํ•˜์—ฌ ๋™์ผํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋Œ€ํ•œ REST API๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›๋‹ˆ๋‹ค.

1. JAX-RS ์‚ฌ์–‘

JAX-RS๋Š” REST ์•„ํ‚คํ…์ฒ˜ ์Šคํƒ€์ผ์˜ ์›์น™์— ๋”ฐ๋ผ ์„ค๊ณ„ ๋ฐ ๊ตฌํ˜„๋œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœ, ๊ณต๊ฐœ ๋ฐ ์•ก์„ธ์Šคํ•˜๊ธฐ ์œ„ํ•œ ์ด์‹ ๊ฐ€๋Šฅํ•œ API๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Java EE 6 ๋ฆด๋ฆฌ์Šค๋Š” Java API for RESTful ์›น ์„œ๋น„์Šค(JAX-RS) [ JSR 311 ] ๋ฅผ ๋„์ž…ํ•˜์—ฌ RESTful ์›น ์„œ๋น„์Šค API๋ฅผ ํ‘œ์ค€ํ™”ํ•˜๋Š” ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„๋ฅผ ๋ฐŸ์•˜์Šต๋‹ˆ๋‹ค.

JAX-RS๋Š” ๋ชจ๋“  Java EE ํ˜ธํ™˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„์—์„œ REST API ์ฝ”๋“œ์˜ ์ด์‹์„ฑ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ์ตœ์‹  ๋ฒ„์ „์€ Java EE 7 ํ”Œ๋žซํผ์˜ ์ผ๋ถ€๋กœ ๋ฆด๋ฆฌ์Šค๋œ JAX-RS 2.0 [JSR 339] ์ž…๋‹ˆ๋‹ค.

JAX-RS๋Š” ์ผ๋ฐ˜ Java ๊ฐ์ฒด์— Java ์–ด๋…ธํ…Œ์ด์…˜์„ ์ ์šฉํ•˜๋Š” ๋ฐ ์ค‘์ ์„ ๋‘ก๋‹ˆ๋‹ค. JAX-RS์—๋Š” ํŠน์ • URI ํŒจํ„ด ๋ฐ HTTP ์ž‘์—…์„ Java ํด๋ž˜์Šค์˜ ํŠน์ • ๋ฉ”์†Œ๋“œ์— ๋ฐ”์ธ๋”ฉํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์ž…๋ ฅ/์ถœ๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.

JAX-RS๊ฐ€ ์‚ฌ์–‘์ด๋ผ๊ณ  ์ด๋ฏธ ๋งํ–ˆ๋“ฏ์ด, REST API ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ ค๋ฉด ๊ตฌํ˜„์ด ํ•„์š”ํ•˜๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์œ ๋ช…ํ•œJAX-RS ๊ตฌํ˜„์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

2. JAX-RS ์–ด๋…ธํ…Œ์ด์…˜

JAX-RS 2.0์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ํ•„์ˆ˜ ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

2.1. @Path(โ€˜resourcePathโ€™)

๊ธฐ๋ณธ @Path ์–ด๋…ธํ…Œ์ด์…˜์€ URI์™€ ๊ด€๋ จ๋œ URI ๊ฒฝ๋กœ๋ฅผ ์ผ์น˜์‹œํ‚ค๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋ฆฌ์†Œ์Šค ํด๋ž˜์Šค ๋˜๋Š” ๋ฉ”์„œ๋“œ์— ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@Path("/configurations")
public class ConfigurationResource
{
  	@Path("/{id}")
  	@GET
  	public Response getConfigurationById(@PathParam("id") Integer id) {
  	  	//...
  	}

}

2.2. @POST

@POST ์–ด๋…ธํ…Œ์ด์…˜์ด ๋‹ฌ๋ฆฐ(annotated) ๋ฉ”์„œ๋“œ๋Š” ์ผ์น˜ํ•˜๋Š” ๋ฆฌ์†Œ์Šค ๊ฒฝ๋กœ์— ๋Œ€ํ•œ HTTP POST์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

@POST
@Consumes("application/xml")
public Response createConfiguration(Configuration config) {
  	//...
}

2.3. @PUT

@PUT์–ด๋…ธํ…Œ์ด์…˜์ด ๋‹ฌ๋ฆฐ ๋ฉ”์„œ๋“œ(annotated)๋Š” ์ผ์น˜ํ•˜๋Š” ๋ฆฌ์†Œ์Šค ๊ฒฝ๋กœ์— ๋Œ€ํ•œ HTTP PUT์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

@PUT
@Consumes("application/xml")
public Response updateConfiguration(@PathParam("id") Integer id, Configuration config){
  	//...
}

2.4. @GET

@GET ์–ด๋…ธํ…Œ์ด์…˜์ด ๋‹ฌ๋ฆฐ ๋ฉ”์„œ๋“œ(annotated)๋Š” ์ผ์น˜ํ•˜๋Š” ๋ฆฌ์†Œ์Šค ๊ฒฝ๋กœ์— ๋Œ€ํ•œ HTTP GET์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

@GET
@Path("/{id}")
public Response getConfigurationById(@PathParam("id") Integer id){
  	//...
}

2.5. @DELETE

@DELETE ์–ด๋…ธํ…Œ์ด์…˜์ด ๋‹ฌ๋ฆฐ ๋ฉ”์„œ๋“œ๋Š” ์ผ์น˜ํ•˜๋Š” ๋ฆฌ์†Œ์Šค ๊ฒฝ๋กœ์— ๋Œ€ํ•œ HTTP DELETE์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

@DELETE
@Path("/{id}")
public Response deleteConfiguration(@PathParam("id") Integer id){
  	//...
}

2.6. @PathParam(โ€œ๋งค๊ฐœ๋ณ€์ˆ˜ ์ด๋ฆ„โ€)

@PathParam์€ URL์—์„œ ๋ฉ”์†Œ๋“œ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๊ฐ’(๋ฆฌ์†Œ์Šค ์‹๋ณ„์ž)์„ ์ฃผ์ž…ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

@DELETE
@Path("/{id}")
public Response deleteConfiguration(@PathParam("id") Integer id){
  	//...
}

์œ„์˜ ์˜ˆ์—์„œ id from/{id}์˜ ๊ฐ’์€ @PathParam("id")์˜ Integer id ์™€ ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด URI HTTP DELETE /configurations/22312๋Š” ์œ„์˜ ๋ฉ”์„œ๋“œ์— ๋งคํ•‘ ๋˜๊ณ  id๋Š” 22312์œผ๋กœ ์ฑ„์›Œ์ง‘๋‹ˆ๋‹ค.

2.7. @Produces

@Produces์–ด๋…ธํ…Œ์ด์…˜์€ ์–ด๋…ธํ…Œ์ด์…˜์ด ์žˆ๋Š” ์ž์› ๋ฉ”์†Œ๋“œ์— ์˜ํ•ด ์ „๋‹ฌ๋˜๋Š” MIME ์œ ํ˜•์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ํด๋ž˜์Šค ์ˆ˜์ค€๊ณผ ๋ฉ”์„œ๋“œ ์ˆ˜์ค€์—์„œ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํด๋ž˜์Šค ์ˆ˜์ค€์—์„œ ์ •์˜๋œ ๊ฒฝ์šฐ ๋ฆฌ์†Œ์Šค ํด๋ž˜์Šค์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋Š” ๋ฉ”์„œ๋“œ์—์„œ ์žฌ์ •์˜๋˜์ง€ ์•Š์œผ๋ฉด ๋™์ผํ•œ MIME ํ˜•์‹์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

2.8. @Consumes

@Consumes ์–ด๋…ธํ…Œ์ด์…˜์€ ์–ด๋…ธํ…Œ์ด์…˜์ด ์žˆ๋Š” ๋ฆฌ์†Œ์Šค ๋ฉ”์„œ๋“œ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” MIME ์œ ํ˜•์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

@POST
@Consumes("application/xml")
public Response createConfiguration(Configuration config) {
  	//...
}

2.9. @Context

HATEOAS ๋งํฌ๋ฅผ ๋นŒ๋“œํ•˜๊ธฐ ์œ„ํ•ด์„œ JAX-RS 2.0์€ @Context ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์–ป์„ ์ˆ˜ ์žˆ๋Š” UriInfoํด๋ž˜์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

@Context
UriInfo uriInfo;

๊ธฐ๋ณธ์ ์œผ๋กœ JAX-RS ๋Ÿฐํƒ€์ž„์€ ๋ช…์‹œ์ ์œผ๋กœ ๊ตฌํ˜„๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ HEAD ๋ฐ OPTIONS ๋ฉ”์†Œ๋“œ๋ฅผ ์ž๋™์œผ๋กœ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

HEAD์˜ ๊ฒฝ์šฐ ๋Ÿฐํƒ€์ž„์€ ๊ตฌํ˜„๋œ GET ๋ฉ”์„œ๋“œ(์žˆ๋Š” ๊ฒฝ์šฐ)๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์‘๋‹ต ์—”ํ‹ฐํ‹ฐ(์„ค์ •๋œ ๊ฒฝ์šฐ)๋ฅผ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค.

OPTIONS ๋ฉ”์„œ๋“œ๋Š” โ€˜Allowโ€™ ํ—ค๋”์—์„œ ์ง€์›๋˜๋Š” ๋ฆฌ์†Œ์Šค ๋ฉ”์„œ๋“œ ์ง‘ํ•ฉ์„ ํฌํ•จํ•œ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3. Maven ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒ์„ฑ

Maven ์€ ํ”„๋กœ์ ํŠธ ๋นŒ๋“œ, ๋ณด๊ณ  ๋ฐ ์ค‘์•™ ์ •๋ณด์˜ ๋ฌธ์„œํ™”๋ฅผ ํฌํ•จํ•œ ์†Œํ”„ํŠธ์›จ์–ด ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ ๋ฐ ์ดํ•ด ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์˜ˆ) pom.xml.

Eclipse ์—์„œ maven์„ ์‚ฌ์šฉํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ƒ์„ฑํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ๋”ฐ๋ฅด์„ธ์š”.

  • ๋‹ค์Œ์—์„œ ์ƒˆ ํ”„๋กœ์ ํŠธ ๋งˆ๋ฒ•์‚ฌ ์—ด๊ธฐ File > New > Maven Project

Create Maven Application - Step 1

  • Next ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

Create Maven Application - Step 2

  • maven-archtype-webapp์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

Create Maven Application - Step 3

  • ํ”„๋กœ์ ํŠธ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•˜๊ณ  Finish ๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

Create Maven Application - Step 4

4. JAX-RS ์ข…์†์„ฑ ํฌํ•จ

JAX-RS 2.0์€ JDK 1.7 ๊ณผ ํ•จ๊ป˜ ๋ฒˆ๋“ค๋กœ ์ œ๊ณต ๋˜๋ฏ€๋กœ JAVA_HOME์— JDK 1.7 ์ด์ƒ ๋ฒ„์ „์ด ์žˆ๋Š” ๊ฒฝ์šฐ JAX-RS๋ฅผ ๋ณ„๋„๋กœ ํฌํ•จํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์œ„์— ๋‚˜์—ด๋œ ๊ตฌํ˜„ ์ค‘ ํ•˜๋‚˜๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด ์˜ˆ์ œ์—์„œ๋Š” RESTEasy 3.1.2.Final ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  	<modelVersion>4.0.0</modelVersion>
  	<groupId>net.restfulapi.app</groupId>
  	<artifactId>NetworkManagement</artifactId>
  	<packaging>war</packaging>
  	<version>0.0.1-SNAPSHOT</version>
  	<name>NetworkManagement</name>
  	<url>http://maven.apache.org</url>
  	<repositories>
  	  	<repository>
        	  	<id>jboss</id>
        	  	<name>jboss repo</name>
        	 <url>http://repository.jboss.org/nexus/content/groups/public/</url>
  	  	</repository>
  	</repositories>
  	<build>
  	  	<plugins>
  	  	<plugin>
        	  	<groupId>org.apache.maven.plugins</groupId>
              	  	<artifactId>maven-compiler-plugin</artifactId>
              	  	<version>3.2</version>
              	  	<configuration>
              	  	<source>1.8</source>
              	  	<target>1.8</target>
              	  	</configuration>
        	  	</plugin>
  	  	</plugins>
  	  	<finalName>NetworkManagement</finalName>
  	</build>
  	<dependencies>
  	  	<dependency>
        	  	<groupId>org.jboss.resteasy</groupId>
        	  	<artifactId>resteasy-jaxrs</artifactId>
        	  	<version>3.1.2.Final</version>
  	  	</dependency>
 
  	  	<dependency>
        	  	<groupId>org.jboss.resteasy</groupId>
        	  	<artifactId>resteasy-jaxb-provider</artifactId>
        	  	<version>3.1.2.Final</version>
  	  	</dependency>
  	  	
  	  	<dependency>
        	  	<groupId>org.jboss.resteasy</groupId>
        	  	<artifactId>resteasy-servlet-initializer</artifactId>
        	  	<version>3.1.2.Final</version>
  	  	</dependency>
 
  	  	<dependency>
        	  	<groupId>junit</groupId>
        	  	<artifactId>junit</artifactId>
        	  	<version>3.8.1</version>
        	  	<scope>test</scope>
  	  	</dependency>
  	</dependencies>
</project>

resteasy-servlet-initializer์•„ํ‹ฐํŒฉํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Servlet 3.0 ์ปจํ…Œ์ด๋„ˆ์—์„œ ๋ฆฌ์†Œ์Šค ๋ฐ ๊ณต๊ธ‰์ž๋ฅผ ์ž๋™์œผ๋กœ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

5. ๋ฆฌ์†Œ์Šค ํ‘œํ˜„ ์ƒ์„ฑ

JAX-RS ์—์„œ๋Š”, ์ž์› ํ‘œํ˜„์€ JAXB ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ POJO ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. ์˜ˆ) @XmlRootElement, @XmlAttribute and @XmlElement ๋“ฑ๋“ฑ.

์ด ์˜ˆ์ œ์—์„œ๋Š” ๋‘ ๊ฐ€์ง€ ํ‘œํ˜„์„ ๊ณต๊ฐœํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ž๋ฐ” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด ๋ด…์‹œ๋‹ค.

5.1. ๊ตฌ์„ฑ์˜ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค

package net.restfulapi.app.rest.domain;
 
import java.util.List;
 
import javax.ws.rs.core.Link;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 
@XmlRootElement(name = "configurations")
@XmlAccessorType(XmlAccessType.FIELD)
public class Configurations
{
  	@XmlAttribute
  	private Integer size;
 
  	@XmlJavaTypeAdapter(Link.JaxbAdapter.class)
  	@XmlElement
  	private Link link;
 
  	@XmlElement
  	private List<Configuration> configurations;
 
  	public Integer getSize() {
  	  	return size;
  	}
 
  	public void setSize(Integer size) {
  	this.size = size;
  	}
 
  	public Link getLink() {
  	  	return link;
  	}
 
  	public void setLink(Link link) {
  	  	this.link = link;
  	}
 
  	public List<Configuration> getConfigurations() {
  	  	return configurations;
  	}
 
  	public void setConfigurations
  	  	(List<Configuration> configurations) {
  	  	this.configurations = configurations;
  	}
}

5.2. ๋‹จ์ผ ๊ตฌ์„ฑ ๋ฆฌ์†Œ์Šค

package net.restfulapi.app.rest.domain;
 
import javax.ws.rs.core.Link;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 
import net.restfulapi.app.rest.domain.common.Status;
 
@XmlRootElement(name="configuration")
@XmlAccessorType(XmlAccessType.FIELD)
public class Configuration
{
  	@XmlAttribute
  	private Integer id;
 
  	@XmlJavaTypeAdapter(Link.JaxbAdapter.class)
  	@XmlElement
  	private Link link;
 
  	@XmlElement
  	private String content;
 
  	@XmlElement
  	private Status status;
 
  	public Link getLink() {
  	  	return link;
  	}
 
  	public void setLink(Link link) {
  	  	this.link = link;
  	}
 
  	public Integer getId() {
  	  	return id;
  	}
 
  	public void setId(Integer id) {
  	  	this.id = id;
  	}
 
  	public String getContent() {
  	  	return content;
  	}
 
  	public void setContent(String content) {
  	  	this.content = content;
  	}
 
  	public Status getStatus() {
  	  	return status;
  	}
 
  	public void setStatus(Status status) {
  	  	this.status = status;
  	}
}

5.3. ๋ฉ”์‹œ์ง€ ๋ฆฌ์†Œ์Šค [๋ฆฌ์†Œ์Šค ํ‘œํ˜„์ด ํ•„์š”ํ•˜์ง€ ์•Š์„ ๋•Œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์•Œ๋ฆฌ๊ธฐ]

package net.restfulapi.app.rest.domain.common;
 
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlRootElement(name = "message")
public class Message {
 
  	public Message() {
  	  	super();
  	}
 
  	public Message(String content) {
  	  	super();
  	  	this.content = content;
  	}
 
  	private String content;
 
  	public String getContent() {
  	  	return content;
  	}
 
  	public void setContent(String content) {
  	  	this.content = content;
  	}
}

๋˜ํ•œ ConfigurationDB ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ DB ๊ธฐ๋Šฅ์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ํ–ˆ์Šต๋‹ˆ๋‹ค. Configuration๋ฆฌ์†Œ์Šค ์ปฌ๋ ‰์…˜๊ณผ ๊ฐœ๋ณ„ Configuration ๋ฆฌ์†Œ์Šค์—์„œ CRUD ์ž‘์—…์˜ ์ •์  ์œ ํ‹ธ๋ฆฌํ‹ฐ ๋ฉ”์„œ๋“œ๋ฅผ ๋…ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

package net.restfulapi.app.dao;
 
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
 
import net.restfulapi.app.rest.domain.Configuration;
import net.restfulapi.app.rest.domain.common.Status;
 
public class ConfigurationDB
{
  	private static Map<Integer, Configuration> configurationDB
  	  	= new ConcurrentHashMap<Integer, Configuration>();
  	private static AtomicInteger idCounter = new AtomicInteger();
 
  	public static Integer createConfiguration(String content, Status status){
  	  	Configuration c = new Configuration();
        	c.setId(idCounter.incrementAndGet());
        	c.setContent(content);
        	c.setStatus(status);
        	configurationDB.put(c.getId(), c);
  	  	return c.getId();
  	}
 
  	public static Configuration getConfiguration(Integer id){
  	  	return configurationDB.get(id);
  	}
 
  	public static List<Configuration> getAllConfigurations(){
  	  	return new ArrayList<Configuration>(configurationDB.values());
  	}
 
  	public static Configuration removeConfiguration(Integer id){
  	  	return configurationDB.remove(id);
  	}
 
  	public static Configuration updateConfiguration(Integer id, Configuration c){
  	  	return configurationDB.put(id, c);
  	}
}

6. REST ๋ฆฌ์†Œ์Šค ์ƒ์„ฑ

๋‘ ๋ฒˆ์งธ ์„น์…˜์—์„œ JAX-RS ์ฃผ์„์— ๋Œ€ํ•ด ์ด๋ฏธ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ REST ๋ฆฌ์†Œ์Šค์— ์ ์šฉํ•˜๊ณ  REST ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์ž‘์—…์— HTTP ๋ฉ”์„œ๋“œ๋ฅผ ๋งคํ•‘ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ ๋ฐฉ๋ฒ• ์œ„์— ๋”ฐ๋กœ ์„ค๋ช…์ด ํ•„์š” ์—†๋„๋ก ์ฝ”๋“œ ์ฃผ์„์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

package net.restfulapi.app.rest.service;
 
import java.util.List;
 
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Link;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
 
import net.restfulapi.app.dao.ConfigurationDB;
import net.restfulapi.app.rest.domain.Configuration;
import net.restfulapi.app.rest.domain.Configurations;
import net.restfulapi.app.rest.domain.common.Message;
import net.restfulapi.app.rest.domain.common.Status;
 
/**
* ์ด REST ๋ฆฌ์†Œ์Šค์—๋Š” ๊ณตํ†ต ๊ฒฝ๋กœ "/configurations"๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
* ๊ทธ๋ฆฌ๊ณ  ๊ตฌ์„ฑ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค์™€ ๊ฐœ๋ณ„ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
* ์ด ๋ฆฌ์†Œ์Šค์˜ ๊ธฐ๋ณธ MIME ์œ ํ˜•์€ "application/XML"์ž…๋‹ˆ๋‹ค.
* */
@Path("/configurations")
@Produces("application/xml")
public class ConfigurationResource
{
  	/**
  	* ์ด ๋‘ ๊ฐ€์ง€ ๊ธฐ๋ณธ ๊ตฌ์„ฑ์œผ๋กœ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.
  	* */
  	static {
  	  	ConfigurationDB.createConfiguration("Some Content", Status.ACTIVE);
  	  	ConfigurationDB.createConfiguration("Some More Content", Status.INACTIVE);
  	}
  	
  	/**
  	* uriInfo ๋ฅผ ์‚ฌ์šฉํ•ด ํ˜„์žฌ์˜ context pass๋ฅผ ์–ป๊ณ , HATEOAS ๋งํฌ๋ฅผ ๊ตฌ์ถ•ํ•œ๋‹ค
  	* */
  	@Context
  	UriInfo uriInfo;
 
  	/**
  	* ๊ฒฝ๋กœ "HTTP GET /configurations"์— ๋งคํ•‘๋œ ๊ตฌ์„ฑ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
  	* */
  	@GET
  	public Configurations getConfigurations() {
 
  	  	List<Configuration> list = ConfigurationDB.getAllConfigurations();
 
  	  	Configurations configurations = new Configurations();
        	configurations.setConfigurations(list);
        	configurations.setSize(list.size());
 
  	  	// ๊ธฐ๋ณธ ์ปฌ๋ ‰์…˜ ๋งํฌ ์„ค์ •
  	  	Link link = Link.fromUri(uriInfo.getPath()).rel("uri").build();
        	configurations.setLink(link);
 
  	  	// ๊ตฌ์„ฑ ํ•ญ๋ชฉ์— ๋งํฌ ์„ค์ •
  	  	for(Configuration c: list){
  	  	Link lnk = Link.fromUri(uriInfo.getPath() + "/" + c.getId()).rel("self").build();
        	c.setLink(lnk);
  	  	}
  	  	return configurations;
  	}
 
  	/**
  	* ๊ฒฝ๋กœ 'HTTP GET /configurations/{id}'์— ๋งคํ•‘๋œ ๊ฐœ๋ณ„ ๊ตฌ์„ฑ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
  	* */
  	@GET
  	@Path("/{id}")
  	public Response getConfigurationById(@PathParam("id") Integer id){
  	  	Configuration config = ConfigurationDB.getConfiguration(id);
 
  	  	if(config == null) {
        	  	return Response.status(javax.ws.rs.core.Response.Status.NOT_FOUND)
                    	  	.build();
  	  	}
 
  	  	if(config != null){
        	  	UriBuilder builder = UriBuilder.fromResource(ConfigurationResource.class)
                           	  	.path(ConfigurationResource.class, "getConfigurationById");
        	  	Link link = Link.fromUri(builder.build(id))
                    	  	.rel("self")
                    	  	.build();
              	config.setLink(link);
  	  	}
 
  	  	return Response.status(javax.ws.rs.core.Response.Status.OK)
              	  	.entity(config)
              	  	.build();
  	}
 
  	/**
  	* ๊ตฌ์„ฑ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค์— ์ƒˆ ๊ตฌ์„ฑ ๋ฆฌ์†Œ์Šค ๋งŒ๋“ค๊ธฐ
  	 */
  	@POST
  	@Consumes("application/xml")
  	public Response createConfiguration(Configuration config){
  	  	if(config.getContent() == null) {
        	  	return Response.status(javax.ws.rs.core.Response.Status.BAD_REQUEST)
                    	  	.entity(new Message("Config content not found"))
                    	  	.build();
  	  	}
 
  	  	Integer id = ConfigurationDB.createConfiguration(config.getContent(), config.getStatus());
  	  	Link lnk = Link.fromUri(uriInfo.getPath() + "/" + id).rel("self")
                    	  	.build();
  	  	return Response.status(javax.ws.rs.core.Response.Status.CREATED)
              	  	.location(lnk.getUri())
              	  	.build();
  	}
 
  	/**
  	* ๊ฒฝ๋กœ "/configurations/{id}"์˜ "id"์—์„œ ๊ธฐ์กด ๊ตฌ์„ฑ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.
  	* */
  	@PUT
  	@Path("/{id}")
  	@Consumes("application/xml")
  	public Response updateConfiguration(@PathParam("id") Integer id, Configuration config){
 
  	  	Configuration origConfig = ConfigurationDB.getConfiguration(id);
  	  	if(origConfig == null) {
        	  	return Response.status(javax.ws.rs.core.Response.Status.NOT_FOUND)
                    	  	.build();
  	  	}
 
  	  	if(config.getContent() == null) {
        	  	return Response.status(javax.ws.rs.core.Response.Status.BAD_REQUEST)
                    	  	.entity(new Message("Config content not found"))
                    	  	.build();
  	  	}
 
  	  	ConfigurationDB.updateConfiguration(id, config);
  	  	return Response.status(javax.ws.rs.core.Response.Status.OK)
                    	  	.entity(new Message("Config Updated Successfully"))
                    	  	.build();
  	}
 
  	/**
  	* ๊ฒฝ๋กœ "/configurations/{id}"์˜ "id"์—์„œ ๊ตฌ์„ฑ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.
  	* */
  	@DELETE
  	@Path("/{id}")
  	public Response deleteConfiguration(@PathParam("id") Integer id){
 
  	  	Configuration origConfig = ConfigurationDB.getConfiguration(id);
  	  	if(origConfig == null) {
        	  	return Response.status(javax.ws.rs.core.Response.Status.NOT_FOUND).build();
  	  	}
 
  	  	ConfigurationDB.removeConfiguration(id);
  	  	return Response.status(javax.ws.rs.core.Response.Status.OK).build();
  	}
}

7. ๋Ÿฐํƒ€์ž„์— ๋ฆฌ์†Œ์Šค ๋“ฑ๋ก

JAX-RS REST ๋ฆฌ์†Œ์Šค๋ฅผ ์„œ๋ฒ„ ๋Ÿฐํƒ€์ž„์— ๋“ฑ๋กํ•˜๋ ค๋ฉด javax.ws.rs.core.Applicationํด๋ž˜์Šค๋ฅผ ํ™•์žฅํ•˜๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํด๋ž˜์Šค ๊ฒฝ๋กœ์— ๋„ฃ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

package net.restfulapi.app.rest;
 
import java.util.HashSet;
import java.util.Set;
 
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
 
import net.restfulapi.app.rest.service.ConfigurationResource;
 
@ApplicationPath("/network-management")
public class NetworkApplication extends Application {
 
  	private Set<Object> singletons = new HashSet<Object>();
  	private Set<Class<?>> empty = new HashSet<Class<?>>();
 
  	public NetworkApplication() {
        	singletons.add(new ConfigurationResource());
  	}
 
  	@Override
  	public Set<Class<?>> getClasses() {
  	  	return empty;
  	}
 
  	@Override
  	public Set<Object> getSingletons() {
  	  	return singletons;
  	}
}

์—ฌ๊ธฐ @ApplicationPath์–ด๋…ธํ…Œ์ด์…˜์€ ์ด ํด๋ž˜์Šค๋ฅผ ์„œ๋ธ”๋ฆฟ 3.0 ์ปจํ…Œ์ด๋„ˆ์˜ ์ž๋™ ์Šค์บ” ํ”„๋กœ์„ธ์Šค์— ๋Œ€ํ•œ REST ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ์‹๋ณ„ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ REST ํŠน์ • ๊ตฌ์„ฑ์„ ์ „ํ˜€ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  web.xml ํŒŒ์ผ์„ ๊ฑฐ์˜ ๋น„์šฐ๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
  	  	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  	  	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  	<display-name>Archetype Created Web Application</display-name>
</web-app>

8. Demo

์ด ํ”„๋กœ์ ํŠธ๋ฅผ ๋นŒ๋“œํ•˜์—ฌ ์›น ์„œ๋ฒ„์— ๋ฐฐํฌํ•˜๊ณ  ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ ๋ธŒ๋ผ์šฐ์ € ํด๋ผ์ด์–ธํŠธ์—์„œ ์œ„์˜ URI๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ REST API๋ฅผ ํ…Œ์ŠคํŠธํ•˜์‹ญ์‹œ์˜ค.

  • HTTP GET

    http://localhost:8080/NetworkManagement/network-management/configurations

๊ตฌ์„ฑ ์ปฌ๋ ‰์…˜์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

HTTP GET - Configuration Collection Resource

HTTP GET

http://localhost:8080/NetworkManagement/network-management/configurations/1

๊ฐœ๋ณ„ ๊ตฌ์„ฑ์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

HTTP GET - Individual Configuration Resource

HTTP POST

http://localhost:8080/NetworkManagement/network-management/configurations

์ƒˆ ๊ตฌ์„ฑ ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

HTTP POST - Create New Resource

HTTP PUT

http://localhost:8080/NetworkManagement/network-management/configurations/1

๊ตฌ์„ฑ ๋ฆฌ์†Œ์Šค๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

HTTP PUT - Update Individual Configuration Resource

HTTP DELETE

http://localhost:8080/NetworkManagement/network-management/configurations/1

๊ตฌ์„ฑ ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.

HTTP DELETE - Individual Configuration Resource

์ฃผ์–ด์ง„ ๋‹ค์šด๋กœ๋“œ ๋งํฌ๋ฅผ ํด๋ฆญํ•˜์—ฌ ์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜์‹ญ์‹œ์˜ค.

์†Œ์Šค์ฝ”๋“œ ๋‹ค์šด๋กœ๋“œ

4๏ธโƒฃ FAQs

PUT vs POST

์ด๊ฒƒ์€ ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ์‹œ์Šคํ…œ์„ ์„ค๊ณ„ํ•  ๋•Œ HTTP PUT๊ณผ HTTP POST ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•˜๋Š” ๋ฐ ์–ด๋ ค์›Œ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ RFC 2616์€ ์ด ๋‘˜์„ ๋งค์šฐ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ตฌ๋ถ„ํ•˜์ง€๋งŒ, ๋ณต์žกํ•œ ํ‘œํ˜„ ๋•Œ๋ฌธ์— ํ—ท๊ฐˆ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

PUT ๋˜๋Š” POST ๋ฉ”์„œ๋“œ๋ฅผ ์–ธ์ œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€ ์•Œ์•„๋ด…์‹œ๋‹ค.

1. PUT ๊ณผ POST ์˜ ์ฐจ์ด

PUTPOST
RFC-2616์€ PUT method๊ฐ€ request body์— ์ฒจ๋ถ€๋œ entity๋ฅผRequest-URI๋ฅผ ํ˜ธ์ŠคํŒ…ํ•˜๋Š” ์„œ๋ฒ„์— ์ €์žฅ์„ ์š”๊ตฌํ•œ๋‹ค๊ณ  ๋ช…์‹œํ–ˆ์Šต๋‹ˆ๋‹ค.

Request-URI๊ฐ€ ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒฝ์šฐ ์—…๋ฐ์ดํŠธ ์ž‘์—…์ด ๋ฐœ์ƒํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ Request-URI๊ฐ€ ์œ ํšจํ•œ ๋ฆฌ์†Œ์Šค URI์ธ ๊ฒฝ์šฐ ์ƒ์„ฑ ์ž‘์—…์ด ๋ฐœ์ƒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฆฌ์†Œ์Šค ์‹๋ณ„์ž๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ–ˆ์„ ๋•Œ).

PUT /questions/{question-id}
์ด POST๋ฐฉ๋ฒ•์€ ์š”์ฒญ์— ์ฒจ๋ถ€๋œ ์—”ํ„ฐํ‹ฐ๋ฅผ Request-Line์˜ Request-URI์— ์˜ํ•ด ์‹๋ณ„๋œ ๋ฆฌ์†Œ์Šค์˜ ์ƒˆ ํ•˜์œ„ ํ•ญ๋ชฉ์œผ๋กœ ์›๋ณธ ์„œ๋ฒ„์— ์ˆ˜๋ฝํ•˜๋„๋ก ์š”์ฒญํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

์ด๋Š” ๋ณธ์งˆ์ ์œผ๋กœ POSTrequest-URI๊ฐ€ ์ปฌ๋ ‰์…˜ URI์—ฌ์•ผ ํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

POST /questions
PUT๋ฉ”์„œ๋“œ๋Š” ๋ฉฑ๋“ฑ์ˆ˜ ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์š”์ฒญ์„ ์—ฌ๋Ÿฌ ๋ฒˆ ์žฌ์‹œ๋„ํ•˜๋Š” ๊ฒฝ์šฐ ๋‹จ์ผ ์š”์ฒญ ํ˜ธ์ถœ๊ณผ ๋™์ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

*๋…ธํŠธ: ๋ฉฑ๋“ฑ์ˆ˜๋ž€?์—ฐ์‚ฐ์„ ์—ฌ๋Ÿฌ๋ฒˆ ์ ์šฉํ•˜๋”๋ผ๋„ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ฌ๋ผ์ง€์ง€ ์•Š๋Š” ์„ฑ์งˆ์„ ๋œปํ•ฉ๋‹ˆ๋‹ค.

๋„ค์ด๋ฒ„ ๋ฉ”์ธ ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ๊ณ ์นจ ์—ฌ๋Ÿฌ๋ฒˆ ํ•ด๋„ ๋˜‘๊ฐ™์€ ํ™”๋ฉด ๋‚˜์˜ค๋Š”๊ฒƒ๋„ ์ผ์ข…์˜ idempotent๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
POST๋ฉฑ ๋“ฑ์„ฑ์ด ์•„๋‹™๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์š”์ฒญ์„ N๋ฒˆ ์žฌ์‹œ๋„ํ•˜๋ฉด ์„œ๋ฒ„์— ์ƒ์„ฑ๋œ N๊ฐœ์˜ ์„œ๋กœ ๋‹ค๋ฅธ URI๊ฐ€ ์žˆ๋Š” N๊ฐœ์˜ ๋ฆฌ์†Œ์Šค๊ฐ€ ์ƒ๊น๋‹ˆ๋‹ค.
์ด๋ฏธ ๋ฆฌ์†Œ์Šค ์ปฌ๋ ‰์…˜์˜ ์ผ๋ถ€์ธ ๋ฆฌ์†Œ์Šค ํ•˜๋‚˜๋ฅผ ์ˆ˜์ •ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

PUT์€ ๋ฆฌ์†Œ์Šค ์ „์ฒด๋ฅผ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค. ๋ฆฌ์†Œ์Šค์˜ ์ผ๋ถ€๋ฅผ ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค๋ฉด PATCH๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๋ฆฌ์†Œ์Šค ์ปฌ๋ ‰์…˜ ์•„๋ž˜์— ์ž์‹ ๋ฆฌ์†Œ์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
PUT๋ฉฑ๋“ฑ์› ์ด์ง€๋งŒ ์‘๋‹ต์„ ์บ์‹œ ํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.์‘๋‹ต์— ์ ์ ˆํ•œ Cache-Control ๋˜๋Š” Expires ํ—ค๋” ํ•„๋“œ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฉด ์ด ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ์บ์‹œ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค .

๊ทธ๋Ÿฌ๋‚˜ 303(๊ธฐํƒ€ ์ฐธ์กฐ) ์‘๋‹ต์„ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์—์ด์ „ํŠธ๊ฐ€ ์บ์‹œ ๊ฐ€๋Šฅํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋„๋ก ์ง€์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ผ๋ฐ˜์ ์œผ๋กœ ํ˜„์—…์—์„œ๋Š”UPDATE ์ž‘์—…์— PUT์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.ํ•ญ์ƒ CREATE ์ž‘์—…์—๋Š” POST๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

2. PUT vs POST ์˜ˆ์ œ

๋„คํŠธ์›Œํฌ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์„ค๊ณ„ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. POST์™€ PUT์„ ์–ธ์ œ ์‚ฌ์šฉํ•˜๋Š”์ง€ ๋” ์ž˜ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ๋ช‡ ๊ฐ€์ง€ URI์™€ ๊ทธ ๋ชฉ์ ์„ ๋‚˜์—ดํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค

GET 	/device-management/devices       : ๋ชจ๋“  ์žฅ์น˜( device) ๊ฐ€์ ธ์˜ค๊ธฐ
POST 	/device-management/devices       : ์ƒˆ ์žฅ์น˜ ๋งŒ๋“ค๊ธฐ

GET 	/device-management/devices/{id}   : "id"๋กœ ์‹๋ณ„๋˜๋Š” ์žฅ์น˜ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
PUT 	/device-management/devices/{id}   : "id"๋กœ ์‹๋ณ„๋˜๋Š” ์žฅ์น˜ ์ •๋ณด๋ฅผ ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค.
DELETE	/device-management/devices/{id}   : โ€œidโ€๋กœ ์žฅ์น˜ ์‚ญ์ œ

๋‹ค๋ฅธ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•ด์„œ๋„ ์œ ์‚ฌํ•œ URI ๋””์ž์ธ ๋ฐฉ์‹์„ ๋”ฐ๋ฅด์„ธ์š”.

N+1 Problem

1. N+1 ๋ฌธ์ œ

N+1 ๋ฌธ์ œ๋Š” ๋Œ€๋ถ€๋ถ„ ORM์˜ ๋งฅ๋ฝ์—์„œ ๋…ผ์˜๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ๋ฌธ์ œ์—์„œ ์‹œ์Šคํ…œ์€ ๋ถ€๋ชจ ์—”ํ„ฐํ‹ฐ๋งŒ ์š”์ฒญํ•œ ํ•œ ๋ถ€๋ชจ ์—”ํ„ฐํ‹ฐ์˜ N๊ฐœ์˜ ์ž์‹์„ ๋กœ๋“œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ORM์€ ์ง€์—ฐ ๋กœ๋“œ๊ฐ€ ๋น„ํ™œ์„ฑํ™”๋œ ์ƒํƒœ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ์ƒ์œ„ ์—”ํ„ฐํ‹ฐ์— ๋Œ€ํ•ด ํ•˜๋‚˜์˜ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด N๊ฐœ์˜ ํ•˜์œ„ ์—”ํ„ฐํ‹ฐ์— ๋Œ€ํ•ด ๊ฐ๊ฐ ํ•˜๋‚˜์”ฉ N๊ฐœ์˜ ์ฟผ๋ฆฌ๊ฐ€ ์ถ”๊ฐ€๋กœ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์ด N+1 ๋ฌธ์ œ๋Š” ์ข…์ข… ์‹ฌ๊ฐํ•œ ์„ฑ๋Šฅ ๋ณ‘๋ชฉ ํ˜„์ƒ์œผ๋กœ ๊ฐ„์ฃผ๋˜๋ฏ€๋กœ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ์„ค๊ณ„ ์ˆ˜์ค€์—์„œ ํ•ด๊ฒฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

2. REST API์˜ N+1 ๋ฌธ์ œ

๋Œ€๋ถ€๋ถ„ ์ง์ ‘์ ์œผ๋กœ ๊ด€๋ จ๋˜์–ด ์žˆ์ง€๋งŒ N+1 ๋ฌธ์ œ๋Š” ORM์—๋งŒ ๊ตญํ•œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋Š” REST API์™€ ๊ฐ™์€ ์›น API์˜ ์ปจํ…์ŠคํŠธ์™€๋„ ๊ด€๋ จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Web API์˜ ๊ฒฝ์šฐ N+1 ๋ฌธ์ œ๋Š” ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํ•˜๋‚˜์˜ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค + N๊ฐœ์˜ ์ž์‹ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ์„œ๋ฒ„๋ฅผ N+1๋ฒˆ ํ˜ธ์ถœํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค.

์ด๋Š” ์ฃผ๋กœ ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ชจ๋‘ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ์ž์‹ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์ถฉ๋ถ„ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ์ฑ… ๋ชจ์Œ์„ ๋ฆฌ์†Œ์Šค๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” REST API๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

<books uri="/books" size="100">
	<book uri="/books/1" id="1">
		<isbn>3434253561</isbn>
	</book>
	<book uri="/books/2" id="2">
		<isbn>3423423534</isbn>
	</book>
	<book uri="/books/3" id="3">
		<isbn>5352342344</isbn>
	</book>
	...
	...
</books>

์—ฌ๊ธฐ /books๋ฆฌ์†Œ์Šค ๋ฐ˜ํ™˜ ๋ชฉ๋ก์—๋Š” ๊ทธ๊ฒƒ id๊ณผ ๋งŒ ํฌํ•จํ•˜๋Š” ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜์–ด isbn์žˆ์Šต๋‹ˆ๋‹ค.

name์ด ์ •๋ณด๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ISBN์ด ์•„๋‹Œ UI ๋กœ ์ฑ…์„ ํ‘œ์‹œํ•˜๋ ค๋Š” ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ UI๋ฅผ ๋นŒ๋“œํ•˜๋Š” ๋ฐ ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค .

๊ฒฝ์šฐ์— ๋”ฐ๋ผ ํด๋ผ์ด์–ธํŠธ๋Š” ์ €์ž ์ด๋ฆ„ ๋ฐ ๋ฐœํ–‰ ์—ฐ๋„์™€ ๊ฐ™์€ ๋‹ค๋ฅธ ์ •๋ณด๋„ ํ‘œ์‹œํ•˜๊ณ ์ž ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„์˜ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ /books/{id}์—์„œ ๊ฐ ๊ฐœ๋ณ„ ์ฑ… ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•ด N๋ฒˆ ๋” ๋งŽ์€ ์š”์ฒญ์„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ „์ฒด ํด๋ผ์ด์–ธํŠธ๋Š” REST API๋ฅผ N+1๋ฒˆ ํ˜ธ์ถœํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์œ„์˜ ์‹œ๋‚˜๋ฆฌ์˜ค๋Š” ์˜ˆ์‹œ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค์˜ ์ •๋ณด๊ฐ€ ๋ถ€์กฑํ•˜๋ฉด REST API์—์„œ N+1 ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์•„์ด๋””์–ด์ž…๋‹ˆ๋‹ค.

3. N+1 ๋ฌธ์ œ๋ฅผ ํ‘ธ๋Š” ๋ฐฉ๋ฒ•

์œ„์—์„œ ์ด์•ผ๊ธฐํ•œ ๋ฌธ์ œ์— ๋Œ€ํ•ด ์ข‹์€ ์ ์ด ์žˆ๋‹ค๋ฉด ๋ฌธ์ œ๊ฐ€ ์ •ํ™•ํžˆ ๋ฌด์—‡์ธ์ง€ ์•Œ๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ๋งค์šฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค ๋‚ด์˜ ๋‹จ์ผ ๋ฆฌ์†Œ์Šค์— ์ถฉ๋ถ„ํ•œ ์ •๋ณด๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

API ์†Œ๋น„์ž์™€ ์ƒ์˜ํ•˜๊ฑฐ๋‚˜, ์œ ์‚ฌํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐ ํ•ด๋‹น ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์— ๋Œ€ํ•œ ์‹œ์žฅ ์กฐ์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ฑฐ๋‚˜, ๋‹จ์ˆœํžˆ ๊ณ ๊ฐ ์ž…์žฅ์— ์„œ์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ํด๋ผ์ด์–ธํŠธ ์š”๊ตฌ ์‚ฌํ•ญ์— ๋Œ€ํ•œ ์ดํ•ด๊ฐ€ ํ–ฅ์ƒ๋จ์— ๋”ฐ๋ผ API๋ฅผ ์ ์ฐจ ๋ฐœ์ „์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ API ๋ฒ„์ „ ๊ด€๋ฆฌ ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค .

โ€˜qโ€™ Parameter

1. API ํด๋ผ์ด์–ธํŠธ๋Š” ์—ฌ๋Ÿฌ ํ˜•์‹์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

REST API๋Š” ๋ณด๋‹ค ๊ตฌ์ฒด์ ์ธ MIME ์œ ํ˜• ๊ณผ ๊ฐ™์€ ๋‹ค์–‘ํ•œ ํ˜•์‹์œผ๋กœ ๋ฆฌ์†Œ์Šค ํ‘œํ˜„์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋˜๋Š” ๋ธŒ๋ผ์šฐ์ €๋Š” HTTP Accept ํ—ค๋”์—์„œ ์ง€์›๋˜๋Š” ๋ชจ๋“  MIME ์œ ํ˜•์„ ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ์ˆ ์ ์œผ๋กœ Acceptํ—ค๋”๋Š” ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„๋œ ๊ฐ’ ํ˜•์‹(csv) ์œผ๋กœ ์—ฌ๋Ÿฌ ๊ฐ’์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋˜๋Š” ํ˜•์‹์„ Accept์š”์ฒญํ•˜๋Š” ํ—ค๋” ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

Accept : text/html,application/xml

2. โ€˜qโ€™ ๋งค๊ฐœ๋ณ€์ˆ˜

๋•Œ๋•Œ๋กœ ํด๋ผ์ด์–ธํŠธ๋Š” ์—ฌ๋Ÿฌ ์œ ํ˜•์˜ MIME์„ ์š”์ฒญํ•  ๋•Œ ๊ธฐ๋ณธ ์„ค์ •์„ ์ง€์ •ํ•˜๊ธฐ๋ฅผ ์›ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ธฐ๋ณธ ์„ค์ •์„ ์ง€์ •ํ•˜๊ธฐ ์œ„ํ•ด q๋งค๊ฐœ๋ณ€์ˆ˜( ์ƒ๋Œ€ ํ’ˆ์งˆ ๊ณ„์ˆ˜ )๊ฐ€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

๋งค๊ฐœ๋ณ€์ˆ˜ ์˜ ๊ฐ’์€ q๋Š” 0์—์„œ 1 ์‚ฌ์ด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค . 0์€ ๊ฐ€์žฅ ๋‚ฎ์€ ๊ฐ’(์ฆ‰, ๊ฐ€์žฅ ์„ ํ˜ธ๋„๊ฐ€ ๊ฐ€์žฅ ๋‚ฎ์Œ)์ด๊ณ  1์ด ๊ฐ€์žฅ ๋†’์€ ๊ฐ’(์ฆ‰, ๊ฐ€์žฅ ์„ ํ˜ธ๋จ)์ž…๋‹ˆ๋‹ค.

์ƒ˜ํ”Œ ์‚ฌ์šฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Accept : text/html, application/xml;q=0.9, */*;q=0.8

์œ„์˜ ์˜ˆ์—์„œ ํด๋ผ์ด์–ธํŠธ๋Š” ๋จผ์ € text/html ํ˜•์‹์˜ ์‘๋‹ต์„ ์„ ํ˜ธํ•  ๊ฒƒ์ž„์„ ์„œ๋ฒ„์— ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„๊ฐ€ ์š”์ฒญ๋œ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•ด text/html ํ˜•์‹์„ ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฉด ํ˜•์‹์„ ๋ณด๋‚ด์•ผ application/xmlํ•ฉ๋‹ˆ๋‹ค. ๋‘ ํ˜•์‹ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ ์ง€์›ํ•˜๋Š” ํ˜•์‹( */*)์œผ๋กœ ์‘๋‹ต์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค .

3. HTTP ์‚ฌ์–‘์— ๋”ฐ๋ฆ„

HTTP ์‚ฌ์–‘์—์„œ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ฐ ๋ฏธ๋””์–ด ๋ฒ”์œ„ ๋’ค์—๋Š” ์ƒ๋Œ€ ํ’ˆ์งˆ ์š”์†Œ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” โ€œqโ€ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์‹œ์ž‘ํ•˜๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ ์ˆ˜๋ฝ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ โ€œqโ€ ๋งค๊ฐœ๋ณ€์ˆ˜(๊ฐ€ ์žˆ๋‹ค๋ฉด)๋Š” media-range ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ accept-params์—์„œ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

ํ’ˆ์งˆ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์‚ฌ์šฉ์ž ๋˜๋Š” ์‚ฌ์šฉ์ž ์—์ด์ „ํŠธ๊ฐ€ 0์—์„œ 1 ์‚ฌ์ด์˜ โ€˜qโ€™ ๊ฐ’ ์ฒ™๋„๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๋‹น ๋ฏธ๋””์–ด ๋ฒ”์œ„์— ๋Œ€ํ•œ ์ƒ๋Œ€์  ์„ ํ˜ธ๋„๋ฅผ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ๊ฐ’์€ 1 ์ž…๋‹ˆ๋‹ค.

๋™์ผํ•œ q๊ฐ’์— ๋Œ€ํ•ด ๋‘ ๊ฐœ์˜ MIME ์œ ํ˜•์ด ์žˆ๋Š” ๊ฒฝ์šฐ ๋‘˜ ์ค‘ ๋” ๊ตฌ์ฒด์ ์ธ ์œ ํ˜•์ด ์šฐ์„ ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋‘˜ ๋‹ค application/xml๋ฐ /0.9์˜ ๊ธฐ๋ณธ ์„ค์ •์ด ์žˆ๋Š” application/xml๊ฒฝ์šฐ ์„œ๋ฒ„์—์„œ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

ํ—ค๋” ํ•„๋“œ๊ฐ€ ์—†์œผ๋ฉด Acceptํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ชจ๋“  ๋ฏธ๋””์–ด ์œ ํ˜•์„ ์ˆ˜๋ฝํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

ํ—ค๋” ํ•„๋“œ๊ฐ€ ์žˆ๊ณ  Accept์„œ๋ฒ„๊ฐ€ ๊ฒฐํ•ฉ๋œ ํ•„๋“œ ๊ฐ’์— ๋”ฐ๋ผ ์ˆ˜์šฉ ๊ฐ€๋Šฅํ•œ ์‘๋‹ต์„ ๋ณด๋‚ผ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ ์„œ๋ฒ„๋Š” 406 (not acceptable) ์‘๋‹ต์„ ๋ณด๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

5๏ธโƒฃ Resources

What is an API?

API(์ „์ฒด ํ˜•์‹์€ Application Programming Interface)๋Š” ๋‹ค๋ฅธ ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ๋น„์ฆˆ๋‹ˆ์Šค ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์ƒํ˜ธ ์ž‘์šฉํ•˜๊ธฐ๋ฅผ ์›ํ•  ๊ฒฝ์šฐ ์ค€์ˆ˜ํ•ด์•ผํ•˜๋Š” ์•ฝ์†ํ•œ ๊ณ„์•ฝ(๋˜๋Š” ์‚ฌ์–‘)์ž…๋‹ˆ๋‹ค.

API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‘ ๊ฐœ ์ด์ƒ์˜ ์†Œํ”„ํŠธ์›จ์–ด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ์ž˜ ์ •์˜๋œ ์ปดํ“จํŒ… ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ์„œ๋กœ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1. ์‹ค์ƒํ™œ์—์„œ์˜ API ์˜ˆ์‹œ

๋ชจ๋ฐ”์ผ ์•ฑ์€ API์˜ ๋งค์šฐ ์นœ์ˆ™ํ•œ ์˜ˆ ์ค‘ ํ•˜๋‚˜์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋ฐ”์ผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ชจ๋“  UI ๊ด€๋ จ ๋ถ€๋ถ„์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋ฐ”์ผ ์•ฑ์— ํ‘œ์‹œ๋˜๋Š” ๋ชจ๋“  ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ๋Š” API๋ฅผ ํ†ตํ•ด ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ๋ชจ๋“  ๋‚ ์”จ ์ •๋ณด, ์ด๋ฉ”์ผ, ๊ฒŒ์ž„ ์ ์ˆ˜, ๋ผ์ด๋ธŒ ๋ฐฉ์†ก ๋ฐ ๋” ๋งŽ์€ ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ๋Š” ์„œ๋ฒ„์— ๋ฐฐํฌ๋œ API์—์„œ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋งŽ์€ ์ตœ์‹  ์›น ์‚ฌ์ดํŠธ๋Š” AJAX, ์›น ์†Œ์ผ“ ๋“ฑ๊ณผ ๊ฐ™์€ ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฃผ๋ฌธํ˜• ๋ฐ์ดํ„ฐ(ํ•„์š”ํ•  ๋•Œ ์ •ํ™•ํžˆ ์„œ๋ฒ„์—์„œ ๊ฐ€์ ธ์˜ด)๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ์ƒํ˜ธ ์ž‘์šฉ์€ API๋ฅผ ํ†ตํ•ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๋˜ ๋‹ค๋ฅธ ์˜ˆ๋Š” ์†Œ์…œ ๊ณต์œ  ๋ฒ„ํŠผ์ž…๋‹ˆ๋‹ค. ํด๋ฆญํ•˜๋ฉด ์ž‘์—… ํ™•์ธ์„ ์œ„ํ•œ ํŒ์—…์ด ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

ํ™•์ธํ•˜๋ฉด ํ•ด๋‹น ๊ฒŒ์‹œ๋ฌผ์ด API๋ฅผ ํ†ตํ•ด ์„ ํƒํ•œ ์†Œ์…œ ๋ฏธ๋””์–ด ์›น์‚ฌ์ดํŠธ์™€ ๊ณต์œ ๋ฉ๋‹ˆ๋‹ค. ์†Œ์…œ ๊ณต์œ  ๋ฒ„ํŠผ์€ ํ•ด๋‹น ์›น์‚ฌ์ดํŠธ์—์„œ ์ œ๊ณตํ•˜๋Š” API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ธํ„ฐ๋„ท์˜ ๋ชจ๋“  URL์„ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.

2. API ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

ํŠน์ • ๋น„์ฆˆ๋‹ˆ์Šค ๋ชฉํ‘œ ๋˜๋Š” ์ž‘์—…์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด API๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์•Œ ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. API์™€ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๋งŒ ์•Œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๋ชจ๋“  ํ•ญ๊ณต๊ถŒ ์˜ˆ์•ฝ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ํ•ญ๊ณต์‚ฌ์—์„œ ๊ณต๊ฐœํ•œ API๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ณ ๊ฐ์ด ์ด๋Ÿฌํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‚ฌ์šฉํ•˜๊ณ  ํ•ญ๊ณต๊ถŒ์„ ์˜ˆ์•ฝํ•  ๋•Œ๋งˆ๋‹ค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์Šน๊ฐ ๋ฐ ํ•ญ๊ณตํŽธ ์˜ˆ์•ฝ ์ •๋ณด๋ฅผ API์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์•ฝ API๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ๊ณ ๊ฐ์„ ์œ„ํ•ด ํ‹ฐ์ผ“์„ ์˜ˆ์•ฝํ•˜๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์‘๋‹ต์œผ๋กœ ์˜ˆ์•ฝ ์„ธ๋ถ€ ์ •๋ณด์™€ ํ•จ๊ป˜ ์„ฑ๊ณต์ ์ธ ์‘๋‹ต์„ ๋ฐ›์Šต๋‹ˆ๋‹ค.

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

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ชจ๋“  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜/๋ชจ๋ฐ”์ผ ์•ฑ์€ API๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ API๋ฅผ ๋‹ค๋ฅธ ์†Œํ”„ํŠธ์›จ์–ด์— ๋…ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3. API์˜ ๋ชฉ์ ์€?

์†Œํ”„ํŠธ์›จ์–ด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์€ ์กฐ๊ฐ์œผ๋กœ ๊ฐœ๋ฐœ๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์œ„์น˜์—์„œ ์—ฌ๋Ÿฌ ๋ฒˆ ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ์ž‘์„ฑ๋ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋Š” API์™€ ๊ฐ™์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ๋‹ค๋ฅธ ๊ตฌ์„ฑ ์š”์†Œ ๋ฐ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์— ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

API๋Š” ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ํ‘œ์ค€, ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅ, ์‚ฌ์šฉ์ž๊ฐ€ ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ณ  ์ถ”์ƒํ™”ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. ์ถ”์ƒํ™”๋Š” ์ตœ์†Œํ•œ์˜ ๊ด€๋ จ ์ •๋ณด๋งŒ ๋‹ค๋ฅธ ์—”ํ„ฐํ‹ฐ์— ๋…ธ์ถœํ•˜๊ณ  ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋…ผ๋ฆฌ๋ฅผ ๋ณดํ˜ธํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ API๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋„์›€์ด ๋  ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๊ฐœ๋ฐœ์ž์˜ ์‚ถ๋„ ํŽธ์•ˆํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ •์˜๋œ API ๋ฒ”์œ„๋Š” ๊ตฌ์„ฑ ์š”์†Œ์˜ ์„ค๊ณ„, ํ…Œ์ŠคํŠธ, ๊ตฌ์ถ•, ๊ด€๋ฆฌ ๋ฐ ๋ฒ„์ „ ๊ด€๋ฆฌ์— ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

4. API ๊ฐœ๋ฐœ ๋ฐฉ๋ฒ•

4.1. API ์‚ฌ์–‘

์ด๋ฏธ ๋งํ–ˆ๋“ฏ์ด API๋Š” ๋‚ด๋ถ€ ์ž‘๋™ ๋ฐฉ์‹์„ ๋…ธ์ถœํ•˜์ง€ ์•Š๊ณ  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋…ธ์ถœํ•˜๋Š” ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ถ”์ƒ ๊ตฌ์„ฑ ์š”์†Œ์ž…๋‹ˆ๋‹ค. ์ด ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ€์žฅ ๋จผ์ € ํ•ด์•ผ ํ•  ์ผ์€ ํ‘œ์ค€์ ์ด๊ณ  ๊นจ๋—ํ•˜๋ฉฐ ์ž˜ ๋ฌธ์„œํ™”๋˜๊ณ  ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์šด API ์‚ฌ์–‘์ž…๋‹ˆ๋‹ค.

์‚ฌ์–‘์€ ๋‹ค์Œ์„ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ์ˆ˜ํ–‰ํ•  ๋งค์šฐ ๋ช…ํ™•ํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ์šด์˜
  • API URL ๋˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค
  • HTTP ํ”„๋กœํ† ์ฝœ ๋ฐ ๋ฉ”์„œ๋“œ
  • ์š”์ฒญ ๊ตฌ์กฐ ๋ฐ ๊ฐœ๋ณ„ ํ•„๋“œ
  • ์‘๋‹ต ๊ตฌ์กฐ ๋ฐ ๊ฐœ๋ณ„ ํ•„๋“œ
  • ํ•ด๋‹น๋˜๋Š” ๊ฒฝ์šฐ ์š”์ฒญ์˜ ํ•„๋“œ์— ์œ ํšจํ•œ ๊ฐ’
  • ๋ฐ์ดํ„ฐ ํŒŒ์ผ๋ง ๋ฐ ์ •๋ ฌ์„ ์œ„ํ•œ ๋ชจ๋“  ๋ฉ”์ปค๋‹ˆ์ฆ˜
  • ๋ชจ๋“  ์ธ์ฆ/๊ถŒํ•œ ์ •๋ณด
  • ๊ฐ€๋Šฅํ•œ ์„ฑ๊ณต ๋ฐ ์˜ค๋ฅ˜ ์ฝ”๋“œ
  • ๊ทธ๋ฆฌ๊ณ  ๊ธฐํƒ€ ๊ด€๋ จ ์ •๋ณด

4.2. API ๋ณด์•ˆ

์ •๋ณด๋Š” ๋ชจ๋“  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜, ํŠนํžˆ ์‚ฌ์šฉ์ž์˜ ๋น„๊ณต๊ฐœ ๊ฐœ์ธ ์ •๋ณด (NPI ๋ฐ์ดํ„ฐ) ์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค . ์ด ์ •๋ณด๋ฅผ ๋ณดํ˜ธํ•˜๊ธฐ ์œ„ํ•ด API๋Š” ๋ฌด๋‹จ ์•ก์„ธ์Šค๋กœ๋ถ€ํ„ฐ ๋ณดํ˜ธ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ณด์•ˆ ์ž๊ฒฉ ์ฆ๋ช…์ด ์žˆ๋Š” ์Šน์ธ๋œ ์‚ฌ์šฉ์ž๋งŒ API์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

4.3. ๊ฐ์‚ฌ ๋กœ๊น…

๊ณต๊ฐœ์ ์œผ๋กœ ๋…ธ์ถœ๋œ API๋Š” ๋งค์ผ ์ˆ˜์ฒœ ๋ช…์˜ ์‚ฌ์šฉ์ž๊ฐ€ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ API๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ๋‚จ์šฉํ•˜๋Š”์ง€ ์ดํ•ดํ•˜๋ ค๋ฉด API ์‚ฌ์šฉ๊ณผ ๊ด€๋ จ๋œ ์ค‘์š”ํ•œ ์ •๋ณด๋ฅผ ๊ธฐ๋กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

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

4.4. ์„ฑ๋Šฅ

API ์„ฑ๋Šฅ์€ ์ฒ˜์Œ๋ถ€ํ„ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๋ฐ ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„์—์„œ ์š”์ฒญ์ด ์ฒ˜๋ฆฌ๋˜๋Š” ๋™์•ˆ ์‚ฌ์šฉ์ž๋ฅผ ์ฐจ๋‹จํ•˜๋ ค๋Š” ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์€ ์—†์Šต๋‹ˆ๋‹ค. ํŠน์ • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋งŒ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์œ„์น˜๋ฅผ ์ฐจ๋‹จํ•  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋ฉ๋‹ˆ๋‹ค (์˜ˆ: ์†ก๊ธˆ ๋ฐ ์ฒญ๊ตฌ์„œ ์ง€๋ถˆ)

์„ฑ๋Šฅ์ด ์ข‹์ง€ ์•Š์€ API๋Š” ์†Œ๋น„์ž๊ฐ€ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋น„์ฆˆ๋‹ˆ์Šค์— ์†์‹ค์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

API ์„ค๊ณ„ ๋ฐ ๋ชจ๋ฒ” ์‚ฌ๋ก€์— ๋Œ€ํ•œ ๋‹น์‹ ์˜ ์ƒ๊ฐ์„ ์•Œ๋ ค์ฃผ์„ธ์š”.

SOAP vs REST

SOAP ( Simple Object Access Protocol )๋Š” XML๊ณผ ์Šคํ‚ค๋งˆ์— ํฌ๊ฒŒ ์˜์กด ํ•˜๋Š” ๋งค์šฐ ๊ฐ•๋ ฅํ•œ ํ˜•์‹์˜ ๋ฉ”์‹œ์ง• ํ”„๋ ˆ์ž„์›Œํฌ ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

REST ( REpresentational State Transfer )๋Š” ๊ธฐ์กด ๊ธฐ์ˆ ๊ณผ ๋„๋ฆฌ ์ฑ„ํƒ๋œ ๊ธฐ์ˆ , ํŠนํžˆ HTTP๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์ƒˆ๋กœ์šด ํ‘œ์ค€์„ ๋งŒ๋“ค์ง€ ์•Š๋Š” ์•„ํ‚คํ…์ฒ˜ ์Šคํƒ€์ผ ์ž…๋‹ˆ๋‹ค. REST๋Š” ๋ฐ์ดํ„ฐ๋ฅผ XML, YAML ๋˜๋Š” ๊ธฐํƒ€ ๊ธฐ๊ณ„ ํŒ๋… ๊ฐ€๋Šฅ ํ˜•์‹์œผ๋กœ ๊ตฌ์กฐํ™”ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ผ๋ฐ˜์ ์œผ๋กœ JSON์ด ์„ ํ˜ธ๋ฉ๋‹ˆ๋‹ค.

SOAP ๋ฐ REST โ€“ ๋‘˜ ๋‹ค SOA ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ์ถ•์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉํ•  ํ•ญ๋ชฉ์˜ ์„ ํƒ์€ ๋น„์ฆˆ๋‹ˆ์Šค ๋ฐ ์•„ํ‚คํ…์ฒ˜ ๊ด€์ ์—์„œ ์‹ค์ œ๋กœ ํ•„์š”ํ•œ ํ•ญ๋ชฉ์— ๋”ฐ๋ผ ํฌ๊ฒŒ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

ํŠน์ • ํ™˜๊ฒฝ์—์„œ์˜ ๊ฐ•์ ๊ณผ ์•ฝ์ ์„ ์‚ดํŽด๋ณด๊ณ  ์ž์‹ ์˜ ํ”„๋กœ์ ํŠธ ๋ฒ”์œ„๋ฅผ ์ดํ•ดํ•จ์œผ๋กœ์จ ๊ฐ€์žฅ ์ •๋ณด์— ์ž…๊ฐํ•œ ๊ฒฐ์ •์„ ๋‚ด๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

SOAP ๋ฐ REST API ๋น„๊ต

1. ๊ธฐ๋ณธ ํ”„๋กœํ† ์ฝœ

SOAP ์ž์ฒด๋Š” SOAP ๊ธฐ๋ฐ˜ API๋ฅผ ๊ฐœ๋ฐœํ•˜๊ธฐ ์œ„ํ•œ ํ”„๋กœํ† ์ฝœ(HTTP๋ฅผ ํ†ตํ•œ)์ž…๋‹ˆ๋‹ค.

REST๋Š” HTTP์™€ ๊ฑฐ์˜ ๋™์˜์–ด์ด์ง€๋งŒ REST ์‚ฌ์–‘์—์„œ๋Š” ์ด๋ฅผ ์š”๊ตฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

2. ๋ฐ์ดํ„ฐ ํ˜•์‹

SOAP๋Š” ๋ฉ”์‹œ์ง• ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ์ „์ ์œผ๋กœ XML์— ์˜์กดํ•˜๋ฉฐ, ์ผ๋ถ€ ๊ฒฝ์šฐ์—๋Š” ๋งค์šฐ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ: javascript๋ฅผ ํ†ตํ•ด ์›น ์„œ๋น„์Šค์— ์•ก์„ธ์Šค).

REST๋Š” CSV(์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„๋œ ๊ฐ’), JSON(JavaScript Object Notation) ๋ฐ RSS(Really Simple Syndication)์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์š”์ ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํ•„์š”ํ•œ ์–ธ์–ด ๋‚ด์—์„œ ๊ตฌ๋ฌธ ๋ถ„์„ํ•˜๊ธฐ ์‰ฌ์šด ํ˜•์‹์œผ๋กœ ํ•„์š”ํ•œ ์ถœ๋ ฅ์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

3. ์ƒํƒœ์œ ์ง€(Statefulness)

RESTful ์›น ์„œ๋น„์Šค๋Š” ์™„์ „ํžˆ ์ƒํƒœ ๋น„์ €์žฅ์ž…๋‹ˆ๋‹ค. ๋Œ€ํ™” ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ํด๋ผ์ด์–ธํŠธ ์ž์ฒด์˜ ์™„์ „ํ•œ ์ฑ…์ž„์ž…๋‹ˆ๋‹ค. ์„œ๋ฒ„๋Š” ์ด๊ฒƒ์„ ๋„์™€์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ SOAP ์›น ์„œ๋น„์Šค๋Š” ์ƒํƒœ ๋น„์ €์žฅ์ด์ง€๋งŒ ์„œ๋ฒ„์—์„œ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜์—ฌ SOAP API๋ฅผ ์ƒํƒœ ์ €์žฅ์œผ๋กœ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

4. ์บ์‹ฑ

REST๋Š” HTTP ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์šฐ์ˆ˜ํ•œ ์บ์‹ฑ ์ธํ”„๋ผ๋ฅผ ์ œ๊ณต GETํ•˜๋ฏ€๋กœ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์บ์‹œ ๊ฐ€๋Šฅ ๋˜๋Š” ์บ์‹œ ๋ถˆ๊ฐ€๋Šฅ์œผ๋กœ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ETag ํ—ค๋” ๋Š” ๊ฐ’์„ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋Š” ์ €๋ ดํ•œ ๋ฐฉ๋ฒ•์ด ์žˆ๋Š” ๊ฒฝ์šฐ ์บ์‹ฑ์„ ๊ตฌํ˜„ํ•˜๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

SOAP๋Š” HTTP๋ฅผ ์ „์†ก ๋ฉ”์ปค๋‹ˆ์ฆ˜์œผ๋กœ ์‚ฌ์šฉํ•  ๋•Œ HTTP POST ์š”์ฒญ์„ ํ†ตํ•ด ์ „์†ก๋ฉ๋‹ˆ๋‹ค. HTTP POST๋Š” ๋ฉฑ๋“ฑ์„ฑ์ด ์•„๋‹ˆ๋ฏ€๋กœ HTTP ์ˆ˜์ค€์—์„œ ์บ์‹œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ SOAP ์‘๋‹ต์€ Response Caching Optimization Module ์— ์ œ๊ณต๋œ ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์บ์‹œ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

5. HTTP ๋™์‚ฌ ์‚ฌ์šฉ

REST๋Š” ์ฃผ๋กœ HTTP๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ ๋˜๋ฉฐ ๋‹ค์–‘ํ•œ CRUD ์ž‘์—…์— ๋Œ€ํ•ด HTTP GET, POST, PUT, DELETE ๋ฐ PATCH ๋ฉ”์„œ๋“œ ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

SOAP๋Š” ๋˜ํ•œ HTTP ํ”„๋กœํ† ์ฝœ์— ๋Œ€ํ•œ ๋ฐ”์ธ๋”ฉ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. HTTP์— ๋ฐ”์ธ๋”ฉํ•  ๋•Œ ๋ชจ๋“  SOAP ์š”์ฒญ์€ HTTP POST๋ฅผ ํ†ตํ•ด ์ „์†ก๋ฉ๋‹ˆ๋‹ค.

6. ๋ณด์•ˆ

REST๋Š” HTTP๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. HTTP ์ž์ฒด๋Š” ๋งค์šฐ ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ํ”„๋กœํ† ์ฝœ์ž…๋‹ˆ๋‹ค. TLS๋ฅผ ํ†ตํ•œ ๊ธฐ๋ณธ ์ธ์ฆ ๋ฐ ํ†ต์‹  ์•”ํ˜ธํ™”๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ถ”๊ฐ€ ๋ณด์•ˆ์€ ์„œ๋ฒ„์—์„œ ์ถ”๊ฐ€๋กœ ๊ตฌํ˜„๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

SOAP ๋ณด์•ˆ์€ WS-SECURITY ๋ฅผ ํ†ตํ•ด ์ž˜ ํ‘œ์ค€ํ™” ๋˜์–ด ์žˆ์œผ๋ฉฐ, ์ด๋Š” ๊ธฐ๋Šฅ์ด ๋งค์šฐ ํ’๋ถ€ํ•˜๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ์— ๊ตฌํ˜„ํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.

7. ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ

๋ฆฌ์†Œ์Šค ์ƒ์„ฑ/์—…๋ฐ์ดํŠธ์— ์‹œ๊ฐ„์ด ๋งŽ์ด ์†Œ์š”๋˜๋Š” ๊ฒฝ์šฐ ๋น„๋™๊ธฐ์‹ ์š”์ฒญ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ REST๋Š” HTTP ์‘๋‹ต ์ฝ”๋“œ 202๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์ž‘์—… ์™„๋ฃŒ ์ƒํƒœ๊ฐ€ ์ž์ฃผ ์—…๋ฐ์ดํŠธ๋  ํ์˜ ์œ„์น˜๋ฅผ ๋ณด๋‚ผ ๊ฒƒ์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. REST๋Š” JAX-RS ์ž์ฒด ์—์„œ ๋น„๋™๊ธฐ API์— ๋Œ€ํ•œ ๊ฝค ์ข‹์€ ์ง€์›์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋ณด์žฅ๋œ ์ˆ˜์ค€์˜ ์•ˆ์ •์„ฑ๊ณผ ๋ณด์•ˆ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ SOAP 1.2๋Š” ์ด๋Ÿฌํ•œ ์œ ํ˜•์˜ ์ž‘์—…์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€ ํ‘œ์ค€์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. WSRM๊ณผ ๊ฐ™์€ ๊ฒƒ โ€“ WS-Reliable Messaging.

์š”์•ฝ

์ „๋ฐ˜์ ์œผ๋กœ REST๋Š” ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์›น์„ ํ™œ์šฉํ•˜๊ณ  ์ž์œ ๋„๊ฐ€ ์ œํ•œ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋ฐœํ•˜๊ธฐ๊ฐ€ ๋” ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค(์„ ํƒ ์‚ฌํ•ญ์ด ์ ์„์ˆ˜๋ก ๋” ๊ฐ„๋‹จํ•ด์ง).

SOAP๋Š” ๋ช‡ ๊ฐ€์ง€ ๋Œ€์•ˆ์„ ์ œ๊ณตํ•˜๋ฉฐ ๊ฐœ๋ฐœํ•˜๊ธฐ๊ฐ€ ์•ฝ๊ฐ„ ๋” ์–ด๋ ต์ง€๋งŒ ๋” ๋งŽ์€ ๋Œ€์•ˆ๊ณผ ์ž‘์—… ์˜์—ญ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

HTTP Methods

REST API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  CRUD(์ƒ์„ฑ, ๊ฒ€์ƒ‰, ์—…๋ฐ์ดํŠธ, ์‚ญ์ œ) ์ž‘์—…์ด ์žˆ๋Š” ๋ชจ๋“  ์ข…๋ฅ˜์˜ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

REST ์ง€์นจ ์€ ์„œ๋ฒ„์— ๋Œ€ํ•œ ํŠน์ • ์œ ํ˜•์˜ ํ˜ธ์ถœ์— ๋Œ€ํ•ด ํŠน์ • HTTP ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค(๊ธฐ์ˆ ์ ์œผ๋กœ ์ด ์ง€์นจ์„ ์œ„๋ฐ˜ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ถŒ์žฅํ•˜์ง€ ์•Š์Œ).

API๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์— ์ ํ•ฉํ•œ HTTP ๋ฉ”์†Œ๋“œ๋ฅผ ์ฐพ์œผ๋ ค๋ฉด ์•„๋ž˜ ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.

1. HTTP GET

GET ์š”์ฒญ ์„ ์‚ฌ์šฉ ํ•˜์—ฌ ๋ฆฌ์†Œ์Šค ํ‘œํ˜„/์ •๋ณด๋งŒ ๊ฒ€์ƒ‰ ํ•˜๊ณ  ์–ด๋–ค ์‹์œผ๋กœ๋“  ์ˆ˜์ •ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค. GET ์š”์ฒญ์€ ๋ฆฌ์†Œ์Šค์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์•ˆ์ „ํ•œ ๋ฐฉ๋ฒ• ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ GET API๋Š” ๋ฉฑ๋“ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋™์ผํ•œ ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•˜๋ฉด ๋‹ค๋ฅธ API(POST ๋˜๋Š” PUT)๊ฐ€ ์„œ๋ฒ„์˜ ๋ฆฌ์†Œ์Šค ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ๊นŒ์ง€ ๋งค๋ฒˆ ๋™์ผํ•œ ๊ฒฐ๊ณผ๊ฐ€ ์ƒ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Request-URI๊ฐ€ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น ํ…์ŠคํŠธ๊ฐ€ ํ”„๋กœ์„ธ์Šค์˜ ์ถœ๋ ฅ์ด ์•„๋‹Œ ํ•œ ํ”„๋กœ์„ธ์Šค์˜ ์†Œ์Šค ํ…์ŠคํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ ์‘๋‹ต์˜ ์—”ํ„ฐํ‹ฐ๋กœ ๋ฐ˜ํ™˜๋˜์–ด์•ผ ํ•˜๋Š” ์ƒ์„ฑ๋œ ๋ฐ์ดํ„ฐ์ž…๋‹ˆ๋‹ค.

1.1. GET API ์‘๋‹ต ์ฝ”๋“œ

  • ์ฃผ์–ด์ง„ HTTP GET API์˜ ๊ฒฝ์šฐ ์„œ๋ฒ„์—์„œ ๋ฆฌ์†Œ์Šค๊ฐ€ ๋ฐœ๊ฒฌ๋˜๋ฉด 200 (OK)์ผ๋ฐ˜์ ์œผ๋กœ XML ๋˜๋Š” JSON ์ฝ˜ํ…์ธ ์ธ ์‘๋‹ต ๋ณธ๋ฌธ๊ณผ ํ•จ๊ป˜ HTTP ์‘๋‹ต ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(ํ”Œ๋žซํผ ๋…๋ฆฝ์ ์ธ ํŠน์„ฑ์œผ๋กœ ์ธํ•ด).

  • ์„œ๋ฒ„์—์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ API๋Š” HTTP ์‘๋‹ต ์ฝ”๋“œ 404 (NOT FOUND)๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ GET ์š”์ฒญ ์ž์ฒด๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ตฌ์„ฑ๋˜์ง€ ์•Š์€ ๊ฒƒ์œผ๋กœ ํ™•์ธ๋˜๋ฉด ์„œ๋ฒ„๋Š” HTTP ์‘๋‹ต ์ฝ”๋“œ 400 (BAD REQUEST)๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค .

1.2. ์˜ˆ์‹œ URI

HTTP GET http://www.appdomain.com/users
HTTP GET http://www.appdomain.com/users?size=20&page=5
HTTP GET http://www.appdomain.com/users/123
HTTP GET http://www.appdomain.com/users/123/address

2. HTTP POST

POST API ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ ์ข…์† ๋ฆฌ์†Œ์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค . ์˜ˆ๋ฅผ ๋“ค์–ด ํŒŒ์ผ์ด ํ•ด๋‹น ํŒŒ์ผ์„ ํฌํ•จํ•˜๋Š” ๋””๋ ‰ํ† ๋ฆฌ์— ์ข…์†๋˜๊ฑฐ๋‚˜ ํ–‰์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์— ์ข…์†๋ฉ๋‹ˆ๋‹ค.

REST์— ๋Œ€ํ•ด ์—„๊ฒฉํ•˜๊ฒŒ ์ด์•ผ๊ธฐํ•  ๋•Œ POST ๋ฉ”์„œ๋“œ๋Š” ๋ฆฌ์†Œ์Šค ์ปฌ๋ ‰์…˜์— ์ƒˆ ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์‘๋‹ต์— ์ ์ ˆํ•œ Cache-Control ๋˜๋Š” Expires ํ—ค๋” ํ•„๋“œ ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฉด ์ด ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ์บ์‹œ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

POST๋Š” ์•ˆ์ „ํ•˜์ง€๋„ ๋ฉฑ๋“ฑ๋„ ์•„๋‹ˆ๋ฉฐ ๋‘ ๊ฐœ์˜ ๋™์ผํ•œ POST ์š”์ฒญ์„ ํ˜ธ์ถœํ•˜๋ฉด ๋™์ผํ•œ ์ •๋ณด(๋ฆฌ์†Œ์Šค ID ์ œ์™ธ)๋ฅผ ํฌํ•จํ•˜๋Š” ๋‘ ๊ฐœ์˜ ๋‹ค๋ฅธ ๋ฆฌ์†Œ์Šค๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

2.1. POST API ์‘๋‹ต ์ฝ”๋“œ

  • ์ด์ƒ์ ์œผ๋กœ๋Š” ๋ฆฌ์†Œ์Šค๊ฐ€ ์›๋ณธ ์„œ๋ฒ„์—์„œ ์ƒ์„ฑ๋œ ๊ฒฝ์šฐ ์‘๋‹ต์€ HTTP ์‘๋‹ต ์ฝ”๋“œ 201(Created) ์ด์–ด์•ผ ํ•˜๊ณ  ์š”์ฒญ ์ƒํƒœ๋ฅผ ์„ค๋ช…ํ•˜๊ณ  ์ƒˆ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐธ์กฐํ•˜๋Š” ์—”ํ„ฐํ‹ฐ์™€ Location ํ—ค๋”๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์—ฌ๋Ÿฌ ๋ฒˆ POST ๋ฉ”์„œ๋“œ๋กœ ์ˆ˜ํ–‰๋œ ์ž‘์—…์œผ๋กœ ์ธํ•ด URI๋กœ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฆฌ์†Œ์Šค๊ฐ€ ์ƒ์„ฑ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ HTTP ์‘๋‹ต ์ฝ”๋“œ 200 (OK)๋˜๋Š” 204 (No Content)์ ์ ˆํ•œ ์‘๋‹ต ์ƒํƒœ์ž…๋‹ˆ๋‹ค.

2.2. ์˜ˆ์‹œ URI

HTTP POST http://www.appdomain.com/users
HTTP POST http://www.appdomain.com/users/123/accounts

3. HTTP PUT

PUT API๋ฅผ ์ฃผ๋กœ ์‚ฌ์šฉ ํ•˜์—ฌ ๊ธฐ์กด ๋ฆฌ์†Œ์Šค๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค(๋ฆฌ์†Œ์Šค๊ฐ€ ์—†์œผ๋ฉด API์—์„œ ์ƒˆ ๋ฆฌ์†Œ์Šค ์ƒ์„ฑ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Œ).

์š”์ฒญ์ด ์บ์‹œ๋ฅผ ํ†ต๊ณผํ•˜๊ณ  Request-URI๊ฐ€ ํ•˜๋‚˜ ์ด์ƒ์˜ ํ˜„์žฌ ์บ์‹œ๋œ ์—”ํ„ฐํ‹ฐ๋ฅผ ์‹๋ณ„ํ•˜๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น ํ•ญ๋ชฉ์€ ์˜ค๋ž˜๋œ ๊ฒƒ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(SHOULD). PUT ๋ฉ”์†Œ๋“œ์— ๋Œ€ํ•œ ์‘๋‹ต์€ ์บ์‹œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

3.1. PUT API ์‘๋‹ต ์ฝ”๋“œ

  • PUT API์— ์˜ํ•ด ์ƒˆ ๋ฆฌ์†Œ์Šค๊ฐ€ ์ƒ์„ฑ๋œ ๊ฒฝ์šฐ ์›๋ณธ ์„œ๋ฒ„๋Š” HTTP ์‘๋‹ต ์ฝ”๋“œ 201 (Created) ์‘๋‹ต์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์—์ด์ „ํŠธ์— ์•Œ๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค .

  • ๊ธฐ์กด ์ž์›์ด ์ˆ˜์ •๋˜๋ฉด 200 (OK)๋˜๋Š” 204 (No Content) ์‘๋‹ต ์ฝ”๋“œ๋ฅผ ๋ณด๋‚ด์„œ ์š”์ฒญ์ด ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋˜์—ˆ์Œ์„ ๋‚˜ํƒ€๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

3.2. ์˜ˆ์‹œ URI

HTTP PUT http://www.appdomain.com/users/123
HTTP PUT http://www.appdomain.com/users/123/accounts/456

POST API์™€ PUT API ์˜ ์ฐจ์ด์ ์€ ์š”์ฒญ URI์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. POST ์š”์ฒญ์€ ๋ฆฌ์†Œ์Šค ์ปฌ๋ ‰์…˜์— ๋Œ€ํ•ด ์ˆ˜ํ–‰๋˜๋Š” ๋ฐ˜๋ฉด PUT ์š”์ฒญ์€ ๋‹จ์ผ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•ด ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.

4. HTTP ์‚ญ์ œ

์ด๋ฆ„์ด ์ ์šฉ๋˜๋ฉด DELETE API ๋Š” ๋ฆฌ์†Œ์Šค (Request-URI๋กœ ์‹๋ณ„๋จ)๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

DELETE ์ž‘์—…์€ ๋ฉฑ๋“ฑ์› ์ž…๋‹ˆ๋‹ค. ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ญ์ œํ•˜๋ฉด ๋ฆฌ์†Œ์Šค ์ปฌ๋ ‰์…˜์—์„œ ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค.

์–ด๋–ค ์‚ฌ๋žŒ๋“ค์€ DELETE ๋ฉ”์†Œ๋“œ๋ฅผ ๋ฉฑ๋“ฑ์„ฑ์ด ์•„๋‹Œ ๊ฒƒ์œผ๋กœ ๋งŒ๋“ ๋‹ค๊ณ  ์ฃผ์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ํ† ๋ก ๊ณผ ๊ฐœ์ธ์ ์ธ ์˜๊ฒฌ์˜ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

์š”์ฒญ์ด ์บ์‹œ๋ฅผ ํ†ต๊ณผํ•˜๊ณ  Request-URI๊ฐ€ ํ•˜๋‚˜ ์ด์ƒ์˜ ํ˜„์žฌ ์บ์‹œ๋œ ์—”ํ„ฐํ‹ฐ๋ฅผ ์‹๋ณ„ํ•˜๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น ํ•ญ๋ชฉ์€ ์˜ค๋ž˜๋œ ๊ฒƒ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์‘๋‹ต์€ ์บ์‹œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

4.1. DELETE API ์‘๋‹ต ์ฝ”๋“œ

  • DELETE ์š”์ฒญ์˜ ์„ฑ๊ณต์ ์ธ ์‘๋‹ต์€ ์‘๋‹ต์— ์ƒํƒœ๋ฅผ ์„ค๋ช…ํ•˜๋Š” ์—”ํ„ฐํ‹ฐ๊ฐ€ ํฌํ•จ๋œ ๊ฒฝ์šฐ HTTP ์‘๋‹ต code 200 (OK)์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ์ž‘์—…์ด ๋Œ€๊ธฐ์—ด์— ์žˆ๋Š” ๊ฒฝ์šฐ 202 (Accepted)์ƒํƒœ๊ฐ€ ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์ƒํƒœ๋Š” ์ž‘์—…์ด ์ˆ˜ํ–‰๋˜์—ˆ์ง€๋งŒ ์‘๋‹ต์— ์—”ํ„ฐํ‹ฐ๊ฐ€ ํฌํ•จ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ 204 (No Content)์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ๋ฆฌ์†Œ์Šค์—์„œ DELETE API๋ฅผ ๋ฐ˜๋ณต์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋ฉด ๊ฒฐ๊ณผ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  • ๊ทธ๋Ÿฌ๋‚˜ ๋ฆฌ์†Œ์Šค์—์„œ DELETE๋ฅผ ๋‘ ๋ฒˆ์งธ ํ˜ธ์ถœํ•˜๋ฉด ์ด๋ฏธ ์ œ๊ฑฐ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— 404(NOT FOUND)๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

4.2. ์˜ˆ์‹œ

HTTP DELETE http://www.appdomain.com/users/123
HTTP DELETE http://www.appdomain.com/users/123/accounts/456

5. HTTP ํŒจ์น˜

HTTP PATCH ์š”์ฒญ์€ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ถ€๋ถ„์ ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ ์ž…๋‹ˆ๋‹ค.

PUT ์š”์ฒญ์ด ํ‘œ์‹œ๋˜๋ฉด ๋ฆฌ์†Œ์Šค ์—”ํ„ฐํ‹ฐ๋„ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ข€ ๋” ์ •ํ™•ํ•˜๊ฒŒ ํ•˜์ž๋ฉด PATCH ๋ฐฉ๋ฒ•์€ ๊ธฐ์กด ๋ฆฌ์†Œ์Šค๋ฅผ ๋ถ€๋ถ„์ ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜๋Š” ์˜ฌ๋ฐ”๋ฅธ ์„ ํƒ์ด๋ฉฐ ๋ฆฌ์†Œ์Šค ์ „์ฒด๋ฅผ ๊ต์ฒดํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ PUT์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ PATCH API๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ•œ ๊ฒฝ์šฐ ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Œ์„ ์œ ์˜ํ•˜์‹ญ์‹œ์˜ค.

๋ธŒ๋ผ์šฐ์ €, ์„œ๋ฒ„ ๋ฐ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ PATCH์— ๋Œ€ํ•œ ์ง€์›์€ ๋ณดํŽธ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. IE8, PHP, Tomcat, Django ๋ฐ ๊ธฐํƒ€ ๋งŽ์€ ์†Œํ”„ํŠธ์›จ์–ด์— ๋Œ€ํ•œ ์ง€์›์ด ๋ˆ„๋ฝ๋˜์—ˆ๊ฑฐ๋‚˜ ์ค‘๋‹จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

PATCH ์š”์ฒญ์˜ ์š”์ฒญ ํŽ˜์ด๋กœ๋“œ๋Š” PUT ์š”์ฒญ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๊ฐ„๋‹จํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ

HTTP GET /users/1

์•„๋ž˜ ์‘๋‹ต์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

{ "id": 1, "username": "admin", "email": "email@example.org"}

์ด๋ฉ”์ผ ์—…๋ฐ์ดํŠธ๋ฅผ ์œ„ํ•œ ์ƒ˜ํ”Œ ํŒจ์น˜ ์š”์ฒญ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

HTTP PATCH /users/1
[{ "op": "replace", "path": "/email", "value": "new.email@example.org" }]

HTTP ์‚ฌ์–‘์— ๋”ฐ๋ผ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐ€๋Šฅํ•œ ์ž‘์—…์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

[
 { "op": "test",  "path": "/a/b/c",  "value": "foo"  },
 { "op": "remove",  "path": "/a/b/c"  },
 { "op": "add",  "path": "/a/b/c",  "value": [ "foo", "bar" ] },
 { "op": "replace", "path": "/a/b/c",  "value": 42 },
 { "op": "move",  "from": "/a/b/c",  "path": "/a/b/d" },
 { "op": "copy", "from": "/a/b/d",  "path": "/a/b/e" }
 ]

PATCH ๋ฐฉ๋ฒ•์€ POST ๋˜๋Š” PUT ๋ฐฉ๋ฒ•์„ ๋Œ€์ฒดํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ „์ฒด ๋ฆฌ์†Œ์Šค๋ฅผ ๊ต์ฒดํ•˜๋Š” ๋Œ€์‹  ๋ธํƒ€(diff)๋ฅผ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.

6. HTTP ๋ฉ”์†Œ๋“œ ์š”์•ฝ

์•„๋ž˜ ํ‘œ๋Š” ์œ„์—์„œ ๋…ผ์˜ํ•œ HTTP ๋ฉ”์†Œ๋“œ์˜ ์‚ฌ์šฉ์„ ์š”์•ฝํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

HTTP ๋ฉ”์†Œ๋“œCRUD์ปฌ๋ ‰์…˜ ๋ฆฌ์†Œ์Šค(์˜ˆ: /users)๋‹จ์ผ ๋ฆฌ์†Œ์Šค(์˜ˆ: /users/123)
POST๋งŒ๋“ค๋‹ค201(Created), ์ƒˆ ID๋ฅผ ํฌํ•จํ•˜๋Š” /users/{id}์— ๋Œ€ํ•œ ๋งํฌ๊ฐ€ ์žˆ๋Š” โ€˜์œ„์น˜โ€™ ํ—ค๋”๋‹จ์ผ ๋ฆฌ์†Œ์Šค์—์„œ POST๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.
GET์ฝ๋‹ค200(OK), ์‚ฌ์šฉ์ž ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค. ํŽ˜์ด์ง€ ๋งค๊น€, ์ •๋ ฌ ๋ฐ ํ•„ํ„ฐ๋ง์„ ์‚ฌ์šฉํ•˜์—ฌ ํฐ ๋ชฉ๋ก ํƒ์ƒ‰200(OK), ๋‹จ์ผ ์‚ฌ์šฉ์ž. 404(์ฐพ์„ ์ˆ˜ ์—†์Œ), ID๊ฐ€ ์—†๊ฑฐ๋‚˜ ์œ ํšจํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ
PUT์—…๋ฐ์ดํŠธ/๊ต์ฒด405(Method not allowed), ์ „์ฒด ๋ฆฌ์†Œ์Šค ์ปฌ๋ ‰์…˜์˜ ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๋ฅผ ์—…๋ฐ์ดํŠธํ•˜์ง€ ์•Š์œผ๋ ค๋Š” ๊ฒฝ์šฐ200(Ok) ๋˜๋Š” 204(No Content). ID๊ฐ€ ์—†๊ฑฐ๋‚˜ ์œ ํšจํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ 404(Not Founded) ์‚ฌ์šฉ
PATCH๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ/์ˆ˜์ •405(Method not allowed), ์ปฌ๋ ‰์…˜ ์ž์ฒด๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š์œผ๋ ค๋Š” ๊ฒฝ์šฐ200(Ok) ๋˜๋Š” 204(No Content). ID๊ฐ€ ์—†๊ฑฐ๋‚˜ ์œ ํšจํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ 404(Not Founded) ์‚ฌ์šฉ
DELETE์‚ญ์ œ405(Method not allowed), ์ „์ฒด ์ปฌ๋ ‰์…˜์„ ์‚ญ์ œํ•˜์ง€ ์•Š์œผ๋ ค๋Š” ๊ฒฝ์šฐ โ€” ์ฃผ์˜ํ•ด์„œ ์‚ฌ์šฉ200(Ok) ๋˜๋Š” 404(Not Founded) ID๊ฐ€ ์—†๊ฑฐ๋‚˜ ์œ ํšจํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ

7. ์šฉ์–ด์ง‘

7.1. ์•ˆ์ „ํ•œ ๋ฐฉ๋ฒ•

์ •์˜๋œ ์˜๋ฏธ ์ฒด๊ณ„๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ฝ๊ธฐ ์ „์šฉ์ธ ๊ฒฝ์šฐ ์š”์ฒญ ๋ฉ”์„œ๋“œ๋Š” ์•ˆ์ „ํ•œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” ๋Œ€์ƒ ๋ฆฌ์†Œ์Šค์— ์•ˆ์ „ํ•œ ๋ฐฉ๋ฒ•์„ ์ ์šฉํ•œ ๊ฒฐ๊ณผ ์›๋ณธ ์„œ๋ฒ„์˜ ์ƒํƒœ ๋ณ€๊ฒฝ์„ ์š”์ฒญํ•˜์ง€ ์•Š์œผ๋ฉฐ ์˜ˆ์ƒํ•˜์ง€๋„ ์•Š์Šต๋‹ˆ๋‹ค.

GET, HEAD, OPTIONS ๋ฐ TRACE ๋ฉ”์„œ๋“œ๋Š” ์•ˆ์ „ํ•œ ๋ฉ”์„œ๋“œ๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค . HTTP ์‚ฌ์–‘์— ๋”ฐ๋ผ GET ๋ฐ HEAD ๋ฉ”์„œ๋“œ๋Š” ๋ฆฌ์†Œ์Šค ํ‘œ์‹œ ๊ฒ€์ƒ‰์—๋งŒ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋ฉฐ ์„œ๋ฒ„์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์—…๋ฐ์ดํŠธ/์‚ญ์ œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.์•ˆ์ „ํ•œ ๋ฐฉ๋ฒ•๊ณผ ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ๋ฐฉ๋ฒ•์„ ๊ตฌ๋ถ„ ํ•˜๋Š” ๋ชฉ์ ์€ ์ž๋™ํ™”๋œ ๊ฒ€์ƒ‰ ํ”„๋กœ์„ธ์Šค(์ŠคํŒŒ์ด๋”)์™€ ์บ์‹œ ์„ฑ๋Šฅ ์ตœ์ ํ™”(ํ”„๋ฆฌํŽ˜์นญ)๊ฐ€ ํ”ผํ•ด๋ฅผ ์ž…์„ ์—ผ๋ ค ์—†์ด ์ž‘๋™ํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์•ˆ์ „ํ•œ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ์‚ฌ์šฉ์ž ์—์ด์ „ํŠธ๊ฐ€ POST, PUT ๋ฐ DELETE ์™€ ๊ฐ™์€ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ๊ณ ์œ ํ•œ ๋ฐฉ์‹์œผ๋กœ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ์•ˆ์ „ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋Š” ์ž‘์—…์ด ์š”์ฒญ๋˜๊ณ  ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋ฆฌ์†Œ์Šค๋ฅผ ์—…๋ฐ์ดํŠธ/์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„ ๋“ฑ์„ ์ฃผ์˜ํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

7.2. ๋ฉฑ๋“ฑ์ˆ˜ ๋ฉ”์„œ๋“œ

๋ฉฑ๋“ฑ์„ฑ์ด๋ผ๋Š” ์šฉ์–ด๋Š” ํ•œ ๋ฒˆ ๋˜๋Š” ์—ฌ๋Ÿฌ ๋ฒˆ ์‹คํ–‰๋˜๋Š” ๊ฒฝ์šฐ ๋™์ผํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ž‘์—… ์„ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด ๋ณด๋‹ค ํฌ๊ด„์ ์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

HTTP ์‚ฌ์–‘์—์„œ PUT, DELETE ๋ฐ ์•ˆ์ „ํ•œ ๋ฉ”์„œ๋“œ( GET, HEAD, OPTIONS, TRACE )๋Š” ๋ฉฑ๋“ฑ ๋ฉ”์„œ๋“œ ์ž…๋‹ˆ๋‹ค.๋ฉฑ๋“ฑ์€ ์˜๋„ํ•˜์ง€ ์•Š์€ ํšจ๊ณผ๋ฅผ ์ผ์œผํ‚ค์ง€ ์•Š๊ณ  ํ•„์š”ํ•œ ๋งŒํผ ์ž์ฃผ ์ž‘์—…์„ ๋ฐ˜๋ณตํ•˜๊ฑฐ๋‚˜ ์žฌ์‹œ๋„ํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•˜๋ฏ€๋กœ ๋งŽ์€ ์ƒํ™ฉ์—์„œ ํŽธ๋ฆฌํ•œ ์†์„ฑ์ž…๋‹ˆ๋‹ค.

๋ฉฑ๋“ฑ์„ฑ์ด ์—†๋Š” ์ž‘์—…์˜ ๊ฒฝ์šฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์ž‘์—…์ด ์ด๋ฏธ ์ˆ˜ํ–‰๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ์ถ”์ ํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.์•ˆ์ „ํ•œ ๋ฉ”์„œ๋“œ ์˜ ์ •์˜์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ฉฑ๋“ฑ ์†์„ฑ์€ ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญํ•œ ๊ฒฝ์šฐ์—๋งŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„๋Š” ๊ฐ ์š”์ฒญ์„ ๊ฐœ๋ณ„์ ์œผ๋กœ ๊ธฐ๋กํ•˜๊ฑฐ๋‚˜ ๊ฐœ์ • ์ œ์–ด ๊ธฐ๋ก์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Richardson Maturity Model

1. Richardson Maturity Model ์ด๋ž€?

Leonard Richardson์€ 100๊ฐ€์ง€ ๋‹ค๋ฅธ ์›น ์„œ๋น„์Šค ๋””์ž์ธ์„ ๋ถ„์„ํ•˜๊ณ  ์ด๋Ÿฌํ•œ ๋””์ž์ธ์„ 4๊ฐ€์ง€ ๋ฒ”์ฃผ๋กœ ๋‚˜๋ˆ„์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฒ”์ฃผ๋Š” ์›น ์„œ๋น„์Šค๊ฐ€ ์–ผ๋งˆ๋‚˜ REST๋ฅผ ์ค€์ˆ˜ํ•˜๋Š”์ง€ ์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

REST ์„œ๋น„์Šค์˜ ์ด ๋ถ„ํ•  ๋ชจ๋ธ์€ ์„ฑ์ˆ™๋„ ์ˆ˜์ค€์„ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•ด Richardson Maturity Model ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

image-20221115144522324

Richardson ์€ ์„œ๋น„์Šค์˜ ์„ฑ์ˆ™๋„๋ฅผ ๊ฒฐ์ •ํ•˜๊ธฐ ์œ„ํ•ด ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ์š”์†Œ๋ฅผ ์‚ฌ์šฉ ํ–ˆ์Šต๋‹ˆ๋‹ค.

  1. URI
  2. HTTP ๋ฉ”์†Œ๋“œ
  3. HATEOAS(ํ•˜์ดํผ๋ฏธ๋””์–ด)

์„œ๋น„์Šค๊ฐ€ ์ด๋Ÿฌํ•œ ์š”์†Œ๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ• ์ˆ˜๋ก ๋” ์„ฑ์ˆ™ํ•œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค.

2. ์„ฑ์ˆ™๋„

๊ทธ์˜ ๋ถ„์„์—์„œ Richardson์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ด 4๊ฐœ์˜ ์„ฑ์ˆ™๋„ ์ˆ˜์ค€์„ ์„ค๋ช…ํ–ˆ์Šต๋‹ˆ๋‹ค.

Richardson Maturity Model

2.1. Level Zero

์„ฑ์ˆ™๋„ ๋ ˆ๋ฒจ 0์€ URI, HTTP ๋ฉ”์†Œ๋“œ ๋ฐ HATEOAS ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์„ฑ์ˆ™๋„๊ฐ€ 0์ธ ์„œ๋น„์Šค๋Š” ๋‹จ์ผ URI๋ฅผ ๊ฐ€์ง€๋ฉฐ ๋‹จ์ผ HTTP ๋ฉ”์†Œ๋“œ(์ผ๋ฐ˜์ ์œผ๋กœ POST)๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๋Œ€๋ถ€๋ถ„์˜ SOAP ์›น ์„œ๋น„์Šค๋Š” ๋‹จ์ผ URI๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋์ ์„ ์‹๋ณ„ํ•˜๊ณ  HTTP POST๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ SOAP ๊ธฐ๋ฐ˜ ํŽ˜์ด๋กœ๋“œ๋ฅผ ์ „์†กํ•˜์—ฌ ๋‚˜๋จธ์ง€ HTTP ๋™์‚ฌ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค.

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ XML-RPC ๊ธฐ๋ฐ˜ ์„œ๋น„์Šค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ POX( Plain Old XML )๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋‹จ์ผ POST ๋ฉ”์„œ๋“œ ๋์ ์œผ๋กœ SOA ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ๊ตฌ์ถ•ํ•˜๊ณ  XML์„ ์‚ฌ์šฉํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„์— ํ†ต์‹ ํ•˜๋Š” ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

2.2. Level One

์„ฑ์ˆ™๋„ 1๋‹จ๊ณ„ ๋Š” URI ๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ HTTP ๋ฉ”์†Œ๋“œ ๋ฐ HATEOAS๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์„ฑ์ˆ™๋„ ์ˆ˜์ค€ 1์˜ ์„œ๋น„์Šค๋Š” ๋งŽ์€ URI๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋‹จ์ผ HTTP ๋™์‚ฌ(์ผ๋ฐ˜์ ์œผ๋กœ HTTP POST)๋งŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์„œ๋น„์Šค๋Š” ์‹œ์Šคํ…œ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ฐ ๋ฆฌ์†Œ์Šค์— ๊ณ ์œ ํ•œ URI๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ณ ์œ ํ•œ URI๋Š” ํ•˜๋‚˜์˜ ๊ณ ์œ ํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐœ๋ณ„์ ์œผ๋กœ ์‹๋ณ„ํ•˜๋ฏ€๋กœ ์ด๋Ÿฌํ•œ ์„œ๋น„์Šค๊ฐ€ ์ˆ˜์ค€ 0๋ณด๋‹ค ์šฐ์ˆ˜ํ•ฉ๋‹ˆ๋‹ค.

2.3. Level Two

๋ ˆ๋ฒจ 2๋Š” URI์™€ HTTP ๋ฉ”์†Œ๋“œ ๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ HATEOAS๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ ˆ๋ฒจ 2 ์„œ๋น„์Šค๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ฃผ์†Œ ์ง€์ • ๊ฐ€๋Šฅํ•œ ๋ฆฌ์†Œ์Šค์™€ ๊ฐ™์€ ์ˆ˜๋งŽ์€ URI๋ฅผ ํ˜ธ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์„œ๋น„์Šค๋Š” ๋…ธ์ถœ๋œ ๊ฐ ๋ฆฌ์†Œ์Šค์—์„œ CRUD(Create, Read, Update ๋ฐ Delete) ์„œ๋น„์Šค์™€ ๊ฐ™์€ ์—ฌ๋Ÿฌ HTTP ๋™์‚ฌ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ ์ผ๋ฐ˜์ ์œผ๋กœ ๋น„์ฆˆ๋‹ˆ์Šค ์—”ํ„ฐํ‹ฐ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฆฌ์†Œ์Šค ์ƒํƒœ๋Š” ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ ˆ๋ฒจ 2 ์„œ๋น„์Šค์˜ ๋””์ž์ด๋„ˆ๋Š” ์‚ฌ๋žŒ๋“ค์ด ์ผ๋ฐ˜์ ์œผ๋กœ ์ œ๊ณต๋œ ๋ฌธ์„œ๋ฅผ ์ฝ๊ณ  API๋ฅผ ๋งˆ์Šคํ„ฐํ•˜๋Š” ๋ฐ ์–ด๋Š ์ •๋„ ๋…ธ๋ ฅ์„ ๊ธฐ์šธ์ผ ๊ฒƒ์œผ๋กœ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค.

์„ฑ์ˆ™๋„ ์ˆ˜์ค€ 2๋Š” REST ์›์น™์˜ ๊ฐ€์žฅ ์ธ๊ธฐ ์žˆ๋Š” ์‚ฌ์šฉ ์‚ฌ๋ก€๋กœ, HTTP ์š”์ฒญ ๋ฐฉ๋ฒ•์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋‹ค๋ฅธ ๋™์‚ฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์ง€์ง€ํ•˜๋Š” ๋ฐ˜๋ฉด ์‹œ์Šคํ…œ์—๋Š” ์—ฌ๋Ÿฌ ๋ฆฌ์†Œ์Šค๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2.4. Level Three

์„ฑ์ˆ™๋„ 3๋‹จ๊ณ„๋Š” URI์™€ HTTP, HATEOAS 3๊ฐ€์ง€ ๋ชจ๋‘๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋ ˆ๋ฒจ 3์€ ๋ฆฌ์ฒ˜๋“œ์Šจ ๋ชจ๋ธ์˜ ๊ฐ€์žฅ ์„ฑ์ˆ™ํ•œ ๋ ˆ๋ฒจ๋กœ, ์‰ฝ๊ฒŒ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ˆ˜์ค€์„ ์‚ฌ์šฉํ•˜๋ฉด HATEOAS๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‘๋‹ต์ด ์ž๊ธฐ ์„ค๋ช…์ (self-descriptive)์ด ๋˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.

๋ ˆ๋ฒจ 3 ์„œ๋น„์Šค๋Š” ๋ฆฌ์†Œ์Šค ์ถ”์ ์„ ํ†ตํ•ด ์„œ๋น„์Šค ์†Œ๋น„์ž๋ฅผ ์•ˆ๋‚ดํ•˜์—ฌ ๊ฒฐ๊ณผ์ ์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒํƒœ ์ „ํ™˜์„ ์œ ๋ฐœํ•ฉ๋‹ˆ๋‹ค.

HTTP Response Codes

REST API๋Š” HTTP ์‘๋‹ต ๋ฉ”์‹œ์ง€์˜ ์ผ๋ถ€์ธ ์ƒํƒœ ํ‘œ์‹œ์ค„(Status-Line) ์„ ์‚ฌ์šฉํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์š”์ฒญ์˜ ์ค‘์š”ํ•œ ๊ฒฐ๊ณผ๋ฅผ ์•Œ๋ ค์ค๋‹ˆ๋‹ค. RFC 2616์€ ์•„๋ž˜์™€ ๊ฐ™์ด ์ƒํƒœ ํ‘œ์‹œ์ค„ ๊ตฌ๋ฌธ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

HTTP๋Š” ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์˜ ๊ฒฐ๊ณผ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ด๋Ÿฌํ•œ ํ‘œ์ค€ ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์ƒํƒœ ์ฝ”๋“œ๋Š” 5๊ฐ€์ง€ ๋ฒ”์ฃผ๋กœ ๋‚˜๋‰ฉ๋‹ˆ๋‹ค.

  • 1xx: ์ •๋ณด - ์ „์†ก ํ”„๋กœํ† ์ฝœ ์ˆ˜์ค€ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
  • 2xx: ์„ฑ๊ณต โ€“ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ˆ˜๋ฝ๋˜์—ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • 3xx: ๋ฆฌ๋””๋ ‰์…˜ โ€“ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์š”์ฒญ์„ ์™„๋ฃŒํ•˜๊ธฐ ์œ„ํ•ด ๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • 4xx: ํด๋ผ์ด์–ธํŠธ ์˜ค๋ฅ˜ โ€“ ์ด ๋ฒ”์ฃผ์˜ ์˜ค๋ฅ˜ ์ƒํƒœ ์ฝ”๋“œ๋Š” ํด๋ผ์ด์–ธํŠธ๋ฅผ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค.
  • 5xx: ์„œ๋ฒ„ ์˜ค๋ฅ˜ โ€“ ์„œ๋ฒ„๋Š” ์ด๋Ÿฌํ•œ ์˜ค๋ฅ˜ ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

1xx Status Codes [Informational]

์ƒํƒœ์ฝ”๋“œ์„ค๋ช…
100 Continue์ž„์‹œ ์‘๋‹ต์ž…๋‹ˆ๋‹ค. ์š”์ฒญ์˜ ์ดˆ๊ธฐ ๋ถ€๋ถ„์ด ์ˆ˜์‹ ๋˜์—ˆ์œผ๋ฉฐ ์•„์ง ์„œ๋ฒ„์—์„œ ๊ฑฐ๋ถ€๋˜์ง€ ์•Š์•˜์Œ์„ ํด๋ผ์ด์–ธํŠธ์— ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” ์š”์ฒญ์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์„ ๊ณ„์† ์ „์†กํ•˜๊ฑฐ๋‚˜ ์š”์ฒญ์ด ์ด๋ฏธ ์™„๋ฃŒ๋œ ๊ฒฝ์šฐ ์ด ์‘๋‹ต์„ ๋ฌด์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„๋Š” ์š”์ฒญ์ด ์™„๋ฃŒ๋œ ํ›„ ์ตœ์ข… ์‘๋‹ต์„ ๋ณด๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
101 Switching Protocolํด๋ผ์ด์–ธํŠธ์˜ ์—…๊ทธ๋ ˆ์ด๋“œ ์š”์ฒญ ํ—ค๋”์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ ์ „์†ก๋˜๋ฉฐ ์„œ๋ฒ„๊ฐ€ ์ „ํ™˜ํ•˜๋Š” ํ”„๋กœํ† ์ฝœ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
102 Processing (WebDAV)์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์„ ์ˆ˜์‹ ํ•˜์—ฌ ์ฒ˜๋ฆฌ ์ค‘์ด์ง€๋งŒ ์•„์ง ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์‘๋‹ต์ด ์—†์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
103 Early Hints์ฃผ๋กœ Linkํ—ค๋”์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์„œ๋ฒ„๊ฐ€ ์ตœ์ข… ์‘๋‹ต์„ ์ค€๋น„ํ•˜๋Š” ๋™์•ˆ ์‚ฌ์šฉ์ž ์—์ด์ „ํŠธ๊ฐ€ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ฏธ๋ฆฌ ๋กœ๋“œํ•˜๊ธฐ ์‹œ์ž‘ํ•˜๋„๋ก ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

2xx Status Codes [Success]

์ƒํƒœ์ฝ”๋“œ์„ค๋ช…
200 OK์š”์ฒญ์ด ์„ฑ๊ณตํ–ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
201 Created์š”์ฒญ์ด ์„ฑ๊ณตํ–ˆ์œผ๋ฉฐ ๊ฒฐ๊ณผ์ ์œผ๋กœ ์ƒˆ ๋ฆฌ์†Œ์Šค๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
202 Accepted์š”์ฒญ์ด ์ˆ˜์‹ ๋˜์—ˆ์ง€๋งŒ ์•„์ง ์™„๋ฃŒ๋˜์ง€ ์•Š์•˜์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๋กœ๊ทธ ์‹คํ–‰ ์š”์ฒญ ๋ฐ ์ผ๊ด„ ์ฒ˜๋ฆฌ์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
203 Non-Authoritative Informationentity-header์—์„œ ๋ฐ˜ํ™˜๋œ ๋ฉ”ํƒ€ ์ •๋ณด๊ฐ€ ์›๋ณธ ์„œ๋ฒ„์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ์ข… ์ง‘ํ•ฉ์ด ์•„๋‹ˆ๋ผ ๋กœ์ปฌ ๋˜๋Š” ํƒ€์‚ฌ ๋ณต์‚ฌ๋ณธ์—์„œ ์ˆ˜์ง‘๋จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ œ์‹œ๋œ ์„ธํŠธ๋Š” ์›๋ž˜ ๋ฒ„์ „์˜ ํ•˜์œ„ ์„ธํŠธ ๋˜๋Š” ์ƒ์œ„ ์„ธํŠธ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
204 No Content์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ–ˆ์ง€๋งŒ ์‘๋‹ต ๋ณธ๋ฌธ์„ ๋ฐ˜ํ™˜ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„๋Š” ์—…๋ฐ์ดํŠธ๋œ ๋ฉ”ํƒ€ ์ •๋ณด๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
205 Reset Content์ด ์š”์ฒญ์„ ๋ณด๋‚ธ ๋ฌธ์„œ๋ฅผ ์žฌ์„ค์ •ํ•  ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
206 Partial Content๋ฆฌ์†Œ์Šค์˜ ์ผ๋ถ€๋งŒ ์š”์ฒญํ•˜๊ธฐ ์œ„ํ•ด ํด๋ผ์ด์–ธํŠธ์—์„œ Range ํ—ค๋”๋ฅผ ๋ณด๋‚ผ ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
207 Multi-Status (WebDAV)์—ฌ๋Ÿฌ ์ž‘์—…์ด ๋ฐœ์ƒํ–ˆ์œผ๋ฉฐ ๊ฐ ์ž‘์—…์˜ ์ƒํƒœ๊ฐ€ ์‘๋‹ต ๋ณธ๋ฌธ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Œ์„ ํด๋ผ์ด์–ธํŠธ์— ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
208 Already Reported (WebDAV)ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ฒ„์— ๋™์ผํ•œ ๋ฆฌ์†Œ์Šค(๋™์ผํ•œ ๋ฐ”์ธ๋”ฉ ์‚ฌ์šฉ)๊ฐ€ ์ด์ „์— ์–ธ๊ธ‰๋˜์—ˆ์Œ์„ ์•Œ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒํƒœ ํ‘œ์‹œ์ค„์— ์ง„์ •ํ•œ HTTP ์‘๋‹ต ์ฝ”๋“œ๋กœ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์œผ๋ฉฐ ๋ณธ๋ฌธ์—๋งŒ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.
226 IM Used์„œ๋ฒ„๋Š” ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ GET ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ–ˆ์œผ๋ฉฐ ์‘๋‹ต์€ ํ˜„์žฌ ์ธ์Šคํ„ด์Šค์— ์ ์šฉ๋œ ํ•˜๋‚˜ ์ด์ƒ์˜ ์ธ์Šคํ„ด์Šค ์กฐ์ž‘ ๊ฒฐ๊ณผ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

3xx Status Codes [Redirection]

์ƒํƒœ์ฝ”๋“œ์„ค๋ช…
300 Multiple Choices์š”์ฒญ์— ๊ฐ€๋Šฅํ•œ ์‘๋‹ต์ด ๋‘ ๊ฐœ ์ด์ƒ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์—์ด์ „ํŠธ ๋˜๋Š” ์‚ฌ์šฉ์ž๋Š” ๊ทธ ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
301 Moved Permanently301 Moved Permanently์š”์ฒญํ•œ ๋ฆฌ์†Œ์Šค์˜ URL์ด ์˜๊ตฌ์ ์œผ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ƒˆ URL์€ ์‘๋‹ต์˜ Location ํ—ค๋” ํ•„๋“œ์— ์˜ํ•ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. ์ด ์‘๋‹ต์€ ๋‹ฌ๋ฆฌ ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š” ํ•œ ์บ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
302 Found302 Found์š”์ฒญํ•œ ๋ฆฌ์†Œ์Šค์˜ URL์ด ์ผ์‹œ์ ์œผ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ƒˆ URL์€ ์‘๋‹ต์˜ ์œ„์น˜ ํ•„๋“œ์— ์˜ํ•ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. ์ด ์‘๋‹ต์€ Cache-Control ๋˜๋Š” Expires ํ—ค๋” ํ•„๋“œ๋กœ ํ‘œ์‹œ๋˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ์บ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
303 See Other์‘๋‹ต์€ ๋‹ค๋ฅธ URI์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ ํ•ด๋‹น ๋ฆฌ์†Œ์Šค์—์„œ GET ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒ€์ƒ‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(SHOULD).
304 Not Modifiedํด๋ผ์ด์–ธํŠธ๊ฐ€ ์‘๋‹ต์ด ์ˆ˜์ •๋˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ณ„์†ํ•ด์„œ ๋™์ผํ•œ ์บ์‹œ๋œ ๋ฒ„์ „์˜ ์‘๋‹ต์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
305 Use Proxy (Deprecated)ํ”„๋ก์‹œ์—์„œ ์š”์ฒญ๋œ ์‘๋‹ต์— ์•ก์„ธ์Šคํ•ด์•ผ ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
306 (Unused)์˜ˆ์•ฝ๋œ ์ƒํƒœ ์ฝ”๋“œ์ด๋ฉฐ ๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
307 Temporary Redirectํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ด์ „ ์š”์ฒญ์— ์‚ฌ์šฉ๋œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ๋‹ค๋ฅธ URI์—์„œ ์š”์ฒญ๋œ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ์˜ค๋„๋ก ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด์ „ ์š”์ฒญ์—์„œ ์‚ฌ์šฉ๋œ ๊ฒƒ๊ณผ ๋™์ผํ•œ HTTP ๋ฉ”์†Œ๋“œ๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค๋Š” ์ ์„ ์ œ์™ธํ•˜๊ณ ๋Š” 302 Found์™€ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.
308 Permanent Redirect (experimental)๋ฆฌ์†Œ์Šค๊ฐ€ ์ด์ œ Location ํ—ค๋”๋กœ ์ง€์ •๋œ ๋‹ค๋ฅธ URI์— ์˜๊ตฌ์ ์œผ๋กœ ์žˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. 301 Moved Permanently์™€ ๋น„์Šทํ•˜์ง€๋งŒ ์ด์ „ ์š”์ฒญ์—์„œ ์‚ฌ์šฉ๋œ ๊ฒƒ๊ณผ ๋™์ผํ•œ HTTP ๋ฉ”์„œ๋“œ๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค๋Š” ์ ๋งŒ ์ œ์™ธํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

4xx Status Codes [Client Error]

์ƒํƒœ์ฝ”๋“œ์„ค๋ช…
400 Bad Request์ž˜๋ชป๋œ ๊ตฌ๋ฌธ์œผ๋กœ ์ธํ•ด ์„œ๋ฒ„์—์„œ ์š”์ฒญ์„ ์ดํ•ดํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” ์ˆ˜์ • ์—†์ด ์š”์ฒญ์„ ๋ฐ˜๋ณตํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.
401 Unauthorized์š”์ฒญ์— ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” ์ ์ ˆํ•œ Authorization ํ—ค๋” ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์š”์ฒญ์„ ๋ฐ˜๋ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
402 Payment Required (Experimental)ํ–ฅํ›„ ์‚ฌ์šฉ์„ ์œ„ํ•ด ์˜ˆ์•ฝ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋””์ง€ํ„ธ ๊ฒฐ์ œ ์‹œ์Šคํ…œ์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
403 Forbidden์Šน์ธ๋˜์ง€ ์•Š์€ ์š”์ฒญ์ž…๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” ์ฝ˜ํ…์ธ ์— ๋Œ€ํ•œ ์•ก์„ธ์Šค ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค. 401๊ณผ ๋‹ฌ๋ฆฌ ํด๋ผ์ด์–ธํŠธ์˜ ID๋Š” ์„œ๋ฒ„์— ์•Œ๋ ค์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.
404 Not Found์„œ๋ฒ„๊ฐ€ ์š”์ฒญํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
405 Method Not Allowed์š”์ฒญ HTTP ๋ฉ”์„œ๋“œ๋Š” ์„œ๋ฒ„์— ์•Œ๋ ค์ ธ ์žˆ์ง€๋งŒ ๋น„ํ™œ์„ฑํ™”๋˜์–ด ํ•ด๋‹น ๋ฆฌ์†Œ์Šค์— ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
406 Not Acceptable์„œ๋ฒ„๋Š” ์š”์ฒญ์—์„œ ๋ณด๋‚ธ Accept ํ—ค๋”์—์„œ ์‚ฌ์šฉ์ž ์—์ด์ „ํŠธ๊ฐ€ ์ œ๊ณตํ•œ ๊ธฐ์ค€์„ ์ค€์ˆ˜ํ•˜๋Š” ์ฝ˜ํ…์ธ ๋ฅผ ์ฐพ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.
407 Proxy Authentication Requiredํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋จผ์ € ํ”„๋ก์‹œ๋กœ ์ž์‹ ์„ ์ธ์ฆํ•ด์•ผ ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
408 Request Timeout์„œ๋ฒ„๊ฐ€ ์„œ๋ฒ„์˜ ํ• ๋‹น๋œ ์‹œ๊ฐ„ ์ดˆ๊ณผ ๊ธฐ๊ฐ„ ๋‚ด์— ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ์™„์ „ํ•œ ์š”์ฒญ์„ ๋ฐ›์ง€ ๋ชปํ–ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
409 Conflict๋ฆฌ์†Œ์Šค์˜ ํ˜„์žฌ ์ƒํƒœ์™€ ์ถฉ๋Œํ•˜์—ฌ ์š”์ฒญ์„ ์™„๋ฃŒํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
410 Gone์š”์ฒญํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ๋” ์ด์ƒ ์„œ๋ฒ„์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
411 Length Required์„œ๋ฒ„๋Š” ์ •์˜๋œ Content-Length ์—†์ด ์š”์ฒญ ์ˆ˜๋ฝ์„ ๊ฑฐ๋ถ€ํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” ์œ ํšจํ•œ Content-Length ํ—ค๋” ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒฝ์šฐ ์š”์ฒญ์„ ๋ฐ˜๋ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
412 Precondition Failedํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ—ค๋”์— ์„œ๋ฒ„๊ฐ€ ์ถฉ์กฑํ•˜์ง€ ์•Š๋Š” ์ „์ œ ์กฐ๊ฑด์„ ํ‘œ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค.
413 Request Entity Too Large์š”์ฒญ ์—”ํ„ฐํ‹ฐ๊ฐ€ ์„œ๋ฒ„์—์„œ ์ •์˜ํ•œ ์ œํ•œ๋ณด๋‹ค ํฝ๋‹ˆ๋‹ค.
414 Request-URI Too Longํด๋ผ์ด์–ธํŠธ๊ฐ€ ์š”์ฒญํ•œ URI๊ฐ€ ์„œ๋ฒ„๊ฐ€ ํ•ด์„ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋ณด๋‹ค ๊น๋‹ˆ๋‹ค.
415 Unsupported Media Type์š”์ฒญ์˜ Content-type์— ์žˆ๋Š” media-type์€ ์„œ๋ฒ„์—์„œ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
416 Requested Range Not Satisfiable์š”์ฒญ์˜ Range ํ—ค๋” ํ•„๋“œ์— ์ง€์ •๋œ ๋ฒ”์œ„๋ฅผ ์ถฉ์กฑํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
417 Expectation FailedExpect ์š”์ฒญ ํ—ค๋” ํ•„๋“œ์— ํ‘œ์‹œ๋œ ์˜ˆ์ƒ์€ ์„œ๋ฒ„์—์„œ ์ถฉ์กฑ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
418 Iโ€™m a teapot (RFC 2324)4์›”์˜ ์—‰๋šฑํ•œ ๋†๋‹ด(๋งŒ์šฐ์ ˆ)์œผ๋กœ ์ •์˜๋˜์—ˆ์œผ๋ฉฐ ์‹ค์ œ HTTP ์„œ๋ฒ„์—์„œ๋Š” ๊ตฌํ˜„๋˜์ง€ ์•Š์„ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋ฉ๋‹ˆ๋‹ค. (RFC 2324)
420 Enhance Your Calm (Twitter)ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์†๋„ ์ œํ•œ์„ ๋ฐ›๊ณ  ์žˆ์„ ๋•Œ Twitter Search and Trends API์— ์˜ํ•ด ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.
422 Unprocessable Entity (WebDAV)์„œ๋ฒ„๋Š” ์š”์ฒญ ์—”ํ„ฐํ‹ฐ์˜ ์ฝ˜ํ…์ธ  ์œ ํ˜•๊ณผ ๊ตฌ๋ฌธ์„ ์ดํ•ดํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ์„œ๋ฒ„๋Š” ์–ด๋–ค ์ด์œ ๋กœ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
423 Locked (WebDAV)์•ก์„ธ์Šค ์ค‘์ธ ๋ฆฌ์†Œ์Šค๊ฐ€ ์ž ๊ฒจ ์žˆ์Šต๋‹ˆ๋‹ค.
424 Failed Dependency (WebDAV)์ด์ „ ์š”์ฒญ์˜ ์‹คํŒจ๋กœ ์ธํ•ด ์š”์ฒญ์ด ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.
425 Too Early (WebDAV)์„œ๋ฒ„๊ฐ€ ์žฌ์ƒ๋  ์ˆ˜ ์žˆ๋Š” ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์œ„ํ—˜์„ ๊ฐ์ˆ˜ํ•˜์ง€ ์•Š์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
426 Upgrade Required์„œ๋ฒ„๊ฐ€ ์š”์ฒญ ์ˆ˜ํ–‰์„ ๊ฑฐ๋ถ€ํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋‹ค๋ฅธ ํ”„๋กœํ† ์ฝœ๋กœ ์—…๊ทธ๋ ˆ์ด๋“œํ•œ ํ›„ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
428 Precondition Required์›๋ณธ ์„œ๋ฒ„๋Š” ์กฐ๊ฑด๋ถ€ ์š”์ฒญ์„ ์š”๊ตฌํ•ฉ๋‹ˆ๋‹ค.
429 Too Many Requests์‚ฌ์šฉ์ž๊ฐ€ ์ฃผ์–ด์ง„ ์‹œ๊ฐ„ ๋™์•ˆ ๋„ˆ๋ฌด ๋งŽ์€ ์š”์ฒญ์„ ๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค(โ€œ์†๋„ ์ œํ•œโ€).
431 Request Header Fields Too Largeํ—ค๋” ํ•„๋“œ๊ฐ€ ๋„ˆ๋ฌด ์ปค์„œ ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
444 No Response (Nginx)Nginx ์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ์— ์ •๋ณด๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๊ณ  ์—ฐ๊ฒฐ์„ ๋‹ซ์Šต๋‹ˆ๋‹ค.
449 Retry With (Microsoft)์ ์ ˆํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ ํ›„ ์š”์ฒญ์„ ๋‹ค์‹œ ์‹œ๋„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
450 Blocked by Windows Parental Controls (Microsoft)Windows ์ž๋…€ ๋ณดํ˜ธ๊ฐ€ ์ผœ์ ธ ์žˆ๊ณ  ์ง€์ •๋œ ์›น ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์•ก์„ธ์Šค๋ฅผ ์ฐจ๋‹จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
451 Unavailable For Legal Reasons์‚ฌ์šฉ์ž ์—์ด์ „ํŠธ๊ฐ€ ๋ฒ•์ ์œผ๋กœ ์ œ๊ณตํ•  ์ˆ˜ ์—†๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ–ˆ์Šต๋‹ˆ๋‹ค.
499 Client Closed Request (Nginx)HTTP ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋™์•ˆ ํด๋ผ์ด์–ธํŠธ์— ์˜ํ•ด ์—ฐ๊ฒฐ์ด ๋‹ซํžˆ๋ฏ€๋กœ ์„œ๋ฒ„๊ฐ€ HTTP ํ—ค๋”๋ฅผ ๋‹ค์‹œ ๋ณด๋‚ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

5xx Status Codes [Server Error]

์ƒํƒœ์ฝ”๋“œ์„ค๋ช…
500 Internal Server Error์„œ๋ฒ„์—์„œ ์š”์ฒญ์„ ์ดํ–‰ํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ํ•˜๋Š” ์˜ˆ๊ธฐ์น˜ ์•Š์€ ์กฐ๊ฑด์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.
501 Not ImplementedHTTP ๋ฉ”์„œ๋“œ๋Š” ์„œ๋ฒ„์—์„œ ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฉฐ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
502 Bad Gateway์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์‘๋‹ต์„ ์–ป๊ธฐ ์œ„ํ•ด ๊ฒŒ์ดํŠธ์›จ์ด๋กœ ์ž‘์—…ํ•˜๋Š” ๋™์•ˆ ์„œ๋ฒ„๊ฐ€ ์ž˜๋ชป๋œ ์‘๋‹ต์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.
503 Service Unavailable์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ค€๋น„๊ฐ€ ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.
504 Gateway Timeout์„œ๋ฒ„๊ฐ€ ๊ฒŒ์ดํŠธ์›จ์ด ์—ญํ• ์„ ํ•˜๊ณ  ์žˆ์–ด ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ์ œ๋•Œ ๋ฐ›์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
505 HTTP Version Not Supported (Experimental)์š”์ฒญ์— ์‚ฌ์šฉ๋œ HTTP ๋ฒ„์ „์€ ์„œ๋ฒ„์—์„œ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
506 Variant Also Negotiates (Experimental)์„œ๋ฒ„์— ๋‚ด๋ถ€ ๊ตฌ์„ฑ ์˜ค๋ฅ˜๊ฐ€ ์žˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์„ ํƒํ•œ ๋ณ€ํ˜• ๋ฆฌ์†Œ์Šค๊ฐ€ ๋ช…๋ฐฑํ•œ ์ฝ˜ํ…์ธ  ํ˜‘์ƒ ์ž์ฒด์— ์ฐธ์—ฌํ•˜๋„๋ก ๊ตฌ์„ฑ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ํ˜‘์ƒ ํ”„๋กœ์„ธ์Šค์—์„œ ์ ์ ˆํ•œ ๋์ ์ด ์•„๋‹™๋‹ˆ๋‹ค.
507 Insufficient Storage (WebDAV)์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์„ ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ํ‘œํ˜„์„ ์ €์žฅํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋ฆฌ์†Œ์Šค์—์„œ ๋ฉ”์„œ๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
508 Loop Detected (WebDAV)์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋™์•ˆ ๋ฌดํ•œ ๋ฃจํ”„๋ฅผ ๊ฐ์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค.
510 Not Extended์„œ๋ฒ„๊ฐ€ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด ์š”์ฒญ์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ํ™•์žฅ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
511 Network Authentication Requiredํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋„คํŠธ์›Œํฌ ์•ก์„ธ์Šค ๊ถŒํ•œ์„ ์–ป๊ธฐ ์œ„ํ•ด ์ธ์ฆํ•ด์•ผ ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

200 (OK)

HTTP ์ƒํƒœ 200 (OK) ์ƒํƒœ ์ฝ”๋“œ๋Š” ์š”์ฒญ ์ด ์„œ๋ฒ„์—์„œ ์„ฑ๊ณต์ ์œผ๋กœ ์ฒ˜๋ฆฌ ๋˜์—ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์‘๋‹ต ํŽ˜์ด๋กœ๋“œ๋Š” ์š”์ฒญ์— ๋Œ€ํ•ด ์„ ํƒ๋œ HTTP ๋ฉ”์„œ๋“œ์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

1. ์‘๋‹ต ์—”ํ‹ฐํ‹ฐ

HTTP ๋ฐฉ์‹์‘๋‹ต ํŽ˜์ด๋กœ๋“œ
GET์š”์ฒญ๋œ ๋ฆฌ์†Œ์Šค์— ํ•ด๋‹น ํ•˜๋Š” ์—”ํ„ฐํ‹ฐ ๊ฐ€ ์‘๋‹ต์œผ๋กœ ์ „์†ก๋ฉ๋‹ˆ๋‹ค.
HEAD์‘๋‹ต์—๋Š” HTTP ํ—ค๋” ํ•„๋“œ๋งŒ ์žˆ๊ณ  ํŽ˜์ด๋กœ๋“œ ๋Š” ์‘๋‹ต์œผ๋กœ ์ „์†ก๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
POST์‘๋‹ต์—๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ง„ํ–‰ ์ƒํƒœ ํ‘œํ˜„ ๋˜๋Š” ์š”์ฒญ์—์„œ ์ˆ˜ํ–‰๋œ ์ž‘์—…์˜ ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
PUT์š”์ฒญ์˜ ์ง„ํ–‰ ์ƒํƒœ ํ‘œ์‹œ๊ฐ€ ์‘๋‹ต์œผ๋กœ ์ „์†ก๋ฉ๋‹ˆ๋‹ค.
DELETE์š”์ฒญ์˜ ์ง„ํ–‰ ์ƒํƒœ ํ‘œ์‹œ๊ฐ€ ์‘๋‹ต์œผ๋กœ ์ „์†ก๋ฉ๋‹ˆ๋‹ค.
OPTIONSAllow ํ—ค๋” ๋ฅผ ์‚ฌ์šฉ ํ•˜์—ฌ ๋ฆฌ์†Œ์Šค์™€ ์—ฐ๊ฒฐ๋œ ์œ ํšจํ•œ ์š”์ฒญ ๋ฐฉ๋ฒ• ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค .
์˜ˆ:
Allow: HEAD, GET, OPTIONS
Content-Length: 18
Content-Type: text/plain;charset=UTF-8
Date: Thu, 06 Apr 2017 06:43:59 GMT
Server: Apache-Coyote/1.1
TRACE์ตœ์ข… ์„œ๋ฒ„์—์„œ ๋ฐ›์€ ์š”์ฒญ ๋ฉ”์‹œ์ง€์˜ ํ‘œํ˜„์ž…๋‹ˆ๋‹ค.

2. ์ค‘์š”ํ•œ ์‚ฌ์‹ค

  • 200 ์‘๋‹ต ์—๋Š” ํ•ญ์ƒ ํŽ˜์ด๋กœ๋“œ ๊ฐ€ ์žˆ์ง€๋งŒ ์›๋ณธ ์„œ๋ฒ„๋Š” ๊ธธ์ด๊ฐ€ 0์ธ ํŽ˜์ด๋กœ๋“œ ๋ณธ๋ฌธ ๋˜๋Š” ๋นˆ ํŽ˜์ด๋กœ๋“œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์„œ๋ฒ„๊ฐ€ ์‘๋‹ต์œผ๋กœ ํŽ˜์ด๋กœ๋“œ๋ฅผ ๋ณด๋‚ด์ง€ ์•Š์œผ๋ ค๋ฉด ๋Œ€์‹  HTTP ์ƒํƒœ 204(No Content) ๋ฅผ ๋ณด๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ธฐ๋ณธ์ ์œผ๋กœ 200(OK) ์‘๋‹ต(ํ—ค๋” ๋ฐ ํŽ˜์ด๋กœ๋“œ)์€ ์บ์‹œ ๊ฐ€๋Šฅ ํ•ฉ๋‹ˆ๋‹ค. ์ฑ„์นญ์„ ์žฌ์ •์˜ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์‘๋‹ต์—๋Š” ์บ์‹œ ๊ฐ๊ฐ์˜ ์บ์‹œ ํ—ค๋” ๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

201 (Created)

HTTP ์ƒํƒœ 201์€ HTTP POST์š”์ฒญ ๊ฒฐ๊ณผ ์„œ๋ฒ„์— ํ•˜๋‚˜ ์ด์ƒ์˜ ์ƒˆ ๋ฆฌ์†Œ์Šค๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ƒ์„ฑ ๋˜์—ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

1. HTTP ํ—ค๋”

Location์‘๋‹ต์—๋Š” ์ƒˆ๋กœ ์ƒ์„ฑ๋œ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” HTTP ํ—ค๋” ๋ชฉ๋ก์˜ ํ—ค๋” ํ•„๋“œ์— URI๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ์‘๋‹ต ํŽ˜์ด๋กœ๋“œ์—๋Š” ์‚ฌ์šฉ์ž ๋˜๋Š” ์‚ฌ์šฉ์ž ์—์ด์ „ํŠธ๊ฐ€ ๊ฐ€์žฅ ์ ํ•ฉํ•œ ๊ฒƒ์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฆฌ์†Œ์Šค ํŠน์„ฑ ๋ฐ ์œ„์น˜ ๋ชฉ๋ก์„ ํฌํ•จํ•˜๋Š” ์—”ํ„ฐํ‹ฐ๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Content-Type์—”ํ„ฐํ‹ฐ ํ˜•์‹์€ ํ—ค๋” ํ•„๋“œ ์— ์ง€์ •๋œ ๋ฏธ๋””์–ด ์œ ํ˜•์œผ๋กœ ์ง€์ •๋ฉ๋‹ˆ๋‹ค.

์›๋ณธ ์„œ๋ฒ„๋Š” 201 ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์ „์— ๋ฆฌ์†Œ์Šค๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค . ์กฐ์น˜๋ฅผ ์ฆ‰์‹œ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ ์„œ๋ฒ„๋Š” 202 (Accepted) ์‘๋‹ต์œผ๋กœ ์‘๋‹ตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

2. ์—…๋ฐ์ดํŠธ ์œ ์‹ค ๋ฌธ์ œ

HTTP 201 ์‘๋‹ต ์€ ๋ฐฉ๊ธˆ ์ƒ์„ฑ๋œ ์š”์ฒญ ๋ณ€ํ˜•์— ๋Œ€ํ•œ ์—”ํ„ฐํ‹ฐ ํƒœ๊ทธ์˜ ํ˜„์žฌ ๊ฐ’์„ ๋‚˜ํƒ€๋‚ด๋Š” ETag ์‘๋‹ต ํ—ค๋” ํ•„๋“œ๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

ETagํ—ค๋” ํ•„๋“œ๋Š” โ€œ์—…๋ฐ์ดํŠธ ์†์‹คโ€ ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ดํ›„์˜ ์กฐ๊ฑด๋ถ€ ์š”์ฒญ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—…๋ฐ์ดํŠธ ์†์‹ค ๋ฌธ์ œ๋Š” ์—ฌ๋Ÿฌ ์‚ฌ๋žŒ์ด ์„œ๋กœ์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์•Œ์ง€ ๋ชปํ•œ ์ฑ„ ๋ฆฌ์†Œ์Šค๋ฅผ ํŽธ์ง‘ํ•  ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์ด ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋งˆ์ง€๋ง‰ ์‚ฌ๋žŒ์ด โ€œ์Šน๋ฆฌโ€ํ•˜๊ณ  ์ด์ „ ์—…๋ฐ์ดํŠธ๋Š” ์†์‹ค๋ฉ๋‹ˆ๋‹ค.

ETag๋Š” If-Matchํ—ค๋”์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜์–ด ๋ฆฌ์†Œ์Šค๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•˜๋Š”์ง€ ์„œ๋ฒ„์—์„œ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ผ์น˜ ํ•˜์ง€ ์•Š์œผ๋ฉด ์„œ๋ฒ„๋Š” 412 (Precondition Failed)์‘๋‹ต ETag์„ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ์— ์•Œ๋ฆฝ๋‹ˆ๋‹ค .


202 (Accepted)

HTTP ์ƒํƒœ202 ๋Š” ์š”์ฒญ์ด ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด ์ˆ˜๋ฝ๋˜์—ˆ์ง€๋งŒ ์ฒ˜๋ฆฌ๊ฐ€ ์™„๋ฃŒ๋˜์ง€ ์•Š์•˜์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค . ์ด ์ƒํƒœ ์ฝ”๋“œ๋Š” ์‹ค์ œ ์ž‘์—…์ด ๋ณธ์งˆ์ ์œผ๋กœ ๋น„๋™๊ธฐ์ผ ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

๊ทธ ๋ชฉ์ ์€ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ์„œ๋ฒ„์— ๋Œ€ํ•œ ์‚ฌ์šฉ์ž ์—์ด์ „ํŠธ์˜ ์—ฐ๊ฒฐ์„ ์ง€์†ํ•  ํ•„์š” ์—†์ด ์„œ๋ฒ„๊ฐ€ ์ผ๋ถ€ ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค(์•„๋งˆ๋„ ํ•˜๋ฃจ์— ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋˜๋Š” ๋ฐฐ์น˜ ์ง€ํ–ฅ ํ”„๋กœ์„ธ์Šค)์— ๋Œ€ํ•œ ์š”์ฒญ์„ ์ˆ˜๋ฝ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

1. ์‘๋‹ต ์—”ํ‹ฐํ‹ฐ

์ด ์‘๋‹ต๊ณผ ํ•จ๊ป˜ ๋ฐ˜ํ™˜๋œ ์—”ํ„ฐํ‹ฐ๋Š” ์š”์ฒญ์˜ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ์„ค๋ช…ํ•˜๊ณ  ์‚ฌ์šฉ์ž์—๊ฒŒ ์š”์ฒญ์ด ์ดํ–‰๋  ์‹œ๊ธฐ์˜ ์ถ”์ •์น˜๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š”(๋˜๋Š” ํฌํ•จํ•˜์ง€ ์•Š์€) ์ƒํƒœ ๋ชจ๋‹ˆํ„ฐ๋ฅผ ๊ฐ€๋ฆฌ์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค(๋˜๋Š” ๋‚ด์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค).

2. HTTP ์ƒํƒœ 202 โ€“ ์˜ˆ

์žฅ๊ธฐ ์‹คํ–‰ ๋น„๋™๊ธฐ ์ž‘์—…์„ REST API์— ์ œ์ถœํ•œ ๊ฒฝ์šฐ API๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

HTTP STATUS 202 (Accepted)

{
	"task": {
		"href": "/api/company/job-management/jobs/2130040",
		"id": "2130040"
	}
}

์ด์ œ ์‚ฌ์šฉ์ž ์—์ด์ „ํŠธ๋Š” ์ž‘์—… ์™„๋ฃŒ ์ƒํƒœ์— ๋Œ€ํ•ด HTTP GET ์š”์ฒญ์„ URI /api/company/job-management/jobs/2130040์— ์ฃผ๊ธฐ์ ์œผ๋กœ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„ API์˜ ์‘๋‹ต์€ ์‹ค์ œ ์˜ˆ์ •๋œ ์ž‘์—…์˜ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

2.1. ์ž‘์—…์ด ์‹œ์ž‘๋˜์ง€ ์•Š์Œ
{
	"job" : {
		"@uri" : "/api/company/job-management/jobs/2130040" ,
		"id" : "2130040",
		"name" : "Update Resource",
		"job-state" : "SCHEDULED",
		"job-status" : "UNDETERMINED",
		"percent-complete" : "0",
		"scheduled-start-time" : "01-01-2013 10:50:45 PM GMT",
		"start-time" : "",
		"end-time" : "",
		"owner" : "Admin",
		"summary" : "random text"
	}
}
2.2. ์ž‘์—… ์‹œ์ž‘๋จ
{
	"job" : {
		"@uri" : "/api/company/job-management/jobs/2130040" ,
		"id" : "2130040",
		"name" : "Update Resource",
		"job-state" : "STARTED",
		"job-status" : "INPROGRESS",
		"percent-complete" : "30",
		"scheduled-start-time" : "01-01-2013 10:50:45 PM GMT",
		"start-time" : "01-01-2013 10:50:55 PM GMT",
		"end-time" : "",
		"owner" : "Admin",
		"summary" : "random text"
	}
}
2.3. ์ž‘์—… ์™„๋ฃŒ
{
	"job" : {
		"@uri" : "/api/company/job-management/jobs/2130040" ,
		"id" : "2130040",
		"name" : "Update Resource",
		"job-state" : "COMPLETED",
		"job-status" : "SUCCESS",
		"percent-complete" : "100",
		"scheduled-start-time" : "01-01-2013 10:50:45 PM GMT",
		"start-time" : "01-01-2013 10:50:55 PM GMT",
		"end-time" : ""01-01-2013 10:52:18 PM GMT",
		"owner" : "Admin",
		"summary" : "random text"
	}
}

์œ„์˜ ์˜ˆ๋Š” ์ฐธ๊ณ ์šฉ์ž…๋‹ˆ๋‹ค.


204 (No Content)

HTTP ์ƒํƒœ 204(์ฝ˜ํ…์ธ  ์—†์Œ) ๋Š” ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์„ ์„ฑ๊ณต์ ์œผ๋กœ ์ˆ˜ํ–‰ํ–ˆ์œผ๋ฉฐ ์‘๋‹ต ํŽ˜์ด๋กœ๋“œ ๋ณธ๋ฌธ์— ๋ณด๋‚ผ ์ฝ˜ํ…์ธ ๊ฐ€ ์—†์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

์„œ๋ฒ„๋Š” ์—”ํ‹ฐํ‹ฐ ํ—ค๋”์˜ ํ˜•ํƒœ๋กœ ์—…๋ฐ์ดํŠธ๋œ ๋ฉ”ํƒ€ ์ •๋ณด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ๋ฅผ ์›ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ ํ˜„์žฌ ๋ฌธ์„œ์˜ ํ™œ์„ฑ ๋ณด๊ธฐ์— ์ ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

204 ์‘๋‹ต ์€ ๋ฉ”์‹œ์ง€ ๋ณธ๋ฌธ ์„ ํฌํ•จํ•ด์„œ๋Š” ์•ˆ ๋˜๋ฏ€๋กœ ํ•ญ์ƒ ํ—ค๋” ํ•„๋“œ ๋‹ค์Œ์˜ ์ฒซ ๋ฒˆ์งธ ๋นˆ ์ค„๋กœ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค.

1. Cacheable

๊ธฐ๋ณธ์ ์œผ๋กœ 204 (No Content)์‘๋‹ต์€ ์บ์‹œ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์บ์‹ฑ์„ ์žฌ์ •์˜ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์‘๋‹ต์—๋Š” ์บ์‹œ ๊ฐ๊ฐ์˜ ์บ์‹œ ํ—ค๋” ๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค .

์˜ˆ๋ฅผ ๋“ค์–ด 204 (No Content)์š”์ฒญ ํŽ˜์ด๋กœ๋“œ๊ฐ€ ์•ž๋’ค๋กœ ์ด๋™ํ•  ์ˆ˜ ์—†์„ ๋งŒํผ ์ถฉ๋ถ„ํžˆ ํฐ UPDATE ์ž‘์—…์—์„œ ์ƒํƒœ๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์—์ด์ „ํŠธ๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ ์œ„ํ•ด ์„œ๋ฒ„์— ํŽ˜์ด๋กœ๋“œ๋ฅผ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

204์ž‘์—…์ด ์„ฑ๊ณตํ•˜๋ฉด ์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด UI๋ฅผ ์—…๋ฐ์ดํŠธํ•˜์—ฌ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ž‘์—… ์„ฑ๊ณต์„ ์•Œ๋ฆด ์ˆ˜ ์žˆ๋„๋ก ์„ฑ๊ณต์„ ๋‚˜ํƒ€๋‚ด๋Š” ์‘๋‹ต์„ ํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ ๋ถ„์‚ฐ ๋ฒ„์ „ ์ œ์–ด ์‹œ์Šคํ…œ๊ณผ ๊ฐ™์ด ์ž๋™ํ™”๋œ ๋ฐ์ดํ„ฐ ์ „์†ก์ด ๋„๋ฆฌ ๋ณด๊ธ‰๋  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค์™€ ํ•จ๊ป˜ ์ž์ฃผ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

2. ์—…๋ฐ์ดํŠธ ์œ ์‹ค ๋ฌธ์ œ

์ƒํƒœ ๊ฐ€ 204 ์ธ ๊ฒฝ์šฐ ์„œ๋ฒ„๋Š” ์—…๋ฐ์ดํŠธ ์†์‹ค ๋ฌธ์ œETag ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์„œ๋ฒ„์—์„œ ์ถ”๊ฐ€ ์—…๋ฐ์ดํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์ „์— ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์ธก ๋ฆฌ์†Œ์Šค ํ‘œํ˜„์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก HTTP ํ—ค๋”๋ฅผ ํฌํ•จํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค .

์—…๋ฐ์ดํŠธ ์†์‹ค ๋ฌธ์ œ ๋Š” ์—ฌ๋Ÿฌ ์‚ฌ๋žŒ์ด ์„œ๋กœ์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์•Œ์ง€ ๋ชปํ•œ ์ฑ„ ๋ฆฌ์†Œ์Šค๋ฅผ ํŽธ์ง‘ํ•  ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค .

์ด ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋งˆ์ง€๋ง‰ ์‚ฌ๋žŒ์ด โ€œ์Šน๋ฆฌโ€ํ•˜๊ณ  ์ด์ „ ์—…๋ฐ์ดํŠธ๋Š” ์†์‹ค๋ฉ๋‹ˆ๋‹ค.

ETag๋Š” If-Match ํ—ค๋”์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ ๋ฆฌ์†Œ์Šค๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•˜๋Š”์ง€ ์„œ๋ฒ„์—์„œ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ETag๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์œผ๋ฉด ์„œ๋ฒ„๋Š” 412 (Precondition Failed)์‘๋‹ต์„ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ์— ์•Œ๋ฆฝ๋‹ˆ๋‹ค.


301 (Moved Permanently)

HTTP ์ƒํƒœ 301์€ ๋ฆฌ๋””๋ ‰์…˜ ๊ด€๋ จ ์ƒํƒœ ์ค‘ ํ•˜๋‚˜๋กœ ์š”์ฒญํ•œ ๋ฆฌ์†Œ์Šค๊ฐ€ Locationํ—ค๋” ์—์„œ ์ง€์ •ํ•œ URL๋กœ ์˜๊ตฌ์ ์œผ๋กœ ์ด๋™๋˜์—ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค . ๊ทธ๋ฆฌ๊ณ  ์ดํ›„์˜ ๋ชจ๋“  ์š”์ฒญ์€ ์ƒˆ URI๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฆฌ๋””๋ ‰์…˜์€ ํ•œ URL์—์„œ ๋‹ค๋ฅธ URL๋กœ ์š”์ฒญ์„ ์ „๋‹ฌํ•˜๋Š” ํ”„๋กœ์„ธ์Šค์ž…๋‹ˆ๋‹ค. ์ƒํƒœ 301์— ๋Œ€ํ•œ ์‚ฌ์–‘์€ ๋ฆฌ๋””๋ ‰์…˜์ด ์ˆ˜ํ–‰๋  ๋•Œ ์š”์ฒญ ๋ฉ”์„œ๋“œ(๋ฐ ์š”์ฒญ ๋ณธ๋ฌธ)๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋„๋ก ์š”๊ตฌํ•ฉ๋‹ˆ๋‹ค.

GET ๋˜๋Š” HEAD ๋ฉ”์„œ๋“œ์—๋งŒ HTTP 301์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

1. URL์„ ์˜๊ตฌ์ ์œผ๋กœ ์ด๋™ํ•ด์•ผ ํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

์ผ๋ฐ˜์ ์œผ๋กœ ๋ฆฌ์†Œ์Šค์˜ URL์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์€ ๋ฐ”๋žŒ์งํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ ์ž์›์˜ URL์„ ๋ณ€๊ฒฝํ•ด์•ผ ํ•˜๋Š” ํ”ผํ•  ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ์— ์ง๋ฉดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌํ•œ ๋ช‡ ๊ฐ€์ง€ ์˜ˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • HTTP์—์„œ HTTPs ํ”„๋กœํ† ์ฝœ๋กœ ๋ฆฌ์†Œ์Šค ์ด๋™
  • ๋ฆฌ์†Œ์Šค๊ฐ€ ํ• ์ธ๋˜์—ˆ์œผ๋ฉฐ ์ƒˆ URL์—์„œ ๋Œ€์ฒด ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. ์œ„์น˜ ํ—ค๋”

์„œ๋ฒ„๋Š” Location๋ฆฌ์†Œ์Šค์˜ ์ƒˆ ์œ„์น˜๋ฅผ ํฌํ•จํ•˜๋Š” ์‘๋‹ต์— ํ—ค๋” ํ•„๋“œ๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

2.1. ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ
GET /index.php HTTP/1.1
Host: www.example.com
2.2. ์„œ๋ฒ„ ์‘๋‹ต
HTTP/1.1 301 Moved Permanently
Location: https://example.com/index.asp

3. Cachable

301 ์‘๋‹ต์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์บ์‹œ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. (์ฆ‰, ๋ฉ”์†Œ๋“œ ์ •์˜ ๋˜๋Š” ๋ช…์‹œ์  ์บ์‹œ ์ œ์–ด์— ์˜ํ•ด ๋‹ฌ๋ฆฌ ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š” ํ•œ.)

์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ด๋Ÿฌํ•œ ์บ์‹œ ํ—ค๋” ๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

4. ์‘๋‹ต ์ฒ˜๋ฆฌ

  • ํด๋ผ์ด์–ธํŠธ์— ๋งํฌ ํŽธ์ง‘ ๊ธฐ๋Šฅ์ด ์žˆ๋Š” ๊ฒฝ์šฐ ์š”์ฒญ๋œ URL์— ๋Œ€ํ•œ ๋ชจ๋“  ์ฐธ์กฐ๋ฅผ ์ƒˆ URL๋กœ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฒ€์ƒ‰ ์—”์ง„(Google ๋ฐ Bing)์€ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์—์„œ ์ด์ „ URL์„ ๋Œ€์ฒดํ•˜๋ฉฐ ์ด์ „ URL์€ ๊ฒฐ๊ตญ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค. ๋งํฌ ์ฃผ์Šค๋Š” ์ด์ „ URL์—์„œ ์ƒˆ URL๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.
  • ๋ธŒ๋ผ์šฐ์ €๋Š” ์ƒˆ ์œ„์น˜ URL์„ ์ฝ๊ณ  ์š”์ฒญ์„ ์ƒˆ ์œ„์น˜๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•œ ํ›„ ์ž๋™์œผ๋กœ 301 ์‘๋‹ต ์ฝ”๋“œ๋ฅผ ๊ฐ์ง€ํ•ฉ๋‹ˆ๋‹ค.