ํ•ด์™ธ์ฃผ์‹ ํฌํŠธํด๋ฆฌ์˜ค ๊ณต๊ฐœ 9์›” 2์ฃผ์ฐจ

๊ฐœ์š”#

์ง€๊ธˆ ํ˜„์‹œ์ ์— ์ œ๊ฐ€ ๊ฐ€์ง„ ํ•ด์™ธ์ฃผ์‹ ํฌํŠธํด๋ฆฌ์˜ค์™€ ์–ด๋–ค ์ƒ๊ฐ์œผ๋กœ ํ•ด์™ธ์ฃผ์‹์„ ํ•ด์™”์œผ๋ฉฐ, ์•ž์œผ๋กœ์˜ ๊ณ„ํš์€ ๋ฌด์—‡์ธ์ง€ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.

ํฌํŠธํด๋ฆฌ์˜ค๋ฅผ ๊ณต๊ฐœํ•˜๋Š” ์ด์œ ์™€ ์ฃผ์˜์‚ฌํ•ญ#

์ œ๊ฐ€ ํฌํŠธํด๋ฆฌ์˜ค๋ฅผ ๊ณต๊ฐœํ•˜๋Š” ์ด์œ ๋Š” ์•„์ด๋Ÿฌ๋‹ˆํ•˜๊ฒŒ๋„ ๊ทธ ๋™์•ˆ ํฌํŠธํด๋ฆฌ์˜ค๊ฐ€ ์—†์—ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋ธ”๋กœ๊ทธ์— ์ •๊ธฐ์ ์œผ๋กœ ํฌํŠธํด๋ฆฌ์˜ค๋ฅผ ๊ณต๊ฐœํ•˜์ž๋Š” ๊ฒฐ์‹ฌ์€ ํฌํŠธํด๋ฆฌ์˜ค๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ด€๋ฆฌํ•˜์ž. ๋ผ๋Š” ๊ฒฐ์‹ฌ์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ํ™•์žฅํŒ์ธ ์…ˆ์ด์ฃ .

์ฆ๊ถŒ์‚ฌ ์•ฑ์—์„œ ์ข…๋ชฉ ๋น„์ค‘์„ ๋ณด์—ฌ์ฃผ๊ธด ํ•˜์ง€๋งŒ ์—ฌ๋Ÿฌ ์ฆ๊ถŒ์‚ฌ์™€ ์—ฌ๋Ÿฌ ๊ณ„์ขŒ์— ํฉ์–ด์ ธ ์žˆ๋Š” ์ „์ฒด ์ž์‚ฐ์„ ๊ด€๋ฆฌํ•˜๊ธฐ์—๋Š” ํ•œ๊ณ„๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๋ถ€๋ถ„์„ ์ž๋™ํ™”ํ•˜๋ ค๊ณ  ํ† ์ด ํ”„๋กœ์ ํŠธ๋กœ ๊ฐœ๋ฐœ์„ ์‹œ๋„ํ–ˆ์—ˆ์ง€๋งŒ, ๋ฐฐ๋ณด๋‹ค ๋ฐฐ๊ผฝ์ด ๋” ์ปค์ง€๋Š” ๊ผด์ด๋ผ ์ผ๋‹จ ์ˆ˜๊ธฐ๋กœ ๊ตฌ๊ธ€ ์‹œํŠธ์— ์ž‘์„ฑํ•˜๊ธฐ๋กœ ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์ €๋Š” ํŠธ๋ ˆ์ด๋”๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ์ข…๋ชฉ์„ ๊ธฐ์ˆ ์ ์œผ๋กœ ๋ถ„์„ํ•˜๋Š” ํˆฌ์ž์ž๋„ ์•„๋‹ˆ์ฃ . ๊ฒฝ์ œ ๊ด€๋ จ ๋‰ด์Šค ๊ธฐ์‚ฌ๋‚˜ ์œ ํŠœ๋ธŒ ์˜์ƒ์„ ํ†ตํ•ด ๊พธ์ค€ํžˆ ๊ณต๋ถ€๋Š” ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค๋งŒ, ์ œ๊ฐ€ ๊ด€์‹ฌ์žˆ๋Š” ๋ถ„์•ผ๋‚˜ ์ข…๋ชฉ ์•ˆ์—์„œ ๊ฒ€์ƒ‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹œ์•ผ๋„ ํ•œ์ •์ ์ž…๋‹ˆ๋‹ค. ์ฆ‰ ์ œ๊ฐ€ ์•ž์œผ๋กœ ์ด ๊ณต๊ฐ„์— ์ ๋Š” ์–ด๋– ํ•œ ํˆฌ์ž๊ด€๋ จ ๊ธ€์€ ์ข…๋ชฉ์ถ”์ฒœ์ด๋‚˜ ํˆฌ์ž ๊ถŒ์œ ๊ฐ€ ์•„๋‹˜์„ ๋ช…์‹œํ•ฉ๋‹ˆ๋‹ค.

ํฌํŠธํด๋ฆฌ์˜ค ๊ณต๊ฐœ#

๊ฒฝ์ œ์  ์ž์œ .png

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

ํ‰๊ฐ€๊ธˆ์•ก๊ฐ€์น˜๋กœ ๋ณด์•˜์„ ๋•Œ 300๋‹ฌ๋Ÿฌ ์•„๋ž˜์— ์žˆ๋Š” ์ข…๋ชฉ๋“ค์€ ๋งค์ˆ˜๋ฅผ ์œ„ํ•œ ๋ถ€ํ‘œ๋กœ ์‚ฌ๋†“์€ ๊ฒƒ๋“ค์ž…๋‹ˆ๋‹ค. ์‚ฌ๊ณ  ์‹ถ์€๋ฐ ๋„ˆ๋ฌด ์˜ฌ๋ž๋‹ค๊ณ  ์ƒ๊ฐ๋ผ์„œ ๊ณ„์† ๋งค์ˆ˜ ํƒ€์ด๋ฐ๋งŒ ์žฌ๋˜ ๋†ˆ๋“ค์ด์ฃ . ๊ทธ๋ฆฌ๊ณ  ๊ทธ ๋งค์ˆ˜ ํƒ€์ด๋ฐ์€ ๋ช‡ ์ฃผ๊ฐ€ ์ง€๋‚˜๋„ ์˜ค์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค... ์กฐ์ •์„ ๊ธฐ๋‹ค๋ฆฌ๋˜ ์–ด๋Š ๋‚  ์—ญ์‹œ๋‚˜ ๋น„์‹ธ๋‹ค๊ณ  ์ƒ๊ฐ๋˜์—ˆ์ง€๋งŒ ๊ทธ๋ƒฅ ์‹œ์žฅ๊ฐ€๋กœ 30-40๋งŒ์› ๊ธ์—ˆ์Šต๋‹ˆ๋‹ค. ์ œ๊ฐ€ ์‚ฐ ๊ฐ€๊ฒฉ๋Œ€๋น„ํ•ด์„œ ์ˆ˜์ต๋ฅ ์ด ํฌ๊ฒŒ ๋งˆ์ด๋„ˆ์Šค๊ฐ€ ๋˜์—ˆ์„ ๋•Œ ์‚ด ์ƒ๊ฐ์œผ๋กœ์š”. ๊ทธ๋Ÿฐ๋ฐ ๊ทธ๋ ‡๊ฒŒ ์†Œ๋Ÿ‰ ์‚ฐ ์ข…๋ชฉ๋“ค์ด ํ…Œ์Šฌ๋ผ๋ณด๋‹ค ์ˆ˜์ต๋ฅ ์ด ๋†’๋„ค์š”. ์ฐธโ€ฆ

์ง€๊ธˆ๊นŒ์ง€ ํˆฌ์ž ์›์น™?#

๋”ฑํžˆ ํˆฌ์ž ์›์น™์„ ์ •ํ•œ ์ ์€ ์—†์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋Œ€๋žต์ ์œผ๋กœ ์•„๋ž˜ ํ•ญ๋ชฉ๋“ค์„ ์ƒ๊ฐํ•˜๋ฉด์„œ ์‚ฌ๊ฑฐ๋‚˜ ํŒ”์•˜๋˜ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ํ˜์‹ ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋Š” ์ œํ’ˆ์ด๋‚˜ ๊ธฐ์—… ๋ฐฉํ–ฅ์„ฑ์ด ๊ณต๊ฐœ๋˜๋ฉด ์‚ฐ๋‹ค.
    • ํ…Œ์Šฌ๋ผ, ๋งˆ์ดํฌ๋กœ์†Œํ”„ํŠธ, ํ€„์ปด, ๋””์ฆˆ๋‹ˆ
  • ๋‚ด๊ฐ€ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์ข‹์•„ํ•˜๋Š” ์ œํ’ˆ, ์ž์ฃผ ์†Œ๋น„ํ•˜๋Š” ์ œํ’ˆ์„ ๊ฐ€์ง„ ๊ธฐ์—…์„ ์‚ฐ๋‹ค.
    • ์ฝ”์นด์ฝœ๋ผ, ์ฟ ํŒก, ๋ฐ์ดํ„ฐ๋…, ์œ ๋‹ˆํ‹ฐ
  • ํŽ€๋”๋ฉ˜ํƒˆ์ด ํ”๋“ค๋ฆฌ์ง€ ์•Š์€ ๊ธฐ์—…์ด ์ตœ๊ณ ๊ฐ€ ๋Œ€๋น„ ํ•˜๋ฝ์ด ํด ๋•Œ ์‚ฐ๋‹ค.
    • ํ…Œ์Šฌ๋ผ
  • ๋” ์ข‹์€ ํˆฌ์žํ•  ๊ณณ์ด ์ƒ๊ฒผ๋Š”๋ฐ ํ˜„๊ธˆ์ด ์—†์œผ๋ฉด ํŒ๋‹ค.

๋‚ด๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์ƒ๊ฐ#

์ €๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ์ƒ๊ฐ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒ๊ฐ์€ ๋งค์ผ๋งค์ผ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์ง€๋งŒ, ์ง€๊ธˆ๊นŒ์ง€ ๋˜ ์•ž์œผ๋กœ๋„ ์ด๋Ÿฐ ์ƒ๊ฐ์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ํˆฌ์ž๋ฅผ ํ•  ์ƒ๊ฐ์ž…๋‹ˆ๋‹ค.

  • ๋งˆ์ดํฌ๋กœ์†Œํ”„ํŠธ ํ™€๋กœ๋ Œ์ฆˆ๋Š” ๋ชจ๋ฐ”์ผ์˜ ๋‹ค์Œ ๊ธฐ๊ธฐ๋ผ๊ณ  ์ƒ๊ฐ๋  ์ •๋„๋กœ ํ˜์‹ ์ ์ด๋‹ค. ํ•˜์ง€๋งŒ ์ตœ๊ทผ ํ–‰๋ณด๋ฅผ ๋ณด๋ฉด ์ผ์ƒ์— ์ ์šฉ๋˜๊ธฐ์—๋Š” ์ƒ๋‹นํ•œ ๊ฐœ์„  ๋ฐ ์‹œ๊ฐ„์ด ํ•„์š”ํ•ด๋ณด์ธ๋‹ค.
  • ๋‚ด์—ฐ๊ธฐ๊ด€์ฐจ์—์„œ ์ „๊ธฐ์ฐจ๋กœ ์ „ํ™˜์€ ์ด๋ฏธ ์‹œ์ž‘๋˜์—ˆ๊ณ , ํ™˜๊ฒฝ๋ฌธ์ œ์™€ ๊ฒน์ณ ์„ ํƒ์ด ์•„๋‹Œ ํ•„์ˆ˜๊ฐ€ ๋˜์—ˆ๋‹ค. ํ…Œ์Šฌ๋ผ๋Š” ์ „๊ธฐ์ฐจ ์„นํ„ฐ ๋‚ด ํผ์ŠคํŠธ ๋ฌด๋ฒ„๋กœ OTA, FSD, 4680 ๋ฐฐํ„ฐ๋ฆฌ ๋“ฑ ์œผ๋กœ ๋‹ค๋ฅธ ๊ธฐ์—…๋“ค๊ณผ ๊ธฐ์ˆ ์  ๊ฒฉ์ฐจ๋ฅผ ๋ฒŒ๋ฆฌ๊ณ  ์žˆ๋‹ค.
  • ์„ธ์ƒ์— ๋ˆ์ด ๋„ˆ๋ฌด ๋งŽ์ด ํ’€๋ฆฐ๋‹ค. ํ™”ํ์˜ ๊ฐ€์น˜๋Š” ๊ณ„์†ํ•ด์„œ ๋–จ์–ด์ง€๊ณ  ์žˆ๋‹ค. ํ˜„๊ธˆ์„ ๊ทธ๋ƒฅ ๋‘๋ฉด ๋…น์•„ ๋‚ด๋ฆฐ๋‹ค. ๋…น์ง€ ์•Š๋Š” ์ž์‚ฐ์„ ๋ณด์œ ํ•ด์•ผ ํ•œ๋‹ค.
  • ๋…ธ๋™์˜ ๊ฐ€์น˜๋Š” ๋กœ๋ด‡๊ณผ ์ธ๊ณต์ง€๋Šฅ์˜ ๋ฐœ์ „์œผ๋กœ ๊ณ„์†ํ•ด์„œ ํ•˜๋ฝํ•  ๊ฒƒ์ด๋ฉฐ ์ƒ๋Œ€์ ์œผ๋กœ ๋ถ€๋™์‚ฐ๊ณผ ๊ธฐ์ˆ ์˜ ๊ฐ€์น˜(๊ธฐ์ˆ ์„ ๋ณด์œ ํ•œ ํšŒ์‚ฌ์˜ ๊ฐ€์น˜)๋Š” ๊ณ„์†ํ•ด์„œ ๋†’์•„์งˆ ๊ฒƒ์ด๋‹ค.
  • ๊ฐ€์žฅ ๊ฐ€์น˜์žˆ๋Š” ํˆฌ์ž๋Š” ๋‚˜ ์ž์‹ ์— ํˆฌ์žํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋‚˜์˜ ์„ฑ์žฅ์„ ์œ„ํ•ด์„œ๋ผ๋ฉด ์‹œ๊ฐ„๊ณผ ๋ˆ์„ ์•„๋ผ์ง€ ๋ง์ž.

์•ž์œผ๋กœ์˜ ๊ณ„ํš#

  • ์ตœ๊ทผ์— ์ฝ์€ Tesla: Sometimes A Great Company Isn't A Great Stock ์ด๋ผ๋Š” ๊ธ€์€ ์ƒ๋‹น ๋ถ€๋ถ„ ๊ณต๊ฐํ•ฉ๋‹ˆ๋‹ค. ์œ„๋Œ€ํ•œ ํšŒ์‚ฌ๋ผ๊ณ ํ•ด์„œ ๋ฌด์กฐ๊ฑด ์ข‹์€ ์ฃผ์‹์ด๋ผ๊ณ  ๋ณผ ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค. ์ œ๊ฐ€๋ณด๊ธฐ์—๋„ ๋‹ค๋ฅธ ๊ธฐ์—…๋“ค์˜ ํ˜„์žฌ ์˜์—…์ด์ต์ด๋‚˜ ๋ฏธ๋ž˜๊ฐ€์น˜์— ๋น„ํ•ด์„œ ๊ณ ํ‰๊ฐ€๋˜์–ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค๋งŒ, ๊ทธ๋ž˜๋„ ํ…Œ์Šฌ๋ผ 100์ฃผ๋Š” ๋ณด์œ ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์•ผ ํ›„ํšŒํ•˜์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™์•„์š”. ์„ค์‚ฌ ๋‹ค์‹œ 500๋‹ฌ๋Ÿฌ, ํ˜น์€ ๋” ๊นŠ์€ ๋‚˜๋ฝ์œผ๋กœ ๋–จ์–ด์ง€๋”๋ผ๋„ ๋ง์ด์ฃ . ๊ทธ๋ ‡๊ฒŒ ๋–จ์–ด์ง€๋ฉด ๋” ์‚ฌ๋ฉด ๋˜๊ตฌ์š”!
  • ์ €์˜ ํฌํŠธํด๋ฆฌ์˜ค์™€ ์œ„ ๊ณ„ํš์„ ๋ณด์‹œ๋ฉด ์•Œ๊ฒ ์ง€๋งŒ, ์ €์—๊ฒŒ ํ•ด์™ธ์ฃผ์‹์€ "ํ•ด์™ธ์ฃผ์‹=ํ…Œ์Šฌ๋ผ" ๋ผ๊ณ ํ•ด๋„ ๋ฌด๋ฐฉํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์•ž์œผ๋กœ ์„นํ„ฐ๋ณ„, ๋ฐฐ๋‹น์ฃผ๊ธฐ๋ณ„๋กœ ๋‹ค์–‘ํ•˜๊ฒŒ ๋ถ„์‚ฐํ•ด์„œ ํˆฌ์žํ•  ์ƒ๊ฐ์ด๊ณ  ๊ทธ๋Ÿฌ๊ธฐ์— ๋”์šฑ ๋ช…ํ™•ํ•œ ๋งค๋งค์›์น™ ์ˆ˜๋ฆฝํ•  ํ•„์š”๋ฅผ ๋Š๋‚๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„์€ ์—ฌ๋Ÿฌ ์ฑ…๊ณผ ์˜์ƒ์„ ํ†ตํ•ด ๊ณ„์† ๊ณ ๋ฏผ์ค‘์ด๊ณ , ์ •๋ฆฌ๊ฐ€ ๋˜๋ฉด ๋‹ค์‹œ ์ ์–ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋งˆ์น˜๋ฉฐ#

