๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

201221

ยท ์•ฝ 8๋ถ„

PMP ๊ฐ€์ด๋“œ#

OAuth#

OAuth ๊ธฐ์ˆ ์˜ ์ฐธ์—ฌ์ž

Our Service ( example.com ), User(์‚ฌ์šฉ์ž), Their(Google, Facebook, Twitter ๋“ฑ๋“ฑ)


User์—๊ฒŒ Their์˜ id , pw ๋ฅผ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌ๋ฐ›๋Š” ๋ฐฉ๋ฒ•

  • User : ์ฒ˜์Œ๋ณด๋Š” ์„œ๋น„์Šค๋ฅผ ๋ฏฟ์„ ์ˆ˜ ์—†๋‹ค.

  • Our Service : ์œ ์ €์˜ id , pw ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•ด์•ผํ•  ์ฑ…์ž„์„ ์ง€๋‹ˆ๊ฒŒ ๋œ๋‹ค.

  • Their Service : ์ œ 3์ž์˜ ์„œ๋น„์Šค๊ฐ€ ๋ณธ์ธ๋“ค์˜ id , pw ๋ฅผ ๊ฐ–๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์— ๋ถˆ๋งŒ์ด ์ƒ๊ธด๋‹ค.


Their๊ฐ€ accessToken ์„ ๋ฐœ๊ธ‰ํ•˜๋Š” ๋ฐฉ๋ฒ•

  • accessToken ์€ id , pw ๊ฐ€ ์•„๋‹ˆ๋‹ค.

  • Their Service๋Š” ์ œ๊ณตํ•˜๊ธฐ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ๋งŒ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค.


์šฉ์–ด#

  • Client(Our Service)

  • Resource Owner(User)

  • Resource Server(Their) + Authorization Server(์ธ์ฆ ์„œ๋ฒ„๋ฅผ ๋”ฐ๋กœ ๊ตฌ๋ถ„ํ•˜๊ธฐ๋„ ํ•จ)


๋“ฑ๋ก#

2020-12-21-201221-image-0

  • Client ID : ์„œ๋น„์Šค๋ฅผ ์‹๋ณ„ํ•˜๋Š” ์•„์ด๋””

  • Client Secret : ์„œ๋น„์Šค์— ๋Œ€ํ•œ ๋น„๋ฐ€๋ฒˆํ˜ธ (์ ˆ๋Œ€๋กœ ๋…ธ์ถœ์ด ๋˜์–ด์„  ์•ˆ๋œ๋‹ค.)

  • Authorized redirect URIs : Resource Server๊ฐ€ ์ธ์ฆ ์ฝ”๋“œ๋ฅผ ์ œ๊ณตํ•  ์„œ๋น„์Šค์˜ URL

  • Scope : Resource Server์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ (ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์ธ์ฆ๋งŒ ์ œ๊ณต ๊ฐ€๋Šฅ )

์†Œ์…œ ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ์€ ๋‹ค์Œ์˜ ๋งํฌ๊ฐ€ ๋‹ด๊ฒจ์žˆ๋‹ค.

  • http://{๋ฆฌ์†Œ์Šค ์„œ๋ฒ„์˜ ์ฃผ์†Œ}/?{ํด๋ผ์ด์–ธํŠธ ID=id}&{์Šค์ฝ”ํ”„=b,c}&{๋ฆฌ๋‹ค์ด๋ ‰ํŠธ URL=url}

๋ฆฌ์†Œ์Šค ์„œ๋ฒ„๋Š” ์œ ์ €์˜ ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ๋ฐ›๊ณ , ํด๋ผ์ด์–ธํŠธ ์•„์ด๋””์™€ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ URL์ด ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ๊ถŒํ•œ ํ—ˆ์šฉ์— ๋Œ€ํ•œ ์•ˆ๋‚ด๋ฅผ ์œ ์ €์—๊ฒŒ ์ „๋‹ฌํ•˜๊ณ , ์œ ์ €๊ฐ€ ํ—ˆ์šฉํ•œ ๊ถŒํ•œ์ด ๋ฌด์—‡์ธ์ง€์— ๋Œ€ํ•ด ์ €์žฅํ•œ๋‹ค.

