์์
1.
๊ฐ๋ฐ ํ๊ฒฝ ์ค์น
a.
VS CODE ์ค์น
b.
JDK ์ค์น
c.
ํ์ฅ ์ค์น
2.
์ํคํ
์ฒ ํจํด
a.
MVC
b.
REST API
3.
์ค์ต
a.
๊ฒ์ํ ํ๋ก์ ํธ
i.
MVC
ii.
REST
4.
์ง์์๋ต
๊ฐ๋ฐ ํ๊ฒฝ ์ค์น
1.
VS CODE ์ค์น
2.
JDK ์ค์น
3.
ํ์ฅ ์ค์น
VS CODE ์ค์น
VS CODE ์คํ ํ๋ฉด
JDK ์ค์น
ํ์ฅ ์ค์น
1.
Java
2.
Spring
์ํคํ ์ฒ ํจํด
1.
MVC
2.
REST API
MVC
์ํํธ์จ์ด๋ฅผ Model-View-Controller ์ฃผ์ ๊ตฌ์ฑ์์๋ก ๋ถ๋ฆฌํ์ฌ ๊ฐ๋ฐํ๋ ๋ฐฉ๋ฒ๋ก
โข
Model : ๋ฐ์ดํฐ์ ๋น์ฆ๋์ค ๋ก์ง์ ๋ด๋น
โข
View : ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ฅผ ํํ
โข
Controller : ๋ชจ๋ธ๊ณผ ๋ทฐ๋ฅผ ์ ์ดํ๋ ์ญํ
์น๊ฐ๋ฐ์์์ MVC ํจํด
โข
Model: ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํธ ์์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ณ ์ ์ฅํ๋ ๋ถ๋ถ
โฆ
Service
โฆ
DTO
โฆ
DAO
โข
View: ์น ํ์ด์ง๋ฅผ ํํํ๋ฉฐ, ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ง๋ ๋ถ๋ถ
โฆ
jsp
โฆ
html
โข
Controller: HTTP ์์ฒญ์ ์ฒ๋ฆฌํ๊ณ , ์ ์ ํ ๋ชจ๋ธ์ ํธ์ถํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ณ , ์ ์ ํ ๋ทฐ๋ฅผ ์ ํํ์ฌ, ์ ์ ํ ๋ทฐ ํ์ด์ง๋ฅผ ์ ํํ์ฌ ๋ฐํํ๋ ๋ถ๋ถ
โฆ
Controller
Spring MVC ๊ตฌ์กฐ
Spring Web MVC ๊ตฌ์ฑ์์
1.
Dispatcher Servlet:
โข
์น ์ ํ๋ฆฌ์ผ์ด์
์ ๋ชจ๋ ํด๋ผ์ด์ธํธ ์์ฒญ์ ๋ฐ์๋ค์ด๊ณ ์ฒ๋ฆฌํ๋ ํต์ฌ ์๋ธ๋ฆฟ์
๋๋ค.
2.
Handler Mapping:
โข
ํด๋ผ์ด์ธํธ ์์ฒญ์ ์ฒ๋ฆฌํ ํธ๋ค๋ฌ(์ปจํธ๋กค๋ฌ)๋ฅผ ๊ฒฐ์ ํ๊ธฐ ์ํ ๊ท์น์ ์ ์ํฉ๋๋ค.
3.
Handler Adapter:
โข
์ ํ๋ ํธ๋ค๋ฌ(์ปจํธ๋กค๋ฌ)๊ฐ ์ค์ ์์ฒญ์ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๊ฒฐ์ ํ๊ณ ์คํํฉ๋๋ค.
4.
View Resolver:
โข
ํธ๋ค๋ฌ(์ปจํธ๋กค๋ฌ)์์ ์ ํ๋ ๋ทฐ ์ด๋ฆ์ ๋ทฐ๋ก ๋ณํํ๊ณ ์์ฑํ์ฌ ํด๋ผ์ด์ธํธ์ ๋ฐํํฉ๋๋ค.
5.
Controller:
โข
ํด๋ผ์ด์ธํธ ์์ฒญ์ ๋ฐ์๋ค์ด๊ณ ์ฒ๋ฆฌํ๋ ๋น์ฆ๋์ค ๋ก์ง์ ํฌํจํ๋ ์ปดํฌ๋ํธ์
๋๋ค.
6.
Model:
โข
์ปจํธ๋กค๋ฌ๊ฐ ์์ฑํ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ๋ทฐ์ ์ ๋ฌํ๋ ๊ฐ์ฒด์
๋๋ค.
7.
View:
โข
๋ทฐ ํ
ํ๋ฆฟ(์: JSP, Thymeleaf)์ ์ฌ์ฉํ์ฌ ๋ชจ๋ธ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ค์ ์๋ต(HTML ํ์ด์ง)์ ์์ฑํ๋ ์ปดํฌ๋ํธ์
๋๋ค.
8.
Service:
โข
๋น์ฆ๋์ค ๋ก์ง์ ๊ตฌํํ๊ณ ์ ๊ณตํ๋ ์๋น์ค ๋ ์ด์ด์ ์ปดํฌ๋ํธ์
๋๋ค.
9.
Repository:
โข
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํธ์์ฉํ๋ ๋ฐ์ดํฐ ์ก์ธ์ค ๋ ์ด์ด์ ์ปดํฌ๋ํธ์
๋๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๋ ๋ฐ ๋ฐ์ดํฐ ๊ด๋ฆฌ๋ฅผ ๋ด๋นํฉ๋๋ค.
MVC ํจํด ๋์ ์์
1.
ํด๋ผ์ด์ธํธ๊ฐ ์๋ฒ์ ์์ฒญ์ ํ๋ฉด, Front controller์ธ DispatcherServlet ํด๋์ค๊ฐ ์์ฒญ์ ๋ฐ๋๋ค.
2.
DispatcherServlet์ ํ๋ก์ ํธ ํ์ผ ๋ด์ servlet-context.xml ํ์ผ์ @Controller ์ธ์๋ฅผ ํตํด ๋ฑ๋กํ ์์ฒญ ์์ ์ปจํธ๋กค๋ฌ๋ฅผ ์ฐพ์ ๋ฉํ(mapping)๋ ์ปจํธ๋กค๋ฌ๊ฐ ์กด์ฌํ๋ฉด @RequestMapping์ ํตํด ์์ฒญ์ ์ฒ๋ฆฌํ ๋ฉ์๋๋ก ์ด๋ํ๋ค.
3.
์ปจํธ๋กค๋ฌ๋ ํด๋น ์์ฒญ์ ์ฒ๋ฆฌํ Service ๋ฅผ ๋ฐ์ ๋น์ฆ๋์ค ๋ก์ง์ ์๋น์ค์๊ฒ ์์ํ๋ค.
4.
Service ๋ ์์ฒญ์ ํ์ํ ์์
์ ์ํํ๊ณ , ์์ฒญ์ ๋ํด DB์ ์ ๊ทผํด์ผํ๋ค๋ฉด DAO์ ์์ฒญํ์ฌ ์ฒ๋ฆฌ๋ฅผ ์์ํ๋ค.
5.
DAO๋ DB์ ๋ณด๋ฅผ DTO๋ฅผ ํตํด ๋ฐ์ ์๋น์ค์๊ฒ ์ ๋ฌํ๋ค.
6.
์๋น์ค๋ ์ ๋ฌ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ปจํธ๋กค๋ฌ์๊ฒ ์ ๋ฌํ๋ค.
7.
์ปจํธ๋กค๋ฌ๋ Model(๋ชจ๋ธ) ๊ฐ์ฒด์๊ฒ ์์ฒญ์ ๋ง๋ View(๋ทฐ) ์ ๋ณด๋ฅผ ๋ด์ DispatcherServlet์๊ฒ ์ ์กํ๋ค.
8.
DispatcherServlet์ ViewResolver์๊ฒ ์ ๋ฌ๋ฐ์ View ์ ๋ณด๋ฅผ ์ ๋ฌํ๋ค.
9.
ViewResolver๋ ์๋ตํ View์ ๋ํ JSP๋ฅผ ์ฐพ์ DispatcherServlet์๊ฒ ์ ๋ฌํ๋ค.
10.
DispatcherServlet์ ์๋ตํ ๋ทฐ์ ๋ ๋๋ง๋ฅผ ์ง์ํ๊ณ ๋ทฐ๋ ๋ก์ง์ ์ฒ๋ฆฌํ๋ค.
11.
DispatcherServlet์ ํด๋ผ์ด์ธํธ์๊ฒ ๋ ๋๋ง๋ ๋ทฐ๋ฅผ ์๋ตํ๋ฉฐ ์์ฒญ์ ๋ง์น๋ค.
REST API
REST (Representational State Transfer)
์ํ ํํ ์ ์ก ์ํคํ
์ฒ
present [prษชหzent]
: ๋ณด์ฌ์ฃผ๋ค
represent [หreprษชหzent]
: ๋ค์ ๋ณด์ฌ์ฃผ๋ค, ๋์ ํํํ๋ค
re-(๋ค์) + present(๋ณด์ฌ์ฃผ๋ค) ๋ค์ ๋ณด์ฌ์ฃผ๋ค, ๋ํํ๋ค, ๋๋ณํ๋ค
representational [ หreprษชzenหteษชสnl ]
: ํํํ๋, ๋ณด์ฌ์ฃผ๋
REST
์ํ ํํ ์ ์ก ์ํคํ ์ฒ
์์์ ์ํ๋ฅผ ํํํ์ฌ ์ ๋ฌํ๋ ์ํคํ
์ฒ
URI ๋ก ์์์ ๋์ ํ์ฌ ํํํ๊ณ , ์๋ฒ๊ฐ ํด์ผ ํ ํ์(์๋ฒ์ ์ํ)๋ฅผ HTTP ๋ฉ์๋๋ก ํํํ๋ ๊ฒ์ ์์น์ผ๋ก ํ๋ ์ํคํ
์ฒ
โข
๋คํธ์ํฌ ์ํคํ
์ฒ ์ค์ ํ๋์
๋๋ค.
โข
ํ๋ก ํธ์๋ ๋ฐ ๋ฐฑ์๋์ ๋
๋ฆฝ์ฑ๊ณผ ํ์ฅ์ฑ ํฅ์์ํต๋๋ค.
Overview
โข
REST ์์ธํ ์์๋ณด๊ธฐ
โข
RESTful
โข
RESTful API
โข
CRUD
โข
RESTful CRUD
โข
REST ์ํคํ
์ฒ๋ฅผ ์ฌ์ฉํ๋ ์ด์
โข
Server Side Rendering (SSR)
โข
Client Side Rendering (CSR)
โข
Non-RESTful VS RESTful
โข
REST ์ํคํ
์ฒ์ 6๊ฐ์ง ์์น
REST ์์ธํ ์์๋ณด๊ธฐ
2000 ๋
๋ก์ด ํ๋ฉ (Roy Fielding) ์ ๋ฐ์ฌ ๋
ผ๋ฌธ์์ ์๊ฐ๋ ๊ฐ๋
์ด๋ค.
REST ์ํคํ
์ฒ๋ฅผ ์ ์ํ ํต์ฌ ์ธ๋ฌผ ์ค ํ ๋ช
์ผ๋ก, HTTP ํ๋กํ ์ฝ๊ณผ ์๋ ์์ด๋ ์น (WWW)์ ํต์ฌ ํ์คํ์ ๊ธฐ์ฌํ์ต๋๋ค. ํ๋ฉ์ ๊ทธ์ ๋ฐ์ฌํ์ ๋
ผ๋ฌธ์์ REST(Representational State Transfer) ์ํคํ
์ฒ๋ฅผ ์๊ฐํ์ฌ, ๋ถ์ฐ ํ์ดํผ๋ฏธ๋์ด ์์คํ
์ ์ํ ์ค๊ณ ์์น์ ์ ์ํ์ต๋๋ค. ์ดํ ๋ง์ ์น ์๋น์ค์ API๊ฐ REST ์ํคํ
์ฒ ์คํ์ผ์ ์ ์ฉํ์ฌ ๊ตฌ์ถ๋์์ต๋๋ค.
REST๋ Representational State Transfer์ ์ฝ์๋ก, ์น ๊ฐ๋ฐ์์ ๋คํธ์ํฌ ์ ํ๋ฆฌ์ผ์ด์
์ ์ค๊ณํ๋ ๋ฐ ์์ฃผ ์ฌ์ฉ๋๋ ์ํคํ
์ฒ ์คํ์ผ์
๋๋ค. REST์ ์์น์ ์ค์ํ๋ RESTful API๋ ๋ค๋ฅธ ์์คํ
๊ฐ์ HTTP๋ฅผ ํตํด ํต์ ํ๊ณ ๋ฐ์ดํฐ๋ฅผ ๊ตํํ ์ ์๊ฒ ํด์ค๋๋ค.
REST๋ ๊ฐ๋จํ๊ณ ์ ์ฐํ ์ํคํ
์ฒ๋ก, ์์์ URI(Uniform Resource Identifier)๋ก ํํํ๊ณ , HTTP ๋ฉ์๋(GET, POST, PUT, DELETE ๋ฑ)๋ฅผ ์ฌ์ฉํ์ฌ ํด๋น ์์์ ๋ํ ์ก์
์ ์ํํฉ๋๋ค. ๋ํ, RESTful API๋ ์ํ๋ฅผ ๊ด๋ฆฌํ์ง ์๊ณ , ์์ฒญ์ ํ์ํ ๋ชจ๋ ์ ๋ณด๋ฅผ ์์ฒญ ์์ฒด์ ํฌํจ์ํต๋๋ค.
์ด๋ฌํ RESTful API์ ์ฅ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
โข
๊ฐ๊ฒฐ์ฑ: ์ง๊ด์ ์ด๊ณ ๊ฐ๊ฒฐํ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํฉ๋๋ค.
โข
ํ์ฅ์ฑ: ์์คํ
์ ๋์จํ๊ฒ ๊ฒฐํฉํ์ฌ ํ์ฅ์ด ์ฉ์ดํฉ๋๋ค.
โข
๊ฐ์์ฑ: ์์์ ๋ํ ํ์คํ๋ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๋ฏ๋ก, ๊ฐ๋ฐ์๋ค์ด API๋ฅผ ์ดํดํ๊ณ ์ฌ์ฉํ๊ธฐ ์ฝ์ต๋๋ค.
๋ฐ๋ผ์, RESTful API๋ ํ๋์ ์ธ ์น ๊ฐ๋ฐ์์ ๋งค์ฐ ์ค์ํ ์ญํ ์ ๋ด๋นํ๊ณ ์์ผ๋ฉฐ, ๋ง์ ์น ์ ํ๋ฆฌ์ผ์ด์
๊ณผ ์๋น์ค๊ฐ REST๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌ์ถ๋๊ณ ์์ต๋๋ค.
RESTful
: REST ์ํคํ
์ฒ๋ฅผ ๋ฐ๋ฅด๋ ์์คํ
๋๋ ์๋น์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ์ฉ์ด์
๋๋ค
RESTful API
REST ์ํคํ
์ฒ ์์น์ ๋ฐ๋ฅด๋ API๋ก, RESTful ์๋น์ค๋ฅผ ์ํ ์ธํฐํ์ด์ค์
๋๋ค. ์ด API๋ ์น ์๋น์ค๋ฅผ ๊ตฌ์ถํ๊ฑฐ๋ ํตํฉํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
์ฃผ๋ก HTTP๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ฉฐ, ์์์ URL๋ก ํํํ๊ณ HTTP ๋ฉ์๋(GET, POST, PUT, DELETE ๋ฑ)๋ฅผ ์ฌ์ฉํ์ฌ ์์์ ๊ด๋ฆฌํ๋ฉฐ, JSON ๋๋ XML๊ณผ ๊ฐ์ ๋ฐ์ดํฐ ํ์์ ํตํด ๋ฐ์ดํฐ๋ฅผ ๊ตํํฉ๋๋ค.
RESTful API๋ ๊ฐ๋จํ๊ณ ์ง๊ด์ ์ด๋ฉฐ, ์๋ฒ์ ํด๋ผ์ด์ธํธ ์ฌ์ด์ ํต์ ์ ํจ์จ์ ์ผ๋ก ์ํํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
CRUD
CRUD๋ ๋ฐ์ดํฐ์ ๊ธฐ๋ณธ์ ์ธ ์์
์ ๋ํ๋ด๋ ์ฝ์ด๋ก, Create(์์ฑ), Read(์ฝ๊ธฐ), Update(์์ ), Delete(์ญ์ )์ ๋ค ๊ฐ์ง ๊ธฐ๋ณธ ์์
์ ๋งํฉ๋๋ค. ์ด ๋ค ๊ฐ์ง ์์
์ ์ฃผ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ด๋ จ๋ ์์
์์ ์ฌ์ฉ๋ฉ๋๋ค:
RESTful CRUD
CRUD ์์
| ์์ฒญ ๋ฉ์๋ | ์ค๋ช
|
Create | POST | ์๋ก์ด ๋ฐ์ดํฐ ๋ ์ฝ๋๋ฅผ ์์ฑ |
Read | GET | ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ฑฐ๋ ์กฐํ |
Update | PUT/PATCH | ๋ฐ์ดํฐ ๋ ์ฝ๋๋ฅผ ์์ ๋๋ ๊ฐฑ์ |
Delete | DELETE | ๋ฐ์ดํฐ๋ฅผ ์ญ์ |
RESTful API๋ ์ด๋ฌํ HTTP ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์๋ฒ์ ์์์ ๊ด๋ฆฌํ๋ ๋ฐ ํ์ฉ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, POST ์์ฒญ์ ํตํด ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๊ณ , GET ์์ฒญ์ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ฑฐ๋ ์กฐํํ๋ฉฐ, PUT ๋๋ PATCH ์์ฒญ์ ํตํด ๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ณ , DELETE ์์ฒญ์ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ ์ ์์ต๋๋ค. ์ด๋ฌํ HTTP ๋ฉ์๋๋ฅผ ์ด์ฉํ์ฌ ๊ฐ๊ฐ์ CRUD ์์
์ ์ํํ๋ ๊ฒ์ด RESTful API์ ์ฃผ์ ํน์ง ์ค ํ๋์
๋๋ค.
REST ์ํคํ ์ฒ๋ฅผ ์ฌ์ฉํ๋ ์ด์
RESTful API๋ ์ผ๋ฐ์ ์ผ๋ก HTTP ํ๋กํ ์ฝ์ ๋ฐ๋ฅด๊ณ , ์์ฒญ๊ณผ ์๋ต์ ํ์คํ๋ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํจ์ผ๋ก์จ, ๋ค์ํ ์ธ์ด๋ ํ๋ซํผ ๊ฐ์ ์ํธ์ด์ฉ์ฑ์ ๋ณด์ฅํฉ๋๋ค. ์ด๋ ํ๋ก ํธ์๋์ ๋ฐฑ์๋๋ฅผ ๋ถ๋ฆฌํ๊ณ , ๊ฐ ์์ญ์ ๋
๋ฆฝ์ ์ผ๋ก ๊ฐ๋ฐํ ๋ ๋งค์ฐ ์ ์ฉํฉ๋๋ค. ๋ฐ๋ผ์ ํ๋ก ํธ์๋์ ๋ฐฑ์๋๋ฅผ ๋
๋ฆฝ์ ์ผ๋ก ๊ฐ๋ฐํ๋ ๊ฒฝ์ฐ RESTful API๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ผ๋ก ๊ถ์ฅ๋ฉ๋๋ค.
REST ๋ ๋คํธ์ํฌ ์ํคํ
์ฒ์ ์ผ์ข
์
๋๋ค.
์ฃผ์ ๋คํธ์ํฌ ์ํคํ ์ฒ ์ข ๋ฅ
1.
๊ณ์ธตํ๋ ์ํคํ
์ฒ(Layered Architecture)
: ๋คํธ์ํฌ ์์คํ
์ด ์ฌ๋ฌ ๊ณ์ธต์ผ๋ก ๊ตฌ์ฑ๋์ด ์์ผ๋ฉฐ, ๊ฐ ๊ณ์ธต์ ํน์ ํ ์ญํ ๊ณผ ์ฑ
์์ ๊ฐ์ต๋๋ค. OSI 7๊ณ์ธต ๋ชจ๋ธ์ด ์ด๋ฌํ ๊ณ์ธตํ ์ํคํ
์ฒ์ ํ ์์
๋๋ค.
2.
RESTful ์ํคํ
์ฒ(Representational State Transfer)
: REST๋ ํด๋ผ์ด์ธํธ์ ์๋ฒ ๊ฐ์ ํต์ ์ ์ํ ์น ์ํคํ
์ฒ์ ํ ํํ๋ก, ๋ฆฌ์์ค๋ฅผ URL์ ํตํด ์๋ณํ๊ณ HTTP ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ฆฌ์์ค์ ์ ๊ทผํ๋ ์ํคํ
์ฒ ์์น์
๋๋ค.
3.
๋ง์ดํฌ๋ก์๋น์ค ์ํคํ
์ฒ(Microservices Architecture)
: ์ด ์ํคํ
์ฒ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์ฌ๋ฌ ์์ ์๋น์ค๋ก ๋ถํ ํ์ฌ ๊ฐ ์๋น์ค๊ฐ ๋
๋ฆฝ์ ์ผ๋ก ๊ตฌ์ฑ๋๊ณ ์คํ๋๋๋ก ํ๋ ๊ตฌ์กฐ๋ฅผ ๋งํฉ๋๋ค.
Server Side Rendering (SSR)
์๋ฒ ์ธก ๋ ๋๋ง(Server-Side Rendering, SSR)์ ์ฌ์ฉ์๊ฐ ์นํ์ด์ง์ ์ ์ํ์ ๋, ์๋ฒ์์ ํด๋น ํ์ด์ง๋ฅผ ์์ ํ ๋ ๋๋งํ๊ณ ์์ฑ๋ HTML ๋ฌธ์๋ก ํด๋ผ์ด์ธํธ์๊ฒ ์ ๊ณตํ๋ ๊ธฐ์ ์
๋๋ค. ํด๋ผ์ด์ธํธ์์๋ ์๋ฒ๋ก๋ถํฐ ์ ๋ฌ๋ ์์ฑ๋ HTML์ ๋ฐ์ ํ๋ฉด์ ํ์ํ๋ ๋ฐฉ์์
๋๋ค.
Client Side Rendering (CSR)
ํด๋ผ์ด์ธํธ ์ธก ๋ ๋๋ง (Client-Side Rendering ๋๋ CSR)์ ์น ์ ํ๋ฆฌ์ผ์ด์
์ ์ฌ์ฉ์์ ๋ธ๋ผ์ฐ์ ์์ JavaScript๋ฅผ ์ฌ์ฉํ์ฌ ์์ ํ ๋ ๋๋งํ๋ ํ๋ก์ธ์ค๋ฅผ ์๋ฏธํฉ๋๋ค. ์ด ๋ฐฉ์์ ์น ์ ํ๋ฆฌ์ผ์ด์
์ ์ ์ ํ์ผ์ ๋ก๋ํ๊ณ ์ฌ์ฉ์ ์ํธ ์์ฉ์ ๋ฐ๋ผ API์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ DOM์ ์กฐ์ํ์ฌ ๋ด์ฉ์ ๋์ ์ผ๋ก ํ์ํฉ๋๋ค.
CSR(Client-Side Rendering)์์๋ ์ฃผ๋ก JSON ๋๋ XML๊ณผ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ๋ ๋๋งํ๊ณ , React, Vue, Angular ๋ฑ์ ํ๋ ์์ํฌ ๋๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ํด๋ผ์ด์ธํธ ์ธก์์ ์น ์ ํ๋ฆฌ์ผ์ด์
์ ๋ ๋๋ง์ ๋ด๋นํฉ๋๋ค. ํ์ด์ง ๋ก๋ฉ ํ, ํ๋ก ํธ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋ฒ์์ ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋์ ์ผ๋ก ๋ ๋๋งํ์ฌ ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ค๋๋ค. ์ด ๊ณผ์ ์ ํด๋ผ์ด์ธํธ ์ธก์์ ์ด๋ฃจ์ด์ง๋ฏ๋ก ๋ธ๋ผ์ฐ์ ์์ ๋น ๋ฅด๊ฒ ํ๋ฉด์ ํ์ํ ์ ์์ต๋๋ค.
Non-RESTful ์์คํ
Non-RESTful ์์คํ
์ REST ์ํคํ
์ฒ์ ์์น์ ๋ฐ๋ฅด์ง ์๋ ์์คํ
์ ์๋ฏธํฉ๋๋ค. ์ด๋ฌํ ์์คํ
์ REST์ ๊ธฐ๋ณธ ์์น ์ค ์ผ๋ถ ๋๋ ์ ํ ์ ์ฉ๋์ง ์์ ์ ์์ต๋๋ค.
๋นRESTful ์์คํ
์์๋ ์์์ URI๋ก ํํํ๋ ๊ฒ์ด ๋ถ๋ช
ํํ๊ฑฐ๋ ์ผ๊ด์ฑ์ด ์์ ์ ์์ต๋๋ค. ๋ํ, HTTP ๋ฉ์๋๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฌ์ฉํ์ง ์๊ฑฐ๋, Hypermedia๋ฅผ ํ์ฉํ์ง ์๋ ๋ฑ REST ์ํคํ
์ฒ์์ ๊ท์ ํ ์์น์ ๋ฐ๋ฅด์ง ์๋ ํน์ฑ์ ๋ณด์ผ ์ ์์ต๋๋ค.
RESTful ์์คํ
RESTful ์์คํ
์ REST์ ๊ธฐ๋ณธ ์์น์ธ ์์ ์๋ณ, ์๊ธฐ์์ ํ ๋ฉ์์ง, HATEOAS(ํ์ดํผ๋ฏธ๋์ด ์ ์ด ์ํ) ๋ฑ์ ์ ์ฉํ๋ ์์คํ
์ ๊ฐ๋ฆฌํต๋๋ค. ์ด๋ฌํ ์์คํ
์ ์ผ๊ด๋ URI, HTTP ๋ฉ์๋์ ์ฌ์ฉ, Hypermedia์ ์ ๊ทน์ ์ธ ํ์ฉ๊ณผ ๊ฐ์ REST ์ํคํ
์ฒ์ ์์น์ ๋ฐ๋ฅด๋ฉฐ, ์ด๋ฅผ ํตํด ํ์ฅ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ด ํฅ์๋ฉ๋๋ค.
Non-RESTful VS RESTful
REST ์ํคํ ์ฒ์ 6๊ฐ์ง ์์น
1.
์ธํฐํ์ด์ค ์ผ๊ด์ฑ (Uniform Interface)
2.
๋ฌด์ํ (Stateless)
3.
์บ์ฑ ๊ฐ๋ฅ (Cacheable)
4.
๊ณ์ธตํ (Layered System)
5.
Code on Demand
6.
ํด๋ผ์ด์ธํธ/์๋ฒ ๊ตฌ์กฐ (Client/Server Architecture)
์ธํฐํ์ด์ค ์ผ๊ด์ฑ (Uniform Interface)
์ผ๊ด์ ์ธ ์ธํฐํ์ด์ค๋ก ๋ถ๋ฆฌ๋์ด์ผ ํ๋ค.
REST ์ธํฐํ์ด์ค๋ ์ผ๊ด์ฑ์ ๊ฐ์ ธ์ผ ํฉ๋๋ค. ์ด๋ ๋ฆฌ์์ค์ ์ ๊ทผํ๋ ๋ฐฉ๋ฒ์ด ์ผ๊ด๋์ด์ผ ํจ์ ์๋ฏธํฉ๋๋ค. ๋ฆฌ์์ค์ ๋ํ ์ ๋ณด๋ ๋ฆฌ์์ค ์๋ณ์์ ํจ๊ป ์์ฒญ๋๋ฉฐ, ์๋ฒ๋ ๋ฆฌ์์ค ์ํ๋ฅผ ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋ฌํฉ๋๋ค.
๋ฌด์ํ (Stateless)
๊ฐ ์์ฒญ ๊ฐ ํด๋ผ์ด์ธํธ์ ์ฝํ
์คํธ๊ฐ ์๋ฒ์ ์ ์ฅ๋์ด์๋ ์ ๋๋ค
์์ฒญ ๊ฐ ์ํ ์ ๋ณด๋ฅผ ์ ์งํ์ง ์๋ ์์น์
๋๋ค. ๊ฐ ์์ฒญ์ ๊ทธ ์์ฒญ ์์ฒด์ ํ์ํ ๋ชจ๋ ์ ๋ณด๋ฅผ ํฌํจํด์ผ ํ๋ฉฐ, ์๋ฒ๋ ๊ฐ ์์ฒญ์ ๋ณ๊ฐ์ ์์ฒญ์ผ๋ก ์ทจ๊ธํด์ผ ํฉ๋๋ค.
์บ์ฑ ๊ฐ๋ฅ (Cacheable)
WWW์์์ ๊ฐ์ด ํด๋ผ์ด์ธํธ๋ ์๋ต์ ์บ์ฑํ ์ ์์ด์ผ ํ๋ค.
ํด๋ผ์ด์ธํธ๋ ์๋ต์ ์บ์ฑํ ์ ์์ด์ผ ํฉ๋๋ค. ์๋ฒ๋ ์๋ต์ ์บ์ ์ ์ด ํค๋๋ฅผ ์ถ๊ฐํ์ฌ ์บ์ฑ ๋์์ ์กฐ์ ํ ์ ์์ต๋๋ค.
์บ์ฑ
์บ์ฑ์ ์์ฃผ ์ฌ์ฉ๋๋ ๋ฐ์ดํฐ๋ฅผ ๋ฏธ๋ฆฌ ์ ์ฅํด๋๊ณ ํ์ํ ๋๋ง๋ค ๋น ๋ฅด๊ฒ ์ฌ์ฉํ๋๋ก ํ๋ ๊ธฐ์ ์
๋๋ค.
๊ณ์ธตํ (Layered System)
ํด๋ผ์ด์ธํธ๋ ๋์ ์๋ฒ์ ์ง์ ์ฐ๊ฒฐ๋์๋์ง, ์ฐ๊ฒฐ๋์๋์ง๋ฅผ ์ ์ ์๋ค.
REST๋ ๊ณ์ธตํ๋ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๋๋ค. ์๋ฒ๋ ๋ค์ํ ๊ณ์ธต์ผ๋ก ๋๋์ด ์์ผ๋ฉฐ, ํด๋ผ์ด์ธํธ๋ ์๋ฒ์ ์ง์ ํต์ ํ์ง๋ง, ์ค์ ์๋ฒ๊ฐ ์ฒ๋ฆฌ๋๋ ์์น๋ฅผ ์ ํ์๊ฐ ์์ต๋๋ค.
Code on Demand
์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ๊ฐ ์คํ์ํฌ ์ ์๋ ๋ก์ง์ ์ ์กํ์ฌ ๊ธฐ๋ฅ์ ํ์ฅ์ํฌ ์ ์๋ค.
"Code on Demand"๋ ๋ฆฌ์์ค๊ฐ ์๋ฒ์์ ํด๋ผ์ด์ธํธ๋ก ๋ณด๋ด์ง๋ ๋์์ ํด๋ผ์ด์ธํธ์๊ฒ ์คํ ๊ฐ๋ฅํ ์ฝ๋๋ฅผ ์ ์กํ์ฌ, ํด๋ผ์ด์ธํธ๊ฐ ์คํํ ์ ์๋ ๊ธฐ๋ฅ์ ํ์ฅํ๋ ์์น์ ๊ฐ๋ฆฌํต๋๋ค. ํด๋ผ์ด์ธํธ๋ ์ด ์ฝ๋๋ฅผ ์คํํ ์ ์์ด์ผ ํ๋ฉฐ, ์ผ๋ฐ์ ์ผ๋ก JavaScript๊ฐ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ์ฌ์ฉ ์ฌ๋ก์
๋๋ค.
ํด๋ผ์ด์ธํธ/์๋ฒ ๊ตฌ์กฐ (Client/Server Architecture)
ํด๋ผ์ด์ธํธ-์๋ฒ์ ๊ฐ ํํธ๊ฐ ๋
๋ฆฝ์ ์ผ๋ก ๊ฐ์ ๋ ์ ์๋๋ก ํด์ค๋ค.
REST๋ ํด๋ผ์ด์ธํธ์ ์๋ฒ๊ฐ ๋ถ๋ฆฌ๋์ด์ผ ํ๋ค๋ ์์น์
๋๋ค. ์๋ฒ๋ ๋ฐ์ดํฐ ์ ์ฅ, ๊ด๋ฆฌ, ๋ฐฑ์๋ ๋ก์ง์ ์ฒ๋ฆฌํ๊ณ , ํด๋ผ์ด์ธํธ๋ ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๊ณ ์ฌ์ฉ์ ์์ฒญ์ ์๋ฒ๋ก ์ ์กํฉ๋๋ค.
REST ์ํคํ ์ฒ์ URL ๋ช ๋ช ๊ท์น
๋ช ์ฌ ์ฌ์ฉ
: URL์ ๋ฆฌ์์ค๋ฅผ ๋ํ๋ด๋ฉฐ, ๋ฆฌ์์ค์ ๋ํ ๋์์ HTTP ๋ฉ์๋๋ฅผ ํตํด ์ํ๋๋ฏ๋ก, ๋ช
์ฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฆฌ์์ค๋ฅผ ๋ํ๋ด๋ ๊ฒ์ด ์ข์ต๋๋ค.
๋ณต์ํ ์ฌ์ฉ
: ๋ฆฌ์์ค๋ฅผ ๋ํ๋ผ ๋ ๋ณต์ํ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์๋ฅผ ๋ค์ด, /users, /posts์ ๊ฐ์ด ๋ฆฌ์์ค ๋ณต์ํ์ ์ฌ์ฉํฉ๋๋ค.
ํ์ ๋ฆฌ์์ค๋ฅผ ์ํ ์ค์ฒฉ URL ์ฌ์ฉ
: ๊ด๊ณ๊ฐ ์๋ ๋ฆฌ์์ค์ ๊ฒฝ์ฐ, ์ค์ฒฉ URL ๊ตฌ์กฐ (/super/sub) ๋ฅผ ์ฌ์ฉํ์ฌ ๊ด๊ณ๋ฅผ ๋ช
ํํ ํฉ๋๋ค.
ํ์ดํ(-) ๋์ ์ธ๋์ค์ฝ์ด(_) ์ฌ์ฉ
: ๊ฐ๋
์ฑ์ ๋์ด๊ณ ์๋ณ์ ์ฝ๊ฒ ํ๊ธฐ ์ํด ์ธ๋ ์ค์ฝ์ด(_)๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
(๋จ, ๋ฆฌ์์ค ์ด๋ฆ์ ๋์ด์ฐ๊ธฐ๋ ํ์ดํ(-) ์ฌ์ฉ)
๋จ์ํ๊ณ ์ง๊ด์ ์ธ URL
: URL์ ๋ฆฌ์์ค๋ฅผ ์๋ณํ๋ ๋ฐ ์ฌ์ฉ๋๋ฉฐ, ์ด๊ฒ์ ์ง๊ด์ ์ด๊ณ ๋ช
ํํด์ผ ํฉ๋๋ค. ํ๋์ ๋ฆฌ์์ค์ ํ๋์ URL ์ ๋์ํ๋ ๊ฒ์ด ์ข์ผ๋ฉฐ ํ์ผ ํ์ฅ์ (.html, .jsp ๋ฑ)๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค.
์คํ๋ง๋ถํธ๋ก RESTful API ๊ตฌํํ๊ธฐ
1.
@RestController ํด๋์ค ์ ์
2.
GET, POST, PUT, DELETE ์ปจํธ๋กค๋ฌ ๋ฉ์๋ ์ ์
@RestController ํด๋์ค ์ ์
/**
* ๐ข RestFul
* ๊ฒ์ํ ์ปจํธ๋กค๋ฌ
* - ๊ฒ์๊ธ ๋ชฉ๋ก - [GET] - /board
* - ๊ฒ์๊ธ ์กฐํ - [GET] - /board/10
* - ๊ฒ์๊ธ ๋ฑ๋ก ์ฒ๋ฆฌ - [POST] - /board
* - ๊ฒ์๊ธ ์์ ์ฒ๋ฆฌ - [PUT] - /board
* - ๊ฒ์๊ธ ์ญ์ ์ฒ๋ฆฌ - [DELETE] - /board/10
*/
@Slf4j
@RestController
@RequestMapping("/posts")
public class RestBoardController {
}
Java
๋ณต์ฌ
GET, POST, PUT, DELETE ์ปจํธ๋กค๋ฌ ๋ฉ์๋ ์ ์
โข
๊ฒ์๊ธ ๋ชฉ๋ก - [GET] - /board
โข
๊ฒ์๊ธ ์กฐํ - [GET] - /board/10
โข
๊ฒ์๊ธ ๋ฑ๋ก ์ฒ๋ฆฌ - [POST] - /board
โข
๊ฒ์๊ธ ์์ ์ฒ๋ฆฌ - [PUT] - /board
โข
๊ฒ์๊ธ ์ญ์ ์ฒ๋ฆฌ - [DELETE] - /board/10
๊ฒ์๊ธ ๋ชฉ๋ก - [GET] - /board
/**
* ๊ฒ์๊ธ ๋ชฉ๋ก
* [GET]
* /board
* response : boardList
* @return
*/
@GetMapping()
public ResponseEntity<?> findAll() {
log.info("[GET] - /board");
try {
List<Board> boardList = boardService.list();
return new ResponseEntity<>(boardList, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Java
๋ณต์ฌ
๊ฒ์๊ธ ์กฐํ - [GET] - /board/10
/**
* ๊ฒ์๊ธ ์กฐํ
* [GET]
* /board/{id}
* request : id
* response : board
* @param id - ๊ฒ์๊ธ ๋ฒํธ
* @return
*/
@GetMapping("/{id}")
public ResponseEntity<?> find(@PathVariable Integer id) {
log.info("[GET] - /board/" + id);
try {
Board board = boardService.select(id);
return new ResponseEntity<>(board, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Java
๋ณต์ฌ
๊ฒ์๊ธ ๋ฑ๋ก ์ฒ๋ฆฌ - [POST] - /board
/**
* ๊ฒ์๊ธ ๋ฑ๋ก
* [POST]
* /board
* request : board
* response : โญ, โ
* @param board
* @return
*/
@PostMapping()
public ResponseEntity<?> create(@RequestBody Board board) {
log.info("[POST] - /board");
try {
int result = boardService.insert(board);
if( result == 0 )
return ResponseEntity.badRequest().build();
return new ResponseEntity<>("CREATED", HttpStatus.CREATED);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Java
๋ณต์ฌ
๊ฒ์๊ธ ์์ ์ฒ๋ฆฌ - [PUT] - /board
/**
* ๊ฒ์๊ธ ์์
* [PUT]
* /board
* request : board
* response : โญ, โ
* @param board
* @return
*/
@PutMapping()
public ResponseEntity<?> update(@RequestBody Board board) {
log.info("[PUT] - /board");
try {
int result = boardService.update(board);
if( result == 0 )
return ResponseEntity.badRequest().build();
return new ResponseEntity<>("UPDATED", HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Java
๋ณต์ฌ
๊ฒ์๊ธ ์ญ์ ์ฒ๋ฆฌ - [DELETE] - /board/10
/**
* ๊ฒ์๊ธ ์ญ์
* [DELETE]
* /board/{id}
* request : id
* response : โญ, โ
* @param id
* @return
*/
@DeleteMapping("/{id}")
public ResponseEntity<?> delete(@PathVariable Integer id) {
log.info("[DELETE] - /board/" + id);
try {
int result = boardService.delete(id);
if( result == 0 )
return ResponseEntity.badRequest().build();
return ResponseEntity.ok().build();
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Java
๋ณต์ฌ
์ค์ต
๊ฒ์ํ ํ๋ก์ ํธ
1.
MVC
2.
REST
MVC ๊ธฐ๋ฐ ๊ฒ์ํ ํ๋ก์ ํธ
ํ๋ก์ ํธ ๊ตฌ์กฐ
๐ฆย spring-mybatis
โ
โโโโ๐java
โ โโโโ๐com.aloha.springmybatis
โ โ
โ โโโโ๐controller
โ โ โโโโ๐BoardController.java
โ โ
โ โโโโ๐dto
โ โ โโโโ๐Board.java
โ โ
โ โโโโ๐service
โ โ โ
โ โ โโโโ๐BoardService.java
โ โ โโโโ๐BoardServiceImpl.java
โ โ
โ โโโโ๐mapper
โ โโโโ๐BoardMapper.java
โ
โโโโ๐resources
โ ๐application.properties
โ ๐mybatis-config.xml
โ
โโโโ๐com.aloha.springmybatis.mapper
โโโโโ๐BoardMapper.xml
Plain Text
๋ณต์ฌ
์คํ๋ง ๋ถํธ์์ MyBatis ์ฌ์ฉ
SpringBoot ์์ MyBatis๋ฅผ ์ฌ์ฉํ ๋์๋
์ฃผ๋ก Gradel ๋น๋๋๊ตฌ์ ์ค์ ํ์ผ์ build.gradle ๋๋
Maven ๋น๋๋๊ตฌ์ ์ค์ ํ์ผ์ธ pom.xml ์ ์์กด์ฑ์ ์ถ๊ฐํ์ฌ ์ฌ์ฉํฉ๋๋ค
์์กด์ฑ ์ถ๊ฐ
โข
build.gradle
โข
pom.xml
build.gradle
โข
mysql ๋๋ผ์ด๋ฒ ์์กด์ฑ
โข
MyBatis ์์กด์ฑ
โข
build.gradle ์ ์ฒด์ฝ๋
mysql ๋๋ผ์ด๋ฒ ์์กด์ฑ
runtimeOnly 'com.mysql:mysql-connector-j'
Java
๋ณต์ฌ
MyBatis ์์กด์ฑ
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.3'
Java
๋ณต์ฌ
springboot v3 ๋ฒ์ ์ ๊ธฐ์ค์ผ๋ก ์ฌ์ฉํ ์์กด์ฑ์
๋๋ค.
build.gradle
plugins {
id 'java'
id 'war'
id 'org.springframework.boot' version '3.2.5'
id 'io.spring.dependency-management' version '1.1.4'
}
group = 'com.aloha'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.3'
}
tasks.named('test') {
useJUnitPlatform()
}
Java
๋ณต์ฌ
pom.xml
โข
mysql ๋๋ผ์ด๋ฒ ์์กด์ฑ
โข
MyBatis ์์กด์ฑ
โข
build.gradle ์ ์ฒด์ฝ๋
mysql ๋๋ผ์ด๋ฒ ์์กด์ฑ
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
<scope>runtime</scope>
</dependency>
XML
๋ณต์ฌ
MyBatis ์์กด์ฑ
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.3</version>
<scope>test</scope>
</dependency>
XML
๋ณต์ฌ
springboot v3 ๋ฒ์ ์ ๊ธฐ์ค์ผ๋ก ์ฌ์ฉํ ์์กด์ฑ์
๋๋ค.
build.gradle
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.aloha</groupId>
<artifactId>your-artifact-id</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.2.5</version>
</plugin>
</plugins>
</build>
</project>
XML
๋ณต์ฌ
๋ง์ด๋ฐํฐ์ค ์ค์ ํ์ผ - mybatis-config.xml
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- ์ค์ -->
<settings>
<!-- ์ธ๋์ค์ฝ์ด ์ผ์ด์ค์ธ ์ปฌ๋ผ์ ์นด๋ฉ ์ผ์ด์ค๋ก ๋ณํํ๋ ์ค์ -->
<!-- board_no - boardNo -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!-- ํ์
๋ณ์นญ ์ค์ -->
<typeAliases>
<!-- ํ
์ด๋ธ๊ณผ ๋งคํํ DTO๊ฐ ์๋ ํจํค์ง ๊ฒฝ๋ก ์ง์ -->
<package name="com.aloha.springmybatis.dto"/>
</typeAliases>
</configuration>
XML
๋ณต์ฌ
mapUnderscoreToCamelCase
<settings>
<!-- ์ธ๋์ค์ฝ์ด ์ผ์ด์ค์ธ ์ปฌ๋ผ์ ์นด๋ฉ ์ผ์ด์ค๋ก ๋ณํํ๋ ์ค์ -->
<!-- board_no - boardNo -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
XML
๋ณต์ฌ
์ธ๋์ค์ฝ์ด ์ผ์ด์ค(์ค๋ค์ดํฌ ์ผ์ด์ค)๋ฅผ ์นด๋ฉ ์ผ์ด์ค๋ก ์๋ ๋ณํํด์ฃผ๋ ๊ธฐ๋ฅ ํ์ฑํ
์ด๋ ๊ฒ ์์ฑํ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ธ๋์ค์ฝ์ด ์ผ์ด์ค๋ฅผ ๋ณ๋๋ก ์๋ฐ์ ์นด๋ฉ ์ผ์ด์ค๋ก ๋ณํํ์ง ์์๋ ์๋์ผ๋ก ํ
์ด๋ธ์ ์ปฌ๋ผ๋ช
์ ๊ฐ์ฒด์ ๋ณ์๋ก ๋งคํ ํ ์ ์๊ฒ ๋ณํํด์ค๋๋ค.
typeAliases - package
<typeAliases>
<!-- ํ
์ด๋ธ๊ณผ ๋งคํํ DTO๊ฐ ์๋ ํจํค์ง ๊ฒฝ๋ก ์ง์ -->
<package name="com.aloha.springmybatis.dto"/>
</typeAliases>
XML
๋ณต์ฌ
resultType ์์ฑ์์ dto ๊ฐ์ฒด (ํจํค์ง.ํด๋์ค๋ช
) (ํด๋์ค๋ช
)
์ด ์ค์ ์ ๊ตฌ์ฑํ๋ฉด Mapper ํ์ผ์์ resultType ์์ฑ์ด ํจํค์ง๋ถํฐ ํด๋์ค๊น์ง ๋ค ์ง์ ํ์ง ์์๋, ๋งคํํ ๊ฐ์ฒด๊ฐ ์๋ ํจํค์ง๋ฅผ ์ฌ๊ธฐ ์ค์ ํจ์ผ๋ก์จ, ๊ฐ์ฒด ์ด๋ฆ๋ง ์์ฑํด๋ ์กฐํ์ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ฒด์ ๋ฐ๋ก ๋งคํํ ์ ์์ต๋๋ค.
<!-- ๊ฒ์๊ธ ์กฐํ -->
<select id="select" resultType="com.aloha.springmybatis.dto.Board">
XML
๋ณต์ฌ
์ด ์ค์ ์ ์ฌ์ฉํ์ง ์์ผ๋ฉด ย ๋ค์๊ณผ ๊ฐ์ด ํจํค์ง๋ถํฐ ํด๋์ค๋ช
๊น์ง resultType ์์ฑ์ ๋ค ์์ฑํด์ผ ๋์ง๋ง, ์ด ์ค์ ์ ์ฌ์ฉํ๋ฉด ๊ฐ์ฒด๋ช
๋ง ์์ฑํด๋ ๋ฉ๋๋ค.
<!-- ๊ฒ์๊ธ ์กฐํ -->
<select id="select" resultType="Board">
XML
๋ณต์ฌ
๋ฐ๋ผ์ ์กฐํ ๊ฒฐ๊ณผ๋ฅผ ๋งคํํ ๊ฐ์ฒด๋ค์ด ์๋ ํจํค์ง๋ค์ ๋ฏธ๋ฆฌ ์ง์ ํด ๋์ผ๋ฉด . ๋ค์๊ณผ ๊ฐ์ด ๊ฐ๊ฒฐํ๊ฒ ์์ฑ ๊ฐ์ ์์ฑํ ์ ์์ต๋๋ค .
ํ๋ก์ ํธ ์ค์ - application.properties
DB ๋๋ผ์ด๋ฒ์ MyBatis์ ์ค์ ์ ํ๋ก์ ํธ์ ์๋ ค์ฃผ๊ธฐ ์ํด์๋ ย application.properties ํ์ผ์ ๋ค์๊ณผ ๊ฐ์ด ๋ฐ์ดํฐ ์์ค์ Mybatis ๊ด๋ จ ์ค์ ์ ์์ฑํด์ผ ํฉ๋๋ค.
application.properties ๋ ์คํ๋ง ๋ถํธ์ ํ๋ก์ ํธ ์ค์ ํ์ผ์
๋๋ค.
โข
๋ฐ์ดํฐ ์์ค ์ค์
โข
mybatis-config.xml ์ค์
๋ฐ์ดํฐ ์์ค ์ค์
# ๋ฐ์ดํฐ ์์ค - MySQL
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/aloha?serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true&useSSL=false&autoReconnection=true&autoReconnection=true
spring.datasource.username=aloha
spring.datasource.password=123456
Plain Text
๋ณต์ฌ
mybatis-config.xml ์ค์
# Mybatis ์ค์
# Mybatis ์ค์ ๊ฒฝ๋ก : ~/resources/mybatis-config.xml
mybatis.config-location=classpath:mybatis-config.xml
# Mybatis ๋งคํผ ํ์ผ ๊ฒฝ๋ก : ~/๋ฉ์ธํจํค์ง/mapper/**Mapper.xml
mybatis.mapper-locations=classpath:mybatis/mapper/**/**.xml
Plain Text
๋ณต์ฌ
โข
classpath: ๋ผ๊ณ ์ง์ ํ๋ฉด, ~/resources ๊ฒฝ๋ก ํ์๋ถํฐ ๊ฒฝ๋ก๋ฅผ ์ง์ ํ ์ ์๋ค.
โข
classpath:mybatis/mapper/**/**.xml ๋ผ๊ณ ์ง์ ํ๋ฉด, ~/resources ๊ฒฝ๋ก๋ถํฐ ๋ชจ๋ ๊ฒฝ๋ก์ ๋ชจ๋ ํ์ ํ์ผ์ ํ์ฅ์๊ฐ .xml ์ด๋ฉด ๋ง์ด๋ฐํฐ์ค ๋งคํผ(SQL) ํ์ผ๋ก ์ธ์ํ๋๋ก ์ง์ ํ๋ค.
mybatis-config.xml ์ค์ ํ์ผ ์์ด ์ ์ฉํ๊ธฐ
# ์ปฌ๋ผ๋ช
์ ๋ณ์๋ช
์ผ๋ก ์๋๋งคํ : board_no โก boardNo
mybatis.configuration.map-underscore-to-camel-case=true
# resultType ์์ฑ์์ dto ๊ฐ์ฒด (ํจํค์ง.ํด๋์ค๋ช
) โก (ํด๋์ค๋ช
)
mybatis.type-aliases-package=com.aloha.springmybatis.dto
# Mybatis ๋งคํผ ํ์ผ ๊ฒฝ๋ก : ~/๋ฉ์ธํจํค์ง/mapper/**Mapper.xml
mybatis.mapper-locations=classpath:mybatis/mapper/**/**.xml
Plain Text
๋ณต์ฌ
MyBatis์ ์ค์ ํ์ผ์ ์ฌ์ฉํด์ ๋ง์ด๋ฐํฐ์ค์ ์ค์ ์ ๊ด๋ฆฌํ ์๋ ์์ง๋ง . ๊ธฐ๋ณธ์ ์ธ ์ค์ ๋ค์ ์ดํ๋ฆฌ์ผ์ด์
ํ๋กํฌํฐ์ค์์ ๋ฐ๋ก ์ค์ ์ ํ ์๋ ์์ต๋๋ค.
application.properties
spring.application.name=spring-mybatis
# ๋ฐ์ดํฐ ์์ค - MySQL
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/aloha?serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true&useSSL=false&autoReconnection=true&autoReconnection=true
spring.datasource.username=aloha
spring.datasource.password=123456
# Mybatis ์ค์
# Mybatis ์ค์ ๊ฒฝ๋ก : ~/resources/mybatis-config.xml
# mybatis.config-location=classpath:mybatis-config.xml
# ์ปฌ๋ผ๋ช
์ ๋ณ์๋ช
์ผ๋ก ์๋๋งคํ : board_no โก boardNo
mybatis.configuration.map-underscore-to-camel-case=true
# resultType ์์ฑ์์ dto ๊ฐ์ฒด (ํจํค์ง.ํด๋์ค๋ช
) โก (ํด๋์ค๋ช
)
mybatis.type-aliases-package=com.aloha.springmybatis.dto
# Mybatis ๋งคํผ ํ์ผ ๊ฒฝ๋ก : ~/๋ฉ์ธํจํค์ง/mapper/**Mapper.xml
mybatis.mapper-locations=classpath:mybatis/mapper/**/**.xml
Plain Text
๋ณต์ฌ
DB ๊ตฌ์ถ
์ด๋ฒ ์ค์ต์์๋ MySQL์ ๋๋ผ์ด๋ฒ๋ฅผ ์ฌ์ฉํฉ๋๋ค . MySQL์ ์ค์น๊ฐ ํ์ํ๊ฑฐ๋ . ๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ ๋ฐฉ๋ฒ์ ์๊ณ ์ถ๋ค๋ฉด ์์ ํ์ด์ง๋ฅผ ์ฐธ์กฐํด ์ฃผ์ธ์ .
โข
์คํค๋ง : aloha
โข
ํ
์ด๋ธ ์์ฑ
โฆ
board
board
CREATE TABLE `board` (
`no` int NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL,
`writer` varchar(100) NOT NULL,
`content` text,
`reg_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`upd_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`views` int NOT NULL DEFAULT '0',
PRIMARY KEY (`no`)
) COMMENT='๊ฒ์ํ';
SQL
๋ณต์ฌ
๋ก์ง ์์ฑ
โข
DTO ์์ฑ
โข
SQL Mapper ์์ฑ
โข
Mapper ์ธํฐํ์ด์ค ์์ฑ
โข
Service ์์ฑ
โข
Controller ์์ฑ
โข
View ์์ฑ
DTO ์์ฑ
โข
Board.java
Board.java
Board dto๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ board ํ
์ด๋ธ๊ณผ ๋งคํํ๊ธฐ ์ํ ๋ฐ์ดํฐ ์ ์ก ๊ฐ์ฒด์
๋๋ค
/**
* Board
* - ๊ฒ์๊ธ ์ ๋ณด
*/
@Data
public class Board {
private int no;
private String title;
private String writer;
private String content;
private Date regDate;
private Date updDate;
private int views;
}
Java
๋ณต์ฌ
SQL Mapper ์์ฑ
SQL Mapper์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์ฒญ์ ๋ณด๋ด๊ธฐ ์ํ SQL ์ฟผ๋ฆฌ๋ค์ xml ํ๊ทธ ํ์์ผ๋ก ์ ์ํฉ๋๋ค
โข
๊ธฐ๋ณธ Mapper ํ์ผ ํ์
โข
๊ธฐ๋ณธ CRUD Mapper ํ์ผ ์ฝ๋
โข
BoardMapper.xml
๊ธฐ๋ณธ Mapper ํ์ผ ํ์
Mybatis Mapper ํ์ผ์๋ ์ต์์ ํ๊ทธ๋ก <mapper> ํ๊ทธ๋ฅผ ์์ฑํ๊ณ ๋ค์์คํ์ด์ค ์์ฑ์ ์์ฑํด์ ๋ํผ ์ธํฐํ์ด์ค์ ๊ฒฝ๋ก๋ฅผ ์ง์ ํฉ๋๋ค.
namespace="๋งคํผ ์ธํฐํ์ด์ค ๊ฒฝ๋ก"
namespace์ ์์ฑํ Mapper ์ธํฐํ์ด์ค์ ๊ฒฝ๋ก๊ฐ ์ธํฐํ์ด์ค ํ์ผ์ ๊ฒฝ๋ก์ ์ผ์น ํด์ผํฉ๋๋ค.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace="๋งคํผ ์ธํฐํ์ด์ค ๊ฒฝ๋ก" -->
<mapper namespace="com.aloha.springmybatis.mapper.XXXMapper">
</mapper>
XML
๋ณต์ฌ
๊ธฐ๋ณธ CRUD Mapper ํ์ผ ์ฝ๋
SQL ํ๊ทธ
<select id="select" resultType="base">
Mapper ์ธํฐํ์ด์ค ๋ฉ์๋
public Base select(int baseNo) throws Exception;
๊ฐ SQL ํ๊ทธ์ id ์์ฑ๊ฐ์ด Mapper ์ธํฐํ์ด์ค์ ๋ฉ์๋ ๋ช
๊ณผ ์ผ์นํด์ผํฉ๋๋ค.
๋ก์ง์ ํตํด์ Mapper ์ธํฐํ์ด์ค์ ๋ฉ์๋๊ฐ ํธ์ถ์ด ๋๋ฉด, ์ด์ ๋งคํ๋์ด ์๋ SQL mapper ํ์ผ์ ํด๋น ๋ฉ์๋๋ช
๊ณผ ์ผ์นํ๋ ์์ด๋๋ฅผ ๊ฐ์ง SQL ํ๊ทธ๊ฐ ์คํ๋ฉ๋๋ค
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace="๋งคํผ ์ธํฐํ์ด์ค ๊ฒฝ๋ก" -->
<mapper namespace="com.aloha.springmybatis.mapper.BaseMapper">
<!-- ๊ธฐ๋ณธ ๋ฑ๋ก -->
<insert id="insert">
INSERT INTO base( base_id, base_name )
VALUES ( #{baseId}, #{baseName} )
</insert>
<!-- ๊ธฐ๋ณธ ์กฐํ -->
<select id="select" resultType="base">
SELECT *
FROM base
WHERE base_no = #{baseNo}
</select>
<!-- ๊ธฐ๋ณธ ์์ -->
<update id="update">
UPDATE base
SET base_id = #{baseId}
,base_name = #{baseName}
WHERE base_no = #{baseNo}
</update>
<!-- ๊ธฐ๋ณธ ์์ -->
<delete id="delete">
DELETE FROM base
WHERE base_no = #{baseNo}
</delete>
</mapper>
XML
๋ณต์ฌ
BoardMapper.xml
์ด๋ฒ ์ค์ต์์๋ ๊ฒ์๊ธ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฑ๋ก ์กฐํ ์์ ์ญ์ ํ๋ ์ฟผ๋ฆฌ๋ค์ ๋ค์๊ณผ ๊ฐ์ด SQL ํ๊ทธ๋ก ์์ฑํด ๋ด
๋๋ค.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace="๋งคํผ ์ธํฐํ์ด์ค ๊ฒฝ๋ก" -->
<mapper namespace="com.aloha.springmybatis.mapper.BoardMapper">
<!-- ๊ฒ์๊ธ ๋ชฉ๋ก -->
<select id="list" resultType="Board">
SELECT *
FROM board
ORDER BY reg_date DESC
</select>
<!-- ๊ฒ์๊ธ ์กฐํ -->
<select id="select" resultType="Board">
SELECT *
FROM board
WHERE no = #{no}
</select>
<!-- ๊ฒ์๊ธ ๋ฑ๋ก -->
<insert id="insert">
INSERT INTO board( title, writer, content)
VALUES ( #{title}, #{writer}, #{content} )
</insert>
<!-- ๊ฒ์๊ธ ์์ -->
<update id="update">
UPDATE board
SET title = #{title}
,writer = #{writer}
,content = #{content}
WHERE no = #{no}
</update>
<!-- ๊ฒ์๊ธ ์ญ์ -->
<delete id="delete">
DELETE FROM board
WHERE no = #{no}
</delete>
<!-- ๊ฒ์๊ธ ๋ฒํธ ์ต๋๊ฐ -->
<select id="maxPk" resultType="int">
SELECT MAX(no)
FROM board
</select>
</mapper>
XML
๋ณต์ฌ
Mapper ์ธํฐํ์ด์ค ์์ฑ
๋ง์ด๋ฐํฐ์ค ๋งคํผ ์ธํฐํ์ด์ค์ ๋ฉ์๋๋ช
์ ๋งคํผ ํ์ผ์ id ์์ฑ๊ฐ๊ณผ ์ผ์นํด์ผํ๋ค.
- ํด๋น ๋ฉ์๋๊ฐ ํธ์ถ๋๋ฉด, ๋งคํผ XML ํ์ผ์ SQL๋ฅผ ์คํํ๋ค.
โข
BoardMapper.java
BoardMapper.java
@Mapper
public interface BoardMapper {
// ๊ฒ์๊ธ ๋ชฉ๋ก
public List<Board> list() throws Exception;
// ๊ฒ์๊ธ ์กฐํ
public Board select(int no) throws Exception;
// ๊ฒ์๊ธ ๋ฑ๋ก
public int insert(Board board) throws Exception;
// ๊ฒ์๊ธ ์์
public int update(Board board) throws Exception;
// ๊ฒ์๊ธ ์ญ์
public int delete(int no) throws Exception;
// ๊ฒ์๊ธ ๋ฒํธ(๊ธฐ๋ณธํค) ์ต๋๊ฐ
public int maxPk() throws Exception;
}
Java
๋ณต์ฌ
๋งคํผ ํ์ผ์ id์ ์ผ์นํ๋ ๋ฉ์๋๋ช
์ ์์ฑํ๊ณ , ๋งคํผ ํ์ผ์ SQL ํ๊ทธ์ ์ ๋ฌํด ์ค ํ๋ผ๋ฏธํฐ๋ค์ ๋งค๊ฐ๋ณ์๋ก ์์ฑํฉ๋๋ค.
๋ํ ์กฐํ ์ฟผ๋ฆฌ์ ๊ฒฝ์ฐ์๋ ์กฐํ ๊ฒฐ๊ณผ๋ฅผ ๋งคํ ๋ฐ์ ๊ฐ์ฒด ํน์ ์ปฌ๋ ์
์ ๋ฐํ ํ์
์ผ๋ก ์์ฑํ๊ณ , ๋ฑ๋ก, ์์ , ์ญ์ , ์ฟผ๋ฆฌ์ ๊ฒฝ์ฐ์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ฒ๋ฆฌ๋ ํ์ ์๋ฅผ ๋ฐํ๋ฐ๊ธฐ ์ํ์ฌ int ํ์
์ผ๋ก ์์ฑํฉ๋๋ค
Service ์์ฑ
์ด์ ์๋น์ค ์ธํฐํ์ด์ค์ ๊ตฌํ ํด๋์ค๋ฅผ ์์ฑํฉ๋๋ค.
โข
BoardService.java
โข
BoardServiceImpl.java
BoardService.java
์๋น์ค ์ธํฐํ์ด์ค๋ฅผ ํตํด์ ๋น์ฆ๋์ค ๋ก์ง์์ ์ฌ์ฉํ ๊ธฐ๋ฅ์ ๋ํ ๋ฉ์๋์ ํํ๋ฅผ ์ ์ํฉ๋๋ค. ์ด๋ ๊ฒ ์ธํฐํ์ด์ค๋ก ๋ฉ์๋ ํํ๋ฅผ ์ ์ํจ์ผ๋ก์จ, ์ค์ ๋ก ๊ตฌํํ ์ฝ๋์ ๋ํด์ ๋คํ์ฑ๊ณผ ํ์ฅ์ฑ์ ์ ๊ณตํฉ๋๋ค.
public interface BoardService {
// ๊ฒ์๊ธ ๋ชฉ๋ก
public List<Board> list() throws Exception;
// ๊ฒ์๊ธ ์กฐํ
public Board select(int no) throws Exception;
// ๊ฒ์๊ธ ๋ฑ๋ก
public int insert(Board board) throws Exception;
// ๊ฒ์๊ธ ์์
public int update(Board board) throws Exception;
// ๊ฒ์๊ธ ์ญ์
public int delete(int no) throws Exception;
}
Java
๋ณต์ฌ
BoardServiceImpl.java
๊ตฌํ ํด๋์ค์์๋ ๋งคํผ ์ธํฐํ์ด์ค์ ์ ์ ํ ๋ฉ์๋๋ก ํธ์ถํจ์ผ๋ก์จ ๋ฐ์ดํฐ์ ๋ํ์ฌ ์กฐํ, ๋ฑ๋ก, ์์ , ์ญ์ ์์ฒญ์ ๋ณด๋ผ ์ ์๋๋ก ์ฝ๋๋ฅผ ์์ฑํฉ๋๋ค. ๋ํ ๊ฐ ๋ฉ์๋์์๋ ์๋น์ค์ ๊ฐ ๊ธฐ๋ฅ์ ๋ํ ์ถ๊ฐ ๋ก์ง์ ํ์ฅํ๊ฑฐ๋ ๊ด๋ จ๋ ๋ก๊ทธ ๋ฐ ์ฒ๋ฆฌ๋ค์ ํ ์ ์์ต๋๋ค.
@Service // ์๋น์ค ์ญํ ์ ์คํ๋ง ๋น
public class BoardServiceImpl implements BoardService {
@Autowired
private BoardMapper boardMapper;
/**
* ๊ฒ์๊ธ ๋ชฉ๋ก ์กฐํ
*/
@Override
public List<Board> list() throws Exception {
// TODO : boardMapper ๋ก list() ํธ์ถ
/*
* โก List<Board> boardList ๋ก ๋ฐ์์ด
* โก return boardList
*/
List<Board> boardList = boardMapper.list();
return boardList;
}
/**
* ๊ฒ์๊ธ ์กฐํ
* - no ๋งค๊ฐ๋ณ์๋ก ๊ฒ์๊ธ ๋ฒํธ๋ฅผ ์ ๋ฌ๋ฐ์์
* ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์กฐํ ์์ฒญ
*/
@Override
public Board select(int no) throws Exception {
// TODO : boardMapper ๋ก select(no) ํธ์ถ
/*
* โก Board board ๋ก ๋ฐ์์ด
* โก return board
*/
Board board = boardMapper.select(no);
return board;
}
/**
* ๊ฒ์๊ธ ๋ฑ๋ก
*/
@Override
public int insert(Board board) throws Exception {
// TODO : boardMapper ๋ก insert(Board) ํธ์ถ
/*
* โก int result ๋ก ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ(๊ฐ์) ๋ฐ์์ด
* โก return result
*/
int result = boardMapper.insert(board);
return result;
}
/**
* ๊ฒ์๊ธ ์์
*/
@Override
public int update(Board board) throws Exception {
// TODO : boardMapper ๋ก update(Board) ํธ์ถ
/*
* โก int result ๋ก ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ(๊ฐ์) ๋ฐ์์ด
* โก return result
*/
int result = boardMapper.update(board);
return result;
}
/**
* ๊ฒ์๊ธ ์ญ์
*/
@Override
public int delete(int no) throws Exception {
// TODO : boardMapper ๋ก delete(no) ํธ์ถ
/*
* โก int result ๋ก ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ(๊ฐ์) ๋ฐ์์ด
* โก return result
*/
int result = boardMapper.delete(no);
return result;
}
}
Java
๋ณต์ฌ
Controller ์์ฑ
์ปจํธ๋กค๋ฌ์์๋ ์์ฒญ ๊ฒฝ๋ก๋ฅผ ๋งคํํ์ฌ ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ๋ํ์ฌ ์ ์ ํ ์๋น์ค ๋ก์ง ๋ฐ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ณ , ํด๋ผ์ด์ธํธ์๊ฒ ์๋ตํ ๋ทฐ ํ์ด์ง๋ฅผ ์ง์ ํฉ๋๋ค.
์์ฒญ ๊ฒฝ๋ก ๋งคํ
๋ฐ์ดํฐ ์์ฒญ
๋ทฐ ํ์ด์ง ์ง์
BoardController.java
package com.aloha.springmybatis.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.aloha.springmybatis.dto.Board;
import com.aloha.springmybatis.service.BoardService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
/**
* /board ๊ฒฝ๋ก๋ก ์์ฒญ ์์ ๋ ์ฒ๋ฆฌ
* [GET] - /board/list : ๊ฒ์๊ธ ๋ชฉ๋ก ํ๋ฉด
* [GET] - /board/read : ๊ฒ์๊ธ ์กฐํ ํ๋ฉด
* [GET] - /board/insert : ๊ฒ์๊ธ ๋ฑ๋ก ํ๋ฉด
* [POST] - /board/insert : ๊ฒ์๊ธ ๋ฑ๋ก ์ฒ๋ฆฌ
* [GET] - /board/update : ๊ฒ์๊ธ ์์ ํ๋ฉด
* [POST] - /board/update : ๊ฒ์๊ธ ์์ ์ฒ๋ฆฌ
* [POST] - /board/delete : ๊ฒ์๊ธ ์ญ์ ์ฒ๋ฆฌ
*/
@Slf4j // ๋ก๊ทธ ์ด๋
ธํ
์ด์
@Controller // ์ปจํธ๋กค๋ฌ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋ก
@RequestMapping("/board") // ํด๋ ์ค ๋ ๋ฒจ ์์ฒญ ๊ฒฝ๋ก ๋งคํ
// - /board/~ ๊ฒฝ๋ก์ ์์ฒญ์ ์ด ์ปจํธ๋กค๋ฌ์์ ์ฒ๋ฆฌ
public class BoardController {
// โญ๋ฐ์ดํฐ ์์ฒญ๊ณผ ํ๋ฉด ์ถ๋ ฅ
// Controller --> Service (๋ฐ์ดํฐ ์์ฒญ)
// Controller <-- Service (๋ฐ์ดํฐ ์ ๋ฌ)
// Controller --> Model (๋ชจ๋ธ ๋ฑ๋ก)
// View <-- Model (๋ฐ์ดํฐ ์ถ๋ ฅ)
@Autowired // ์์กด์ฑ ์๋ ์ฃผ์
private BoardService boardService; // @Service๋ฅผ --Impl ์ ๋ฑ๋ก
/**
* ๊ฒ์๊ธ ๋ชฉ๋ก ์กฐํ ํ๋ฉด
* @return
* @throws Exception
*/
@GetMapping("/list")
public String list(Model model) throws Exception {
// ๋ฐ์ดํฐ ์์ฒญ
List<Board> boardList = boardService.list();
// ๋ชจ๋ธ ๋ฑ๋ก
model.addAttribute("boardList", boardList);
// ๋ทฐ ํ์ด์ง ์ง์
return "/board/list"; // resources/templates/board/list.html
}
/**
* ๊ฒ์๊ธ ์กฐํ ํ๋ฉด
* - /board/read?no=๐
* @param no
* @return
* @throws Exception
*/
// @RequestParam("ํ๋ผ๋ฏธํฐ๋ช
")
// - ์คํ๋ง ๋ถํธ 3.2๋ฒ์ ์ดํ, ์๋ตํด๋ ์๋ ๋งคํ๋๋ค.
// - ์คํ๋ง ๋ถํธ 3.2๋ฒ์ ์ด์, ํ์๋ก ๋ช
์ํด์ผ ๋งคํ๋๋ค.
@GetMapping("/read")
public String read(@RequestParam("no") int no, Model model) throws Exception {
// ๋ฐ์ดํฐ ์์ฒญ
Board board = boardService.select(no);
// ๋ชจ๋ธ ๋ฑ๋ก
model.addAttribute("board", board);
// ๋ทฐํ์ด์ง ์ง์
return "/board/read";
}
/**
* ๊ฒ์๊ธ ๋ฑ๋ก ํ๋ฉด
* @return
*/
@GetMapping("/insert")
public String insert() {
return "/board/insert";
}
/**
* ๊ฒ์๊ธ ๋ฑ๋ก ์ฒ๋ฆฌ
* @param board
* @return
* @throws Exception
*/
@PostMapping("/insert")
public String insertPro(Board board) throws Exception {
// ๋ฐ์ดํฐ ์์ฒญ
int result = boardService.insert(board);
// ๋ฆฌ๋ค์ด๋ ํธ
// โญ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์ฑ๊ณต
if( result > 0 ) {
return "redirect:/board/list";
}
// โ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์คํจ
return "redirect:/board/insert?error";
}
/**
* ๊ฒ์๊ธ ์์ ํ๋ฉด
* @param no
* @param model
* @return
* @throws Exception
*/
@GetMapping("/update")
public String update(@RequestParam("no") int no, Model model) throws Exception {
Board board = boardService.select(no);
model.addAttribute("board", board);
return "/board/update";
}
/**
* ๊ฒ์๊ธ ์์ ์ฒ๋ฆฌ
* @param board
* @return
* @throws Exception
*/
@PostMapping("/update")
public String updatePro(Board board) throws Exception {
int result = boardService.update(board);
if( result > 0 ) {
return "redirect:/board/list";
}
int no = board.getNo();
return "redirect:/board/update?no="+ no + "&error";
}
/**
* ๊ฒ์๊ธ ์ญ์ ์ฒ๋ฆฌ
* @param no
* @return
* @throws Exception
*/
@PostMapping("/delete")
public String delete(@RequestParam("no") int no) throws Exception {
int result = boardService.delete(no);
if( result > 0 ) {
return "redirect:/board/list";
}
return "redirect:/board/update?no=" + no + "&error";
}
}
Java
๋ณต์ฌ
View ์์ฑ
โข
board
โฆ
list.html
โฆ
insert.html
โฆ
read.html
โฆ
update.html
โข
index.html
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>๋ฉ์ธ ํ๋ฉด</title>
</head>
<body>
<h1>SpringBoot x MyBatis</h1>
<h3>๊ฒ์ํ ํ๋ก์ ํธ</h3>
<ul>
<li>Spring Boot 3.x</li>
<li>Thymeleaf</li>
<li>MySQL 8.x</li>
<li>MyBatis 3.0</li>
</ul>
<div>
<a href="/board/list">๊ฒ์ํ</a>
</div>
</body>
</html>
HTML
๋ณต์ฌ
โข
board
list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>๊ฒ์๊ธ ๋ชฉ๋ก</title>
</head>
<body>
<h1>๊ฒ์๊ธ ๋ชฉ๋ก</h1>
<a href="/board/insert">๊ธ์ฐ๊ธฐ</a>
<table border="1">
<tr>
<th width="50">๋ฒํธ</th>
<th width="300">์ ๋ชฉ</th>
<th width="100">์์ฑ์</th>
<th width="200">๋ฑ๋ก์ผ์</th>
<th width="200">์์ ์ผ์</th>
<th widht="100">์กฐํ์</th>
</tr>
<th:block th:each="board : ${boardList}">
<tr>
<td align="center" th:text="${board.no}"></td>
<td>
<!-- th:???="|๋ฌธ์์ด+${ํํ์}|" -->
<a th:href="|/board/read?no=${board.no}|"
th:text="${board.title}"></a>
</td>
<td align="center" th:text="${board.writer}"></td>
<!--
์ ํธ๋ฆฌํฐ๊ฐ์ฒด.๋ฉ์๋()
#dates.format( ๋ ์ง๊ฐ์ฒด๋ช
, '๋ ์งํฌ๋งท' )
- #dates.format( board.regDate, 'yyyy-MM-dd HH:mm:ss' )
-->
<td align="center">
<span th:text="${ #dates.format( board.regDate, 'yyyy-MM-dd HH:mm:ss' ) }"></span>
</td>
<td align="center">
<span th:text="${ #dates.format( board.updDate, 'yyyy-MM-dd HH:mm:ss' ) }"></span>
</td>
<td align="center" th:text="${board.views}"></td>
</tr>
</th:block>
</table>
</body>
</html>
HTML
๋ณต์ฌ
insert.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>๊ฒ์๊ธ ๋ฑ๋ก</title>
</head>
<body>
<h1>๊ฒ์๊ธ ๋ฑ๋ก</h1>
<form action="/board/insert" method="post">
<input type="text" name="title" id="title">
<input type="text" name="writer" id="writer">
<input type="text" name="content" id="content">
<input type="submit" value="๋ฑ๋ก">
</form>
</body>
</html>
HTML
๋ณต์ฌ
read.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>๊ฒ์๊ธ ์กฐํ</title>
</head>
<body>
<h1>๊ฒ์๊ธ ์กฐํ</h1>
<form action="/board/delete" method="post">
<input type="hidden" name="no" th:value="${board.no}">
<table>
<tr>
<td>์ ๋ชฉ</td>
<td>
<input type="text" name="title" th:value="${board.title}">
</td>
</tr>
<tr>
<td>์์ฑ์</td>
<td>
<input type="text" name="writer" th:value="${board.writer}">
</td>
</tr>
<tr>
<td colspan="2">
<textarea name="content" id="content" cols="40" rows="5"
th:text="${board.content}"></textarea>
</td>
</tr>
</table>
<div>
<button type="button" onclick="moveUpdate()">์์ </button>
<button type="button" onclick="moveList()">๋ชฉ๋ก</button>
</div>
</form>
<script>
// ๐ฉโ๐ป ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ
let no = "[[${board.no}]]"
// ์์ ํ๋ฉด ์ด๋
function moveUpdate() {
location.href = '/board/update?no=' + no
}
// ๋ชฉ๋ก ํ๋ฉด ์ด๋
function moveList() {
location.href = '/board/list'
}
</script>
</body>
</html>
HTML
๋ณต์ฌ
update.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>๊ฒ์๊ธ ์์ </title>
</head>
<body>
<h1>๊ฒ์๊ธ ์์ </h1>
<form id="form" action="/board/update" method="post">
<input type="hidden" name="no" th:value="${board.no}">
<table>
<tr>
<td>์ ๋ชฉ</td>
<td>
<input type="text" name="title" th:value="${board.title}">
</td>
</tr>
<tr>
<td>์์ฑ์</td>
<td>
<input type="text" name="writer" th:value="${board.writer}">
</td>
</tr>
<tr>
<td colspan="2">
<textarea name="content" id="content" cols="40" rows="5"
th:text="${board.content}"></textarea>
</td>
</tr>
</table>
<div>
<button type="submit">์์ </button>
<button type="button" onclick="actionDelete()">์ญ์ </button>
<button type="button" onclick="moveList()">๋ชฉ๋ก</button>
</div>
</form>
<script>
let form = document.getElementById('form')
// ๐ฉโ๐ป ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ
let no = "[[${board.no}]]"
// ์์ ํ๋ฉด ์ด๋
function moveUpdate() {
location.href = '/board/update?no=' + no
}
// ์ญ์ ์์ฒญ
function actionDelete() {
let check = confirm('์ ๋ง๋ก ์ญ์ ํ์๊ฒ ์ต๋๊น?')
if( check ) {
form.action = '/board/delete'
form.submit()
}
}
// ๋ชฉ๋ก ํ๋ฉด ์ด๋
function moveList() {
location.href = '/board/list'
}
</script>
</body>
</html>
HTML
๋ณต์ฌ
๊ธฐ๋ฅ ๋ช
์ธ์
โข
๊ฒ์๊ธ ๋ฑ๋ก
โข
๊ฒ์๊ธ ๋ชฉ๋ก ์กฐํ
โข
๊ฒ์๊ธ ์กฐํ
โข
๊ฒ์๊ธ ์์
โข
๊ฒ์๊ธ ์ญ์
๊ฒ์๊ธ ๋ฑ๋ก
๊ฒ์๊ธ ๋ฑ๋ก ์, ์ฌ์ฉ์๊ฐ /board/insert.html ์์ ๊ฒ์๊ธ ์ ๋ณด (์ ๋ชฉ, ์์ฑ์, ๋ด์ฉ)๋ฅผ ์
๋ ฅํ๊ณ , ์ฌ๋ฌ ํ์ผ์ ์ฒจ๋ถํ์ฌ ์์ฒญํ๋ค.
โข
๊ฒ์๊ธ ์ ๋ณด ๋ฑ๋ก
โข
ํ์ผ ์
๋ก๋
๊ฒ์๊ธ ์ ๋ณด ๋ฑ๋ก
โข
Model
โฆ
BoardService.java
โช
insert(Board)
โฆ
BoardServiceImpl.java
โช
insert(Board)
โข
๊ฒ์๊ธ ์ ๋ณด ๋ฑ๋ก
โฆ
BoardMapper ์ insert(Board) ํธ์ถ
โข
ํ์ผ ์
๋ก๋
โฆ
FileService ์ upload(List<Files>) ํธ์ถ
โฆ
BoardMapper.java
โช
insert(Board)
โข
BoardMapper.xml ์ id=โinsertโ ์ฟผ๋ฆฌ์ ์ฐ๊ฒฐ
โฆ
BoardMapper.xml
โช
<insert id=โinsertโ โฆ >
โข
์ ์ฉ๋ ๋ฐ์ดํฐ ํ์ ์๋ฅผ ๋ฐํ ( 0 ๋๋ 1 )
โข
View
โฆ
~/board/insert.html
โช
[POST] ๋ฐฉ์์ผ๋ก FORM ์์ฒญ
โข
ํ๋ผ๋ฏธํฐ
โฆ
์ ๋ชฉ : title
โฆ
์์ฑ์ : writer
โฆ
๋ด์ฉ : content
โฆ
ํ์ผ : file
โข
Controller
โฆ
BoardController.java
โช
@GetMapping(โ/board/insertโ)
โข
์๋ต
โฆ
/board/insert
โช
@PostMapping(โ/board/insertโ)
โข
@RequestBody Board board
โข
BoardService ์ insert() ๋ฉ์๋ ์์ฒญ
โข
์๋ต
โฆ
์์ฒญ ์ฑ๊ณต : (redirect) /board/list
โฆ
์์ฒญ ์คํจ : (redirect) /board/insert?error
๊ฒ์๊ธ ๋ชฉ๋ก ์กฐํ
๊ฒ์๊ธ ์ ์ ์ฒด ๋ชฉ๋ก์ ์กฐํํฉ๋๋ค.
โข
๊ฒ์๊ธ ๋ชฉ๋ก ์ ์ฒด ์กฐํ
๊ฒ์๊ธ ๋ชฉ๋ก - MVC
โข
Model : BoardService
โข
View : /board/list.html
โข
Controller : BoardController.java
๊ฒ์๊ธ ๋ชฉ๋ก ์กฐํ
โข
Model
โฆ
BoardService.java
โช
list()
โฆ
BoardServiceImpl.java
โช
list()
โฆ
BoardMapper.java
โช
list()
โข
BoardMapper.xml ์ id=โlistโ ์ฟผ๋ฆฌ์ ์ฐ๊ฒฐ
โฆ
BoardMapper.xml
โช
<seledct id=โlistโ resultType=โBoardโ โฆ >
โข
resultType=โBoardโ
โฆ
์กฐํ๋ board ํ
์ด๋ธ์ Board ๊ฐ์ฒด๋ก ๋งคํ
โข
View
โฆ
~/board/list.html
โข
Controller
โฆ
BoardController.java
โช
@GetMapping(โ/board/listโ)
โข
Model boardList
โข
์๋ต
โฆ
/board/list
๊ฒ์๊ธ ์กฐํ
๊ฒ์๊ธ ์ ๋ณด ํ ๊ฑด์ ์กฐํํฉ๋๋ค.
โข
๊ฒ์๊ธ ์ ๋ณด ์กฐํ
โข
์ฒจ๋ถ ํ์ผ ๋ชฉ๋ก ์กฐํ
๊ฒ์๊ธ ์ ๋ณด ์กฐํ
โข
Model
โฆ
BoardService.java
โช
select(no)
โฆ
BoardServiceImpl.java
โช
select(no)
โฆ
BoardMapper.java
โช
select(no)
โข
BoardMapper.xml ์ id=โselectโ ์ฟผ๋ฆฌ์ ์ฐ๊ฒฐ
โฆ
BoardMapper.xml
โช
<seledct id=โselectโ resultType=โBoardโ โฆ >
โข
resultType=โBoardโ
โฆ
์กฐํ๋ board ํ
์ด๋ธ์ Board ๊ฐ์ฒด๋ก ๋งคํ
โข
View
โฆ
~/board/read.html
โข
Controller
โฆ
BoardController.java
โช
@GetMapping(โ/board/readโ)
โข
Model board
โข
์๋ต
โฆ
/board/read
๊ฒ์๊ธ ์์
๊ฒ์๊ธ ์ ๋ณด ํ ๊ฑด์ ์์ ํฉ๋๋ค.
โข
๊ฒ์๊ธ ์ ๋ณด ์์
โข
ํ์ผ ์ญ์ (AJAX)
๊ฒ์๊ธ ์ ๋ณด ์์
โข
Model
โฆ
BoardService.java
โช
update(board)
โฆ
BoardServiceImpl.java
โช
update(board)
โฆ
BoardMapper.java
โช
update(board)
โข
BoardMapper.xml ์ id=โupdateโ ์ฟผ๋ฆฌ์ ์ฐ๊ฒฐ
โฆ
BoardMapper.xml
โช
<update id=โupdateโ โฆ >
โข
์ ์ฉ๋ ๋ฐ์ดํฐ ํ์ ์๋ฅผ ๋ฐํ ( 0 ๋๋ 1 )
โข
View
โฆ
~/board/update.html
โข
Controller
โฆ
BoardController.java
โช
@GetMapping(โ/board/updateโ)
โข
Model board
โข
์๋ต
โฆ
/board/update
โช
@PostMapping(โ/board/updateโ)
โข
@RequestBody Board board
โข
BoardService ์ update() ๋ฉ์๋ ์์ฒญ
โข
์๋ต
โฆ
์์ฒญ ์ฑ๊ณต : (redirect) /board/list
โฆ
์์ฒญ ์คํจ : (redirect) /board/update?error
๊ฒ์๊ธ ์ญ์
๊ฒ์๊ธ ์ ๋ณด ํ ๊ฑด์ ์ญ์ ํฉ๋๋ค.
โข
๊ฒ์๊ธ ์ญ์
โข
์ฒจ๋ถ ํ์ผ ์ญ์
๊ฒ์๊ธ ์ญ์
โข
Model
โฆ
BoardService.java
โช
delete(no)
โฆ
BoardServiceImpl.java
โช
delete(no)
โฆ
BoardMapper.java
โช
delete(no)
โข
BoardMapper.xml ์ id=โdeleteโ ์ฟผ๋ฆฌ์ ์ฐ๊ฒฐ
โฆ
BoardMapper.xml
โช
<delete id=โdeleteโ โฆ >
โข
์ ์ฉ๋ ๋ฐ์ดํฐ ํ์ ์๋ฅผ ๋ฐํ ( 0 ๋๋ 1 )
โข
View
โฆ
~/board/update.html ์์ [์ญ์ ] ๋ฒํผ์ผ๋ก ์์ฒญ
โข
Controller
โฆ
BoardController.java
โช
@GetMapping
โข
โช
@PostMapping(โ/board/deleteโ)
โข
@RequestBody Board board
โข
BoardService ์ delete() ๋ฉ์๋ ์์ฒญ
โข
์๋ต
โฆ
์์ฒญ ์ฑ๊ณต : (redirect) /board/list
โฆ
์์ฒญ ์คํจ : (redirect) /board/update?error