์ €์˜ ํ•ด์™ธ ์ฃผ์‹๊ณผ ๊ตญ๋‚ด ๋น„์œจ์€ 6:4 ์ •๋„ ๋˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋˜ ๋” ํฐ ๊ด€์ ์—์„œ ์•”ํ˜ธํ™”ํ์™€ ์ฃผ์‹ ๋น„์œจ์€ ๋Œ€๋žต 10:1 ์ •๋„์ž…๋‹ˆ๋‹ค. ๋„ค, ๊ณ ์œ„ํ—˜์ž์‚ฐ์ธ ์•”ํ˜ธํ™”ํ๊ฐ€ ๊ฐ€์žฅ ํฐ ๋น„์ค‘์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์š”... ์‚ฌ์‹ค ์ด๋Ÿฐ ๋ถ€๋ถ„์ด ํ•ด์™ธ ์ฃผ์‹ ๋‚ด์—์„œ ๋ฐฐ๋ถ„์„ ํฌ๊ฒŒ ๊ณ ๋ คํ•˜์ง€ ์•Š์•˜๋˜ ์ด์œ ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ์ผ๋‹จ ํ˜„๊ธˆ, ๋‹ฌ๋Ÿฌ, ์ฑ„๊ถŒ, ์ฃผ์‹, ๋ถ€๋™์‚ฐ, ์•”ํ˜ธํ™”ํ์™€ ๊ฐ™์€ ๋” ํฐ ์ž์‚ฐ ๊ด€์ ์—์„œ ์•ˆ์ „์ž์‚ฐ๊ณผ ์œ„ํ—˜์ž์‚ฐ์˜ ๋น„์ค‘์„ ์กฐ์ ˆํ•˜๋Š” ๊ฒƒ์ด ๊ธ‰์„ ๋ฌด์ฃ ... ์ถ”ํ›„ ๊ตญ๋‚ด ์ฃผ์‹๊ณผ ์•”ํ˜ธํ™”ํ ํฌํŠธํด๋ฆฌ์˜ค๋„ ์ •๋ฆฌํ•ด์„œ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐํšŒ๊ฐ€ ์žˆ์—ˆ์œผ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

Intellij ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ ๋‹จ์ถ•ํ‚ค

๊ฐœ์š”#

์‹ค๋ฌด์—์„œ ์ธํ…”๋ฆฌ์ œ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค๋ณด๋ฉด ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ์ ํŠธ๋“ค์ด ์ ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ตœ๊ทผ์— ํ”„๋กœ์ ํŠธ๋ฅผ ์—ด๊ณ  ๋‹ซ๋Š”๋ฐ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค.

์ •๋ฆฌ๋˜์ง€ ์•Š์€ ์ž‘์—… ํ™˜๊ฒฝ#

์ €๋Š” ๋‹จ์ถ•ํ‚ค ์‚ฌ์šฉ์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋„๊ตฌ๊ฐ€ ์žˆ๋‹ค๋ฉด, ๊ทธ๋ฆฌ๊ณ  ๊ทธ ๋„๊ตฌ์—์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Šฅ ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค๋ฉด ๋‹จ์ถ•ํ‚ค๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด ์‹œ๊ฐ„์„ ํˆฌ์žํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํˆฌ์žํ•œ ์‹œ๊ฐ„์€ ์ดํ›„ ๋ฐ˜๋ณต๋˜๋Š” ์ž‘์—…์— ์†Œ์š”๋˜๋Š” ์‹œ๊ฐ„์„ ์ค„์—ฌ์ค˜์„œ ๊ธด ์‹œ๊ฐ„์œผ๋กœ ๋ดค์„ ๋•Œ ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.

MSA ๋กœ ๊ตฌ์„ฑ๋œ ์„œ๋น„์Šค๋ฅผ ์šด์˜ํ•˜๋‹ค๋ณด๋ฉด ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์—ด์–ด์„œ ์ž‘์—…ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ์š”. ์–ด๋Š์ƒˆ ์ธํ…”๋ฆฌ์ œ์ด ์ฐฝ๋งŒ 5๊ฐœ๊ฐ€ ๋„˜์–ด๊ฐ€๋ฒ„๋ ค์„œ ํšจ์œจ์ด ๋–จ์–ด์งˆ ๋•Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž‘์—…์ด ๋๋‚˜๋ฉด ๋ฐ”๋กœ๋ฐ”๋กœ ์ฐฝ์„ ๋‹ซ์•„ ์ •๋ฆฌํ•ด์•ผํ•˜๋ฉด ์ข‹์„ํ…๋ฐ ๋ง์ด์ฃ .

์‚ฌ์‹ค ์ธํ…”๋ฆฌ์ œ์ด ์ฐฝ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ณด๊ฒ ๋‹ค๊ณ  ์—ด์–ด๋‘” ์ˆ˜๋งŽ์€ ํฌ๋กฌ์ฐฝ๊ณผ ํ„ฐ๋ฏธ๋„์ฐฝ์— ์ž‘์—… ๊ณต๊ฐ„์ด ๋ฎํ˜€๋ฒ„๋ฆฌ๊ฒŒ ๋˜๋ฉด, ์ €๋Š” ๊ถ๊ทน๊ธฐ์ธ ์žฌ์‹œ์ž‘์„ ์‹œ์ „ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ธํ…”๋ฆฌ์ œ์ด ์ฐฝ์ด ๋งŽ์ด ์—ด๋ ค์žˆ์„ ๋•Œ๋Š” ์ธํ…”๋ฆฌ์ œ์ด ๋ชจ๋“  ์ฐฝ์„ ๋‹ซ๊ณ  ๋‹ค์‹œ ํ•„์š”ํ•œ ํ”„๋กœ์ ํŠธ๋ฅผ ์—ด์–ด์„œ ์ž‘์—…์„ ๊ณ„์†ํ•ด๊ฐ”์ฃ .

๋„ˆ๋ฌด ์นœ์ ˆํ•œ ์ธํ…”๋ฆฌ์ œ์ด#

์ธํ…”๋ฆฌ์ œ์ด์—์„œ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์ธ์ง€๋Š” ํ™•์‹คํ•˜์ง€ ์•Š์ง€๋งŒ, ์ฐฝ์ด ์—ฌ๋Ÿฌ๊ฐœ ์—ด๋ฆฐ ์ƒํƒœ๋กœ ์•ฑ์„ ์žฌ์‹œ์ž‘ํ•˜๋ฉด, ์นœ์ ˆํ•˜๊ฒŒ๋„ ์ด์ „์— ์—ด๋ ค์žˆ๋˜ ๋ชจ๋“  ์ฐฝ์„ ๋‹ค์‹œ ์—ด์–ด์ค๋‹ˆ๋‹ค. ๋‹ค์‹œ ๊น”๋”ํ•˜๊ฒŒ ์‹œ์ž‘ํ•˜๊ฒ ๋‹ค๊ณ  ์žฌ์‹œ์ž‘ํ–ˆ๋Š”๋ฐ, ํšจ๊ณผ๊ฐ€ ์—†๋Š” ์…ˆ์ด์ฃ . ๊ทธ๋ž˜์„œ ์˜ค๋žซ๋™์•ˆ ์ €๋Š” ์ธํ…”๋ฆฌ์ œ์ด ์ฐฝ์„ ํ•˜๋‚˜์”ฉ ์ฐพ์•„๊ฐ€๋ฉฐ ๋„๊ธฐ๋ฅผ ์‹œ์ „ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ตœ์†Œํ™” ํ•ด๋†“์€ ์ฐฝ๋“ค๋„ ์žˆ๊ณ , ๋งฅ ๋ฐ์Šคํฌํƒ‘ ํ™”๋ฉด ์—ฌ๊ธฐ์ €๊ธฐ ํฉ์–ด์ ธ ์žˆ์–ด์„œ ์•ฝ๊ฐ„์€ ๋ฒˆ๊ฑฐ๋กœ์šด ์ž‘์—…์ด์˜€์ง€๋งŒ, ๋‚ด๊ฐ€ ์ง‘์ค‘ํ•ด์•ผ ํ•  ์ฐฝ๋งŒ ์—ด์–ด๋†“์œผ๋ฉด ์—…๋ฌด ํšจ์œจ์ด 3~5% ์ •๋„๋Š” ํ–ฅ์ƒ๋˜๋Š” ๊ฒƒ ๊ฐ™์€ ๋Š๋‚Œ์„ ๋ฐ›์•˜์ฃ . (๊ธฐ๋ถ„ํƒ“์ด๊ฒ ์ง€๋งŒ) ๊ทธ๋ฆฌ๊ณ  ์ด๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋Š” ๋‹จ์ถ•ํ‚ค๋ฅผ ์ฐพ์•„๋ณด์•˜์ง€๋งŒ, ์ผ๋‹จ ์ œ ์„ ์—์„œ๋Š” ๋ชป ์ฐพ์•˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋งŒ๋Šฅ ๋‹จ์ถ•ํ‚ค CMD+SHIFT+A#

์ธํ…”๋ฆฌ์ œ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ Cmd + Shift + A ๋ฅผ ๋ชจ๋ฅด๋Š” ์‚ฌ๋žŒ์ด ์žˆ์„๊นŒ์š”? ๋งŒ์•ฝ์— ์ง€๊ธˆ๊นŒ์ง€ ๋ชฐ๋ž๋‹ค๋ฉด, ๋„ค, ์ œ๊ฐ€ ๋‹น์‹ ์˜ ๋ฏธ๋ž˜ ์‹œ๊ฐ„ ์ƒ๋‹น๋ถ€๋ถ„์„ ์ ˆ์•ฝํ•ด๋“œ๋ฆฌ๊ฒŒ ๋์Šต๋‹ˆ๋‹ค. Cmd + Shift + A ๋Š” ์ธํ…”๋ฆฌ์ œ์ด์—์„œ ์•ก์…˜ ํŒ์—…์ฐฝ์„ ์—ด์–ด์ฃผ๋Š” ๋‹จ์ถ•ํ‚ค์ž…๋‹ˆ๋‹ค. ์–ด๋–ค ์•ก์…˜์ด ์ˆ˜ํ–‰๋˜๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ ์ˆ˜ํ–‰ํ•  ์•ก์…˜์„ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋Š” ํŒ์—…์ฐฝ์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋‹จ์ถ•ํ‚ค์ด์ฃ .

์ž ๊ทธ๋Ÿผ ์ œ๊ฐ€ ์ด๋ฒˆ์— ์†Œ๊ฐœํ•˜๋ ค๊ณ  ํ•˜๋Š” ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ์— ๋Œ€ํ•ด์„œ ๋งํ•ด๋ณด์ฃ . ํ•˜๋‚˜์”ฉ ์ฐฝ์„ ์ฐพ์•„์„œ ๋‹ซ๋Š”๋ฐ ์•„๋‹ˆ๋ผ Close All Projects ๋ผ๊ณ  ์ž…๋ ฅํ•˜๋ฉด ๋ชจ๋“  ํ”„๋กœ์ ํŠธ๊ฐ€ ๋‹ซํžˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์‚ฌ์‹ค ์ด ๊ธฐ๋Šฅ์€ ํ™”๋ฉด ์ƒ๋‹จ File ๋ฉ”๋‰ด์—์„œ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ป๊ฒŒ ๋ณด๋ฉด ์ €๊ฑธ ์ž…๋ ฅํ•˜๋Š๋‹ˆ, ๋งˆ์šฐ์Šค์— ์†์„ ์˜ฎ๊ฒจ File โ†’ Close All Projects ๋ฅผ ๋ˆ„๋ฅด๋Š”๊ฒŒ ๋” ๋น ๋ฅผ์ˆ˜๋„ ์žˆ์ฃ . ํ•˜์ง€๋งŒ, ์ „์ฒด๋ฅผ ์ž…๋ ฅํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค๋ฉด ์ด์•ผ๊ธฐ๊ฐ€ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

์ € ๊ธฐ๋Šฅ์— ์•ž๊ธ€์ž์ธ CAP ๋ผ๊ณ  ์ž…๋ ฅํ•˜๋ฉด ๋ฐ”๋กœ ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์ฃ . ๋งŒ์•ฝ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์ด ์กฐ๊ธˆ ์•„๋ž˜ ์žˆ๋‹ค๋ฉด ์กฐ๊ธˆ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ์ž…๋ ฅํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. CAPro ์™€ ๊ฐ™์€ ํ˜•ํƒœ๋กœ์š”.

Monosnap 2021-09-05 16-21-49.png

์ด๋Ÿฐ ์•ž๊ธ€์ž ๊ฒ€์ƒ‰ ๋ฐฉ์‹์€ ์ธํ…”๋ฆฌ์ œ์ด ์ „๋ฐ˜์—์„œ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ํŒŒ์ผ์ด๋‚˜ ํด๋ž˜์Šค๋ฅผ ์ฐพ์„ ๋•Œ๋„ ๋™์ผํ•˜๊ฒŒ ์ฐพ์œผ๋ฉด ๋˜์ง€์š”. (์ด๋Ÿฐ ๊ฒ€์ƒ‰ ๋ฐฉ์‹์„ ์นญํ•˜๋Š”๊ฒŒ ์žˆ๋Š”๋ฐ ๊ธฐ์–ต์ด ์ž˜ ์•ˆ๋‚˜๋„ค์š”)

๋ณด๋„ˆ์Šค ์ตœ๊ทผ ํ”„๋กœ์ ํŠธ ์—ด๊ธฐ#

๋ชจ๋‘ ๋‹ซ์•˜์œผ๋ฉด ์›ํ•˜๋Š” ํ”„๋กœ์ ํŠธ๋“ค์„ ์—ด์–ด์•ผ๊ฒ ์ฃ . ๊ทธ๋ฆฌ๊ณ  ์•„๋งˆ ๋Œ€๋ถ€๋ถ„ ์—ด์–ด์•ผ ํ•˜๋Š” ํ”„๋กœ์ ํŠธ๋“ค์€ ์ตœ๊ทผ์— ์—ด์—ˆ๋˜ ํ”„๋กœ์ ํŠธ์ผ๊ฑฐ์˜ˆ์š”. ์ตœ๊ทผ ํ”„๋กœ์ ํŠธ ์—ด๊ธฐ? Open Recent Project Action ํŒ์—…์„ ์—ด์–ด์„œ ๋ญ๋ผ๊ณ  ์ž…๋ ฅํ•ด์•ผํ•˜๋Š”์ง€ ๊ฐ์ด ์˜ค์‹œ๋‚˜์š”? ORP ๋ผ๊ณ  ์ž…๋ ฅํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.!

๋งˆ์น˜๋ฉฐ#

์‚ฌ์‹ค ์ ๊ณ  ๋ณด๋ฉด ๊ฐ„๋‹จํ•œ ๊ธฐ๋Šฅ์ธ๋ฐ, ์ €๋Š” ์ƒ๋‹นํžˆ ์˜ค๋žซ๋™์•ˆ ํŠธ๋ž™ํŒจ๋“œ๋กœ ์†์„ ์˜ฎ๊ฒจ์„œ ์œ„์— ์†Œ๊ฐœํ•œ ๊ธฐ๋Šฅ๋“ค์„ ์‹คํ–‰ํ•ด์™”์Šต๋‹ˆ๋‹ค. ๊ทธ ๋™์•ˆ ๊ทธ ๋ฒˆ๊ฑฐ๋กœ์šด ๊ธฐ๋ถ„๊ณผ ์ˆ˜์—†์ด ์—ฌ๋Ÿฌ ๋ฒˆ ๋‚ญ๋น„๋œ 1~2์ดˆ๋งŒ ๋ชจ์•„๋„ ๋„ทํ”Œ๋ฆญ์Šค์—์„œ ์˜ํ™” ํ•œํŽธ์€ ๋ณผ ์ˆ˜ ์žˆ์—ˆ์„๊ฑฐ์˜ˆ์š”! (์‚ฌ์‹ค ๋„ทํ”Œ๋ฆญ์Šค๊ฐ€ ์ œ์ผ ๋‚ญ๋น„- _ใ… )

๋งŽ์€ ๋ถ„๋“ค์ด ๋ฐ”๋กœ ๊นจ๋‹ฌ์•˜๊ฒ ์ง€๋งŒ, Cmd + Shift + A ์€ ๋น„๋‹จ ํ”„๋กœ์ ํŠธ ์ „์ฒด ๋‹ซ๊ณ  ์ตœ๊ทผ ํ”„๋กœ์ ํŠธ ์—ฌ๋Š” ๊ณณ์—๋งŒ ์‚ฌ์šฉ๋˜๋Š”๊ฒŒ ์•„๋‹™๋‹ˆ๋‹ค. ๋ง๊ทธ๋Œ€๋กœ ์ธํ…”๋ฆฌ์ œ์ด ๋‚ด ๋ชจ๋“  ์•ก์…˜๋“ค์„ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์ฃ . ๋ฌด์–ธ๊ฐ€๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ํด๋ฆญํ•ด์„œ ์‹คํ–‰ํ•˜๊ณ  ์žˆ๋‚˜์š”? Cmd + Shift + A ๋ฅผ ๋ˆŒ๋Ÿฌ์„œ ๊ฒ€์ƒ‰ํ•ด๋ณด์„ธ์š”! ๋‹น์‹ ์˜ ์†Œ์ค‘ํ•œ 1์ดˆ๋ฅผ ์ง€์ผœ์ค„๊ฑฐ์˜ˆ์š”.