๋ฆฌ์†Œ์Šค ์„œ๋ฒ„๋Š” authorization code ๋ฅผ ๋‹ด์•„์„œ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ URL๋กœ ์œ ์ €์˜ ๋ธŒ๋ผ์šฐ์ €๋ฅผ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ์‹œํ‚จ๋‹ค.

ํด๋ผ์ด์–ธํŠธ๋Š” authorization code ๋ฅผ ์œ ์ €์—๊ฒŒ ๋ฐ›๊ณ , ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ URL, ํด๋ผ์ด์–ธํŠธ ID, ํด๋ผ์ด์–ธํŠธ ์‹œํฌ๋ฆฟ์„ ๊ฐ–๊ณ  ๋ฆฌ์†Œ์Šค ์„œ๋ฒ„์— ์š”์ฒญํ•œ๋‹ค.

์ด ๊ณผ์ •์ด ์™„๋ฃŒ๋˜๋ฉด access token์„ ๋ฐœ๊ธ‰ํ•œ๋‹ค.

access token์„ Header: { Authorization : Bearer token } ์— ๋‹ด์•„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.


OAuth๋ฅผ ํ™œ์šฉํ•ด์„œ API ์‚ฌ์šฉํ•˜๊ธฐ#

2020-12-21-201221-image-1

Using OAuth 2.0 to Access Google APIs | Google Identity


Database Naming Convention#

๋ณต์ˆ˜ํ˜• vs ๋‹จ์ˆ˜ํ˜•#

  • ํ…Œ์ด๋ธ”์€ ์—”ํ‹ฐํ‹ฐ์˜ ์ธ์Šคํ„ด์Šค๋“ค์„ ํ‘œํ˜„ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์˜๋ฏธ์ ์œผ๋กœ ๋ณต์ˆ˜ํ˜•์ด ๋” ๋งž๋‹ค.

  • ํ…Œ์ด๋ธ”์„ ๋‹จ์ˆ˜ํ˜•์„ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ SQL ๋ฌธ์—์„œ SELECT activity.name ์œผ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜์žˆ๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.

    • ํ•˜์ง€๋งŒ ๋ณต์ˆ˜ํ˜•์„ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ SQL alias๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ทน๋ณต ๊ฐ€๋Šฅํ•˜๋‹ค.

    • SELECT id, name, description FROM products product WHERE product.name = โ€˜fooโ€™ AND product.description = โ€˜barโ€™

  • REST API์—์„œ ์ž์›์— ๋Œ€ํ•œ ์š”์ฒญ ์—ญ์‹œ ํ…Œ์ด๋ธ”์— ๋”ฐ๋ผ ๋ณต์ˆ˜ํ˜•์œผ๋กœ ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ex) GET /users/1

The table naming dilemma: singular vs. plural

camelCase vs snake_case#

  • MySQL ์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๋ฐ์ดํ„ฐ ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด์˜ ๋””๋ ‰ํ† ๋ฆฌ์— ํ•ด๋‹นํ•˜๊ณ , ํ…Œ์ด๋ธ”์€ํŒŒ์ผ์— ํ•ด๋‹นํ•œ๋‹ค. ๋”ฐ๋ผ์„œ, ์šด์˜์ฒด์ œ์˜ ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, ํ…Œ์ด๋ธ” ๋ฐ ํŠธ๋ฆฌ๊ฑฐ ์ด๋ฆ„์˜ ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„์— ์˜ํ–ฅ์„ ์ค€๋‹ค.

  • Windows๋Š” ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ถ„ํ•˜์ง€ ์•Š์ง€๋งŒ Unix๋Š” ๊ตฌ๋ถ„, macOS๋Š” ๊ตฌ๋ถ„ํ•˜์ง€ ์•Š๋Š” ํŒŒ์ผ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ถ„ํ•˜๋Š” ๋ณผ๋ฅจ๋„ ์ง€์›ํ•จ.

  • ๋”ฐ๋ผ์„œ snake_case ๊ฐ€ ์ด์‹์„ฑ๊ณผ ์‚ฌ์šฉ ํŽธ์˜์„ฑ ์ธก๋ฉด์—์„œ ๊ฐ€์žฅ ๊ถŒ์žฅ๋œ๋‹ค.

  • ํ•˜์ง€๋งŒ camelCase ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋„ ์žˆ๊ณ , JS๊ฐ€ camelCase๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—์–ป์„ ์ˆ˜ ์žˆ๋Š” ํŽธ์˜์„ฑ์ด ์žˆ๋‹ค.

  • ๋ฌด์—‡๋ณด๋‹ค ์ผ๊ด€๋œ ๊ทœ์น™์„ ์ฑ„ํƒํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹๋‹ค.

