html
์คํ๋ง ๋ถํธ API ํฅ์: RESTful ๊ท์น ์ค์ ๋ฐ ๋ณด์ ๊ฐํ
๋ชฉ์ฐจ
- ์๊ฐ .......................................................... 1
- RESTful API ๊ท์น ์ดํดํ๊ธฐ ... 3
- REST ์ค์๋ฅผ ์ํ URL ํจํด ์ ๋ฐ์ดํธ .......................................................... 7
- ์คํ๋ง ๋ถํธ์์ ๋ณด์ ์ค์ ๊ตฌ์ฑ ................................................................................................................... 12
- ํ ํฐ ๊ธฐ๋ฐ ์ธ์ฆ ๊ตฌํ ................................................................. 18
- ์ค๋ฅ ์ฒ๋ฆฌ ๋ฐ ์๋ต ์ฝ๋ ............. 25
- Swagger ๋ฌธ์๋ฅผ ์ฌ์ฉํ ํ ์คํธ ......... 30
- ๊ฒฐ๋ก ............................................................ 35
- ์ถ๊ฐ ์๋ฃ ....................................... 38
์๊ฐ
๋์์์ด ์งํํ๋ ์น ๊ฐ๋ฐ ํ๊ฒฝ์์ ๊ฒฌ๊ณ ํ๊ณ ์์ ํ API๋ฅผ ๋ง๋๋ ๊ฒ์ ๋งค์ฐ ์ค์ํฉ๋๋ค. ์ด ์ ์์ฑ ์ RESTful ๊ท์น์ ์ค์ํ๊ณ ๋ณด์ ์กฐ์น๋ฅผ ๊ฐํํ์ฌ ์คํ๋ง ๋ถํธ API๋ฅผ ํฅ์์ํค๋ ๋ฐฉ๋ฒ์ ๋ค๋ฃน๋๋ค. URL ๊ตฌ์กฐํ, ๋ณด์ ์ค์ , ํ ํฐ ๊ธฐ๋ฐ ์ธ์ฆ, ์ค๋ฅ ์ฒ๋ฆฌ ๋ฐ Swagger ๋ฌธ์๋ฅผ ์ฌ์ฉํ ์ฒ ์ ํ ํ ์คํธ๋ฅผ ์ํ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ํ๊ตฌํ ๊ฒ์ ๋๋ค. ์ด๋ณด์์ด๋ ๊ธฐ๋ณธ ์ง์์ ๊ฐ์ง ๊ฐ๋ฐ์์ด๋ ๊ด๊ณ์์ด ์ด ๊ฐ์ด๋๋ API ๊ฐ๋ฐ ๊ธฐ์ ์ ํฅ์์ํค๋ ๋ช ํํ๊ณ ๊ฐ๊ฒฐํ๋ฉฐ ์คํ ๊ฐ๋ฅํ ํต์ฐฐ๋ ฅ์ ์ ๊ณตํฉ๋๋ค.
์ฃผ์ ํ์ด๋ผ์ดํธ
- RESTful ๊ท์น: ์ฐ์ ํ์ค URL ํจํด ์ดํด ๋ฐ ๊ตฌํ.
- ๋ณด์ ํฅ์: ์คํ๋ง ๋ถํธ๋ฅผ ๊ตฌ์ฑํ์ฌ ๊ถํ ๋ถ์ฌ ๋ฐ ์ธ์ฆ์ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌ.
- ํ ํฐ ๊ด๋ฆฌ: JWT ํ ํฐ์ ํ์ฉํ์ฌ ์์ ํ API ์ ๊ทผ.
- ์ค๋ฅ ์ฒ๋ฆฌ: ๋ค์ํ ์๋๋ฆฌ์ค๋ฅผ ์ฐ์ํ๊ฒ ์ฒ๋ฆฌํ๊ธฐ ์ํ ์ ์ ํ ์๋ต ์ฝ๋ ๊ตฌํ.
- ํ ์คํธ ๋ฐ ๋ฌธ์ํ: Swagger๋ฅผ ํ์ฉํ์ฌ API ํ ์คํธ ๋ฐ ๋ฌธ์ํ.
์ฅ๋จ์
์ฅ์ | ๋จ์ |
---|---|
์ฐ์ ํ์ค API ์ค๊ณ ๋ณด์ฅ | ์ด๊ธฐ ์ค์ ์ ํ์ต ๊ณก์ ์ด ํ์ํ ์ ์์ |
๊ฒฌ๊ณ ํ ๊ตฌ์ฑ์ผ๋ก ๋ณด์ ๊ฐํ | ๊ฐ๋จํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฒฝ์ฐ ๋ณต์ก์ฑ์ด ์ฆ๊ฐํ ์ ์์ |
์ ์ง๋ณด์ ๋ฐ ํ์ฅ์ฑ ์ฉ์ด | ์ฒ ์ ํ ํ ์คํธ ๋ฐ ๊ฒ์ฆ์ด ํ์ํจ |
๋ช ํํ ๋ฌธ์๋ฅผ ํตํด ๊ฐ๋ฐ์ ๋ฐ ์ฌ์ฉ์ ๊ฒฝํ ๊ฐ์ | ๋ณด์ ๋ ์ด์ด๊ฐ ์ถ๊ฐ๋๋ฉด์ ์ฑ๋ฅ ์ค๋ฒํค๋ ๊ฐ๋ฅ์ฑ |
์ธ์ ๊ทธ๋ฆฌ๊ณ ์ด๋์ ์ฌ์ฉํ ๊ฒ์ธ๊ฐ
ํ์ฅ์ฑ, ๋ณด์์ฑ ๋ฐ ์ ์ง๋ณด์์ฑ์ด ํ์ํ API๋ฅผ ๊ฐ๋ฐํ ๋ ์ด๋ฌํ ๊ดํ์ ๊ตฌํํ์ญ์์ค. ๋ฏผ๊ฐํ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ณ , ์ฌ์ฉ์ ์ธ์ฆ์ด ํ์ํ๋ฉฐ, ๋์ ์ ๋ขฐ์ฑ์ ๋ชฉํ๋ก ํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด์์ ์ ๋๋ค.
RESTful API ๊ท์น ์ดํดํ๊ธฐ
REST(Representational State Transfer)๋ ํ์ฅ ๊ฐ๋ฅํ๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ์น ์๋น์ค๋ฅผ ์์ฑํ๊ธฐ ์ํ ํ์คํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ ์ํคํ ์ฒ ์คํ์ผ์ ๋๋ค. RESTful ๊ท์น์ ์ค์ํ๋ฉด API๊ฐ ์ง๊ด์ ์ด๊ณ ์ผ๊ด๋๋ฉฐ ํด๋ผ์ด์ธํธ๊ฐ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๊ฒ ๋ฉ๋๋ค.
REST์ ํต์ฌ ์์น
- ๋ฌด์ํ์ฑ(Statelessness): ํด๋ผ์ด์ธํธ์ ๊ฐ ์์ฒญ์ ์์ฒญ์ ์ฒ๋ฆฌํ๋ ๋ฐ ํ์ํ ๋ชจ๋ ์ ๋ณด๋ฅผ ํฌํจํฉ๋๋ค.
- ํด๋ผ์ด์ธํธ-์๋ฒ ์ํคํ ์ฒ: ํด๋ผ์ด์ธํธ์ ์๋ฒ ๊ฐ์ ๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ๋ ํ์ฅ์ฑ์ ํฅ์์ํต๋๋ค.
- ์ผ๊ด๋ ์ธํฐํ์ด์ค(Uniform Interface): ๋ฆฌ์์ค์ ์ํธ์์ฉํ๊ธฐ ์ํ ์ผ๊ด๋๊ณ ํ์คํ๋ ์ ๊ทผ ๋ฐฉ์.
- ๊ณ์ธตํ ์์คํ (Layered System): ๊ณ์ธต์ ๊ตฌ์กฐ๋ก ๊ตฌ์ฑ๋ ์ํคํ ์ฒ๋ฅผ ํ์ฉํฉ๋๋ค.
์ผ๋ฐ์ ์ธ RESTful URL ํจํด
- ๋ช ์ฌ๋ก์์ ๋ฆฌ์์ค: URL์ ๋ฆฌ์์ค๋ฅผ ๋ํ๋ด์ผ ํฉ๋๋ค(์: /users, /orders).
- HTTP ๋ฉ์๋ ์ฌ์ฉ:
- GET: ๋ฆฌ์์ค ์กฐํ.
- POST: ์๋ก์ด ๋ฆฌ์์ค ์์ฑ.
- PUT: ๊ธฐ์กด ๋ฆฌ์์ค ์ ๋ฐ์ดํธ.
- DELETE: ๋ฆฌ์์ค ์ญ์ .
- ๊ณ์ธต์ ๊ตฌ์กฐ: ์ค์ฒฉ๋ ๋ฆฌ์์ค๋ ๊ทธ ๊ด๊ณ๋ฅผ ๋ฐ์ํด์ผ ํฉ๋๋ค(์: /users/{userId}/orders).
RESTful ๊ท์น ์ค์์ ์ด์
- ์ผ๊ด์ฑ: ๊ฐ๋ฐ์๊ฐ API๋ฅผ ์ดํดํ๊ณ ์ฌ์ฉํ๊ธฐ ์ฝ์ต๋๋ค.
- ํ์ฅ์ฑ: API์ ํ์ฅ ๋ฐ ์ ์ง๋ณด์๊ฐ ๊ฐ๋จํด์ง๋๋ค.
- ์ํธ์ด์ฉ์ฑ: ๋ค์ํ ํด๋ผ์ด์ธํธ ๋ฐ ์๋น์ค์์ ํธํ์ฑ์ด ํฅ์๋ฉ๋๋ค.
REST ์ค์๋ฅผ ์ํ URL ํจํด ์ ๋ฐ์ดํธ
API์ URL ํจํด์ด RESTful ๊ท์น์ ์ค์ํ๋๋ก ํ๋ ๊ฒ์ ์ง๊ด์ ์ด๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ์น ์๋น์ค๋ฅผ ์์ฑํ๋ ๋ฐ ์ค์ํฉ๋๋ค. ์ด ์น์ ์์๋ ์ฐ์ ํ์ค์ ๋ฐ๋ฅด๊ธฐ ์ํด ์คํ๋ง ๋ถํธ API์ URL ๊ตฌ์กฐ๋ฅผ ์ ๋ฐ์ดํธํ๋ ๋ฐฉ๋ฒ์ ์๋ดํฉ๋๋ค.
ํ์ฌ URL ํจํด ๋ฌธ์ ์
์ ๊ณต๋ ๊ฐ์์์๋ ์ด๊ธฐ URL ํจํด์ด RESTful ํ์ค์ ์ค์ํ์ง ์์์ต๋๋ค. ํนํ, ์ํฐํฐ ์๋ณ์(userId)๊ฐ URL ๋ด์์ ์ฌ๋ฐ๋ฅด๊ฒ ์์นํ์ง ์์ ๋ถ์ผ์น ๋ฐ ์ ์ฌ์ ์ธ ๋ณด์ ๊ฒฐํจ์ ์ด๋ํ์ต๋๋ค.
URL ๊ตฌ์กฐ ์์
์๋ชป๋ URL ๊ตฌ์กฐ:
1 |
/user/updateAuthorities |
RESTful URL ๊ตฌ์กฐ:
1 |
/users/{userId}/authorities |
๊ตฌํ ๋จ๊ณ
- URL์ ์ํฐํฐ ์ ์:
- userId๋ฅผ ๋ฆฌ์์ค์ ๋์ ์ฌ์ด์ ์์น์ํต๋๋ค.
- ์ปจํธ๋กค๋ฌ ๋งคํ ์
๋ฐ์ดํธ:
- ์๋ก์ด URL ๊ตฌ์กฐ๋ฅผ ๋ฐ์ํ๋๋ก ์ปจํธ๋กค๋ฌ์ @RequestMapping ์ ๋ ธํ ์ด์ ์ ์์ ํฉ๋๋ค.
- ์คํ๋ง ๋ถํธ์์์ ์
๋ฐ์ดํธ ์์:
12345678910111213@RestController@RequestMapping("/users")public class AuthController {@PutMapping("/{userId}/authorities")public ResponseEntity<AccountViewDTO> updateAuthorities(@PathVariable Long userId,@RequestBody AuthoritiesDTO authoritiesDTO) {// ๋ฉ์๋ ๊ตฌํ}}
์ ๋ฐ์ดํธ๋ ๊ตฌ์กฐ์ ์ด์
- ๋ช ํ์ฑ: ๋ฆฌ์์ค(users)์ ํน์ ์ฌ์ฉ์({userId})๋ฅผ ๋ช ํํ๊ฒ ๋ํ๋ ๋๋ค.
- ํ์ฅ์ฑ: ์ฌ์ฉ์์ ๊ด๋ จ๋ ์ถ๊ฐ ๋์์ ์ฝ๊ฒ ํ์ฅํ ์ ์์ต๋๋ค.
- ์ผ๊ด์ฑ: RESTful API ํ์ค๊ณผ ์ผ์นํ์ฌ ๊ฐ๋ฐ์์๊ฒ ๋ ์ง๊ด์ ์ ๋๋ค.
URL ๊ตฌ์กฐ์ ํ ๋น๊ต
์ธก๋ฉด | RESTful์ด ์๋ URL | RESTful URL |
---|---|---|
์ํฐํฐ ์์น | ์๋ํฌ์ธํธ์ ๋์ ํฌํจ | ๊ฒฝ๋ก ์ธ๊ทธ๋จผํธ์ ์ํฐํฐ ์๋ณ์ ํฌํจ |
HTTP ๋ฉ์๋ ์ฌ์ฉ | HTTP ๋ฉ์๋ ํ์ฉ๋์ง ์์ | ์ ์ ํ HTTP ๋ฉ์๋ ํ์ฉ |
ํ์ฅ์ฑ | ํ์ฅ์ฑ ์ ํ๋จ | ์ค์ฒฉ๋ ๊ฒฝ๋ก๋ก ๋์ ํ์ฅ์ฑ |
๋ช ํ์ฑ | ๋์ ์งํฅ์ | ๋ฆฌ์์ค ์งํฅ์ |
์คํ๋ง ๋ถํธ์์ ๋ณด์ ์ค์ ๊ตฌ์ฑ
๋ณด์์ API ๊ฐ๋ฐ์ ์ค์ํ ์ธก๋ฉด์ ๋๋ค. ๋ณด์ ์ค์ ์ ์ ์ ํ ๊ตฌ์ฑํ๋ฉด ์น์ธ๋ ์ฌ์ฉ์๋ง์ด ๋ฆฌ์์ค์ ์ ๊ทผํ๊ฑฐ๋ ์์ ํ ์ ์๋๋ก ๋ณด์ฅ๋ฉ๋๋ค. ์ด ์น์ ์์๋ ์ ๋ฐ์ดํธ๋ RESTful URL ํจํด์ ๋ง๊ฒ ์คํ๋ง ๋ถํธ์์ ๋ณด์์ ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ์ ํ๊ตฌํฉ๋๋ค.
์ด๊ธฐ ๋ณด์ ๊ตฌ์ฑ ๋ฌธ์ ์
์ด๊ธฐ ๋ณด์ ์ค์ ์์๋ ๋จ์ผ ์์ผ๋์นด๋ ๋ฌธ์(*)๋ฅผ ์ฌ์ฉํ์ฌ ํ๊ณ๊ฐ ์์์ต๋๋ค:
- ์ ์ฐ์ฑ ๋ถ์กฑ: * ์์ผ๋์นด๋๋ ๊ด๋ฒ์ํ๊ฒ ์ ์ฉ๋๋ฉฐ ํน์ URL ํจํด์ ์ถฉ์กฑํ์ง ๋ชปํ ์ ์์ต๋๋ค.
- ์ ์ฌ์ ์ค๋ฅ: ๋ถ์ ์ ํ ์์ผ๋์นด๋ ์ฌ์ฉ์ ์ ํ๋ฆฌ์ผ์ด์ ์ถฉ๋์ด๋ ์๋ํ์ง ์์ ์ ๊ทผ ๊ถํ์ ์ด๋ํ ์ ์์ต๋๋ค.
๊ณ ๊ธ ์์ผ๋์นด๋ ์ฑํ
๋ณด์ ์ค์ ์ ๊ฐํํ๊ธฐ ์ํด ๋ ์ ๋ฐํ ์์ผ๋์นด๋ ํจํด์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ํนํ, * ๋์ /**๋ฅผ ์ฌ์ฉํ๋ฉด ์์ผ๋์นด๋๊ฐ URL ๊ฒฝ๋ก ์ ์ฒด์ ์ฌ๋ฐ๋ฅด๊ฒ ์ ์ฉ๋ฉ๋๋ค.
๊ตฌํ ๋จ๊ณ
- ๋ณด์ ๊ตฌ์ฑ ์
๋ฐ์ดํธ:
- URL ๋งคํ์ ์์ผ๋์นด๋ ํจํด์ ์กฐ์ ํ๊ธฐ ์ํด SecurityConfig ํด๋์ค๋ฅผ ์์ ํฉ๋๋ค.
- ๊ตฌ์ฑ ์
๋ฐ์ดํธ ์์:
12345678910111213141516@Configuration@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/users/**").hasRole("ADMIN").anyRequest().authenticated().and().httpBasic();}} - ์ค๋ช
:
- antMatchers("/users/**"): /users/ ์๋์ ๋ชจ๋ ์๋ํฌ์ธํธ์ ๊ท์น์ ์ ์ฉํฉ๋๋ค.
- .hasRole("ADMIN"): ADMIN ์ญํ ์ ๊ฐ์ง ์ฌ์ฉ์์๊ฒ๋ง ์ ๊ทผ์ ์ ํํฉ๋๋ค.
- .anyRequest().authenticated(): ๋ค๋ฅธ ๋ชจ๋ ์์ฒญ์ ๋ํด ์ธ์ฆ์ ์๊ตฌํฉ๋๋ค.
์ ๋ฐํ ์์ผ๋์นด๋ ์ฌ์ฉ์ ์ด์
- ์ธ๋ถํ๋ ์ ์ด: ๋ค๋ฅธ URL ์ธ๊ทธ๋จผํธ์ ๋ํ ์ ๊ทผ ๊ท์น์ ์ง์ ํ ์ ์์ต๋๋ค.
- ๋ณด์ ๊ฐํ: ์ ๊ทผ ๊ท์น์ ์ ํํ๊ฒ ์ ์ํ์ฌ ๋ฌด๋จ ์ ๊ทผ์ ์ํ์ ์ค์ ๋๋ค.
- ์ ์ฐ์ฑ: ํฅํ API ํ์ฅ ๋ฐ ์์ ์ ์ฝ๊ฒ ์ ์ํ ์ ์์ต๋๋ค.
์ผ๋ฐ์ ์ธ ๋ณด์ ๋ฌธ์ ์ฒ๋ฆฌ
- 500 ๋ด๋ถ ์๋ฒ ์ค๋ฅ: ์์ผ๋์นด๋๊ฐ ์๋ชป ๊ตฌ์ฑ๋๋ฉด ๋ฐ์ํ ์ ์์ต๋๋ค. /**๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ฌ์ฉ๋๋๋ก ํ๋ฉด ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
- ๋ฌด๋จ ์ ๊ทผ: ์ญํ ๋ฐ ๊ถํ์ ์ ์ ํ๊ฒ ์ค์ ํ์ฌ ๋ฌด๋จ ๋ฐ์ดํฐ ์ ๊ทผ์ ์ํ์ ์ํํฉ๋๋ค.
ํ ํฐ ๊ธฐ๋ฐ ์ธ์ฆ ๊ตฌํ
ํ ํฐ ๊ธฐ๋ฐ ์ธ์ฆ, ํนํ JSON Web Tokens(JWT)๋ฅผ ์ฌ์ฉํ๋ฉด API์ ๋ณด์์ฑ๊ณผ ํ์ฅ์ฑ์ด ํฅ์๋ฉ๋๋ค. ์ด ์น์ ์์๋ ์คํ๋ง ๋ถํธ ์ ํ๋ฆฌ์ผ์ด์ ๋ด์์ ํ ํฐ์ ์์ฑ, ๊ด๋ฆฌ ๋ฐ ๊ฒ์ฆํ๋ ๋ฐฉ๋ฒ์ ๋ค๋ฃน๋๋ค.
JWT ์๊ฐ
JWT๋ ๋ ๋น์ฌ์ ๊ฐ์ ์ ์ก๋ ํด๋ ์์ ํํํ๋ ๊ฐ๊ฒฐํ๊ณ URL ์์ ํ ์๋จ์ ๋๋ค. ์์ ํ ์ ๋ณด ๊ตํ์ ๋ณด์ฅํ๋ฉฐ ์ธ์ฆ ๋ฐ ๊ถํ ๋ถ์ฌ ๋ชฉ์ ์ผ๋ก ๋๋ฆฌ ์ฑํ๋๊ณ ์์ต๋๋ค.
์ํฌํ๋ก์ฐ ๊ฐ์
- ์ฌ์ฉ์ ์ธ์ฆ: ์ฌ์ฉ์๊ฐ ์๊ฒฉ ์ฆ๋ช (์: ์ด๋ฉ์ผ ๋ฐ ๋น๋ฐ๋ฒํธ)์ ์ ๊ณต.
- ํ ํฐ ์์ฑ: ์ธ์ฆ์ ์ฑ๊ณตํ๋ฉด JWT๊ฐ ์์ฑ๋์ด ์ฌ์ฉ์์๊ฒ ๋ฐํ๋ฉ๋๋ค.
- ํ ํฐ ์ฌ์ฉ: ํด๋ผ์ด์ธํธ๋ ์ดํ ์์ฒญ์์ Authorization ํค๋์ ํ ํฐ์ ํฌํจํฉ๋๋ค.
- ํ ํฐ ๊ฒ์ฆ: ์๋ฒ๋ ํ ํฐ์ ๊ฒ์ฆํ์ฌ ๋ณดํธ๋ ๋ฆฌ์์ค์ ๋ํ ์ ๊ทผ์ ์น์ธํฉ๋๋ค.
JWT ํ ํฐ ์์ฑ
์คํ๋ง ๋ถํธ์์ ํ ํฐ ์์ฑ ์์:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@Service public class TokenService { private final String SECRET_KEY = "your_secret_key"; public String generateToken(Account account) { return Jwts.builder() .setSubject(account.getEmail()) .claim("roles", account.getRoles()) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + 86400000)) // 1์ผ .signWith(SignatureAlgorithm.HS512, SECRET_KEY) .compact(); } } |
์ค๋ช :
- Subject: ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ์์ ์ด๋ฉ์ผ ๋๋ ๊ณ ์ ์๋ณ์.
- Claims: ์ฌ์ฉ์ ์ญํ ๊ณผ ๊ฐ์ ์ถ๊ฐ ๋ฐ์ดํฐ.
- Issued At & Expiration: ํ ํฐ์ ์ ํจ ๊ธฐ๊ฐ์ ์ ์.
- Signature: ํ ํฐ์ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅ.
JWT ํ ํฐ ๊ฒ์ฆ
ํ ํฐ ๊ฒ์ฆ ์์:
1 2 3 4 5 6 7 8 9 10 |
public boolean validateToken(String token) { try { Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token); return true; } catch (JwtException | IllegalArgumentException e) { return false; } } |
์ค๋ช :
- ํ ํฐ์ ์ํฌ๋ฆฟ ํค๋ฅผ ์ฌ์ฉํ์ฌ ํ์ฑ ๋ฐ ๊ฒ์ฆ๋ฉ๋๋ค.
- ์์ธ๋ ํ ํฐ์ด ์ ํจํ์ง ์๊ฑฐ๋ ๋ณ์กฐ๋์์์ ๋ํ๋ ๋๋ค.
์์ฒญ ์ ํ ํฐ ํฌํจ
ํด๋ผ์ด์ธํธ๋ Authorization ํค๋์ ๋ค์๊ณผ ๊ฐ์ด ํ ํฐ์ ํฌํจํฉ๋๋ค:
1 2 3 |
Authorization: Bearer <token> |
ํ ํฐ ๋ง๋ฃ ๋ฐ ๊ฐฑ์ ์ฒ๋ฆฌ
ํ ํฐ ๋ง๋ฃ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํ ๋ฉ์ปค๋์ฆ์ ๊ตฌํํ์ฌ ์ฌ์ฉ์ ๊ฒฝํ๊ณผ ๋ณด์์ ํฅ์์ํต๋๋ค. ์๋ฅผ ๋ค์ด, ํ ํฐ ๊ฐฑ์ ์๋ํฌ์ธํธ๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ค๋ฅ ์ฒ๋ฆฌ ๋ฐ ์๋ต ์ฝ๋
์ ์ ํ ์ค๋ฅ ์ฒ๋ฆฌ๋ ์ ๋ขฐํ ์ ์๊ณ ์ฌ์ฉ์ ์นํ์ ์ธ API๋ฅผ ๋ง๋๋ ๋ฐ ํ์์ ์ ๋๋ค. ์ด ์น์ ์์๋ ์คํ๋ง ๋ถํธ API์์ ๋ค์ํ ์๋๋ฆฌ์ค๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํ ์๋ฏธ ์๋ ์๋ต ์ฝ๋์ ๋ฉ์์ง๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ ผ์ํฉ๋๋ค.
์ผ๋ฐ์ ์ธ HTTP ์๋ต ์ฝ๋
์ฝ๋ | ์๋ฏธ | ์ฌ์ฉ ์ |
---|---|---|
200 | OK | ์ฑ๊ณต์ ์ธ GET, PUT ๋๋ DELETE ์์ฒญ |
201 | Created | ์ฑ๊ณต์ ์ธ POST ์์ฒญ |
400 | Bad Request | ์๋ชป๋ ์์ฒญ ๋งค๊ฐ๋ณ์ ๋๋ ํ์ด๋ก๋ |
401 | Unauthorized | ๋๋ฝ๋์๊ฑฐ๋ ์ ํจํ์ง ์์ ์ธ์ฆ ์๊ฒฉ ์ฆ๋ช |
403 | Forbidden | ์ธ์ฆ๋์์ง๋ง ํ์ํ ๊ถํ์ด ์์ |
404 | Not Found | ์์ฒญํ ๋ฆฌ์์ค๊ฐ ์กด์ฌํ์ง ์์ |
500 | Internal Server Error | ์์์น ๋ชปํ ์๋ฒ ์ธก ์ค๋ฅ |
๋ง์ถคํ ์ค๋ฅ ์๋ต ๊ตฌํ
๋์ฑ ์ ์ตํ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด, ์ค๋ฅ์ ๋ํ ์ธ๋ถ ์ ๋ณด๋ฅผ ํฌํจํ๋๋ก ์๋ต ๋ณธ๋ฌธ์ ์ฌ์ฉ์ ์ ์ํฉ๋๋ค.
๋ง์ถคํ ์ค๋ฅ ์๋ต ์์:
1 2 3 4 5 6 7 8 9 |
public class ErrorResponse { private int status; private String message; private long timestamp; // ์์ฑ์, Getter, Setter } |
์ปจํธ๋กค๋ฌ ์์:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@PutMapping("/{userId}/authorities") public ResponseEntity<?> updateAuthorities( @PathVariable Long userId, @RequestBody AuthoritiesDTO authoritiesDTO) { Optional<Account> accountOpt = accountService.findById(userId); if (!accountOpt.isPresent()) { ErrorResponse error = new ErrorResponse(400, "Invalid User", System.currentTimeMillis()); return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); } // ์
๋ฐ์ดํธ ์งํ } |
ํน์ ์ค๋ฅ ์๋๋ฆฌ์ค ์ฒ๋ฆฌ
- ์กด์ฌํ์ง ์๋ ์ฌ์ฉ์:
- ์๋ต ์ฝ๋: 400 Bad Request
- ๋ฉ์์ง: "Invalid User"
- ๋ฌด๋จ ์ ๊ทผ:
- ์๋ต ์ฝ๋: 403 Forbidden
- ๋ฉ์์ง: "Access Denied"
- ๋ด๋ถ ์๋ฒ ์ค๋ฅ:
- ์๋ต ์ฝ๋: 500 Internal Server Error
- ๋ฉ์์ง: "An unexpected error occurred"
์ ์ ํ ์ค๋ฅ ์ฒ๋ฆฌ์ ์ด์
- ๋ช ํ์ฑ: ํด๋ผ์ด์ธํธ์๊ฒ ๋ฌด์์ด ์๋ชป๋์๋์ง ๋ช ํํ๊ฒ ์ ๋ณด๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ๋๋ฒ๊น : ๋ฌธ์ ๋ฅผ ๋ ์ฝ๊ฒ ์๋ณํ๊ณ ํด๊ฒฐํ ์ ์๋๋ก ํฉ๋๋ค.
- ์ฌ์ฉ์ ๊ฒฝํ: API์ ์ ๋ขฐ์ฑ๊ณผ ์ ๋ขฐ์ฑ์ ํฅ์์ํต๋๋ค.
Swagger ๋ฌธ์๋ฅผ ์ฌ์ฉํ ํ ์คํธ
Swagger๋ RESTful API๋ฅผ ์ค๊ณ, ๋น๋, ๋ฌธ์ํ ๋ฐ ํ ์คํธํ๊ธฐ ์ํ ๊ฐ๋ ฅํ ๋๊ตฌ์ ๋๋ค. ์ด ์น์ ์์๋ API ํ ์คํธ ๋ฐ ๋ฌธ์ํ๋ฅผ ๊ฐ์ํํ๊ธฐ ์ํด ์คํ๋ง ๋ถํธ ์ ํ๋ฆฌ์ผ์ด์ ์ Swagger๋ฅผ ํตํฉํ๋ ๋ฐฉ๋ฒ์ ๋ค๋ฃน๋๋ค.
Swagger ์๊ฐ
Swagger๋ ๊ฐ๋ฐ์๊ฐ ํด๋ผ์ด์ธํธ ์ธก ์ฝ๋๋ฅผ ์์ฑํ ํ์ ์์ด API ์๋ํฌ์ธํธ๋ฅผ ํ์ํ๊ณ ์ํธ์์ฉํ ์ ์๋ ์ฌ์ฉ์ ์นํ์ ์ธ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํฉ๋๋ค. API์ ์ ๋ ธํ ์ด์ ๊ณผ ๊ตฌ์ฑ์ ๊ธฐ๋ฐ์ผ๋ก ๋ฌธ์๋ฅผ ์๋ ์์ฑํฉ๋๋ค.
์คํ๋ง ๋ถํธ์ Swagger ํตํฉ
- Swagger ์์กด์ฑ ์ถ๊ฐ:
- pom.xml์ ๋ค์ ์์กด์ฑ์ ์ถ๊ฐํฉ๋๋ค:
1 2 3 4 5 6 7 |
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency> |
- Swagger ๊ตฌ์ฑ:
- Swagger ๊ตฌ์ฑ ํด๋์ค๋ฅผ ์์ฑํฉ๋๋ค.
- Swagger ๊ตฌ์ฑ ์์:
1234567891011121314@Configuration@EnableSwagger2public class SwaggerConfig {@Beanpublic Docket api() {return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.basePackage("org.studyeasy.SpringRestdemo.controller")).paths(PathSelectors.any()).build();}}
- Swagger UI ์ ๊ทผ:
- ์ ํ๋ฆฌ์ผ์ด์ ์ด ์คํ๋๋ฉด http://localhost:8080/swagger-ui/๋ก ์ด๋ํ์ฌ Swagger ์ธํฐํ์ด์ค๋ฅผ ํ์ธํฉ๋๋ค.
Swagger๋ฅผ ์ฌ์ฉํ ํ ์คํธ
- ์๋ํฌ์ธํธ ํ์: ์ฌ์ฉ ๊ฐ๋ฅํ ๋ชจ๋ API ์๋ํฌ์ธํธ์ ๊ทธ ์ค๋ช ์ ํ์ธํฉ๋๋ค.
- ์์ฒญ ์คํ: ํ์ํ ๋งค๊ฐ๋ณ์์ ํ์ด๋ก๋๋ฅผ ์ ๊ณตํ์ฌ Swagger UI์์ ์ง์ API ์์ ์ ํ ์คํธํฉ๋๋ค.
- ์๋ต ๊ฒํ : ๋ค์ํ ์๋๋ฆฌ์ค์ ๋ํ ์ํ ์ฝ๋ ๋ฐ ์๋ต ๋ณธ๋ฌธ์ ๋ถ์ํฉ๋๋ค.
Swagger ๋ฌธ์ ๊ฐ์
- ์ ๋ ธํ ์ด์ : @Api, @ApiOperation, @ApiResponse์ ๊ฐ์ Swagger ์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ๋ฌธ์๋ฅผ ํ๋ถํ๊ฒ ๋ง๋ญ๋๋ค.
- API ๊ทธ๋ฃนํ: ๊ด๋ จ ์๋ํฌ์ธํธ๋ฅผ ๊ทธ๋ฃนํํ์ฌ ๊ฐ๋ ์ฑ์ ํฅ์์ํต๋๋ค.
- ๋ณด์ ๊ตฌ์ฑ: ๊ฐ ์๋ํฌ์ธํธ์ ๋ํ ๋ณด์ ์คํค๋ง ๋ฐ ์๊ตฌ ์ฌํญ์ ๋ฌธ์ํํฉ๋๋ค.
Swagger๊ฐ ํ์ฑํ๋ ์ปจํธ๋กค๋ฌ ๋ฉ์๋ ์์
์์:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@RestController @RequestMapping("/users") @Api(value = "User Management System") public class AuthController { @ApiOperation(value = "Update user authorities", response = AccountViewDTO.class) @PutMapping("/{userId}/authorities") public ResponseEntity<?> updateAuthorities( @PathVariable Long userId, @RequestBody AuthoritiesDTO authoritiesDTO) { // ๋ฉ์๋ ๊ตฌํ } } |
Swagger ์ฌ์ฉ์ ์ด์
- ์ธํฐ๋ํฐ๋ธ ๋ฌธ์ํ: API๋ฅผ ์ฝ๊ฒ ํ์ํ๊ณ ํ ์คํธํ ์ ์๋๋ก ํฉ๋๋ค.
- ์ผ๊ด์ฑ: ๋ฌธ์๊ฐ ์ฝ๋๋ฒ ์ด์ค์ ์ต์ ์ํ๋ก ์ ์ง๋๋๋ก ๋ณด์ฅํฉ๋๋ค.
- ๊ฐ๋ฐ์ ํจ์จ์ฑ: ์๋ ๋ฌธ์ํ์ ํ์์ฑ์ ์ค์ฌ ์๊ฐ๊ณผ ๋ ธ๋ ฅ์ ์ ์ฝํฉ๋๋ค.
๊ฒฐ๋ก
RESTful ๊ท์น์ ์ค์ํ๊ณ ๊ฒฌ๊ณ ํ ๋ณด์ ์กฐ์น๋ฅผ ๊ตฌํํ์ฌ ์คํ๋ง ๋ถํธ API๋ฅผ ํฅ์์ํค๋ฉด ์์ ์ฑ, ํ์ฅ์ฑ ๋ฐ ์ฌ์ฉ์ฑ์ด ํฌ๊ฒ ํฅ์๋ฉ๋๋ค. ์ฐ์ ํ์ค์ ๋ฐ๋ฅด๋ URL ๊ตฌ์กฐ๋ฅผ ๊ตฌ์ถํ๊ณ , ์ธ๋ถ์ ์ธ ๋ณด์ ์ค์ ์ ๊ตฌ์ฑํ๋ฉฐ, ํ ํฐ ๊ธฐ๋ฐ ์ธ์ฆ์ ๊ตฌํํ๊ณ , ์ค๋ฅ๋ฅผ ์ฐ์ํ๊ฒ ์ฒ๋ฆฌํ๋ฉฐ, Swagger์ ๊ฐ์ ๋๊ตฌ๋ฅผ ํ์ฉํ์ฌ ๋ฌธ์ํ ๋ฐ ํ ์คํธ๋ฅผ ์ํํจ์ผ๋ก์จ ์์ ํ ๋ฟ๋ง ์๋๋ผ ๊ฐ๋ฐ์ ์นํ์ ์ด๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ API๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
ํต์ฌ ์์
- RESTful ์ค๊ณ: ๋๋ฆฌ ์ธ์ ๋ฐ๋ ํ์ค์ API๋ฅผ ๋ง์ถ์ด ์ผ๊ด์ฑ๊ณผ ๋ช ํ์ฑ์ ๋ณด์ฅํฉ๋๋ค.
- ๋ณด์ ๊ตฌ์ฑ: ์ ์ ํ๊ฒ ๊ตฌ์ฑ๋ ๋ณด์ ์ค์ ์ API๋ฅผ ๋ฌด๋จ ์ ๊ทผ ๋ฐ ์ ์ฌ์ ์ํ์ผ๋ก๋ถํฐ ๋ณดํธํฉ๋๋ค.
- ํ ํฐ ๊ธฐ๋ฐ ์ธ์ฆ: JWT ํ ํฐ์ ์ฌ์ฉ์ ์ธ์ฆ ๋ฐ ๊ถํ ๊ด๋ฆฌ๋ฅผ ์ํ ์์ ํ๊ณ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค.
- ํจ๊ณผ์ ์ธ ์ค๋ฅ ์ฒ๋ฆฌ: ์๋ฏธ ์๋ ์๋ต ์ฝ๋์ ๋ฉ์์ง๋ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํค๊ณ ๋๋ฒ๊น ์ ์ฉ์ดํ๊ฒ ํฉ๋๋ค.
- ํฌ๊ด์ ์ธ ๋ฌธ์ํ: Swagger์ ๊ฐ์ ๋๊ตฌ๋ API ๋ฌธ์ํ ๋ฐ ํ ์คํธ ๊ณผ์ ์ ๊ฐ์ํํ์ฌ ๊ฐ๋ฐ์๊ฐ ๋ ์ฝ๊ฒ ์ ๊ทผํ ์ ์๋๋ก ํฉ๋๋ค.
์ด๋ฌํ ๊ดํ์ ๊ฐ๋ฐ ์ํฌํ๋ก์ฐ์ ํตํฉํจ์ผ๋ก์จ ํ๋์ ์ธ ํ์ค๊ณผ ์ฌ์ฉ์ ๊ธฐ๋์ ๋ถ์ํ๋ ๊ณ ํ์ง API๋ฅผ ๊ตฌ์ถํ ์ ์์ต๋๋ค.
SEO ์ต์ ํ ํค์๋
Spring Boot API, RESTful ๊ท์น, Spring Boot ๋ณด์, JWT ์ธ์ฆ, API ์ค๋ฅ ์ฒ๋ฆฌ, Swagger ๋ฌธ์ํ, ํ ํฐ ๊ธฐ๋ฐ ์ธ์ฆ, REST API ์ค๊ณ, Spring Boot ๋ชจ๋ฒ ์ฌ๋ก, ์์ ํ API ๊ฐ๋ฐ
์ถ๊ฐ ์๋ฃ
- Spring Boot ์ฐธ๊ณ ๋ฌธ์
- RESTful API ์ค๊ณ ๊ฐ์ด๋๋ผ์ธ
- JSON Web Tokens (JWT) ์๊ฐ
- Swagger ๊ณต์ ๋ฌธ์
- Spring Security ๋ฌธ์
- ์คํ๋ง ๋ถํธ์์ ์ค๋ฅ ์ฒ๋ฆฌ
์ฐธ๊ณ : ์ด ๊ธฐ์ฌ๋ AI์ ์ํด ์์ฑ๋์์ต๋๋ค.