Spring Rest Docs & OAS - ์‹œ์ž‘ํ•˜๊ธฐ

๊ฐœ์š”#

์ง€๋‚œ ๊ธ€ Spring Rest Docs & OAS ์˜ ํ•„์š”์„ฑ ์—์„œ ์ด ๋‘˜์˜ ์กฐํ•ฉ์ด ์™œ ํ•„์š”ํ•œ์ง€ ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ด์ œ ๊ฐ„๋‹จํ•œ ์ƒ˜ํ”Œ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด OAS ๋ฅผ ์‚ฌ์šฉํ•ด์„œ API ๋ฌธ์„œ๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ณธ๋ฌธ์— ๋“ฑ์žฅํ•˜๋Š” ์ฝ”๋“œ๋Š” ๊นƒํ—ˆ๋ธŒ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‹œ์ž‘ํ•˜๊ธฐ ์ „์—#

์ด ํŠœํ† ๋ฆฌ์–ผ์€ restdocs-api-spec ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ์— ์ค‘์ ์„ ๋‘๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์•„๋ž˜ ๋‚˜์—ด๋œ ๋ฐฉ๋ฒ•๋“ค์€ ์ƒ์„ธํžˆ ์„ค๋ช…ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  • Sprint Rest Docs ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•
  • Spring Boot Start Web ์œผ๋กœ API ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•

restdocs-api-spec ํ”„๋กœ์ ํŠธ๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์œผ๋ฉฐ, mockmvc ๋ฅผ ์‚ฌ์šฉํ•œ ํ…Œ์ŠคํŠธ์™€ restassured ์„ ์‚ฌ์šฉํ•œ ํ…Œ์ŠคํŠธ ๋‘˜ ๋‹ค ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๋‘ ํ…Œ์ŠคํŠธ์˜ ํฐ ์ฐจ์ด์ ์€ MockMvc ๋Š” @WebMvcTest ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , Rest Assured ๋Š” @SpringBootTest ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ์ ์ธ๋ฐ ์ž์„ธํ•œ ๋‚ด์šฉ์€ MockMvc VS RestAssured ๊ธ€์„ ์ฐธ๊ณ ๋˜์ง€๋งŒ, ์ด ๊ธ€์ด ์ž‘์„ฑ๋œ ์‹œ์ ์€ 2020๋…„ 8์›”๋กœ 1๋…„์ด ์ง€๋‚œ ํ˜„์žฌ๋Š” io.rest-assured:spring-mock-mvc module ์ด ์กด์žฌํ•˜์—ฌ RestAssured ๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ์ „์ฒด Bean ์„ ๋กœ๋“œํ•  ํ•„์š”๊ฐ€ ์—†์–ด์กŒ์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ๊ฐ€๋…์„ฑ์ด๋‚˜, ์ž‘์„ฑ์˜ ํŽธ๋ฆฌํ•จ์„ ๋ณด์•˜์„ ๋•Œ RestAssured ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ์ข‹์•„๋ณด์ด๋‚˜, ์ด์ „์— ์‚ฌ์šฉ ๊ฒฝํ—˜์ด ์—†์–ด์„œ, ์ด ๊ธ€์—์„œ๋Š” ์ต์ˆ™ํ•œ MockMvc ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ถ”ํ›„ RestAssured ๋ฅผ ์‚ฌ์šฉํ•œ ์ƒ˜ํ”Œ๋„ ์ž‘์„ฑํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฐ”๋กœ RestAssured ๋กœ ์‹œ๋„ํ•ด๋ณด๊ณ  ์‹ถ์€ ๋ถ„๋“ค์€ ์•„๋ž˜ ๊ธ€๋“ค์„ ์ฐธ๊ณ ํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ฐ„๋‹จํ•œ ์ƒ˜ํ”Œ API ๊ตฌํ˜„#

๋จผ์ € ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์กฐํšŒํ•˜๋Š” ๊ฐ„๋‹จํ•œ API ๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋“ค ์„ค์ •์„ ํ•ด์ฃผ๊ณ ...

plugins {
id 'org.springframework.boot' version '2.5.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
id 'com.epages.restdocs-api-spec' version '0.11.5' // (1)
}
group = 'net.dezang'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' // (2)
testImplementation 'com.epages:restdocs-api-spec-mockmvc:0.11.5' // (2) For openapi spec
}
openapi3 { // (3)
server = 'http://localhost:8080'
title = 'USER-API'
description = '์‚ฌ์šฉ์ž ๋ฆฌ์†Œ์Šค API ์ž…๋‹ˆ๋‹ค.'
version = '0.1.0'
format = 'yaml'
}
test {
useJUnitPlatform()
}
  • (1) restdocs-api-spec ํ”Œ๋Ÿฌ๊ทธ์ธ ์ถ”๊ฐ€
  • (2) spring-restdocs-mockmvc , restdocs-api-spec-mockmvc ์˜์กด์„ฑ ์ถ”๊ฐ€
  • (3) openapi3 ์— ์„ค์ • ์ •๋ณด ์ž…๋ ฅ

์œ ์ € ์ •๋ณด๋ฅผ ์กฐํšŒํ•˜๋Š” ๊ฐ„๋‹จํ•œ API ๋ฅผ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.

package net.dezang.restdocopenapi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class RestdocOpenapiApplication {
public static void main(String[] args) {
SpringApplication.run(RestdocOpenapiApplication.class, args);
}
}
package net.dezang.restdocopenapi;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
class User {
private Long id;
private String username;
private String password;
private Integer age;
private boolean enabled;
}
package net.dezang.restdocopenapi;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping
public ResponseEntity<List<UserDto.Response>> list() {
List<UserDto.Response> responses = userService.list().stream()
.map(UserDto.Response::of)
.collect(Collectors.toList());
return ResponseEntity.ok(responses);
}
@NoArgsConstructor(access = AccessLevel.PRIVATE)
static class UserDto {
@Data
@AllArgsConstructor
static class Response {
private String username;
private Integer age;
public static Response of(User domain) {
return new Response(domain.getUsername(), domain.getAge());
}
}
}
}
package net.dezang.restdocopenapi;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
@Service
class UserService {
public List<User> list() {
return Collections.singletonList(User.builder()
.id(1L)
.username("dezang")
.password("!topSecret!")
.age(20)
.enabled(true)
.build());
}
}

์šฐ๋ฆฌ๋Š” ์ปจํŠธ๋กค๋Ÿฌ ํ…Œ์ŠคํŠธ์™€ ์ด๋ฅผ ํ†ตํ•ด ๋‚˜์˜ค๋Š” API ๋ฌธ์„œ์— ๊ด€์‹ฌ์ด ์žˆ๊ธฐ์— ๋ ˆํฌ์ง€ํ† ๋ฆฌ ๋ ˆ๋ฒจ์€ ์˜๋„์ ์œผ๋กœ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ ์ƒ˜ํ”Œ์ด์ง€๋งŒ ๋„๋ฉ”์ธ ๊ฐ์ฒด์™€ ์‘๋‹ต ๊ฐ์ฒด๋Š” ๋ถ„๋ฆฌํ•˜์˜€์Šต๋‹ˆ๋‹ค.

OPENAPI SPEC ๋ฌธ์„œ ์ƒ์„ฑ#

package net.dezang.restdocopenapi;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import java.util.Collections;
import static com.epages.restdocs.apispec.MockMvcRestDocumentationWrapper.document; // (1)
import static org.mockito.BDDMockito.given;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@AutoConfigureRestDocs
@WebMvcTest(UserController.class)
class UserApiDoc {
@Autowired
MockMvc mockMvc;
@MockBean
UserService userService;
@Test
void list() {
//given
given(userService.list())
.willReturn(Collections.singletonList(
User.builder()
.username("dezang")
.age(10)
.build()
));
//when
ResultActions resultActions = mockMvc.perform(get("/users"));
//then
resultActions
.andExpect(status().isOk())
.andDo(document("list-user",
responseFields(
fieldWithPath("[].username").description("์‚ฌ์šฉ์ž ์•„์ด๋””"),
fieldWithPath("[].age").description("์‚ฌ์šฉ์ž ๋‚˜์ด")
)))
.andDo(print());
}
}
  • (1): MockMvcRestDocumentation ์ด ์•„๋‹Œ MockMvcRestDocumentationWrapper ๋‚ด document ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑ

์ฝ”๋“œ ์ž‘์„ฑ์€ ๋๋‚ฌ์Šต๋‹ˆ๋‹ค. ์ด์ œ openapi3 ๋ฌธ์„œ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์ œ๊ณตํ•˜๋Š” ํ…Œ์Šคํฌ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

./gradlew openapi3

์œ„ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด, ํ…Œ์ŠคํŠธ๊ฐ€ ๋Œ๊ณ  ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋ฌผ์ด build ๊ฒฝ๋กœ์— ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

build
โ”œโ”€โ”€ api-spec
โ”‚ย ย  โ””โ”€โ”€ openapi3.yaml
...
โ”œโ”€โ”€ generated-snippets
โ”‚ย ย  โ””โ”€โ”€ list-user
โ”‚ย ย  โ”œโ”€โ”€ curl-request.adoc
โ”‚ย ย  โ”œโ”€โ”€ http-request.adoc
โ”‚ย ย  โ”œโ”€โ”€ http-response.adoc
โ”‚ย ย  โ”œโ”€โ”€ httpie-request.adoc
โ”‚ย ย  โ”œโ”€โ”€ request-body.adoc
โ”‚ย ย  โ”œโ”€โ”€ resource.json
โ”‚ย ย  โ”œโ”€โ”€ response-body.adoc
โ”‚ย ย  โ””โ”€โ”€ response-fields.adoc
...

์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ํŒŒ์ผ์ด ์ €๊ธฐ ๋ณด์ด๋„ค์š”. build/api-spec/openapi3.yaml ์ž…๋‹ˆ๋‹ค. ์•„์›ƒํ’‹ ๊ฒฝ๋กœ๋Š” ์ฒ˜์Œ ๊ณต์œ ํ•œ build.gradle ์— openapi3 ์—์„œ ์„ค์ • ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ yaml ํŒŒ์ผ์„ ํ•œ๋ฒˆ ์‚ดํŽด๋ณผ๊นŒ์š”?

openapi: 3.0.1
info:
title: USER-API
description: ์‚ฌ์šฉ์ž ๋ฆฌ์†Œ์Šค API ์ž…๋‹ˆ๋‹ค.
version: 0.1.0
servers:
- url: http://localhost:8080
tags: []
paths:
/users:
get:
tags:
- users
operationId: list-user
responses:
"200":
description: "200"
content:
application/json:
schema:
$ref: '#/components/schemas/users450998075'
examples:
list-user:
value: "[{\"username\":\"dezang\",\"age\":10}]"
components:
schemas:
users450998075:
type: array
items:
type: object
properties:
age:
type: number
description: ์‚ฌ์šฉ์ž ๋‚˜์ด
username:
type: string
description: ์‚ฌ์šฉ์ž ์•„์ด๋””

์ƒ๊ฐ๋ณด๋‹ค ๋ณ„๊ฑฐ ์—†์–ด๋ณด์ด์ง€๋งŒ, ์ŠคํŽ™ ์ž์ฒด๋Š” ๊ฐ•๋ ฅํ•ฉ๋‹ˆ๋‹ค. ์ด์ „ ๊ธ€ Spring Rest Docs & OAS ์˜ ํ•„์š”์„ฑ ์— ๋Œ€ํ•œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ŠคํŽ™ ๋ฌธ์„œ ํ™œ์šฉํ•˜๊ธฐ#

์ด์ œ ์œ ์—ฐํ•œ ๊ฒฐ๊ณผ๋ฌผ์„ ์–ป์—ˆ์œผ๋‹ˆ, OAS ๋ฅผ ์ง€์›ํ•˜๋Š” ๋„๊ตฌ๋‚˜ ์„œ๋น„์Šค๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ผ๋‹จ ์—ฌ๊ธฐ์„œ๋Š” ๋„์ปค๋ฅผ ํ™œ์šฉํ•˜์—ฌ Swagger ๋ฅผ ์‚ฌ์šฉํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

docker run --rm -p 80:8080 \
-v __YOUR_BUILD_PATH__/api-spec:/usr/share/nginx/html/docs/ \
-e URL=docs/openapi3.yaml \
swaggerapi/swagger-ui

๋“œ๋””์–ด API ๋ฌธ์„œ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!

Swagger UI 2021-09-05 13-56-49.png

๋งˆ์น˜๋ฉฐ#

์ด์ œ API ๋ฌธ์„œ๋ฅผ ๋งŒ๋“ค์—ˆ์œผ๋‹ˆ ๋์ผ๊นŒ์š”? REST DOCS + OAS ๋ฅผ ์‹œ์ž‘ํ•˜๊ฒŒ ๋œ ์ด์œ ๊ฐ€ MSA ๊ตฌ์กฐ์—์„œ ๋ถ„์‚ฐ๋˜์–ด์žˆ๋Š” API ๋ฌธ์„œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ํ†ตํ•ฉํ•ด์„œ ๋ณผ ์ˆ˜ ์žˆ์„๊นŒ? ์˜€๋˜ ๊ฒƒ์„ ๊ธฐ์–ตํ•˜์‹œ๋‚˜์š”? ๊ฐ ์„œ๋น„์Šค๊ฐ€ ์–ด๋–ค ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ด์„œ OAS ๋ผ๋Š” ์ŠคํŽ™์„ ์ง€ํ‚จ ๋ฌธ์„œ๋ฅผ ์ƒ์„ฑํ–ˆ๋‹ค๋ฉด, ์ด ๋ฌธ์„œ๋ฅผ ์–ด๋–ป๊ฒŒ ์„œ๋น™ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„๊นŒ์š”? ๋‹ค์Œ ๊ธ€์—์„œ๋Š” ์—ญ์‹œ ๋ถ„์‚ฐ๋˜์–ด ์žˆ๋Š” OAS ํŒŒ์ผ์„ ์–ด๋–ป๊ฒŒ ์ž๋™์œผ๋กœ ํ•œ ๊ณณ์œผ๋กœ ๋ชจ์œผ๊ณ , ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ ๋ณด์—ฌ์ค„ ๊ฒƒ์ธ์ง€ ๊ณ ๋ฏผ์˜ ๊ฒฐ๊ณผ๋ฅผ ๊ณต์œ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

Spring Rest Docs & OAS ์˜ ํ•„์š”์„ฑ

๊ฐœ์š”#

ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด API ๋ฌธ์„œ๊ฐ€ ์ฝ”๋“œ์™€ ์ผ์น˜๋จ์„ ๋ณด์žฅํ•ด์ฃผ๋Š” SPRING REST DOCS ๊ณผ ๋›ฐ์–ด๋‚œ ๋ฒ”์šฉ์„ฑ์„ ์ž๋ž‘ํ•˜๋Š” OPEN API SPEC (OAS 3) ์˜ ์กฐํ•ฉ์œผ๋กœ ๊ฐœ๋ฐœ๋œ API ํ™œ์šฉ๋„๋ฅผ ๊ทน๋Œ€ํ™” ์‹œํ‚ค๋Š” ๋ฒ•์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  API ๋ฌธ์„œ๋ฅผ ํ•œ ๊ณณ์œผ๋กœ ๋ชจ์„ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ๋ณด๋„ˆ์Šค์ž…๋‹ˆ๋‹ค.

SPRING REST DOCS ๊ณผ OAS ์กฐํ•ฉ์ด ํ•„์š”ํ•œ ์ด์œ #

๊ฐœ๋ฐœ๋œ API ๊ฐ€ ๋ชฉ์ ์— ๋งž๊ฒŒ ์ œ๋Œ€๋กœ ์ด์šฉ๋˜๋ ค๋ฉด ๋ฌธ์„œํ™”๋Š” ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค. ์ €๋Š” ์˜ˆ์ „๋ถ€ํ„ฐ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด API ๋ฌธ์„œ๊ฐ€ ์ƒ์„ฑ๋˜๋Š” SPRING REST DOCS ์„ ์‚ฌ์šฉํ•ด์™”์Šต๋‹ˆ๋‹ค. API ๋ฌธ์„œ๋ฅผ ์œ„ํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค๋Š” ์ ์€ ๋ถ„๋ช…ํžˆ ๋ฒˆ๊ฑฐ๋กœ์› ์ง€๋งŒ, API ๋ฌธ์„œ๊ฐ€ ์ฝ”๋“œ์™€ ์ผ์น˜๋˜์ง€ ์•Š์•„ ๋ฐœ์ƒํ•  ์ˆ˜ ๋งŽ์€ ์ด์Šˆ๋“ค์— ๋น„ํ•˜๋ฉด ๋ณ„๊ฑฐ ์•„๋‹ˆ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. SPRINT REST DOCS ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ์ง€๊ธˆ๊นŒ์ง€๋„ ๋ชป ๋“ค์–ด๋ณด์ง€ ์•Š์•˜์„๊นŒ ์‹ถ์€ AsciiDoc ์ด ๋ถˆ๋งŒ์ด๊ธด ํ–ˆ์Šต๋‹ˆ๋‹ค๋งŒ, ๋งˆํฌ๋‹ค์šด๊ณผ ๋น„์Šทํ•œ ์‚ฌ์šฉ๋ฒ•์— ๋Ÿฌ๋‹์ปค๋ธŒ๊ฐ€ ๊ฑฐ์˜ ์—†๋‹ค์‹œํ”ผํ•˜์—ฌ ์ž˜ ์จ์™”์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ƒ‰๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ์ฐพ์•„๋ด์•ผ ํ•˜๋Š” ์ด์œ ๋Š” ๋„๊ตฌ ์ž์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ, ๋„๊ตฌ๋ฅผ ํ†ตํ•ด ๋งŒ๋“ค์–ด์ง„ ๋ฌธ์„œ ์ ‘๊ทผ์—์„œ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ณ„์†ํ•ด์„œ ๋Š˜์–ด๋‚˜๋Š” API ์„œ๋ฒ„์™€ ๋ถ„์‚ฐ๋˜๋Š” API ๋ฌธ์„œ#

