1) Rest API๋?
HTTP ํ๋กํ ์ฝ์ ์ด์ฉํ์ฌ ๋ธ๋ผ์ฐ์ ๋ ์์ฒญ์ ๋ณด๋ด๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ ๋๋๋งํ์ฌ ํ๋ฉด์ ๋ณด์ฌ์ง๊ฒ ๋ฉ๋๋ค.
HTTP์ ์ด๋ฐ ํน์ง์ ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ ๋ค๋ฅธ ํด๋ผ์ด์ธํธ๋ ์ฌ์ฉํ ์ ์์๊น? ๋ผ๋ ๊ณ ๋ฏผ์ ๊ฐ๋ฐ์๋ค์ ํ๊ฒ ๋์์ต๋๋ค.
์ฆ, ์๋๋ก์ด๋ ์ฑ, ๋ชจ๋ฐ์ผ ์ฑ, Javascript ๋ฑ์์ HTTP๋ก ์์ฒญ์ ๋ณด๋ด๊ณ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ฌ ์ ์์๊น? ํ๋
์๊ฐ์ ํ๊ฒ ๋ ๊ฒ์ ๋๋ค.
์๋ฅผ ๋ค์ด, ์ ๋ถ์์ ๋ฒ์ค ์ดํ ์๊ฐํ๋ฅผ ์ ๊ณตํ๋ค๊ณ ์๊ฐํด ๋ณด๊ฒ ์ต๋๋ค.
์ ๋ถ์์๋ 300๋ฒ ๋ฒ์ค์ ๋ํ ์๊ฐํ๋ฅผ ์ ๊ณตํ๋ URL์ ์๋์ ๊ฐ์ ํํ๋ก ์ ๊ณตํ๋ ๊ฒ์ ๋๋ค.
http://ip์ฃผ์/api/buses/300
์์ ๊ฐ์ URL์ ํธ์ถ ํ๊ฒ ๋์์ ๋ ์๊ฐํ ์ ๋ณด๋ฅผ ํน์ ํ ํํ๋ก ์ ๊ณตํ๋ค๋ฉด,
๊ทธ ์ ๋ณด๋ฅผ ๋ค์ํ ํด๋ผ์ด์ธํธ์์ ์ฌ์ฉํ ์ ์์ ๊ฒ์ ๋๋ค.
HTTP ํ๋กํ ์ฝ์ ์ด์ฉํด ์์ฒญ์ ๋ฐ๊ณ ์๋ง์ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ๋ ๋ฐฉ์์ค์์ REST API๋ผ๋ ๊ฒ์ด ์์ต๋๋ค.
์ด๋ฒ ํ์ต์์๋ REST API์ ๋ํด ํ์ตํด ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
2000๋ ๋์ ๋ก์ด ํ๋ฉ(Roy Fielding) ๋ฐ์ฌ์ ํ์ ๋ ผ๋ฌธ์ REST๋ผ๋ ๊ฐ๋ ์ด ์ฒ์ ๋ฑ์ฅํ์์ต๋๋ค.
REST๋ ‘Representational State Transfer’์ ์ฝ์๋ก ์์์ ์ด๋ฆ์ผ๋ก ๊ตฌ๋ถํ์ฌ ํด๋น ์์์ ์ํ(์ ๋ณด)๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ๋ชจ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
๋ก์ด ํ๋ฉ์ ๋ ผ๋ฌธ์๋ ๋จผ์ ์ํํธ์จ์ด ์ํคํ ์ฒ ์คํ์ผ(architectural style)์ ๋ํด ์ค๋ช ํฉ๋๋ค.
์ํคํ ์ฒ ์คํ์ผ์ด๋ ์ํคํ ์ฒ๊ฐ ์ง์ผ์ผ ํ๋ ์ ์ฝ ์กฐ๊ฑด๋ค์ ์งํฉ์ด๋ผ๊ณ ๋งํ ์ ์์ต๋๋ค.
๋ก์ด ํ๋ฉ์ ์น ์ํคํ ์ฒ์ ์๊ตฌ์ฌํญ๊ณผ ํด๊ฒฐํด์ผํ ๋ฌธ์ ๋ฅผ ์ค๋ช ํ๊ณ ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ์ ๊ทผ ๋ฐฉ๋ฒ์ ๋ ผ๋ฌธ์์ ์ ์ํ๋ฉด์, ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ์ํคํ ์ฒ ์คํ์ผ์ธ REST๋ฅผ ์๊ฐํฉ๋๋ค.
REST๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์น์ ๊ธฐ์กด ๊ธฐ์ ๊ณผ HTTPํ๋กํ ์ฝ์ ๊ทธ๋๋ก ํ์ฉํ๊ธฐ ๋๋ฌธ์ ์น์ ์ฅ์ ์ ์ต๋ํ ํ์ฉํ ์ ์๋ ์ํคํ ์ฒ ์คํ์ผ์ด๋ผ๊ณ ๋งํ ์ ์์ต๋๋ค.
์ด๋ฒ ํ์ต์์๋ ๋ก์ดํ๋ฉ์ด ๋งํ REST์ ๋ํด ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
1. REST ๊ตฌ์ฑ
REST API๋ ๋ค์๊ณผ ๊ฐ์ 3๊ฐ์ง ๋ถ๋ถ์ผ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค.
- ์์(Resource) : ์์์ Data, Meta Data, HATEOAS๋ก ๋๋ฉ๋๋ค.
- ํ์(Verb) : HTTP Method๋ก ํํ๋ฉ๋๋ค.
- ํํ(Representations)
2. REST์ ํน์ง
1) Uniform Interface(์ ๋ํผ ์ธํฐํ์ด์ค)
๊ตฌ์ฑ ์์(ํด๋ผ์ด์ธํธ, ์๋ฒ ๋ฑ) ์ฌ์ด์ ์ธํฐํ์ด์ค๋ ๊ท ์ผ(uniform)ํด์ผํฉ๋๋ค.
์ธํฐํ์ด์ค๋ฅผ ์ผ๋ฐํํจ์ผ๋ก์จ, ์ ์ฒด ์์คํ ์ํคํ ์ฒ๊ฐ ๋จ์ํด์ง๊ณ , ์ํธ ์์ฉ์ ๊ฐ์์ฑ์ด ๊ฐ์ ๋๋ฉฐ,
๊ตฌํ๊ณผ ์๋น์ค๊ฐ ๋ถ๋ฆฌ๋๋ฏ๋ก ๋ ๋ฆฝ์ ์ธ ์งํ๊ฐ ๊ฐ๋ฅํด์ง ์ ์์ต๋๋ค.
2) Stateless (๋ฌด์ํ์ฑ)
ํด๋ผ์ด์ธํธ์ ์๋ฒ์ ํต์ ์๋ ์ํ๊ฐ ์์ด์ผํฉ๋๋ค. ๋ชจ๋ ์์ฒญ์ ํ์ํ ๋ชจ๋ ์ ๋ณด๋ฅผ ๋ด๊ณ ์์ด์ผํฉ๋๋ค.
์์ฒญ ํ๋๋ง ๋ด๋ ๋ฐ๋ก ๋ญ์ง ์ ์ ์์ผ๋ฏ๋ก ๊ฐ์์ฑ์ด ๊ฐ์ ๋๊ณ , task ์คํจ์ ๋ณต์์ด ์ฌ์ฐ๋ฏ๋ก ์ ๋ขฐ์ฑ์ด ๊ฐ์ ๋๋ฉฐ,
์ํ๋ฅผ ์ ์ฅํ ํ์๊ฐ ์์ผ๋ฏ๋ก ๊ท๋ชจ ํ์ฅ์ฑ์ด ๊ฐ์ ๋ ์ ์์ต๋๋ค.
3) Cacheable (์บ์ ๊ฐ๋ฅ)
์บ์๊ฐ ๊ฐ๋ฅํด์ผํฉ๋๋ค. ์ฆ, ๋ชจ๋ ์๋ฒ ์๋ต์ ์บ์๊ฐ ๊ฐ๋ฅํ์ง ๊ทธ๋ ์ง ์๋์ง ์ ์ ์์ด์ผํฉ๋๋ค.
ํจ์จ, ๊ท๋ชจ ํ์ฅ์ฑ, ์ฌ์ฉ์ ์ ์ฅ์์์ ์ฑ๋ฅ์ด ๊ฐ์ ๋ฉ๋๋ค.
4) Self-descriptiveness (์์ฒด ํํ ๊ตฌ์กฐ)
REST์ ๋ ๋ค๋ฅธ ํฐ ํน์ง ์ค ํ๋๋ REST API ๋ฉ์์ง๋ง ๋ณด๊ณ ๋ ์ด๋ฅผ ์ฝ๊ฒ ์ดํดํ ์ ์๋ ์์ฒด ํํ ๊ตฌ์กฐ๋ก ๋์ด ์๋ค๋ ๊ฒ์ ๋๋ค.
5) Client - Server ๊ตฌ์กฐ
ํด๋ผ์ด์ธํธ-์๋ฒ ์คํ์ผ์ ์ฌ์ฉ์ ์ธํฐํ์ด์ค์ ๋ํ ๊ด์ฌ(concern)์ ๋ฐ์ดํฐ ์ ์ฅ์ ๋ํ ๊ด์ฌ์ผ๋ก๋ถํฐ ๋ถ๋ฆฌํจ์ผ๋ก์จ
ํด๋ผ์ด์ธํธ์ ์ด์์ฑ๊ณผ ์๋ฒ์ ๊ท๋ชจํ์ฅ์ฑ์ ๊ฐ์ ํ ์ ์์ต๋๋ค.
6) Layered System(๊ณ์ธตํ ๊ตฌ์กฐ)
REST ์๋ฒ๋ ๋ค์ค ๊ณ์ธต์ผ๋ก ๊ตฌ์ฑ๋ ์ ์์ผ๋ฉฐ ๋ณด์, ๋ก๋ ๋ฐธ๋ฐ์ฑ, ์ํธํ ๊ณ์ธต์ ์ถ๊ฐํด ๊ตฌ์กฐ์์ ์ ์ฐ์ฑ์ ๋ ์ ์๊ณ
PROXY, ๊ฒ์ดํธ์จ์ด ๊ฐ์ ๋คํธ์ํฌ ๊ธฐ๋ฐ์ ์ค๊ฐ๋งค์ฒด๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ํฉ๋๋ค.
3. REST API ์ค๊ณ ๊ฐ์ด๋
REST API ์ค๊ณ ์ ๊ฐ์ฅ ์ค์ํ ํญ๋ชฉ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
1) URI๋ ์ ๋ณด์ ์์์ ํํํด์ผ ํฉ๋๋ค.
resource๋ ๋์ฌ๋ณด๋ค๋ ๋ช ์ฌ๋ฅผ, ๋๋ฌธ์๋ณด๋ค๋ ์๋ฌธ์๋ฅผ ์ฌ์ฉํ๋ค.
resource์ ๋ํ๋จผํธ ์ด๋ฆ์ผ๋ก๋ ๋จ์ ๋ช ์ฌ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
resource์ ์ปฌ๋ ์ ์ด๋ฆ์ผ๋ก๋ ๋ณต์ ๋ช ์ฌ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
resource์ ์คํ ์ด ์ด๋ฆ์ผ๋ก๋ ๋ณต์ ๋ช ์ฌ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
์ : GET /members/1
2) ์์์ ๋ํ ํ์๋ HTTP Method (GET, POST, PUT, DELETE)๋ก ํํํฉ๋๋ค.
3) URI์ HTTP Method๊ฐ ๋ค์ด๊ฐ๋ฉด ์๋ฉ๋๋ค.
์) GET /books/delete/1 (X) -> DELETE /books/1 (O)
4) URI์ ํ์์ ๋ํ ๋์ฌ ํํ์ด ๋ค์ด๊ฐ๋ฉด ์๋ฉ๋๋ค.
(์ฆ, CRUD ๊ธฐ๋ฅ์ ๋ํ๋ด๋ ๊ฒ์ URI์ ์ฌ์ฉํ์ง ์์ต๋๋ค.)
์) GET /books/show/1 (X) -> GET /books/1 (O)
์) GET /books/insert/2 (X) -> POST /books/2 (O)
5) ๊ฒฝ๋ก ๋ถ๋ถ ์ค ๋ณํ๋ ๋ถ๋ถ์ ์ ์ผํ ๊ฐ์ผ๋ก ๋์ฒดํฉ๋๋ค.
(์ฆ, id๋ ํ๋์ ํน์ resource๋ฅผ ๋ํ๋ด๋ ๊ณ ์ ๊ฐ์ ์๋ฏธํฉ๋๋ค.)
์) book์ ์์ฑํ๋ URI: POST /students
์) id=10 ์ธ book์ ์ญ์ ํ๋ URI: DELETE /students/10
6) ์ฌ๋์ ๊ตฌ๋ถ์(/ )๋ ๊ณ์ธต ๊ด๊ณ๋ฅผ ๋ํ๋ด๋๋ฐ ์ฌ์ฉํฉ๋๋ค.
์) http://edwith.org/courses/java
7) URI ๋ง์ง๋ง ๋ฌธ์๋ก ์ฌ๋์(/ )๋ฅผ ํฌํจํ์ง ์์ต๋๋ค.
์) http://edwith.org/courses/ (X)
8) URI์ ํฌํจ๋๋ ๋ชจ๋ ๊ธ์๋ ๋ฆฌ์์ค์ ์ ์ผํ ์๋ณ์๋ก ์ฌ์ฉ๋์ด์ผ ํ๋ฉฐ
URI๊ฐ ๋ค๋ฅด๋ค๋ ๊ฒ์ ๋ฆฌ์์ค๊ฐ ๋ค๋ฅด๋ค๋ ๊ฒ์ด๊ณ , ์ญ์ผ๋ก ๋ฆฌ์์ค๊ฐ ๋ค๋ฅด๋ฉด URI๋ ๋ฌ๋ผ์ ธ์ผ ํฉ๋๋ค.
9) ํ์ดํ(- )์ URI ๊ฐ๋ ์ฑ์ ๋์ด๋๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค.
10) ๋ฐ์ค( _ )์ URI์ ์ฌ์ฉํ์ง ์์ต๋๋ค.
11) URI ๊ฒฝ๋ก์๋ ์๋ฌธ์๊ฐ ์ ํฉํฉ๋๋ค.
URI ๊ฒฝ๋ก์ ๋๋ฌธ์ ์ฌ์ฉ์ ํผํ๋๋ก ํฉ๋๋ค. RFC 3986(URI ๋ฌธ๋ฒ ํ์)์ URI ์คํค๋ง์ ํธ์คํธ๋ฅผ ์ ์ธํ๊ณ ๋
๋์๋ฌธ์๋ฅผ ๊ตฌ๋ณํ๋๋ก ๊ท์ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
12) ํ์ผ ํ์ฅ์๋ URI์ ํฌํจํ์ง ์์ต๋๋ค. Accept header๋ฅผ ์ฌ์ฉํ๋๋ก ํฉ๋๋ค.
์) http://edwith.org/files/java.jpg (X)
์) GET /files/jdk18.exe HTTP/1.1 Host: edwith.org Accept: image/jpg (O)
13) ๋ฆฌ์์ค ๊ฐ์ ์ฐ๊ด ๊ด๊ณ๊ฐ ์๋ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ํํํฉ๋๋ค.
/๋ฆฌ์์ค๋ช /๋ฆฌ์์ค ID/๊ด๊ณ๊ฐ ์๋ ๋ค๋ฅธ ๋ฆฌ์์ค๋ช
์) GET : /books/{bookid}/viewers (์ผ๋ฐ์ ์ผ๋ก ์์ ‘has’์ ๊ด๊ณ๋ฅผ ํํํ ๋)
14) ์์์ ํํํ๋ ์ปฌ๋ ์ (Collection)๊ณผ ๋ํ๋จผํธ(Document)
์ปฌ๋ ์ ์ ๊ฐ์ฒด์ ์งํฉ, ๋ํ๋จผํธ๋ ๊ฐ์ฒด๋ผ๊ณ ์๊ฐํ๋ฉด ๋ฉ๋๋ค. ์ปฌ๋ ์ ๊ณผ ๋ํ๋จผํธ ๋ชจ๋ ๋ฆฌ์์ค๋ก ํํํ ์ ์์ผ๋ฉฐ URI๋ก ํํํ ์ ์์ต๋๋ค.
์) http://edwith.org/courses/1
courses๋ ์ปฌ๋ ์ ์ ๋ํ๋ ๋๋ค. ๋ณต์๋ก ํํํด์ผ ํฉ๋๋ค. courses/1 ์ courses์ค์์ id๊ฐ 1์ธ ๋ํ๋จผํธ๋ฅผ ์๋ฏธํฉ๋๋ค.
4. HTTP ์๋ต ์ํ ์ฝ๋
์ ์ค๊ณ๋ REST API๋ URI๋ง ์ ์ค๊ณ๋๋ ๊ฒ์ด ์๋๋ผ ๊ทธ ๋ฆฌ์์ค์ ๋ํ ์๋ต๋ ์ ํํ๋์ผ ํฉ๋๋ค.
์ ํํ ์๋ต์ ์ํ ์ฝ๋๋ง์ผ๋ก๋ ๋ง์ ์ ๋ณด๋ฅผ ์ ๋ฌํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์์ฃผ ์ฌ์ฉ๋๋ HTTP ์ํ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
5. HATEOAS
์ฐ๋ฆฌ๋ ์น ๊ฒ์ํ์ ์ด์ฉํ๋ค๊ณ ์๊ฐํด๋ณด๊ฒ ์ต๋๋ค. ๊ฒ์ํ ๋ชฉ๋ก๋ณด๊ธฐ ํ๋ฉด์์ ์ ๋ชฉ์ ๋๋ฅด๋ฉด ์์ธ ๋ณด๊ธฐ ํ๋ฉด์ผ๋ก ์ด๋ํฉ๋๋ค. ์์ธ ๋ณด๊ธฐ ํ๋ฉด์์ ๊ธ์ฐ๊ธฐ ๋ฒํผ์ ํด๋ฆญํ๋ฉด ๊ธ์ฐ๊ธฐ ํ๋ฉด์ผ๋ก ์ด๋ํฉ๋๋ค. ์ด๋ ๊ฒ ์น์ด๋ ํ์ดํผ ๋งํฌ๋ฅผ ํตํด ๊ด๊ณ๋ URL๋ก ์ด๋ํ ์ ์์ต๋๋ค.
REST API๋ฅผ ์์ฒญํ ๊ฒฝ์ฐ, ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ ๋ฌ ๋ฐ๊ฒ ๋ฉ๋๋ค. ๊ทธ ๊ฒฐ๊ณผ๋ ๋ณดํต JSONํํ๋ก ๋ฐ๊ฒ ๋ฉ๋๋ค.
์๋ฅผ ๋ค์ด, ๋ค์๊ณผ ๊ฐ์ ์์ฒญ์ ๋ณด๋๋ค๊ณ ์๊ฐํด ๋ณด๊ฒ ์ต๋๋ค.
GET /books/1
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
{
"id" : 1,
"title" : "hello spring",
"author" : "carami"
"price" : 5000
}
์ด๋ ๊ฒ ์์ฒญ์ ํด๋นํ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ด์ค ์ ์๋๋ฐ, ์ด ๊ฒฐ๊ณผ์ ๊ด๋ จ๋ REST API์ ๋ํ ์ ๋ณด๋ฅผ HATEOAS๋ผ๊ณ ๋งํฉ๋๋ค.
HATEOAS๋ ‘Hypermedia As The Engine Of Application State’ ์ ์ฝ์์ ๋๋ค.
์๋์ JSON๋ฌธ์๋ฅผ ๋ณด๋ฉด ‘_links’ ๋ถ๋ถ์ด ๋ณด์ผ ๊ฒ์ ๋๋ค. ์ด ๋ถ๋ถ์ด HATEOAS๋ถ๋ถ์ ๋๋ค.
์๊ธฐ ์์ ์ URL, book ์ปฌ๋ ์ ๊ณผ ๊ด๋ จ๋ URL, book์ ์ฅ์ ์ํ URL ๋ฑ์ด ํํ๋์ด ์๋ ๊ฒ์ ์ ์ ์์ ๊ฒ์ ๋๋ค.
{
"id" : 1,
"title" : "hello spring",
"author" : "carami"
"price" : 5000,
"_links":{
"self":{
"href":"http://localhost:8080/books/1"
},
"query-books":{
"href":"http://localhost/books"
},
"write-books":{
"href":"http://localhost/books"
}
}
}
์ด๋ ๊ฒ, DATA์ ํจ๊ป ๊ด๋ จ๋ URL์ ๋ณด๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ HATEOAS๋ผ๊ณ ๋งํฉ๋๋ค.
6. REST์ ๊ด๋ จ๋ ๋ ผ๋
REST API์ ๋ํ ๋ช ํํ ํ์ค์ ์์ต๋๋ค. ๊ทธ๋ฐ ๋ฌธ์ ๋ก REST API์ ๊ด๋ จ๋์ ๋ง์ ๋ ผ์์ด ๋ฒ์ด์ง๋๋ค.
REST API๋ฅผ ๊ตฌํํ๋ ๊ฐ๋ฐ์๋ค์ ์ํคํ ์ฒ ์คํ์ผ์ ๋ชจ๋ ์งํค๋ ๊ฒ์ด ํ๋ค๊ฒ ์๊ฐํ๋ ๊ฒฝ์ฐ๊ฐ ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
๊ทธ๋ฌ๋ค๋ณด๋, ๋ชจ๋ ์ํคํ ์ฒ ์คํ์ผ์ ์งํค์ง ์๊ณ ๊ฐ๋ฐํ๊ฒ ๋ฉ๋๋ค.
ํนํ REST์ HATEOAS์ ์์ฒด ํํ ๊ตฌ์กฐ(self-descriptiveness)๋ฅผ ๋ง์กฑ ๋ชปํ๋๋ก ๊ฐ๋ฐ๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค.
์ด๋ ๊ฒ REST API๋ฅผ ์๋ฒฝํ๊ฒ ๊ตฌํํ์ง ๋ชปํ ๊ฒฝ์ฐ๋ฅผ Web API๋ผ๊ณ ํฉ๋๋ค.
๋ค์ ์๊ฐ์๋ Web API์ ๋ํด์ ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
2) Web API๋?
์ฝ๋ ์ค์ต ๋งํฌ: mvcexam04
REST API ์ํคํ ์ฒ ์คํ์ผ์ ์๋ฒฝํ๊ฒ ๊ตฌํํ์ง ๋ชปํ ๊ฒฝ์ฐ ์ด๋ฅผ Web API๋ผ๊ณ ๋ถ๋ฅธ๋ค
์ฐ๋ฆฌ๋ ์์์ Spring MVC๋ฅผ ์ด์ฉํด ๊ฐ๋จํ Web ์ดํ๋ฆฌ์ผ์ด์ ์ ์์ฑํ์์ต๋๋ค.
http://localhost:8080/mvcexam/plusform ์ด๋ผ๋ URL์ฃผ์๋ฅผ ๋ธ๋ผ์ฐ์ ์ ์ฃผ์์ฐฝ์ ์ ๋ ฅํ๋ฉด,
2๊ฐ์ ๊ฐ์ ์ ๋ ฅ๋ฐ๋ ํผ(Form)์ด ๋ณด์ฌ์ก๊ณ ํด๋น ํผ์ ๊ฐ์ ์ ๋ ฅํ๊ณ ๋ฒํผ์ ๋๋ฅด๋ฉด 2๊ฐ์ ์ซ์์ ํฉ์ด ์ถ๋ ฅ๋๋ ํ๋ก๊ทธ๋จ์ด์์ต๋๋ค.
mvcexam ํ๋ก์ ํธ์ ๋ง์ ์ ๊ตฌํ๋ Web API๋ฅผ ์ถ๊ฐํด๋ด์ผ๋ก์จ Web API๊ฐ ๋ฌด์์ธ์ง ๊ฐ๋จํ ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
1 PlusResult.java
PlusResultํด๋์ค๋ 3๊ฐ์ ์ ์ ๊ฐ์ ์ ์ฅํ ์ ์๋ ๊ฐ์ฒด์ ๋๋ค.
2 PlusApiController.java
package kr.or.connect.mvcexam.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import kr.or.connect.mvcexam.dto.PlusResult;
// Web Api
@Controller
public class PlusApiController {
@GetMapping("/api/plus")
@ResponseBody //ํด๋น ๋ฉ์๋๋ ๋ทฐ์ด๋ฆ์ ๋ฆฌํด(๋ณดํต์ ๊ทธ๋ผ)ํ๋ ๊ฒ์ด ์๋๋ผ, ๋ฆฌํดํ ๊ฐ์ฒด๋ฅผ ์ถ๋ ฅํ๋ผ๋ ์๋ฏธ
public PlusResult plus(@RequestParam("value1") int value1, @RequestParam("value2") int value2){
PlusResult plusResult = new PlusResult();
plusResult.setValue1(value1);
plusResult.setValue2(value2);
plusResult.setResult(value1 + value2);
return plusResult;
}
}
์ฐ๋ฆฌ๋ ์์์ ์ปจํธ๋กค๋ฌ๋ฅผ ๋ง๋ค์ด ๋ดค์ต๋๋ค. ์ปจํธ๋กค๋ฌ๊ฐ ๊ฐ์ง๋ ๋ฉ์๋๋ String์ ๋ฐํํ๋ ๊ฒ ๊ธฐ์ตํ์๋์?
์ปจํธ๋กค๋ฌ ๋ฉ์๋๊ฐ ๋ฐํํ๋ String๊ฐ์ ๋ทฐ(View)์ด๋ฆ์ด๋ ๋ฆฌ๋ค์ด๋ ํธ๋๋ ๊ฒฝ๋ก๋ฅผ ์๋ฏธํ์์ต๋๋ค.
๊ทธ๋ฐ๋ฐ, ์ง๊ธ ์์ฑํ๋ ์ปจํธ๋กค๋ฌ๋ String์ด ์๋ PlusResult ๊ฐ์ฒด๋ฅผ ๋ฆฌํดํ๊ณ ์์ต๋๋ค.
@ResponseBody
@ResponseBody ์ด๋ ธํ ์ด์ ์ด ๋ถ๊ฒ ๋๋ฉด ํด๋น๋ฉ์๋๋ ๋ทฐ์ด๋ฆ์ ๋ฆฌํดํ๋ ๊ฒ(์ ๊น์ง ๊ทธ๋ผ)์ด ์๋๋ผ,
๋ฆฌํดํ ๊ฐ์ฒด๋ฅผ ์ถ๋ ฅํ๋ผ๋ ์๋ฏธ๋ฅผ ๊ฐ์ง๋๋ค.
์ฌ๊ธฐ๊น์ง ์์ฑ์ ํ๊ณ ์๋ฒ๋ฅผ ์ฌ์์ ํฉ๋๋ค.
http://localhost:8080/mvcexam/api/plus?value1=10&value2=20
3. ์๋ฌ ๋ฐ์
‘No converter found for return value of type: class kr.or.connect.webmvc.dto.PlusResult’
์๋ฌ๋ฉ์์ง๋ฅผ ๋ณด๋ฉด PlusResult์ ๋ํ ์ปจ๋ฒํฐ๊ฐ ์๋ค๋ ๊ฒ์ ๋๋ค.
DispathcerServlet์ ์ปจํธ๋กค๋ฌ ๋ฉ์๋๋ฅผ ์คํํ๊ณ ํด๋น ๋ฉ์๋๊ฐ ๋ฆฌํดํ ๊ฐ์ฒด๋ฅผ ๋ณํ์ํค๋ ค๊ณ ํฉ๋๋ค.
๋ณํ์ ์ํฌ ๋ ๋ฉ์์ง ์ปจ๋ฒํฐ(MessageConverter)๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋๋ฐ ๋ฉ์์ง ์ปจ๋ฒํฐ๊ฐ Bean์ผ๋ก ๋ฑ๋ก๋์ด ์์ง ์์ผ๋ฉด ์์ ๊ฐ์ ์ค๋ฅ๋ฅผ ์ถ๋ ฅํ๊ฒ ๋ฉ๋๋ค. ์์ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ง ์๋๋ก ํ๋ ค๋ฉด MessageConverter๋ฅผ Bean์ผ๋ก ๋ฑ๋กํด์ค์ผ ํฉ๋๋ค.
๋ณดํต Web API๋ JSON, XML ๊ณผ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ํํํ๊ธฐ์ ์๋ง์ ํํ๋ก ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
4. pom.xml ํ์ผ์ jackson ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ๊ฐํฉ๋๋ค.
jackson ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๊ฐ์ฒด๋ฅผ JSON์ผ๋ก ๋๋ JSON์ ๊ฐ์ฒด๋ก ๋ณํ์ํฌ ๋ ์ฃผ๋ก ์ฌ์ฉํฉ๋๋ค.
PlusResult๋ฅผ JSON๋ฉ์์ง๋ก ๋ณํํด์ค๋๋ค.
http://localhost:8080/mvcexam/api/plus?value1=10&value2=20 ํธ์ถ ์
5. {"value1":10,"value2":20,"result":30} - ์ถ๋ ฅ!
๋ค์ ์๊ฐ์ ์ด๋ฐ Web API๋ฅผ ๋ง๋๋ ๋ฐฉ๋ฒ์ ์ข ๋ ์์ธํ ์ดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
'Spring > Boost Course Web' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
5.1 ์ํ์ ์ง๊ธฐ์ - Cookie & Session (0) | 2020.11.19 |
---|---|
4.5 Swagger (0) | 2020.11.19 |
4.4 Controller (0) | 2020.11.19 |
4.2 Layered Architecture (0) | 2020.11.19 |
4.1 Spring MVC (0) | 2020.11.19 |
3.3 Spring JDBC (0) | 2020.11.19 |