MySQL :: MySQL 8.0 Reference Manual :: 9.2.3 Identifier Case Sensitivity

RESTful API#

์„œ๋ฒ„ ์‘๋‹ต์— HTTP ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•ด๋ผ#

์˜ค๋ฅ˜ ๋ฐœ์ƒ์‹œ API ์‚ฌ์šฉ์ž์˜ ํ˜ผ๋™์„ ์—†์• ๊ธฐ ์œ„ํ•ด ์˜ค๋ฅ˜๋ฅผ ์ •์ƒ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ  ๋ฐœ์ƒํ•œ ์˜ค๋ฅ˜์˜ ์ข…๋ฅ˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” HTTP ์‘๋‹ต ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.ย ์ด๋ฅผ ํ†ตํ•ด API ๊ด€๋ฆฌ์ž๋Š” ๋ฐœ์ƒํ•œ ๋ฌธ์ œ๋ฅผ ์ดํ•ดํ•  ์ˆ˜์žˆ๋Š” ์ถฉ๋ถ„ํ•œ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.ย ์˜ค๋ฅ˜๋กœ ์ธํ•ด ์‹œ์Šคํ…œ์ด์ค‘๋‹จ๋˜๋Š” ๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์˜ค๋ฅ˜๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์€ ์ฑ„๋กœ ๋‘˜ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, API ์†Œ๋น„์ž๊ฐ€ ์˜ค๋ฅ˜๋ฅผ ์ฒ˜๋ฆฌํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์ธ ์˜ค๋ฅ˜ HTTP ์ƒํƒœ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • 400 ์ž˜๋ชป๋œ ์š”์ฒญ โ€“ ์ด๋Š” ํด๋ผ์ด์–ธํŠธ ์ธก ์ž…๋ ฅ์ด ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ์— ์‹คํŒจ ํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค .

  • 401 Unauthorized โ€“ ์‚ฌ์šฉ์ž๊ฐ€ ๋ฆฌ์†Œ์Šค์— ์•ก์„ธ์Šค ํ•  ์ˆ˜์žˆ๋Š” ๊ถŒํ•œ์ด ์—†์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค .ย ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ฆ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

  • 403 ๊ธˆ์ง€๋จ โ€“ ์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ฆ๋˜์—ˆ์ง€๋งŒ ๋ฆฌ์†Œ์Šค์— ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์—†์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

  • 404 Not Found โ€“ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

  • 500 ๋‚ด๋ถ€ ์„œ๋ฒ„ ์˜ค๋ฅ˜ โ€“ ์ผ๋ฐ˜์ ์ธ ์„œ๋ฒ„ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.ย ์•„๋งˆ๋„ ๋ช…์‹œ ์ ์œผ๋กœ ๋˜์ ธ์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค.

  • 502ย Bad Gateway โ€“ ์—…์ŠคํŠธ๋ฆผ ์„œ๋ฒ„์˜ ์ž˜๋ชป๋œ ์‘๋‹ต์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

  • 503 ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Œ โ€“ ์„œ๋ฒ„ ์ธก์—์„œ ์˜ˆ๊ธฐ์น˜ ์•Š์€ ์ผ์ด ๋ฐœ์ƒํ–ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค (์„œ๋ฒ„ ๊ณผ๋ถ€ํ•˜, ์‹œ์Šคํ…œ์˜ ์ผ๋ถ€ ์˜ค๋ฅ˜ ๋“ฑ์ด ๋  ์ˆ˜ ์žˆ์Œ).

Best practices for REST API design - Stack Overflow Blog

Best Practices for your REST API

FE API ์—๋Ÿฌ ํ•ธ๋“ค๋ง#

Catch request errors with Axios

Handling Failed HTTP Responses With fetch()