์„œ๋น„์Šค๊ฐ€ ํ™•์žฅํ•จ์— ๋”ฐ๋ผ API ์—”๋“œํฌ์ธํŠธ๊ฐ€ ๋Š˜์–ด๋‚˜๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€ํ”ผํ–ˆ๊ณ , MSA ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœ๋˜๊ณ  ์žˆ๋Š” ์ œํ’ˆ์ธ์ง€๋ผ, API ์ถ”๊ฐ€๋Š” API ์„œ๋ฒ„์˜ ์ถ”๊ฐ€๋กœ ์ด์–ด์กŒ์Šต๋‹ˆ๋‹ค. ๊ฐ ์„œ๋ฒ„๋งˆ๋‹ค REST DOCS ์„ ํ†ตํ•ด ๋งŒ๋“ค์–ด์ง€๋Š” API ๋ฌธ์„œ๋Š” ๊ฐ ์„œ๋ฒ„์˜ ํŠน์ • ์—”๋“œํฌ์ธํŠธ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์—ˆ๊ณ , ์šฐ๋ฆฌ ํŒ€์€ ์—ฌ๊ธฐ์ €๊ธฐ ํฉ์–ด์ ธ์žˆ๋Š” API ๋ฌธ์„œ๋ฅผ ์ฐพ์•„๋‹ค๋‹ˆ๋ฉฐ ๊ฐœ๋ฐœ์„ ํ•ด์•ผํ•˜๋Š”๋ถˆํŽธํ•จ์„ ๊ฒช์–ด์•ผํ–ˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ์ž๋ฐ”๊ฐ€ ์•„๋‹ˆ๋ผ, ๋‹ค๋ฅธ ์–ธ์–ด๋กœ ๊ฐœ๋ฐœ๋œ API์˜ ๊ฒฝ์šฐ REST DOCS ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†์—ˆ๊ณ , ์ด๋Ÿฐ ์ด์œ ๋กœ REST DOCS ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๋Š” API ์„œ๋ฒ„๋Š” ์‚ฌ๋‚ด Notion ์— API ๋ฌธ์„œ๋ฅผ ์ž‘์„ฑํ•ด ๊ณต์œ ํ•˜๋„๋ก ํ•˜์˜€์œผ๋‚˜, ์—ญ์‹œ๋‚˜ ํฌ๊ณ  ์ž‘์€ ์ˆ˜์ • ์‚ฌํ•ญ๋“ค์ด ๋นˆ๋ฒˆํ•˜๊ฒŒ ๋™๊ธฐํ™”๋˜์ง€ ์•Š์•˜๊ณ , ๋…ธ์…˜์— ์žˆ๋Š” API ๋ฌธ์„œ๋Š” ์‹ ๋ขฐ๋ฅผ ์žƒ์–ด๊ฐ€๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ์‚ฌ๋‚ด์— ์žˆ๋Š” ๋ชจ๋“  API ๋ฅผ ํ•œ ๊ณณ์—์„œ ๋ณผ ์ˆ˜ ์žˆ์„๊นŒ?#

์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ์—ฌ๊ธฐ ์ €๊ธฐ ํฉ์–ด์ ธ์žˆ๋Š” API ๋ฅผ ํ•œ ๊ณณ์—์„œ ๋ณผ ์ˆ˜ ์žˆ์„๊นŒ์š”? ๊ทธ๋ž˜์„œ ์‚ฌ๋‚ด์— ์žˆ๋Š” ๋ชจ๋“  ๊ธฐ๋Šฅ๊ณผ ๋ฆฌ์†Œ์Šค๋ฅผ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ™˜๊ฒฝ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„๊นŒ์š”? ์ฒ˜์Œ์—๋Š” ๊ฐ ์„œ๋ฒ„์— ์žˆ๋Š” SPRING REST DOCS ์œผ๋กœ ์ƒ์„ฑ๋œ html ๋ฌธ์„œ๋ฅผ ๋ชจ์•„์„œ ํ•œ ์›น ์„œ๋ฒ„์—์„œ ํ˜ธ์ŠคํŒ…์„ ๊ณ ๋ คํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค๋งŒ, ๊ทธ ๊ฐ๊ฐ์˜ ๋ฌธ์„œ ๋งํฌ๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ๋ณ„๋„ ํŽ˜์ด์ง€๊ฐ€ ํ•„์š”ํ–ˆ๊ณ , ๊ทธ ๊ณณ์—๋Š” Notion ๋งํฌ๋„ ๋“ค์–ด๊ฐ€์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ด€๋ฆฌ๊ฐ€ ์ž˜ ๋  ์ˆ˜ ์žˆ์„๊นŒ์š”? ๋ชจ๋“  API ์„œ๋ฒ„๊ฐ€ ์ฝ”๋“œ๋ฅผ ๊ธฐ๋ฐ˜ํ•˜์—ฌ ๊ฐ™์€ ํ˜•ํƒœ(์ธํ„ฐํŽ˜์ด์Šค)๋กœ API ์ŠคํŽ™์„ ์ •์˜ํ•œ ๊ฒฐ๊ณผ๋ฌผ์„ ๋งŒ๋“ค์–ด ๋‚ผ ์ˆ˜๋Š” ์—†์„๊นŒ์š”?

์ด ์‹œ์ ์—์„œ REST DOCS ์„ ์ž ๊น ํฌ๊ธฐํ•˜๊ณ  ๋‹ค๋ฅธ ๋Œ€์•ˆ์„ ์ฐพ์•„๋ณด๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. API ๋ธ”๋ฃจํ”„๋ฆฐํŠธ, ์Šค์›จ๊ฑฐ ๊ณผ ๊ฐ™์€ ์˜คํ”„์†Œ์Šค๋ถ€ํ„ฐ, ์ตœ๊ทผ ์ž์ฃผ ๋ณด์ด๋Š” ๋ฆฌ๋“œ๋ฏธ๋‹ท์ปด, Stoplight ์œ ๋ฃŒ ์†”๋ฃจ์…˜๋„ ๊ฒ€ํ† ํ•ด๋ณด์•˜์ฃ . ์œ ๋ฃŒ ์†”๋ฃจ์…˜์„ ์•Œ์•„๋ณด๋‹ˆ ์ •์˜๋œ API ๋ฅผ ๋ฏธ๋ คํ•œ ์‚ฌ์ดํŠธ๋กœ ํ˜ธ์ŠคํŒ…ํ•ด์ฃผ๋Š” ์—ญํ• ์„ ์ฃผ๋กœํ•˜๊ณ  API Spec ์ž์ฒด๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋งŒ๋“ค์–ด์„œ ๋„ฃ์–ด์•ผํ–ˆ์Šต๋‹ˆ๋‹ค. (์–ด์ฐŒ๋ณด๋ฉด ๋‹น์—ฐํ•œ ์ด์•ผ๊ธฐ...) ๊ทธ๋Ÿฐ๋ฐ ๋ฌธ์„œ๋ฅผ ์ฝ๋‹ค๋ณด๋‹ˆ OAS 3, Swagger Support ๋ผ๋Š” ๋ฌธ๊ตฌ๊ฐ€ ์—ฌ๊ธฐ์ €๊ธฐ์„œ ๋ณด์ด๋”๊ตฐ์š”. Swagger๋Š” ์‚ฌ์šฉํ•ด๋ดค๊ณ , OAS 3 ๋Š” Open Api Specification v3 ์˜ ์ถ•์•ฝ์–ด์˜€์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•์ด ์–ด๋ ดํ’‹ ๋ณด์ด๋Š” ๊ฒƒ ๊ฐ™์•˜์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜, ๊ด€๊ฑด์€ API Specification.#

์œ„์—์„œ ์–ธ๊ธ‰ํ•œ '๋ชจ๋“  API ์„œ๋ฒ„๊ฐ€ ์ฝ”๋“œ๋ฅผ ๊ธฐ๋ฐ˜ํ•˜์—ฌ ๊ฐ™์€ ํ˜•ํƒœ(์ธํ„ฐํŽ˜์ด์Šค)๋กœ API ์ŠคํŽ™์„ ์ •์˜ํ•œ ๊ฒฐ๊ณผ๋ฌผ์„ ๋งŒ๋“ค์–ด ๋‚ผ ์ˆ˜๋Š” ์—†์„๊นŒ์š”?' ์€ ์ €๋งŒ ๊ณ ๋ฏผํ–ˆ๋˜ ๊ฒƒ์€ ์•„๋‹ˆ์˜€์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ ์˜›๋‚ ๋ถ€ํ„ฐ ์„ ๋ฐฐ๋“ค์ด ๊ณ ๋ฏผํ•ด์™”๊ณ , ๊ทธ์— ๋Œ€ํ•œ ์ •์˜๋„ ๋งŒ๋“ค์–ด ๋†“์•˜์Šต๋‹ˆ๋‹ค.

OpenAPI v3.0 was released in July, 2017, by the OpenAPI Initiative, a consortium of member companies who want to standardize how REST APIs are described. There are various other approaches to API description

OpenAPI v3.0์€ REST API ์„ค๋ช… ๋ฐฉ์‹์„ ํ‘œ์ค€ํ™”ํ•˜๋ ค๋Š” ํšŒ์›์‚ฌ ์ปจ์†Œ์‹œ์—„์ธ OpenAPI Initiative์—์„œ 2017๋…„ 7์›”์— ์ถœ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค. API ์„ค๋ช…์— ๋Œ€ํ•œ ๋‹ค์–‘ํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์ด ์žˆ์Šต๋‹ˆ๋‹ค.

Stoplight - How to choose your api specification

์—ฌ๊ธฐ์„œ ์†Œ๊ฐœํ•˜๋Š” ์ ‘๊ทผ ๋ฐฉ์‹์€ OpenAPI, JSON Schema, API Blueprint, RAML ์ด๋ฉฐ, ์ถ”์ฒœํ•˜๋Š” ๋…€์„์€ OpenAPI v3 ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ ์ €๊ธฐ์„œ ๋ดค๋˜ OAS3 ๋ฐ”๋กœ ๊ทธ ๋…€์„์ด์ฃ . OAS3 ์— ๋Œ€ํ•ด์„œ ์ž์„ธํžˆ ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด ์—ฌ๊ธฐ ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ๊ฐ API ์„œ๋ฒ„๊ฐ€ ์–ด๋–ค ํ˜•์‹์œผ๋กœ ํ‘œ์ค€ํ™”๋œ ๊ฒฐ๊ณผ๋ฌผ์„ ์ƒ์‚ฐํ•ด์•ผํ•˜๋Š”์ง€๋Š” ๊ฒฐ์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค. OAS ์ŠคํŽ™์— ๋งž๋Š” ํ˜•ํƒœ๋กœ yaml ๋˜๋Š” json ํŒŒ์ผ์„ ๋–จ๊ถˆ์ฃผ๋ฉด, ๊ทธ ํŒŒ์ผ์„ ์ด์˜๊ฒŒ ๋ณด์—ฌ์ค„ ๋„๊ตฌ์™€ ์„œ๋น„์Šค๋Š” ๋„๋ ค์žˆ์Šต๋‹ˆ๋‹ค. ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ OSA3 ๋Š” ๊ธฐ๊ณ„, ๋„๊ตฌ๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ๋‹ค๊ณ  ํ•˜๋‹ˆ, ์ผ๋‹จ OAS ์ŠคํŽ™ ํŒŒ์ผ๋งŒ ์žˆ์œผ๋ฉด ๋ญ๋“ ์ง€ ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋„ค์š”. ์ž ๊ทธ๋Ÿผ ์–ด๋–ป๊ฒŒ ์ด ํŒŒ์ผ์„ API ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ์–ป์„ ์ˆ˜ ์žˆ์„๊นŒ์š”? ์‚ฌ๋žŒ์ด ํ•˜๋‚˜ํ•˜๋‚˜ ์ž‘์„ฑํ•  ํ˜•ํƒœ๋Š” ์•„๋‹Œ๋ฐ ๋ง์ด์ฃ .

์Šค์›จ๊ฑฐ๋ฅผ ๋‹ค์‹œ ์จ์•ผ ํ• ๊นŒ?#

OAS ๋Š” API ์ŠคํŽ™์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ€์žฅ ๋Œ€ํ‘œ์ ์ธ ํฌ๋งท์ด๋ผ ๊ฐ์ข… ์–ธ์–ด์—์„œ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ํ”„๋กœ์ ํŠธ๋“ค์ด ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ๋Œ€ํ‘œ์ ์œผ๋กœ Spring ์ชฝ์— SpringDoc Project ์™€ Nodejs ์ชฝ์—๋Š” Swagger-jsdoc ์ด๋ผ๋Š” ํ”„๋กœ์ ํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ๋‚˜ ์Šค์›จ๊ฑฐ๋Š” OAS ์ ๊ทน ์ง€์›ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ์ด์ „๋ถ€ํ„ฐ ์ž๋ฐ”/์Šคํ”„๋ง ์ง„์˜์—์„œ๋„ ๋งŽ์ด ์“ฐ์ด๋Š” ํ”„๋กœ์ ํŠธ ์ž…๋‹ˆ๋‹ค. ์–ด์ฐŒ๋ณด๋ฉด SPRINT REST DOC ๋ณด๋‹ค ๋” ๋งŽ์ด ์“ฐ์ด๋Š” ๋…€์„์ผ์ง€๋„ ๋ชจ๋ฅด๊ฒ ๋„ค์š”. ์Šคํ”„๋ง์—์„œ ์–ด๋…ธํ…Œ์ด์…˜ ๋ช‡ ๊ฐœ๋กœ ๊ธฐ๋ณธ์ ์ธ ๋ฌธ์„œ๋ฅผ ๋š๋”ฑ ๋งŒ๋“ค์–ด์ฃผ๋Š” ๋„๊ตฌ๋‹ˆ๊นŒ์š”. ๋‹ค๋งŒ ์˜ˆ์ „์— ์Šค์›จ๊ฑฐ๋ฅผ ์จ ๋ณธ ์ž…์žฅ์—์„œ ์ปจํŠธ๋กค๋Ÿฌ ์ฝ”๋“œ์— API ์„ค๋ช…๋ฅผ ์œ„ํ•œ ์ฝ”๋“œ๊ฐ€ ๋„ˆ๋ฌด ๋•์ง€๋•์ง€ ๋ถ™์–ด์žˆ์–ด์„œ ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง€๋Š” ๋‹จ์ ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ œํ’ˆ ์ฝ”๋“œ์™€ ๋™๊ธฐํ™”๋„ ๋ณด์žฅํ•˜์ง€ ์•Š๊ตฌ์š”.

Rest Docs ์ด Open API Spec ์„ ๋–จ๊ถˆ์ค„ ์ˆ˜๋งŒ ์žˆ๋‹ค๋ฉด.#

REST DOCS ์‚ฌ์šฉ์„ ํฌ๊ธฐํ•˜๊ณ  ์—ฌ๊ธฐ๊นŒ์ง€ ์™”์ง€๋งŒ, ๋‹ค์‹œ๊ธˆ REST DOCS ์ด ๊ทธ๋ฆฌ์›Œ์ง€๋Š” ์ˆœ๊ฐ„์ž…๋‹ˆ๋‹ค. REST DOCS ์ด ์™„์„ฑ๋œ HTML ๋ฌธ์„œ๋ฅผ ์ตœ์ข… ๊ฒฐ๊ณผ๋ฌผ๋กœ ์ƒ์„ฑํ•˜๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ, OPEN API Spec ์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜๋งŒ ์žˆ๋‹ค๋ฉด, ๋งŽ์€ ๊ฒƒ๋“ค์ด ํ•ด๊ฒฐ๋ ํ…๋ฐ ๋ง์ด์ฃ . ๊ทธ๋Ÿฐ๋ฐ! ๊ทธ๋ ‡๊ฒŒ ๋ช…ํ™•ํ•œ ๋ฐฉํ–ฅ์„ ์žก๊ณ  ๊ตฌ๊ธ€๋ง์„ ํ•˜๋‹ˆ, ์ €์™€ ๊ฐ™์€ ๊ณ ๋ฏผ ๋์— ๊ทธ ํ•ด๋‹ต์„ ์–ป์–ด ๋‚ธ ๋ถ„ ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์—ฌ๊ธฐ์„œ ๋ฐœ๊ฒฌํ•œ ์ด ๋ชจ๋“  ๊ฒƒ์„ ํ•ด๊ฒฐํ•ด์ฃผ๋Š” restdocs-api-spec ํ”„๋กœ์ ํŠธ! ๊ธฐ์กด ํด๋ž˜์Šค๋“ค์„ ๋žฉํ•‘ํ•ด์„œ ๋งŒ๋“ค์–ด๋†”์„œ Import ๋งŒ ๋ฐ”๊ฟ”์ค˜๋„ ๊ธฐ์กด ์ฝ”๋“œ์— ํฐ ๋ณ€ํ™”์—†์ด ์ ์šฉ์ด ๊ฐ€๋Šฅํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ REST DOCS ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค๋ฉด, OPENAPI 3 ์ŠคํŽ™์œผ๋กœ ํŒŒ์ผ์ด ๋š ๋–จ์–ด์ง‘๋‹ˆ๋‹ค. ์œ ๋ ˆ์นด!

