Search

μˆ˜μ—…

μˆ˜μ—…

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

REST API 기반 κ²Œμ‹œνŒ ν”„λ‘œμ νŠΈ

μ§ˆμ˜μ‘λ‹΅