Table of contents
- 1๏ธโฃ Learn REST
- What is REST?
- REST Constraints
- Naming REST Resources
- 1. What is a Resource?
- 2. ๋ชจ๋ฒ ์ฌ๋ก
- 2๏ธโฃ Guides
- 3๏ธโฃ Tech - How To
- Designing REST APIs
- 1. ๋ฆฌ์์ค ์๋ณ โ ๊ฐ์ฒด ๋ชจ๋ธ๋ง
- 2. ๋ชจ๋ธ URI ์์ฑ
- 3. ๋ฆฌ์์ค Representations ๊ฒฐ์
- 4. HTTP ๋ฉ์๋ ํ ๋น
- 4.1. ๋ชจ๋ ์ฅ์น ๋๋ ๊ตฌ์ฑ ํ์(Browse) [๊ธฐ๋ณธ ์ปฌ๋ ์ ]
- 4.2. ์ฅ์น์ ๋ชจ๋ ๊ตฌ์ฑ ํ์(Browse) [๋ณด์กฐ ์ปฌ๋ ์ ]
- 4.3. ๋จ์ผ ์ฅ์น ๋๋ ๊ตฌ์ฑ ํ์(Browse)
- 4.4. ์ฅ์น์์ ๋จ์ผ ๊ตฌ์ฑ ํ์(Browse)
- 4.5. ์ฅ์น ๋๋ ๊ตฌ์ฑ ๋ง๋ค๊ธฐ(Create)
- 4.6. ์ฅ์น ๋๋ ๊ตฌ์ฑ ์ ๋ฐ์ดํธ
- 4.7. ์ฅ์น ๋๋ ๊ตฌ์ฑ ์ ๊ฑฐ
- 4.8. ์ฅ์น์์ ๊ตฌ์ฑ ์ ์ฉ ๋๋ ์ ๊ฑฐ
- 5. ์ถ๊ฐ ์์
- REST APIs with JAX-RS
- 3. Maven ์ ํ๋ฆฌ์ผ์ด์ ์์ฑ
- Designing REST APIs
- 4๏ธโฃ FAQs
- 5๏ธโฃ Resources
- What is an API?
- SOAP vs REST
- HTTP Methods
- Richardson Maturity Model
- HTTP Response Codes
๋ฉ์์ด ์ฌ์์ฒ๋ผ ๋ฐฑ์๋ ์คํฐ๋ ๊ทธ๋ฃน์์ด ํจ๊ป 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๋ง ๋ฉฑ๋ฑ์ด ์ฑ๋ฆฝํ์ง ์์ต๋๋ค.
POST
๋ ๋ฉฑ๋ฑ์ด ์๋๋ค.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๊ฐ ๋ฌด์ํ์ฑ์ด๋ฉด ๋ช ๊ฐ์ง ๋์ ๋๋ ์ด์ ์ด ์์ต๋๋ค.
- ๋ฌด์ํ์ฑ์ API๋ฅผ ์ฌ๋ฌ ์๋ฒ์ ๋ฐฐํฌํ์ฌ ์๋ฐฑ๋ง ๋ช ์ ๋์ ์ฌ์ฉ์๋ก ํ์ฅ(์ค์ผ์ผ ์์)ํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ์ธ์ ๊ด๋ จ ์ข ์์ฑ์ด ์์ผ๋ฏ๋ก ์ด๋ค ์๋ฒ๋ ์์ฒญ์ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
- ๋ฌด์ํ์ฑ์ server-side state synchronization logic์ ๋ชจ๋ ์ ๊ฑฐํ์ฌ REST API์ ๋ณต์ก์ฑ์ ์ค์ผ ์ ์์ต๋๋ค.
- ๋ฌด์ํ์ฑ API๋ ์บ์ํ๊ธฐ๋ ์ฝ์ต๋๋ค. ํน์ ์ํํธ์จ์ด๊ฐ ์์ฒญ ํ๋๋ฅผ ๋ณด๊ณ HTTP ์์ฒญ ๊ฒฐ๊ณผ๋ฅผ ์บ์ํ ์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ ์ ์์ต๋๋ค. ์๋ํ๋ฉด, ์ด์ ์์ฒญ์ ์ํ๊ฐ ์ด ์์ฒญ์ ์บ์ ๊ฐ๋ฅ์ฑ์ ์ํฅ์ ๋ฏธ์น ์ ์๋ค๋ ์ง์์ ์ธ ๋ถํ์ค์ฑ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค.
- ํด๋ผ์ด์ธํธ๋ ์์ฒญ๋ง๋ค ํ์ํ ๋ชจ๋ ์ ๋ณด๋ฅผ ๋ณด๋ด๊ธฐ ๋๋ฌธ์ ์๋ฒ๋ ์์ฉํ๋ก๊ทธ๋จ์์ ๊ฐ ํด๋ผ์ด์ธํธ๊ฐ โ์ด๋โ ์๋์ง ์ถ์ ํ์ง ์์๋ ๋ฉ๋๋ค.
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 ๋ฉ์๋ ๋๋ ์์ ์ ๊ฒฐ์ ํ์ต๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค๋ฅธ ์ธก๋ฉด์์๋ ์์ ํด์ผ ํฉ๋๋ค.
- ๋ก๊น
- ๋ณด์
- ๊ฒ์ ๋ฑ
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
Next
๋ฒํผ์ ํด๋ฆญํฉ๋๋ค.
maven-archtype-webapp
์ ์ ํํฉ๋๋ค.
- ํ๋ก์ ํธ ์ธ๋ถ ์ ๋ณด๋ฅผ ์
๋ ฅํ๊ณ
Finish
๋ฅผ ํด๋ฆญํฉ๋๋ค.
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
http://localhost:8080/NetworkManagement/network-management/configurations/1
๊ฐ๋ณ ๊ตฌ์ฑ์ ๊ฐ์ ธ์ต๋๋ค.
HTTP POST
http://localhost:8080/NetworkManagement/network-management/configurations
์ ๊ตฌ์ฑ ๋ฆฌ์์ค๋ฅผ ๋ง๋ญ๋๋ค.
HTTP PUT
http://localhost:8080/NetworkManagement/network-management/configurations/1
๊ตฌ์ฑ ๋ฆฌ์์ค๋ฅผ ์ ๋ฐ์ดํธํฉ๋๋ค.
HTTP DELETE
http://localhost:8080/NetworkManagement/network-management/configurations/1
๊ตฌ์ฑ ๋ฆฌ์์ค๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
์ฃผ์ด์ง ๋ค์ด๋ก๋ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ์ด ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ค ์ฝ๋๋ฅผ ๋ค์ด๋ก๋ํ์ญ์์ค.
4๏ธโฃ FAQs
PUT vs POST
์ด๊ฒ์ ๋ง์ ์ฌ๋๋ค์ด ์์คํ ์ ์ค๊ณํ ๋ HTTP PUT๊ณผ HTTP POST ๋ฐฉ๋ฒ ์ค ํ๋๋ฅผ ์ ํํ๋ ๋ฐ ์ด๋ ค์ ํฉ๋๋ค.
๊ทธ๋ฌ๋ RFC 2616์ ์ด ๋์ ๋งค์ฐ ๋ช ํํ๊ฒ ๊ตฌ๋ถํ์ง๋ง, ๋ณต์กํ ํํ ๋๋ฌธ์ ํท๊ฐ๋ฆด ์ ์์ต๋๋ค.
PUT ๋๋ POST ๋ฉ์๋๋ฅผ ์ธ์ ์ฌ์ฉํด์ผ ํ๋์ง ์์๋ด ์๋ค.
1. PUT ๊ณผ POST ์ ์ฐจ์ด
PUT | POST |
---|---|
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 ์ด๋ผ๊ณ ํฉ๋๋ค.
Richardson ์ ์๋น์ค์ ์ฑ์๋๋ฅผ ๊ฒฐ์ ํ๊ธฐ ์ํด ์ธ ๊ฐ์ง ์ฃผ์ ์์๋ฅผ ์ฌ์ฉ ํ์ต๋๋ค.
์๋น์ค๊ฐ ์ด๋ฌํ ์์๋ฅผ ๋ง์ด ์ฌ์ฉํ ์๋ก ๋ ์ฑ์ํ ๊ฒ์ผ๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
2. ์ฑ์๋
๊ทธ์ ๋ถ์์์ Richardson์ ๋ค์๊ณผ ๊ฐ์ด ์ด 4๊ฐ์ ์ฑ์๋ ์์ค์ ์ค๋ช ํ์ต๋๋ค.
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 Information | entity-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 Permanently | 301 Moved Permanently์์ฒญํ ๋ฆฌ์์ค์ URL์ด ์๊ตฌ์ ์ผ๋ก ๋ณ๊ฒฝ๋์์ต๋๋ค. ์ URL์ ์๋ต์ Location ํค๋ ํ๋์ ์ํด ์ ๊ณต๋ฉ๋๋ค. ์ด ์๋ต์ ๋ฌ๋ฆฌ ํ์๋์ง ์๋ ํ ์บ์ํ ์ ์์ต๋๋ค. |
302 Found | 302 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 Failed | Expect ์์ฒญ ํค๋ ํ๋์ ํ์๋ ์์์ ์๋ฒ์์ ์ถฉ์กฑ๋ ์ ์์ต๋๋ค. |
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 Implemented | HTTP ๋ฉ์๋๋ ์๋ฒ์์ ์ง์ํ์ง ์์ผ๋ฉฐ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. |
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 | ์์ฒญ์ ์งํ ์ํ ํ์๊ฐ ์๋ต์ผ๋ก ์ ์ก๋ฉ๋๋ค. |
OPTIONS | Allow ํค๋ ๋ฅผ ์ฌ์ฉ ํ์ฌ ๋ฆฌ์์ค์ ์ฐ๊ฒฐ๋ ์ ํจํ ์์ฒญ ๋ฐฉ๋ฒ ๋ชฉ๋ก์
๋๋ค . ์: 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 ์๋ต ์ฝ๋๋ฅผ ๊ฐ์งํฉ๋๋ค.