๋งˆ์น˜๋ฉฐ#

๋ถ„์‚ฐ๋œ API ๋ฌธ์„œ๋“ค, ์ด ๋ฌธ์„œ๋ฅผ ํ•œ ๊ณณ์œผ๋กœ ๋ชจ์œผ๊ณ ์ž ํ–ˆ๋˜ ๊ฐˆ๋ง(?) ๊ณผ OAS ์™€restdocs-api-spec ์ด๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋งŒ๋‚˜๊ฒŒ ๋˜๊ธฐ๊นŒ์ง€์— ์—ฌ์ •์„ ์†Œ๊ฐœํ•ด๋“œ๋ ธ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ๊ธ€์—์„œ๋Š” ๋ณธ๊ฒฉ์ ์œผ๋กœ restdoc-api-spec ์„ ์‚ฌ์šฉํ•ด์„œ OAS ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ , ์Šค์›จ๊ฑฐ์—์„œ ํŒŒ์ผ์„ ๋ณด๊ธฐ ์ข‹์€ ํ˜•ํƒœ๋กœ ์„œ๋น™ํ•˜๋Š” ๋ถ€๋ถ„์„ ์ ์–ด๋ณผ๊ป˜์š”. ๊ธด ๊ธ€ ์ฝ์–ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

Go ์‹œ์ž‘ํ•˜๊ธฐ - 01

๋“ค์–ด๊ฐ€๋ฉฐ#

์ƒˆ๋กœ์šด ๊ฒƒ์— ๋Œ€ํ•œ ๋ฐฐ์›€์€ ์‚ถ์„ ํ’์š”๋กญ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ์ต์ˆ™ํ•จ์—์„œ ๋ฒ—์–ด๋‚˜๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ์‹œ๊ฐ์„ ํฌํ•จํ•˜์—ฌ ๋งŽ์€ ๊ฒƒ์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ฃผ๊ด€์ ์ธ ๋ฐฐ์šฐ๊ณ  ์‹ถ์€ ์–ธ์–ด ๋žญํ‚น 1์œ„์ธ Golang ์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ์ฐจ๊ทผ์ฐจ๊ทผ ๋ฐฐ์›Œ๋‚˜๊ฐ€๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ธ€์€ ๋ˆ„๊ตฐ๊ฐ€์—๊ฒŒ Golang ์— ๋Œ€ํ•œ ์ •๋ณด ์ „๋‹ฌ์„ ๋ชฉํ‘œ๋กœ ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๋‚ด๊ฐ€ ์–ธ์–ด๋ฅผ ๋ฐฐ์›Œ๋‚˜๊ฐ€๋Š” ๊ณผ์ •์„ ๋‹ด์€ ๊ฐœ๋ฐœ ํ•™์Šต ๋กœ๊น…์ž…๋‹ˆ๋‹ค.

๋ชจ๋“  ๊ณผ์ •์— ๋Œ€ํ•œ ์ฝ”๋“œ๋Š” GitHub ์— ๊ณต๊ฐœ๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ„๋‹จํ•˜๊ฒŒ ์‹œ์ž‘ํ•˜๊ธฐ#

๊ฐœ๋ฐœ ํ™˜๊ฒฝ ๊ตฌ์„ฑ#

๋จผ์ € Go๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Go ๋ฅผ ์„ค์น˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์„ค์น˜๋Š” ๋„ˆ๋ฌด๋‚˜ ๊ฐ„๋‹จํ•ด์„œ ์—ฌ๊ธฐ์—์„œ๋Š” ๋”ฐ๋กœ ๋‹ค๋ฃจ์ง€ ์•Š๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด์ œ ์–ด๋–ค ์—๋””ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ฝ”๋”ฉ์„ ํ• ์ง€ ๊ฒฐ์ •ํ•ด์•ผํ•˜๋Š”๋ฐ์š”. ์ €๋Š” ์ธํ…”๋ฆฌ์ œ์ด์˜ ๋…ธ์˜ˆ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ธํ…”๋ฆฌ์ œ์ด๋ฅผ ์‚ฌ์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” Go ๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๋Š”๋ฐ, ํ”Œ๋Ÿฌ๊ทธ์ธ๋งŒ ์„ค์น˜ํ•˜๋ฉด GoLand (JetBrain ์˜ Go ์ „์šฉ IDE) ์˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•˜๋‹ˆ ํ™˜ํ˜ธ์„ฑ์„ ์ง€๋ฅด๋ฉฐ ์–ด์„œ ์„ค์น˜ํ•ด์ค๋‹ˆ๋‹ค.

Preferences 2021-08-15 17-13-09.png

์„ค์น˜๊ฐ€ ๋˜์—ˆ์œผ๋ฉด, ๋นจ๋ฆฌ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ฃ . ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ์ˆœ๊ฐ„๋ถ€ํ„ฐ ๊ทธ ํ”„๋กœ์ ํŠธ์˜ ์—ญ์‚ฌ๋Š” ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์—ญ์‚ฌ๋Š” commit ์œผ๋กœ ๊ธฐ๋ก๋˜์ฃ . ์ขŒ์ธก์—์„œ Go ๋ฅผ ์„ ํƒํ•˜๊ณ  ๋‹ค์Œ์„ ๋ˆŒ๋Ÿฌ ํ”„๋กœ์ ํŠธ ์ด๋ฆ„์„ ์ง€์ •ํ•˜๊ณ  Finish ๋ฅผ ๋ˆ„๋ฅด๋ฉด ํ”„๋กœ์ ํŠธ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. Go ๋ฒ„์ „์ด ์—…๋ฐ์ดํŠธ๋˜๋ฉด์„œ GOPATH ๋ฐฉ์‹์— ํ”„๋กœ์ ํŠธ๋Š” ์ž˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์œผ๋กœ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

New Project 2021-08-15 17-20-32.png

์ž ์ƒˆ๋กœ์šด ์„ธ์ƒ์„ ๋งŒ๋‚  ์ค€๋น„๊ฐ€ ๋˜์—ˆ๋‹ค๋ฉด ์ธ์‚ฌ๋ฅผ ํ•˜๋ฉฐ ์‹œ์ž‘ํ•ด๋ด…๋‹ˆ๋‹ค. main.go ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ  main ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•œ ๋’ค ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

package main
import "fmt"
func main() {
fmt.Print("Hello")
}
Hello, Go World!
Process finished with the exit code 0

๊ฐœ์ธ์ ์œผ๋กœ๋Š” ์ธ์‚ฌ๋งŒ ํ•œ ๋‹ค์„ฏ๋ฒˆ์งธ ํ•˜๋Š” ๊ฒƒ ๊ฐ™๋„ค์š” ๐Ÿ˜

์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค ๊ฐ€์ ธ์˜ค๊ธฐ#

์ธ์‚ฌ๋งŒ ํ•˜๊ณ  ๋๋‚ด๊ธฐ๋Š” ์•„์‰ฌ์šฐ๋‹ˆ ํ•œ ๋ฐœ์ž๊ตญ๋งŒ ๋” ๊ฐ€๋ณผ๊นŒ์š”? ์ถ”ํ›„์— ์˜๋ฏธ์žˆ๋Š” ์•ฑ์„ ๋งŒ๋“ค๋ ค๋ฉด ์™ธ๋ถ€์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์˜ค๋Š”๊ฒŒ ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋‹ค๋ฉด, ๊ทธ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•ด์ฃผ๋Š” ์„œ๋น„์Šค๋ฅผ ์ฐพ์•„๋ณด๊ณ  ๊ทธ ์„œ๋น„์Šค๊ฐ€ API ๋ฅผ ์ง€์›ํ•˜๋Š”์ง€ ํ™•์ธํ•ด๋ณด์„ธ์š”. ๋Œ€๋ถ€๋ถ„์˜ ์„œ๋น„์Šค๋“ค์€ API ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

API ๋ฌธ์„œ ํ™•์ธ#

์—ฌ๊ธฐ์„œ๋Š” ์š”์ฆ˜ ํ•ซํ•œ ์•”ํ˜ธํ™”ํ์˜ ํ˜„์žฌ ์‹œ์„ธ๋ฅผ ๊ฐ€์ง€๊ณ  ์™€๋ณด์ฃ . ์ €๋Š” ์—…๋น„ํŠธ ๊ฑฐ๋ž˜์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์—…๋น„ํŠธ API ๋ฌธ์„œ ์—์„œ ํ˜„์žฌ๊ฐ€ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ์—”๋“œํฌ์ธํŠธ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋”ฉํ•˜๊ธฐ ์ „์— ์ •๋ง๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ๋‚ด๋ ค์˜ค๋Š”์ง€ ํ™•์ธํ•ด๋ณผ๊นŒ์š”?

curl --request GET \
--url https://api.upbit.com/v1/ticker\?markets\=KRW-BTC \
--header 'Accept: application/json'
[{"market":"KRW-BTC","trade_date":"20210815","trade_time":"075919","trade_date_kst":"20210815","trade_time_kst":"165919","trade_timestamp":1629014359000,"opening_price":54817000.00000000,"high_price":55166000.0,"low_price":53420000.0,"trade_price":53614000.0,"prev_closing_price":54812000.00000000,"change":"FALL","change_price":1198000.00000000,"change_rate":0.0218565278,"signed_change_price":-1198000.00000000,"signed_change_rate":-0.0218565278,"trade_volume":0.022,"acc_trade_price":213592738229.775190000,"acc_trade_price_24h":559827073056.69978000,"acc_trade_volume":3918.44716516,"acc_trade_volume_24h":10269.53880782,"highest_52_week_price":81994000.00000000,"highest_52_week_date":"2021-04-14","lowest_52_week_price":11860000.00000000,"lowest_52_week_date":"2020-09-07","timestamp":1629014359797}]

์ž˜ ๊ฐ€์ง€๊ณ  ์˜ค๋„ค์š”. ๊ฐœ๋ฐœํ•˜๊ธฐ์— ์•ž์„œ ์ด๋Ÿฐ ๊ณผ์ •์€ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์ฝ”๋”ฉ์„ ์ž˜๋ชปํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชป ๊ฐ€์ง€๊ณ  ์˜จ ๊ฑด์ง€, ์•„๋‹ˆ๋ฉด ์„œ๋น„์Šค ์ž์ฒด์ ์œผ๋กœ ๋ฌธ์ œ๊ฐ€ ์žˆ์–ด์„œ ๋ชป๊ฐ€์ง€๊ณ  ์˜จ ๊ฒƒ์ธ์ง€ ํ™•์ธ์ด ํ•„์š”ํ•˜์ฃ . ์„œ๋น„์Šค๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์œผ๋‹ˆ ์ด์ œ ์ œ๊ฐ€ ์ฝ”๋”ฉ๋งŒ ์ž˜ํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์˜ค๊ฒ ๋„ค์š”. ๐Ÿคฉ

์‚ฌ์šฉํ•  ํŒจํ‚ค์ง€ ์ฐพ๊ณ  ๋ฌธ์„œ ํ™•์ธํ•˜๊ธฐ#

Go ์—์„œ๋Š” HTTP ์š”์ฒญ์„ ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”? ๊ณ  ํŒจํ‚ค์ง€ ๋ฅผ ๋ชจ์•„๋†“์€ ์‚ฌ์ดํŠธ์— ๊ฐ€์„œ http ๋ฅผ ๊ฒ€์ƒ‰ํ•ด๋ด…๋‹ˆ๋‹ค. JAVA๋กœ ์น˜๋ฉด Maven Repository ๊ฐ™์€ ๊ณณ์ด๊ฒ ๋„ค์š”. ์˜ˆ์ œ๊ฐ€ ์นœ์ ˆํ•˜๊ฒŒ ์จ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ์‹์ƒํ•œ ์ธ์‚ฌ๋Š” ๊ทธ๋งŒํ•˜๊ณ  ์•”ํ˜ธํ™”ํ์˜ ๋Œ€์žฅ์ธ ๋น„ํŠธ์ฝ”์ธ์— ๊ฐ€๊ฒฉ์„ ๊ฐ€์ง€๊ณ  ์™€๋ณผ๊ป˜์š”.

package main
import (
"io/ioutil"
"net/http"
)
func main() {
resp, err := http.Get("https://api.upbit.com/v1/ticker?markets=KRW-BTC")
if err != nil {
panic(err)
}
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
println(string(data))
}
[{"market":"KRW-BTC","trade_date":"20210815","trade_time":"084318","trade_date_kst":"20210815","trade_time_kst":"174318","trade_timestamp":1629016998000,"opening_price":54817000.00000000,"high_price":55166000.0,"low_price":53411000.0,"trade_price":53687000.0,"prev_closing_price":54812000.00000000,"change":"FALL","change_price":1125000.00000000,"change_rate":0.0205247026,"signed_change_price":-1125000.00000000,"signed_change_rate":-0.0205247026,"trade_volume":0.05957287,"acc_trade_price":239700491633.154070000,"acc_trade_price_24h":574757863109.85536000,"acc_trade_volume":4405.80968434,"acc_trade_volume_24h":10554.59700851,"highest_52_week_price":81994000.00000000,"highest_52_week_date":"2021-04-14","lowest_52_week_price":11860000.00000000,"lowest_52_week_date":"2020-09-07","timestamp":1629016998428}]

๋งˆ์น˜๋ฉฐ#

๊ฐ„๋‹จํ•œ ๋ช‡ ์ค„์— ์ฝ”๋“œ๋กœ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์™”์Šต๋‹ˆ๋‹ค. ์ด์ œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์˜ค๋Š” ๋ฒ•์„ ์•Œ์•˜์œผ๋‹ˆ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์—ฌ๊ธฐ์ €๊ธฐ์„œ ๊ฐ€์ง€๊ณ  ์™€์„œ ์š”๋ฆฌ์กฐ๋ฆฌ ๋š๋”ฑ๋š๋”ฑํ•˜๋ฉด ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ํ•˜๋Š” ์•ฑ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒ ์–ด์š”. ๊ทธ๋Ÿฐ๋ฐ... ์ € JSON ๋ฌธ์ž์—ด๋กœ ๋œ ๋†ˆ์„ ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”? Go ์— ์ € ๋ฐ์ดํ„ฐ๋ฅผ ์ด์˜๊ฒŒ ๋‹ด์•„๋†“๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์„๊นŒ์š”? ๋‹ค์Œ ๋ฒˆ์—๋Š” ์ด ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฌด์ œ

๊ฐœ์š”#

๋‚ด ๋จธ๋ฆฌ ์†์— ํ๋ฅด๋Š” ์ƒ๊ฐ์„ ์ ์–ด๋ณธ๋‹ค.

์ƒ๊ฐ์˜ ํ๋ฆ„๋Œ€๋กœ ์ ๋Š”๋‹ค.#

๊ธ€์˜ ๊ตฌ์„ฑ#

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

์ผ๋‹จ ๊ดœ์ฐฎ์€ ๊ธ€์„ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•œ ์‹œ์ž‘์ ์œผ๋กœ ๊ธ€์˜ ๊ตฌ์„ฑ์„ ์ž˜ ์žก๋Š” ๊ฒƒ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋ ค ํ•œ๋‹ค. ๊ทธ ๋ฐฉ๋ฒ•์„ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด ์ด๋Ÿฐ ๊ณ ๋ฏผ์„ ์‹œ์ž‘๋„ ํ•˜์ง€ ์•Š์•˜๊ฒ ์ง€. ๊ธ€์˜ ์ž‘์„ฑ๋„ ์• ์ž์ผํ•˜๊ฒŒ ์ž‘์€ ๊ฒƒ์„ ์‹œ๋„ํ•˜๊ณ , ํšŒ๊ณ ํ•˜๊ณ  ๋” ๋‚˜์€ ๋ฐฉ๋ฒ•์„ ์‹œ๋„ํ•˜๋Š” ํ˜•์‹์œผ๋กœ ์ง„ํ–‰ํ•ด๋ณด๋ คํ•œ๋‹ค. ๊ทธ ์ฒซ๋ฒˆ์งธ ์‹œ์ž‘์œผ๋กœ "๊ฐœ์š”" ์„ธ์…˜๊ณผ "๋งˆ์น˜๋ฉฐ" ์„ธ์„ ์˜ ์ถ”๊ฐ€๋‹ค. ๋‚ด๊ฐ€ ์ ๊ณ ์ž ํ•˜๋Š” ์ฃผ์ œ๋ฅผ ๋ช…ํ™•ํžˆ ํ•˜๋Š” ๊ฒƒ์ด ์šฐ์„ ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—.

140์ž#

140์ž๋ฅผ ์ƒ๊ฐํ•˜๋ฉด ๋– ์˜ค๋ฅด๋Š”๊ฒŒ ๊ธฐ์—…. ํŠธ์œ„ํ„ฐ, ๋‚˜๋Š” ํŠธ์œ„ํ„ฐ๋ฅผ ๋งŽ์ด ํ•˜์ง€ ์•Š์ง€๋งŒ ์•จ๋ก  ๋จธ์Šคํฌ ๋•๋ถ„์— ํŠธ์œ„ํ„ฐ๋กœ ๊ณต์œ ๋œ ์ •๋ณด๋ฅผ ๋‹ค๋ฅธ ๊ฒฝ๋กœ๋ฅผ ํ†ตํ•ด ๋งŽ์ด ์ ‘ํ•œ๋‹ค. ํŠธ์œ„ํ„ฐ๊ฐ€ ์„ฑ๊ณตํ–ˆ๋˜ ์ด์œ  ์ค‘์— ํ•˜๋‚˜๋Š” ์ด "140์ž" ๋กœ ํ•œ์ •์ง€์€ ํŠธ์œ—๋„ ํ•œ๋ชซํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ๊ธ€์ž ์ˆ˜์— ํ•œ๊ณ„ ๋•Œ๋ฌธ์— ์ •๋ณด์˜ ํ•ต์‹ฌ๋งŒ ๋‹ด์•„์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. (๋ฐฉ๊ธˆ ์•ˆ๊ฑฐ์ง€๋งŒ ํ•œ์ค‘์ผ์„ ์ œ์™ธํ•œ ๋‹ค๋ฅธ ๋‚˜๋ผ๋“ค์˜ ํŠธ์œ— ๊ธ€์ž์ˆ˜ ์ œํ•œ์€ 280์ž ๋ผ๊ณ  ํ•œ๋‹ค.) ๊ฐ‘์ž๊ธฐ ์™œ ํŠธ์œ„ํ„ฐ๊ฐ€ ํŠ€์–ด๋‚˜์™”๋ƒ๊ณ ? ๊ฐœ์š”๋Š” 140์ž ์ด๋‚ด๋กœ ์ ์ž! ๋ผ๋Š” ๊ทœ์น™์„ ๋งŒ๋“ค๋ฉด์„œ ๋– ์˜ฌ๋ž๋‹ค.

์ƒ๊ฐ์ด ๋‚ ๋ผ๋‹ค๋‹Œ๋‹ค.#

๋‚ด๊ฐ€ ๊ธ€์„ ์ ๊ฒ ๋‹ค๊ณ  ์ปดํ“จํ„ฐ ์•ž์— ์•‰์•˜์„ ๋•Œ, ๋ถ„๋ช…ํžˆ APY ์™€ ARP ์˜ ๋‹ค๋ฅธ ์  ์„ ์ •๋ฆฌํ•ด์•ผ๊ฒ ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋Š”๋ฐ, ๊ทธ๊ฑธ ์ ๋‹ค๋ณด๋‹ˆ ์•ต์ปค์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๋ฅผ ํ•˜๊ณ  ์žˆ๊ณ , ์•ต์ปค๋ฅผ ์ ๋‹ค๋ณด๋‹ˆ ๋””ํŒŒ์ด์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ์ ๊ณ  ์žˆ๊ณ , ๊ธ€์˜ ๋‚ด์šฉ์ด ๋„ˆ๋ฌด ๋’ค์ฃฝ๋ฐ•์ฃฝ์ด๋ผ, ๋‚˜๋Š” ์™œ ์ด๋Ÿด๊นŒ ์ƒ๊ฐํ•˜๋‹ค๊ฐ€ ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ๊ธ€์„ ์ž˜ ์“ฐ๋Š”์ง€๋ฅผ ์ฐพ์•„๋ณด๋‹ค๊ฐ€, ๊ฐ‘์ž๊ธฐ ์–ด์ œ ์‚ฐ ์œ ๋ฐ๋ฏธ ๊ฐ•์˜๊ฐ€ ์ƒ๊ฐ๋‚˜์„œ ๊ทธ๊ฑธ ์กฐ๊ธˆ ๋ณด๋‹ค๊ฐ€, ์•„ ๊ธ€ ์“ฐ๊ณ  ์‹ถ์€๋ฐ ์–ด๋–ป๊ฒŒํ•˜์ง€ ์‹ถ์–ด์„œ ์„ ํƒํ•œ ๋ฐฉ๋ฒ•์ด, ์ œ๋ชฉ์ด ์—†๋Š” ์ƒ๊ฐ ํ๋ฆ„ ์ ๊ธฐ๋‹ค. ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ์ด ๋‚ ๋ผ๋‹ค๋‹ˆ๋Š” ์ƒ๊ฐ์„ ํ•˜๋‚˜์˜ ์ฃผ์ œ์— ๋ฌถ์–ด ๋†“์„ ์ˆ˜ ์žˆ์„๊นŒ?

๋‚ด๊ฐ€ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•™์Šตํ•˜๋Š” ๋ฐฉ๋ฒ•#

์œ ๋ฐ๋ฏธ๋ฅผ ๋ณด๋ฉด์„œ ๋“ค์—ˆ๋˜ ์ƒ๊ฐ, ๋‚˜๋Š” ์–ด๋–ป๊ฒŒ ์ƒˆ๋กœ์šด ๊ฒƒ์„ ๋ฐฐ์šธ๊นŒ? ์ผ๋‹จ ๋ชจ๋“  ํ•™์Šต์˜ ์‹œ์ž‘์€ "์–ด๋–ค ๋ฌธ์ œ" ๋กœ๋ถ€ํ„ฐ ์‹œ์ž‘๋œ๋‹ค. ๊ทธ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด "์ธํ„ฐ๋„ท" ์„ ๊ฒ€์ƒ‰ํ•˜๋‹ค๋ณด๋ฉด ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์–ป๊ณ  ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ๊ณผ์ •์—์„œ ์• ์จ ๋ฌด์‹œํ•œ ์ œ๋Œ€๋กœ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์•Œ์•„์•ผ ํ•˜๋Š” ์ง€์‹์ด๋‚˜, ๋” ์šฐ์•„ํ•˜๊ฒŒ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ํ‚ค์›Œ๋“œ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด ํ‚ค์›Œ๋“œ๋ฅผ ์กฐ๊ธˆ๋งŒ ๊ณต๋ถ€ํ•ด๋ณด๋ฉด ์—ฌ๊ธฐ์„œ ์•Œ์•„์•ผ ํ•  ๊ฒƒ๋“ค์ด ๋ฌด์ˆ˜ํžˆ ๋งŽ์ด ํŒŒ์ƒ๋œ๋‹ค.

๊ทธ๋ ‡๊ฒŒ ํ•™์Šตํ•ด์•ผ ํ•  ๋Œ€์ƒ์ด ํŒŒ์•…๋˜๋ฉด, ๋‚˜๋Š” ๊ตฌ๊ธ€์— ๊ผญ alternative, compare, vs ์™€ ๊ฐ™์€ ๋‹จ์–ด๋ฅผ ์ž…๋ ฅํ•ด์„œ ๋‚ด๊ฐ€ ์ง€๊ธˆ๋ถ€ํ„ฐ ํ•™์Šตํ•  ๋…€์„์ด ์ตœ์ ์˜ ์†”๋ฃจ์…˜์ธ๊ฐ€? ๋ฅผ ํ™•์ธํ•œ๋‹ค. '์€์ด์•Œ์€ ์—†๋‹ค' ๋ผ๋Š” ๋ง์ฒ˜๋Ÿผ ๋ชจ๋“  ๊ฒƒ์„ ํ•ด๊ฒฐํ•˜๋Š” ๋‹จ ํ•˜๋‚˜์— ๋ฐฉ๋ฒ•์€ ์ž˜ ์กด์žฌํ•˜์ง€ ์•Š์ง€๋งŒ ์ด ๊ณผ์ •์—์„œ ๋‚ด ์„ฑ๊ฒฉ์— ๋” ์ž˜ ๋งž๊ฑฐ๋‚˜ ํ˜„์žฌ ์ƒํ™ฉ์— ๋” ์ ํ•ฉํ•œ ์†”๋ฃจ์…˜์„ ์ฐพ๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋ ‡๊ฒŒ ๋Œ€์ƒ์— ๋Œ€ํ•ด "์ด๊ฑด ๊นŠ๊ฒŒ ์•Œ์•„๋†“์œผ๋ฉด ๋‚ด ์ธ์ƒ์ด ํŽธํ•ด์ง„๋‹ค.", "์ด๊ฑธ ์•ž์œผ๋กœ ๋งŽ์€ ๊ณณ์—์„œ ์‚ฌ์šฉ๋  ๋†ˆ์ด๋ผ ๋‚ด ๋ชธ ๊ฐ’ ์˜ฌ๋ฆด๋ ค๋ฉด ๋ฐฐ์›Œ์•ผ ํ•œ๋‹ค." ์ด๋ผ๋Š” ํ™•์‹ ์ด ์„œ๋ฉด, ๊ฐ€์žฅ ๋จผ์ € ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ํ™•์ธํ•œ๋‹ค. ๋ชจ๋“  ์ •๋‹ต์€ ๊ณต์‹ ๋ฌธ์„œ์— ์žˆ์œผ๋‹ˆ๊นŒ. ๊ทธ๋Ÿฐ๋ฐ ๊ทธ ๊ณต์‹ ๋ฌธ์„œ๋ผ๋Š” ๋…€์„๋“ค์ด ์–‘์ด ๋„ˆ๋ฌด๋‚˜๋„ ๋ฐฉ๋Œ€ํ•ด์„œ, ๊ผญ๊ผญ ์”น์–ด์„œ ์ดํ•ดํ•˜๋ ค๋ฉด ํ•œ ์„ธ์›”์ด๊ณ , ์ „์ฒด์ ์ธ ๋ฌธ์„œ๊ตฌ์„ฑ์„ ํŒŒ์•…ํ•ด์„œ ๋‚˜์ค‘์— ํ•„์š”ํ•  ๋•Œ '๊ณต์‹ ๋ฌธ์„œ์—์„œ ์ด๊ฑฐ์— ๋Œ€ํ•œ๊ฑฐ ๋ณธ ๊ฒƒ ๊ฐ™์€๋ฐ?' ์ •๋„๋งŒ ์ƒ๊ฐ๋‚  ์ˆ˜ ์žˆ๋„๋ก ์ „์ฒด์ ์œผ๋กœ ํ›‘์–ด๋ณธ๋‹ค. ์—ฌ๊ธฐ์„œ ํฐ ์–ธ๋•์ด "์˜์–ด" ์ธ๋ฐ... ์•„์˜ˆ ๋ชป ์ฝ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ์ฝ๋Š” ์†๋„๊ฐ€ ๋งค์šฐ ๋”๋””๊ธฐ ๋•Œ๋ฌธ์— ๋‹ต๋‹ตํ•จ์ด ๋ชฐ๋ ค์˜จ๋‹ค. ๊ตฌ๊ธ€ ๋ฒˆ์—ญ๊ธฐ๊ฐ€ ๋งŽ์€ ๋ถ€๋ถ„ ์„œํฌํŠธํ•ด์ฃผ๊ธด ํ•˜์ง€๋งŒ, ๊ทธ๋ž˜๋„ ๋ถˆํŽธํ•จ์€ ๋งˆ์ฐฌ๊ฐ€์ง€.

์ด ์‹œ์ ์— ํ•„์š”ํ•œ ๊ฒŒ, ๊ฐœ๋ฐœ ์„œ์ ์ด๋‹ค. ๋‚˜๋Š” ๊ฐœ๋ฐœ ์„œ์ ์„ ๊ฝค๋‚˜ ์ข‹์•„ํ•˜๋Š”๋ฐ ์ผ๋‹จ ๋‚ด๊ฐ€ ๋ญ˜ ๋ชจ๋ฅด๋Š”์ง€ ๋ชจ๋ฅด๋Š” ๊ฒƒ์„ ๊นจ๋‹ซ๊ฒŒ ํ•ด์ฃผ๊ณ , ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ๋•Œ ์–ธ์ œ๋“  ๋ฌผ์–ด๋ณผ ์ˆ˜ ์žˆ๋Š” ๋™๋ฃŒ ๊ฐ™์€ ์กด์žฌ๊ฐ€ ๋˜์–ด ์ฃผ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ฐœ๋ฐœ ์„œ์ ์„ ์ฝ๋‹ค๋ณด๋ฉด...

์ž ๊น ์ด๊ฑฐ ์ƒ๊ฐ์˜ ํ๋ฆ„์ธ๋ฐ ์ด ์ƒ๊ฐ์„ ๋„ˆ๋ฌด ๊นŠ๊ฒŒ ํ•œ๋“ฏ... ์กฐ๊ธˆ ๋” ์ •๋ฆฌํ•ด์„œ ๋ณ„๋„ ๊ธ€๋กœ ์ž‘์„ฑํ•ด๋ณด๊ธฐ๋กœ. ์•„๋งˆ ์œ„์™€ ๋น„์Šทํ•˜๊ฒŒ ์ž‘์„ฑํ•œ ๊ธ€์ด ์ € ๊นŠ์€ ์–ด๋”˜๊ฐ€์— ์ €์žฅ๋˜์–ด ์žˆ์„ ๋“ฏํ•˜๋‹ค.

๋ฌด๋…ธ๋™์›”์ด์ฒœ#

์š”์ฆ˜ ๋‚ด๊ฐ€ ๋ฐ€๊ณ  ์žˆ๋Š” ๋ชฉํ‘œ. ๋‹ค๋ฅธ ๋ง๋กœ๋Š” "๊ฒฝ์ œ์  ์ž์œ ", ๊ธธ๊ฒŒ ๋งํ•˜๋ฉด "์ผ์„ ํ•˜์ง€ ์•Š๊ณ , ์•ˆ์ •์ ์œผ๋กœ ์›” ์ด์ฒœ๋งŒ์›์”ฉ ๋“ค์–ด์˜ค๋Š” ํŒŒ์ดํ”„๋ผ์ธ ๋งŒ๋“ค๊ธฐ" ์ธ๋ฐ ๋‹ฌ์„ฑ๋ฅ ์€ 5ํผ์„ผํŠธ๋„ ์•ˆ๋œ๋‹ค. ์•„๋‹ˆ ์•„์ง ๋‹ฌ์„ฑ๋ฅ ์„ ์ฒดํฌํ•  ๋‹จ๊ณ„๋„ ์•„๋‹ˆ์ง€. ํ˜„์žฌ๋Š” ๋ฌด์กฐ๊ฑด ๋…ธ๋™(๊ฐœ๋ฐœ)์„ ํ•ด์„œ ์ˆ˜์ž…์„ ๋งŒ๋“ค๊ณ  ์žˆ๋Š” ์ƒํ™ฉ, ๊ทธ๋‚˜๋งˆ ๋ฐฐ๋‹น์ฃผ๋‚˜ ๋””ํŒŒ์ด ์ƒํƒœ๊ณ„์— ๊ด€์‹ฌ์ด ์žˆ์–ด์„œ ์ด๋Ÿฐ ๋ถ€๋ถ„์œผ๋กœ ํŒŒ์ดํ”„๊ฐ€ ์ƒ๊ธฐ๊ณ  ์žˆ๊ธด ํ•œ๊ฑฐ ๊ฐ™์€๋ฐ ๊ทธ ํฌ๊ธฐ๊ฐ€ ๊ฑฐ์˜ ๋นจ๋Œ€ ์ˆ˜์ค€... ์–ด์ฐŒ๋˜์—ˆ๋“  ์ด๋ ‡๊ฒŒ ๋ชฉํ‘œ๋ฅผ ์„ธ์›Œ๋†“์œผ๋‹ˆ ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์„๊นŒ ๊ณ„์† ๊ณ ๋ฏผํ•˜๊ฒŒ ๋˜๊ณ  ์ด๊ฒƒ์ €๊ฒƒ ๊ณต๋ถ€ํ•˜๊ณ  ์‹œ๋„ํ•˜๋Š” ๋“ฏ.

"๋ฌด๋…ธ๋™" ์ด๋ผ๊ณ  ํ•ด์„œ ์ผ์„ ํ•˜์ง€ ์•Š๋Š” ์‚ถ์„ ๋ชฉํ‘œ๋กœ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ๋‹ค๋งŒ ๋‚˜์˜ ๋…ธ๋™์œผ๋กœ ์ˆ˜์ž…์„ ๋งŒ๋“œ๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ, ๋‚˜์˜ ๋…ธ๋™์„ "์ง€์†์ ์ธ ์ˆ˜์ž…์„ ๋งŒ๋“ค์–ด ์ค„ ํŒŒ์ดํ”„ ๋ผ์ธ" ์„ ๋งŒ๋“œ๋Š”๋ฐ ์“ฐ๋Š” ์‚ถ์„ ์‚ด๊ณ  ์‹ถ๋‹ค. ์ฆ‰ ๋นต์„ ์ƒ์‚ฐํ•˜๋Š” ๊ธฐ๊ณ„์˜ ์‚ถ ๋ณด๋‹ค๋Š” ๋นต์„ ๋งŒ๋“œ๋Š” ๊ธฐ๊ณ„๋ฅผ ์„ค๊ณ„ํ•˜๊ณ  ๋งŒ๋“ค์–ด ๋Œ๋ฆฌ๋Š” ์‚ถ์„ ์‚ด๊ณ  ์‹ถ์€ ๊ฒƒ์ด์ง€, ์ผ ์•ˆํ•˜๋ฉด ๋ฌด๋ฃŒํ•ด์„œ ๊ทธ ๋˜ํ•œ ๊ทธ ๋‚˜๋ฆ„๋Œ€๋กœ์˜ ๊ณ ํ†ต์ธ๋“ฏใ…Ž

๋งˆ์น˜๋ฉฐ#

๊ทธ๋ƒฅ ๋‚ด ๋จธ๋ฆฌ ์†์— ํ๋ฅด๋Š” ์ƒ๊ฐ๋“ค์„ ๋‘์„œ์—†์ด ์ ์–ด๋ณด์•˜๋‹ค. ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์ฝ์–ด์ฃผ๊ธฐ ๋ฐ”๋ผ๊ธฐ ๋ณด๋‹ค๋Š” ๋‚ด ์ƒ๊ฐ์„ ์ •๋ฆฌํ•˜๋Š” ์ฐจ์›์—์„œ... ๊ทธ๋ž˜๋„ ์ •์‹ ์—†์ด ์ ๊ณ ๋‚˜๋‹ˆ ์ƒ๊ฐ์ด ์ข€ ์ •๋ฆฌ๋˜... ์—ˆ์œผ๋ฉด ์ข‹๊ฒ ์ง€๋งŒ, ํฌ๊ฒŒ ๋‹ฌ๋ผ์ง„ ๊ฒƒ์€ ์—†๋Š” ๊ฒƒ ๊ฐ™๋‹ค. ๊ทธ๋ž˜๋„ ๋ฏธ๋ž˜์˜ ๋‚ด๊ฐ€ ์ฝ์œผ๋ฉด ๊ทธ ๋• ๊ทธ๋žฌ์ง€ํ•˜๋ฉด์„œ ์›ƒ์„ ์ˆ˜ ์žˆ์„ํ…Œ๋‹ˆ... โ† ์ด ๋ฌธ์žฅ์„ ์ ์œผ๋ฉด์„œ ์•„์ฃผ ์˜ˆ์ „์— ์ž‘์„ฑํ–ˆ๋˜ ํ…€๋ธ”๋Ÿฌ ๋ธ”๋กœ๊ทธ์— ๋“ค์–ด๊ฐ€๋ดค๋Š”๋ฐ, ๊ทธ ๋•Œ๋„ ๋น„์Šทํ•œ ๊ธ€์„ ์ ์—ˆ๋‹ค. ์ƒ๊ฐ์ด ๊ฐ€๋“ํ•ด ๋ผ๋Š” ๊ธ€์ธ๋ฐ, ๋ฌด๋ ค 8๋…„ ์ „์ด๋‹ค. ๊ทธ ๋•Œ๋‚˜ ์ง€๊ธˆ์ด๋‚˜ ์™œ ํ•ญ์ƒ ์ƒ๊ฐ๋งŒ ๊ฐ€๋“ํ•œ๊ฑด์ง€... 8๋…„ ๋’ค์— ํ™ฉ๋Œ€์žฅ. ์ง€๊ธˆ๋„ ์ƒ๊ฐ์ด ๋งŽ๋‹ˆ?

์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์—์„œ ์•ฑ์„ ์žฌ์‹œ์ž‘ ํ•˜๋Š” ๋ฐฉ๋ฒ•

๊ฐœ์š”#

์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋ฅผ ์ฒ˜์Œ ์ ‘ํ•˜๊ณ  ์‚ฌ์šฉํ•ด์˜จ์ง€ 2๋…„์ด ๋„˜์–ด๊ฐ€๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ฒ˜์Œ์— ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋ฅผ ๋‹ค๋ฃจ๊ฒŒ ๋  ๋•Œ ๋‚œ๊ฐํ–ˆ๋˜ ๋ถ€๋ถ„ ์ค‘์— ํ•˜๋‚˜๊ฐ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์–ด๋–ป๊ฒŒ ๋‚ด๋ ธ๋‹ค๊ฐ€ ์˜ฌ๋ฆฌ๋Š”์ง€์˜€์ฃ . ๊ทธ ๋ฐฉ๋ฒ•์ด ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด์„œ ์กฐ๊ธˆ์”ฉ ๋‚˜์•„์กŒ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋Š”๋ฐ, ๊ทธ ๋ฐฉ๋ฒ•๋“ค์„ ํ•œ๋ฒˆ ์ญ‰ ์†Œ๊ฐœํ•ด๋ณผ๊นŒ ํ•ฉ๋‹ˆ๋‹ค. (๋ณธ๋ฌธ์—์„œ ๋งํ•˜๋Š” "์„œ๋น„์Šค"๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์— ์„œ๋น„์Šค๊ฐ€ ์•„๋‹ˆ๋ผ "์• ํ”Œ๋ฆฌ์ผ€์ด์…˜" or "์„œ๋ฒ„"๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค.)

ํŒŒ๋“œ ์‚ญ์ œ#

kubectl delete pod <pod-name>

๊ฐ€์žฅ ์ฒ˜์Œ์œผ๋กœ ์‚ฌ์šฉํ–ˆ๋˜ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋Š” ๋””ํ”Œ๋กœ์ด๋จผํŠธ์— ์„ ์–ธํ•œ ์ƒํƒœ๋กœ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ๋งž์ถ”๊ธฐ ์œ„ํ•ด ํŒŒ๋“œ๊ฐ€ ์‚ญ์ œ๋˜๋ฉด ์ž๋™์œผ๋กœ ์ƒˆ๋กœ ๋„์›Œ์ค๋‹ˆ๋‹ค. ์ฆ‰ ์‚ญ์ œ๋งŒ ํ•˜๋ฉด ์•Œ์•„์„œ ์ฟ ๋ฒ„๊ฐ€ ๋‹ค์‹œ ๋„์›Œ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์žฌ์‹œ์ž‘์ฒ˜๋Ÿผ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์•„, ์ด ๋ฐฉ๋ฒ•์€ deployment ๋งค๋‹ˆํŽ˜์ŠคํŠธ๋กœ ์ƒ์„ฑ๋œ ํŒŒ๋“œ๋งŒ ํ•ด๋‹น๋ฉ๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์„ ์ญ‰ ์จ์˜ค๋‹ค๊ฐ€ ๋””ํ”Œ๋กœ์ด๋จผํŠธ ํŒŒ๋“œ๊ฐ€ ๋ณต์ˆ˜ ๊ฐœ์ธ ์„œ๋น„์Šค๋ฅผ ์žฌ์‹œ์ž‘ ํ•  ๊ฒฝ์šฐ์— ํŒŒ๋“œ๋ฅผ ํ•˜๋‚˜์”ฉ ์ข…๋ฃŒ์‹œ์ผœ์•ผํ•˜๋Š” ๋ฌธ์ œ์ ์„ ๋งŒ๋‚˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ถ”ํ›„ ๋ผ๋ฒจ๋กœ ๊ฐ™์€ ๋ผ๋ฒจ์ธ ํŒŒ๋“œ๋ฅผ ๋ชจ๋‘ ์‚ญ์ œ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ๋˜์—ˆ์ง€๋งŒ ๊ทธ ๋•Œ๋Š” ์ด๋ฏธ ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์„ ์•Œ๊ณ  ์žˆ์–ด์„œ... ์„œ๋น„์Šค๊ฐ€ ์„ฑ์žฅํ•˜๋ฉด์„œ ํŠน์ • ์„œ๋น„์Šค์— ๋ณต์ˆ˜ ๊ฐœ์— ํŒŒ๋“œ๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„์ง€๋ฉด์„œ ์ด ๋ฐฉ๋ฒ•์€ ๋” ์ด์ƒ ์“ฐ์ง€ ์•Š๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋””ํ”Œ๋กœ์ด๋จผํŠธ ์‚ญ์ œ ํ›„ ์žฌ์ƒ์„ฑ#

kubectl delete -f <deployment-manifest>
kubectl apply -f <deployment-manifest>

๊ฒฐ๋ก ๋ถ€ํ„ฐ ๋งํ•˜๋ฉด ๋น„์ถ”์ฒœํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ๋””ํ”Œ๋กœ์ด๋จผํŠธ๋ฅผ ์‚ญ์ œํ•˜๋ฉด์„œ ์žƒ์–ด๋ฒ„๋ฆฌ๋Š” ์ •๋ณด๋“ค์ด ๋งŽ๊ฑฐ๋“ ์š”. (rollout history ๊ฐ™์€ ์ •๋ณด๋“ค) ์–ด์ฐŒ ๋๋“  ํ•ด๋‹น ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ณต์ˆ˜ ๊ฐœ์— ํŒŒ๋“œ๋ฅผ ๊ฐ€์ง„ ์„œ๋น„์Šค๋„ ๋ชจ๋‘ ์žฌ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋””ํ”Œ๋กœ์ด๋จผํŠธ๋ฅผ ์ง€์šฐ๊ณ  ๋‹ค์‹œ ๋งŒ๋“œ๋Š”๋ฐ ์•ˆ๋  ์ˆ˜๊ฐ€ ์—†์ฃ . ํŒŒ๋“œ๋ฅผ ์‚ญ์ œํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋น„ํ•ด ์žฅ์ ์ด ๋˜ ํ•˜๋‚˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ ์ข…๋ฃŒ ํ›„ ์‹œ์ž‘ํ•˜๋Š” ์‹œ์ ์„ ์‚ฌ์šฉ์ž๊ฐ€ ์ปจํŠธ๋กค ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด์ฃ . ์ฆ‰ ์œ„์—์„œ ์†Œ๊ฐœํ•œ ํŒŒ๋“œ ์‚ญ์ œ๊ฐ€ ์ข…๋ฃŒ ํ›„ ๋ฐ”๋กœ ์‹œ์ž‘ํ•˜๋Š” "restart" ์ด์˜€๋‹ค๋ฉด, ๋””ํ”Œ๋กœ์ด๋จผํŠธ ์‚ญ์ œ ํ›„ ์ƒ์„ฑ์€ "stop", "start" ๋กœ ์ด๋ฒคํŠธ ์‹œ์ ์ด ๋‚˜๋ˆ ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์šด์˜ํ•˜๋‹ค๋ณด๋ฉด ์ž ๊น ๋‚ด๋ ธ๋‹ค๊ฐ€ ์ผ์ • ์‹œ๊ฐ„ ํ›„ ๋„์›Œ์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ƒ๊ธฐ๊ธฐ ๋งˆ๋ จ์ด์ฃ . ๊ทธ๋Ÿผ ๊ทธ ๋•Œ ์ด๋ ‡๊ฒŒ ํ•ด์•ผํ•˜๋Š”๋ฐ ์™œ ๋น„์ถ”์ฒœ์ด๋ƒ๊ตฌ์š”? ๋ฐ”๋กœ ๋‹ค์Œ์— ์†Œ๊ฐœ ์‹œ์ผœ๋“œ๋ฆด ๋ฐฉ๋ฒ•์ด ๋” ์ข‹๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋””ํ”Œ๋กœ์ด๋จผํŠธ์˜ Scale ์„ ๋ณ€๊ฒฝ#

kubectl scale deployment <deployment-name> --replicas 0
kubectl scale deployment <deployment-name> --replicas <n>

์„œ๋น„์Šค ์žฌ์‹œ์ž‘์„ ์œ„ํ•ด์„œ ์ƒ๋‹นํžˆ ์˜ค๋žซ๋™์•ˆ ์จ์™”๊ณ  ํ˜„์žฌ๋„ ์“ฐ๊ณ  ์žˆ๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ๋‹ค๋งŒ ์ง€๊ธˆ์€ "stop", "start" ๋ฐฉ์‹์œผ๋กœ ์ข…๋ฃŒ ํ›„ ์‹œ์ž‘ ์‹œ์ ์„ ์ œ๊ฐ€ ์ปจํŠธ๋กค ํ•˜๊ณ  ์‹ถ์„ ๋•Œ๋งŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰์‹œ ์žฌ์‹œ์ž‘์ผ ๊ฒฝ์šฐ์—๋Š” ๋งˆ์ง€๋ง‰์œผ๋กœ ์†Œ๊ฐœํ•  ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜์ฃ .

Rollout restart ๋ช…๋ น์–ด ์‚ฌ์šฉ#

kubectl rollout restart deployment <deployment-name>

์ €์˜ ์ตœ์ข… ์ข…์ฐฉ์ ์ž…๋‹ˆ๋‹ค. ์‚ฌ์‹ค rollout ๋ช…๋ น์–ด๋ฅผ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋ฅผ ๊ฝค ์˜ค๋žซ๋™์•ˆ ์“ฐ๊ณ ๋‚˜์„œ ์•Œ๊ฒŒ ๋˜์„œ... ์—ญ์‹œ ์ง€์‹์ด ๋ถ€์กฑํ•˜๋ฉด ๋ชธ์ด ๊ณ ์ƒํ•˜๋Š” ๋ฒ•์ด์ฃ . ์ € ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํŒŒ๋“œ๋ฅผ ์žฌ์‹œ์ž‘ํ•ด์ค๋‹ˆ๋‹ค. ๋‹ค๋งŒ ์œ„์— ๋ฐฉ๋ฒ•์ฒ˜๋Ÿผ ๋‹จ์ˆœํžˆ ํŒŒ๋“œ๋ฅผ ์‚ญ์ œํ•˜๊ณ  ์‹œ์ž‘ํ•ด์ฃผ๋Š” ๊ฒƒ์œผ๋กœ ๋๋‚˜๋Š”๊ฒŒ ์•„๋‹™๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ž์„ธํžˆ ๋‹ค๋ฃจ์ง€๋Š” ์•Š๊ฒ ์ง€๋งŒ ์„œ๋น„์Šค์— replica ์ˆ˜๊ฐ€ ๋Š˜์–ด๋‚˜๊ฒŒ ๋˜๋ฉด ๋ฐฐํฌ ์ „๋žต์— ๋Œ€ํ•ด์„œ ๊ณ ๋ฏผ์„ ํ•˜๊ฒŒ ๋˜๊ณ  ๋””ํ”Œ๋กœ์ด๋จผํŠธ์— ์„ค์ •ํ•˜๋Š” ์•„๋ž˜ ์„ค์ •์„ ํ•˜๊ฒŒ ๋ ํ…๋ฐ์š”.

spec:
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate

์ด ์ „๋žต์— ๋งž์ถฐ์„œ ์žฌ์‹œ์ž‘์„ ํ•ด์ค๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๋ฉด ์ด ๋ฐฉ๋ฒ• ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๋ฐฉ๋ฒ•๋“ค์€ ์ˆœ๊ฐ„์ ์œผ๋กœ ๋ชจ๋“  ํŒŒ๋“œ๋ฅผ ์žฌ์‹œ์ž‘ํ•˜๊ฒŒ ๋˜์ง€๋งŒ, rollout restart ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์„ค์ •ํ•œ๋Œ€๋กœ ์ˆœ์ฐจ์ ์œผ๋กœ ํŒŒ๋“œ๋ฅผ ์žฌ์‹œ์ž‘ํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด์ฃ . ๋ฌด์ค‘๋‹จ ์žฌ์‹œ์ž‘์„ ์œ„ํ•ด์„œ๋ผ๋ฉด ํ•„์ˆ˜์ ์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋งˆ์น˜๋ฉฐ#

์ง€๊ธˆ๊นŒ์ง€ ์„œ๋น„์Šค๋ฅผ ์žฌ์‹œ์ž‘ํ•˜๋Š” ๋ฐฉ๋ฒ•๋“ค์„ ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์‚ฌ์‹ค rollout restart ์„ ์ดˆ๊ธฐ๋ถ€ํ„ฐ ์•Œ์•˜์œผ๋ฉด ์ข‹์•˜๊ฒ ๋‹ค ์‹ถ์–ด์„œ ๋‹ค๋ฅธ ๋ถ„๋“ค์—๊ฒŒ ์†Œ๊ฐœํ•˜๊ณ ์ž ์“ด ๊ธ€์ด์ง€๋งŒ, ์ œ๊ฐ€ ์ง€๊ธˆ๊นŒ์ง€ ์‚ฌ์šฉํ–ˆ๋˜ ๋ฐฉ๋ฒ•๋“ค์„ ๋˜์ƒˆ๊ฒจ๋ณด๋ฉด์„œ ๊ฐ ๋ฐฉ๋ฒ•๋“ค์— ์žฅ๋‹จ์ ๋„ ์ •๋ฆฌํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ํ˜น์‹œ ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด ์žˆ์„๊นŒ์š”? ์—ฌ๋Ÿฌ๋ถ„๋“ค์€ ์–ด๋–ค ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜์‹œ๋‚˜์š”? ํ˜„์žฌ ๋Œ“๊ธ€ ๊ธฐ๋Šฅ์€ ์—†์ง€๋งŒ... ์–ด๋–ค ๋ฐฉ๋ฒ•์œผ๋กœ๋“  ์˜๊ฒฌ์ฃผ์„ธ์š” ๐Ÿ˜‹

Java version ์—…๊ทธ๋ ˆ์ด๋“œ ์ฃผ๊ธฐ๋Š”?

์ž๋ฐ” 8๋กœ ๊ฐœ๋ฐœ์„ ์‹œ์ž‘ํ•˜๊ณ  ์ง€๊ธˆ๊นŒ์ง€ ์ญˆ์šฑ 8๋กœ ๊ฐœ๋ฐœ์„ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ์ธ ํ† ์ด ํ”„๋กœ์ ํŠธ๋Š” ์˜ˆ์ „๋ถ€ํ„ฐ 11๋กœ ์ž‘์„ฑํ•ด์™”๊ณ  , ์‹ค๋ฌด์—์„œ๋„ ์ƒˆ๋กญ๊ฒŒ ์‹œ์ž‘ํ•˜๋Š” ํ”„๋กœ์ ํŠธ๋“ค์€ 11์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง€๋งŒ, ์ž๋ฐ” 8๋กœ ์ด๋ฏธ ๊ฐœ๋ฐœ๋œ ํ”„๋กœ์ ํŠธ๋“ค์€ ๋ฒŒ์ง‘์„ ๊ฑด๋“œ๋ฆฌ๋Š” ๊ผด์ด ๋ ๊นŒ๋ด ์—…๊ทธ๋ ˆ์ด๋“œ ํ•˜์ง€ ๋ชปํ•˜๊ณ  ์žˆ์ฃ . ๋ญ ์กฐ๋งŒ๊ฐ„์€ ๋ฐ˜๋“œ์‹œ ํ•ด์•ผ ํ•  ์ผ์ด๊ธด ํ•ฉ๋‹ˆ๋‹ค.

์ตœ๊ทผ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋‹ค๋ณด๋ฉด 14๋ฒ„์ „์ด๋‚˜ ๊ทธ ์ƒ์œ„ ๋ฒ„์ „์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž ๊น ์ด ๋ฒ„์ „๋“ค์€ ์–ผ๋งˆ๋‚˜ ์ง€์›๋˜๋Š” ๊ฒƒ์ผ๊นŒ์š”? ์ตœ์‹  ๋ฒ„์ „์ด๋ผ๊ณ  ๋งˆ๋ƒฅ ์˜ฌ๋ฆฌ๋Š”๊ฒŒ ์ •๋‹ต์ผ๊นŒ์š”? LTS ๊ฐ€ ๋˜๋Š” 11 ๋‹ค์Œ ๋ฒ„์ „์€ ๋ช‡ ์ผ๊นŒ์š”? ํ•จ๊ป˜ ์•Œ์•„๋ด…์‹œ๋‹ค.

Just before the release of JDK 9, Oracle made a number of announcements about how the development, distribution and updating of Java would work moving forward. Rather than the multi-year, feature-driven release cycle, there are now two releases of Java each year. The dates of these are fixed (March and September) and include only the features that are ready at that time. - What Does Long-Term Support Mean for OpenJDK?

This faster release cadence would rapidly make providing extended support impractical, so Oracle said they would designate specific releases of the Oracle JDK binary as having long-term support (LTS). JDK 8 was designated with LTS to get things started, with JDK 11 being the first LTS release under the new model. LTS releases would then occur every three years (so every sixth JDK release).

์œ„ ๋‚ด์šฉ์€ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ •๋ฆฌํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ๋งค๋…„ ๋‘ ๋ฒˆ ๋ฆด๋ฆฌ์ฆˆ, ๋‚ ์งœ๋Š” 3์›”์ด๋ž‘ 9์›”
  • 11 ๋ฒ„์ „์ด ์ž๋ฐ” 8 ์ดํ›„๋กœ ์ฒซ๋ฒˆ์งธ LTS
  • LTS ๋ฆด๋ฆฌ์ฆˆ๋Š” 3๋…„๋งˆ๋‹ค ๋ฐœ์ƒ, 6๊ฐœ์›” ๋งˆ๋‹ค ์—…๋ฐ์ดํŠธ ๋˜๋Š” ๋ฒ„์ „์ด 6๋ฒˆ ์˜ฌ๋ผ๊ฐˆ ๋•Œ๋งˆ๋‹ค ์ž„
  • ๋”ฐ๋ผ์„œ ๋‹ค์Œ LTS ๋ฆด๋ฆฌ์ฆˆ๋Š” 17

์กฐ๊ธˆ ๋” ์ƒ๊ฐํ•ด๋ณด๋ฉด...

  • LTS ๊ฐ€ ์•„๋‹Œ ๋ฒ„์ „์€ ๊ณ ์ž‘ 6๊ฐœ์›” ์ง€์›... 6๊ฐœ์›” ๋’ค์—๋Š” ๋ฒ„๊ทธ ๋‚˜์˜ค๋ฉด ์•Œ์•„์„œ ํ•ด๊ฒฐํ•ด์•ผ ํ•จ ๐Ÿ˜ณ
  • 2021๋…„ 9์›”์— ๋‹ค์Œ LTS ๋ฆด๋ฆฌ์ฆˆ์ธ 17 ์ด ๋‚˜์˜ฌ ์˜ˆ์ •
  • ํ•œ๋‹ฌ ๋‚จ์•˜๋‹ค? (์ข€ ๋” ์ฐธ๊ณ  ์žˆ๋‹ค๊ฐ€ 17 ์“ธ๊นŒ...)
  • ์•ž์œผ๋กœ ๋Œ€์ถฉ 21๋…„ ๋” ์ž๋ฐ”๋ฅผ ์“ด๋‹ค ์น˜๋ฉด... 7 ๋ฒˆ์— LTS...
  • ๊ทธ๋Ÿผ, 11, 17, 23, 29, 35, 41, 47 ๊ฐ€ LTS
  • 21๋…„ ๋’ค๋ฉด ์•„์ดํฐ 32 ๊ฐ€ ๋‚˜์˜ฌ๋ ค๋‚˜... ๊ฐค๋…ธํŠธ๋Š” 31
  • ์ž๋ฐ” 17 ์ดํ›„ ๋ฒ„์ „ ์ฏค์ด๋ฉด Golang ์“ฐ๊ณ  ์žˆ์ง€ ์•Š์„๊นŒ?

์ผ๋‹จ ๋‹ค์Œ New Project ๋ฒ„ํŠผ ๋ˆ„๋ฅผ ๋•Œ๋Š” 17 ๋‚˜์˜ค๊ธฐ ์ „์—” ๋ฌด์กฐ๊ฑด 11 ๋กœ ๋งŒ๋“ค๋‹ค๊ฐ€, ๊ณง 17 ์ด ๋‚˜์˜ค๋ฉด 17 ๋กœ ๋งŒ๋“ค์–ด์•ผ๊ฒ ๋„ค์š”. ๊ทธ๋ฆฌ๊ณ  8 โ†’ 11 โ†’ 17 ๋ณด๋‹ค๋Š” 8 โ†’ 17 ๋กœ ํ•œ๋ฒˆ์— ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํ•˜๋Š”๊ฒŒ ๋” ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ๋ฌด์กฐ๊ฑด ๋ฒ„์ „์„ ์˜ฌ๋ฆฌ๊ธฐ ๋ณด๋‹ค๋Š” ๊ฐ ๋ฒ„์ „์—์„œ ๊ฐœ์„ ๋œ ์ ์€ ๋ฌด์—‡์ธ์ง€, ๋ฌด์Šจ ์ด์œ ๋กœ ๊ทธ๋ ‡๊ฒŒ ๊ฐœ์„ ํ•˜๊ฒŒ ๋œ ๊ฒƒ์ธ์ง€๋ฅผ ์•„๋Š” ๊ฒƒ์ด ๋” ์ค‘์š”ํ•˜๊ฒ ์ง€์š”. ์กฐ๋งŒ๊ฐ„ ๋‹ค์Œ ๋ฒ„์ „์—์„œ ์ถ”๊ฐ€๋œ ๊ธฐ๋Šฅ์„ ์ •๋ฆฌํ•ด๋ด์•ผ๊ฒ ์–ด์š”.

์ฐธ๊ณ #

TIL-20210610

RDS ์ธ์Šคํ„ด์Šค ์‚ฌ์ด์ฆˆ ๋ณ€๊ฒฝ#

  • RDS Aurora Mysql ์ธ์Šคํ„ด์Šค ์‚ฌ์ด์ฆˆ ๋ณ€๊ฒฝ์‹œ ๋ณ€๊ฒฝ ๋Œ€์ƒ์ด ์“ฐ๊ธฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ผ๋ฉด, ์ฝ๊ธฐ๊ฐ€ ์“ฐ๊ธฐ๊ฐ€ ๋˜๋Š” FailOver Time ๋™์•ˆ ์“ฐ๊ธฐ๊ฐ€ ์ผ์‹œ์ ์œผ๋กœ ์ค‘๋‹จ๋˜๋ฉฐ ๊ทธ ๊ธฐ๊ฐ„์€ ์•ฝ 30์ดˆ ์ •๋„ ์†Œ์š”๋œ๋‹ค.

RDS ์ธ์ฝ”๋”ฉ ๋ณ€๊ฒฝ#

ํŒŒ๋ผ๋ฏธํ„ฐ ๊ทธ๋ฃน ๋‚ด ์•„๋ž˜ ์„ค์ •๊ฐ’์„ ๋ณ€๊ฒฝํ•œ๋‹ค.

  • character_set_client: utf8mb4
  • character_set_connection: utf8mb4
  • character_set_database: utf8mb4
  • character_set_filesystem: utf8mb4
  • character_set_results: utf8mb4
  • character_set_server: utf8mb4
  • collation_connection: utf8mb4_general_ci
  • collation_server: utf8mb4_general_ci

ํ™•์ธํ•˜๊ธฐ

show variables like 'c%';

์ธ์ฝ”๋”ฉ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๊ธฐ

alter database [DATABASE_NAME] character set = 'utf8' collate = 'utf8_general_ci';

RDS ๋Š๋ฆฐ ์ฟผ๋ฆฌ ๋กœ๊ทธ ์„ค์ •#

  • RDS ์„ค์ •์—์„œ ๋Š๋ฆฐ ์ฟผ๋ฆฌ ๋กœ๊ทธ ๋ฅผ ์ฒดํฌํ•˜์˜€๋‹ค๊ณ  ๋Š๋ฆฐ ์ฟผ๋ฆฌ ๋กœ๊ทธ๊ฐ€ CloudWatch Logs ์— ์Œ“์ด์ง€ ์•Š๋Š”๋‹ค. ํŒŒ๋ผ๋ฏธํ„ฐ ๊ทธ๋ฃน์—์„œ slow_query_log ๋ฅผ true(1) ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.
  • ๋Š๋ฆฐ ์ฟผ๋ฆฌ์— ํŒ๋‹จ ๊ธฐ์ค€ ์—ญ์‹œ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ทธ๋ฃน์—์„œ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, long_query_time ๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด ๋œ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ 10์ดˆ.
  • log_queries_not_using_indexes ์„ 1 ๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ์ธ๋ฑ์Šค๋ฅผ ํƒ€์ง€ ์•Š๋Š” ๋ชจ๋“  ์ฟผ๋ฆฌ๋ฅผ ๋Š๋ฆฐ ์ฟผ๋ฆฌ๋กœ ๊ธฐ๋กํ•œ๋‹ค.

์ฐธ๊ณ #

No appropriate protocol (protocol is disabled or cipher suites are inappropriate)#

Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
at sun.security.ssl.HandshakeContext.<init>(HandshakeContext.java:171) ~[na:1.8.0_292]
at sun.security.ssl.ClientHandshakeContext.<init>(ClientHandshakeContext.java:98) ~[na:1.8.0_292]
at sun.security.ssl.TransportContext.kickstart(TransportContext.java:220) ~[na:1.8.0_292]
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:428) ~[na:1.8.0_292]
at com.mysql.cj.protocol.ExportControlled.performTlsHandshake(ExportControlled.java:317) ~[mysql-connector-java-8.0.23.jar:8.0.23]
at com.mysql.cj.protocol.StandardSocketFactory.performTlsHandshake(StandardSocketFactory.java:188) ~[mysql-connector-java-8.0.23.jar:8.0.23]
at com.mysql.cj.protocol.a.NativeSocketConnection.performTlsHandshake(NativeSocketConnection.java:97) ~[mysql-connector-java-8.0.23.jar:8.0.23]
at com.mysql.cj.protocol.a.NativeProtocol.negotiateSSLConnection(NativeProtocol.java:333) ~[mysql-connector-java-8.0.23.jar:8.0.23]
... 91 common frames omitted

์ฐธ๊ณ #

๋„ํ์‚ฌ์šฐ๋ฃจ์Šค๋กœ ๋ธ”๋กœ๊ทธ ์‹œ์ž‘

์„ค์น˜ํ•˜๊ธฐ#

https://v2.docusaurus.io/docs/installation/

npx @docusaurus/init@latest init dezang.net classic
cd dezang.net
yarn start

๋นŒ๋“œํ•˜๊ธฐ#

yarn build

This command generates static content into the build directory and can be served using any static contents hosting service.

๋ฐฐํฌํ•˜๊ธฐ#

๋„ํ์‚ฌ์šฐ๋ฃจ์Šค๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฐฐํฌ๋ฅผ ๊ฐ€์ด๋“œํ•ฉ๋‹ˆ๋‹ค.

GIT_USER=<Your GitHub username> USE_SSH=true yarn deploy

์ฒ˜์Œ์—๋Š” ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ github page ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ–ˆ์ง€๋งŒ, ์ข€ ๋” ์„ฑ๋Šฅ์ด ์ข‹์€ (๋ธ”๋กœ๊ทธ์— ๋ฌด์Šจ ์„ฑ๋Šฅ ํƒ€๋ น์ธ์ง€... ์ง์—…๋ณ‘์ด๋ž€...) ์„œ๋น„์Šค๊ฐ€ ์—†์„๊นŒ ์ฐพ์•„๋ณด๋˜ ์ค‘ ๋น„๊ต ์ •๋ฆฌ๋ฅผ ์ž˜ํ•ด๋†“์€ nextJS ๋ญ˜๋กœ ๋ฐฐํฌํ• ๊นŒ? (Netlify, Vercel, Github page) ์„ ๋ณด๊ณ  ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ๊ธ€์— ๋‹ฌ๋ฆฐ ๋Œ“๊ธ€์ด ๊ฒฐ์ •์— ์ค‘์š”ํ•œ ์š”์†Œ๊ฐ€ ๋˜์—ˆ๋Š”๋ฐ์š”.

๊นƒํ—ˆ๋ธŒ Netlify์— ๋น„ํ•ด Vercel์˜ ํŠน์žฅ์ ์€ ์œ ์ผํ•˜๊ฒŒ ์„œ์šธ์— CDN์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Vercel์˜ ๊ฒฝ์šฐ ๊ตญ๋‚ด์—์„œ TTFB๊ฐ€ 30~40ms ๋กœ ์ตœ์ƒ๊ธ‰์„œ๋ฒ„์˜ ์„ฑ๋Šฅ์„ ๋Š๋‚„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!

์‹ค์ œ๋กœ vercel์— ๊ฒฝ์šฐ Vercel Docs-Edge Network-Regions ํŽ˜์ด์ง€๋ฅผ ๋ณด๋ฉด Seoul, South Korea ๊ฐ€ ๋‹น๋‹นํžˆ ์ž๋ฆฌ์žก๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด Netlify ๋Š” Netlify for Business ํ”Œ๋žœ์—๋งŒ 27 global edge locations ๋ผ๊ณ  ๋ช…์‹œํ•ด๋†“์•˜์„ ๋ฟ ํ”„๋ฆฌ ๋ฒ„์ „์— ์—ฃ์ง€๊ฐ€ ์–ด๋””์— ๋ช‡ ๊ฐœ์ธ์ง€๋Š” ๋น„๊ณต๊ฐœ๋กœ ํ•ด๋†“์•˜์ฃ . ํ•œ๊ธ€๋กœ ๋œ ๊ธ€์ด ๋Œ€๋‹ค์ˆ˜์ธ ํ•ด๋‹น ๋ธ”๋กœ๊ทธ๋Š” ํ•œ๊ตญ ์—ฃ์ง€๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒƒ์ด ์„ฑ๋Šฅ์ƒ ์ด์ ์ด ๋†’์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์—ฌ ์ด์ „์— ์จ๋ณธ ์ ์€ ์—†์ง€๋งŒ vercel์— ๋ฐฐํฌํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊นƒํ—ˆ๋ธŒ ๋กœ๊ทธ์ธ ํ›„ ๋ช‡ ๊ฐ€์ง€ ์„ค์ •๋งŒํ•˜๋ฉด ๋ฐ”๋กœ ๋ฐฐํฌ๊ฐ€ ๋˜์—ˆ๊ณ , ์ปค์Šคํ…€ ๋„๋ฉ”์ธ๋„ ์•„์ฃผ ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฌด์—‡๋ณด๋‹ค Let's Encrypt ์—์„œ SSL ์ธ์ฆ์„œ๋ฅผ ์ž๋™์œผ๋กœ ๋ฐœ๊ธ‰๋ฐ›์•„์„œ ์ ์šฉํ•ด์ฃผ๋Š” ๊ฒƒ๋„ ์ข‹์•˜๋„ค์š”.