728x90
๋ฐ˜์‘ํ˜•
์ด๋ฏธ์ง€ ์ถœ์ฒ˜: BleepingComputer

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

ํ•ต์‹ฌ ์š”์•ฝ
  • Active Storage์˜ ์ด๋ฏธ์ง€ variant ์ฒ˜๋ฆฌ ๊ฒฝ๋กœ์—์„œ ๊ฒ€์ฆ์ด ์ถฉ๋ถ„์น˜ ์•Š์•„, ์กฐ์ž‘๋œ ์š”์ฒญ์ด ์„œ๋ฒ„ ์ธก ์ฝ”๋“œ ์‹คํ–‰(RCE)๊นŒ์ง€ ์ด์–ด์งˆ ์ˆ˜ ์žˆ๋Š” ๊ฒฐํ•จ์ด ํŒจ์น˜๋จ
  • ์œ„ํ—˜๋„๊ฐ€ ๋†’๊ฒŒ ํ‰๊ฐ€๋œ ์ด์œ ๋Š” ์ธ์ฆ ์—†์ด ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ์ฒจ๋ถ€ํŒŒ์ผ URL์ด ๊ณต๊ฒฉ ํ‘œ๋ฉด์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์ž„ — ๋กœ๊ทธ์ธ ๋ฒฝ ๋’ค๊ฐ€ ์•„๋‹˜
  • ๋Œ€์‘์€ ๋‹จ์ˆœํ•จ: Rails·Active Storage๋ฅผ ํŒจ์น˜ ๋ฒ„์ „์œผ๋กœ ์˜ฌ๋ฆฌ๊ณ , ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ตœ์†Œ ๊ถŒํ•œ์œผ๋กœ ๊ฒฉ๋ฆฌํ•˜๋ฉฐ, ๋ณ€ํ™˜ ์š”์ฒญ ๋กœ๊ทธ์—์„œ ๋น„์ •์ƒ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ฐพ์Œ

1. ์ด ๊ฒฐํ•จ์˜ ๊ตฌ์กฐ — ์™œ "์ด๋ฏธ์ง€"์—์„œ ์ฝ”๋“œ ์‹คํ–‰์ด ๋‚˜์˜ค๋‚˜

Active Storage๋Š” ์›๋ณธ ํŒŒ์ผ์„ ๊ทธ๋Œ€๋กœ ๋‚ด๋ ค์ฃผ๊ธฐ๋„ ํ•˜์ง€๋งŒ, variant๋ฅผ ๋ถ™์ด๋ฉด ๋ฆฌ์‚ฌ์ด์ฆˆ·ํฌ๋งท ๋ณ€ํ™˜ ๊ฐ™์€ ๊ฐ€๊ณต๋ณธ์„ ๋งŒ๋“ค์–ด ์คŒ. ์ด๋•Œ ์‹ค์ œ ๋ณ€ํ™˜ ์ž‘์—…์€ Rails๊ฐ€ ์ง์ ‘ ํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ image_processing ์ ฌ์„ ๊ฑฐ์ณ ImageMagick(๋˜๋Š” libvips) ๊ฐ™์€ ์™ธ๋ถ€ ๋ฐ”์ด๋„ˆ๋ฆฌ์— ๋„˜๊น€. ์—ฌ๊ธฐ๊ฐ€ ํ•ต์‹ฌ์ž„.

  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๋‚ด๋Š” ๊ฒƒ์€ "์ด ์ด๋ฏธ์ง€๋ฅผ ์ด๋ ‡๊ฒŒ ๋ณ€ํ™˜ํ•ด ๋‹ฌ๋ผ"๋Š” ๋ณ€ํ™˜ ์ง€์‹œ(transformation) ๊ฐ’์ž„
  • Rails๋Š” ๊ทธ ์ง€์‹œ๋ฅผ ์„œ๋ช…(signed blob key)์œผ๋กœ ๋ณดํ˜ธํ•˜์ง€๋งŒ, ๊ฒ€์ฆ์ด ์šฐํšŒ๋˜๊ฑฐ๋‚˜ ํ—ˆ์šฉ ๋ชฉ๋ก์ด ๋А์Šจํ•˜๋ฉด ์˜๋„ํ•˜์ง€ ์•Š์€ ๋ณ€ํ™˜ ์˜ต์…˜์ด ์™ธ๋ถ€ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ๊ธฐ๋กœ ํ˜๋Ÿฌ๊ฐ
  • ImageMagick ๊ณ„์—ด์€ ์˜ต์…˜ ์ž์ฒด๊ฐ€ ๋งค์šฐ ๊ฐ•๋ ฅํ•ด์„œ, ํŠน์ • ์˜ต์…˜์ด ํŒŒ์ผ ๊ฒฝ๋กœ๋‚˜ ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค ์ฐธ์กฐ๋กœ ํ•ด์„๋˜๋ฉด ์‚ฌ์šฉ์ž ์ž…๋ ฅ์ด ๋ช…๋ น ์‹คํ–‰ ๋ฌธ๋งฅ์— ๋„๋‹ฌํ•˜๊ฒŒ ๋จ

์ฆ‰ "์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ์•…์„ฑ์œผ๋กœ ๋งŒ๋“ ๋‹ค"๊ฐ€ ์•„๋‹ˆ๋ผ "์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์ง€์‹œ๋ฅผ ์•…์„ฑ์œผ๋กœ ๋งŒ๋“ ๋‹ค"๋Š” ๊ฒŒ ์ด ์œ ํ˜•์˜ ๋ณธ์งˆ์ž„. ํŒŒ์ผ ํ™•์žฅ์ž ๊ฒ€์‚ฌ, ๋งค์ง๋ฐ”์ดํŠธ ๊ฒ€์‚ฌ, ์•ˆํ‹ฐ๋ฐ”์ด๋Ÿฌ์Šค ์Šค์บ” — ์ „ํ†ต์ ์ธ ์—…๋กœ๋“œ ๋ฐฉ์–ด๊ฐ€ ์ „๋ถ€ ๋ฌด๋ ฅํ•œ ์ด์œ ๊ฐ€ ์—ฌ๊ธฐ ์žˆ์Œ. ๊ฒ€์‚ฌํ•  ํŒŒ์ผ ์ž์ฒด๊ฐ€ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ž„.

2. ์šฐ๋ฆฌ ์„œ๋น„์Šค๊ฐ€ ์˜ํ–ฅ๊ถŒ์ธ์ง€ 30๋ถ„ ์•ˆ์— ํ™•์ธํ•˜๊ธฐ

์‚ฌ๊ณ  ๋Œ€์‘์€ ๋ฒ”์œ„ ํ™•์ •์ด ๋จผ์ €์ž„. ์ˆœ์„œ๋Œ€๋กœ ๋ณด๋ฉด ๋จ.

  • ๋ฒ„์ „ ํ™•์ธ: bundle list | grep -i rails, Rails.version์œผ๋กœ ํ˜„์žฌ ๋ฒ„์ „์„ ๋ฝ‘๊ณ , ๋ฆด๋ฆฌ์Šค ๋…ธํŠธ์— ๋ช…์‹œ๋œ ํŒจ์น˜ ๋ฒ„์ „๊ณผ ๋Œ€์กฐํ•จ. Gemfile.lock์ด ์‹ค์ œ ๋ฐฐํฌ๋ณธ๊ณผ ๊ฐ™์€์ง€๋„ ๊ฐ™์ด ํ™•์ธํ•ด์•ผ ํ•จ — ์Šคํ…Œ์ด์ง•๋งŒ ์˜ฌ๋ฆฌ๊ณ  ํ”„๋กœ๋•์…˜์ด ๋‚จ๋Š” ์‚ฌ๊ณ ๊ฐ€ ์€๊ทผํžˆ ๋งŽ์Œ
  • ์‚ฌ์šฉ ์—ฌ๋ถ€ ํ™•์ธ: grep -rn "variant\|has_one_attached\|has_many_attached" app/๋กœ variant ํ˜ธ์ถœ ์ง€์ ์„ ์ฐพ์Œ. Active Storage๋ฅผ ๋ถ™์—ฌ๋งŒ ๋‘๊ณ  variant๋ฅผ ์•ˆ ์“ด๋‹ค๋ฉด ๋…ธ์ถœ ๋ฉด์ด ํ›จ์”ฌ ์ข์•„์ง
  • ๊ฒฝ๋กœ ๋…ธ์ถœ ํ™•์ธ: rails routes | grep -i active_storage๋กœ /rails/active_storage/representations/... ๊ฐ™์€ ์—”๋“œํฌ์ธํŠธ๊ฐ€ ์™ธ๋ถ€์— ์—ด๋ ค ์žˆ๋Š”์ง€ ๋ด„. CDN์ด๋‚˜ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ ์•ž๋‹จ์—์„œ ์ด ๊ฒฝ๋กœ๊ฐ€ ๊ทธ๋Œ€๋กœ ํ†ต๊ณผ๋˜๋Š”์ง€๋„ ํ™•์ธ ๋Œ€์ƒ์ž„
  • ์ฒ˜๋ฆฌ๊ธฐ ํ™•์ธ: ImageMagick์„ ์“ฐ๋Š”์ง€ libvips๋ฅผ ์“ฐ๋Š”์ง€์— ๋”ฐ๋ผ ์œ„ํ—˜ ์„ฑ๊ฒฉ์ด ๋‹ฌ๋ผ์ง. ๊ฐœ์ธ์ ์œผ๋กœ๋Š” ์ด์ฐธ์— libvips๋กœ ๋„˜์–ด๊ฐ€๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•จ. ์„ฑ๋Šฅ๋„ ๋‚ซ๊ณ  ์˜ต์…˜ ํ‘œ๋ฉด์ด ํ›จ์”ฌ ์ข์Œ

3. ํƒ์ง€ — ๋กœ๊ทธ์—์„œ ๋ฌด์—‡์„ ์ฐพ์„ ๊ฒƒ์ธ๊ฐ€

ํŒจ์น˜๋ฅผ ์˜ฌ๋ ธ๋‹ค๊ณ  ๋์ด ์•„๋‹˜. ํŒจ์น˜ ์ด์ „์— ์ด๋ฏธ ๋“ค์–ด์™”๋Š”์ง€๋ฅผ ๋ด์•ผ ํ•จ. ์›น ์„œ๋ฒ„ ์•ก์„ธ์Šค ๋กœ๊ทธ์™€ Rails ๋กœ๊ทธ๋ฅผ ๊ฐ™์ด ๋†“๊ณ  ๋ณด๋ฉด ์‹ ํ˜ธ๊ฐ€ ์žกํž˜.

  • Active Storage ํ‘œํ˜„(representation) ๊ฒฝ๋กœ์— ๋Œ€ํ•œ ์š”์ฒญ ์ค‘ ๋น„์ •์ƒ์ ์œผ๋กœ ๊ธด ํŒŒ๋ผ๋ฏธํ„ฐ๋‚˜ ์ธ์ฝ”๋”ฉ์ด ์ค‘์ฒฉ๋œ ๊ฐ’ — ์ •์ƒ ํŠธ๋ž˜ํ”ฝ์˜ variant ํ‚ค๋Š” ๊ธธ์ด ๋ถ„ํฌ๊ฐ€ ์ƒ๋‹นํžˆ ์ผ์ •ํ•จ. ์ด ๋ถ„ํฌ์—์„œ ๋ฒ—์–ด๋‚˜๋Š” ๊ฐ’์ด 1์ฐจ ํ›„๋ณด์ž„
  • ๊ฐ™์€ blob์— ๋Œ€ํ•ด ์งง์€ ์‹œ๊ฐ„์— ์ˆ˜์‹ญ~์ˆ˜๋ฐฑ ๋ฒˆ ๋‹ค๋ฅธ ๋ณ€ํ™˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ — ์ •์ƒ ์‚ฌ์šฉ์ž๋Š” ์ธ๋„ค์ผ ์‚ฌ์ด์ฆˆ๋ฅผ ๋ช‡ ์ข…๋ฅ˜๋งŒ ์š”์ฒญํ•จ. ํŒŒ๋ผ๋ฏธํ„ฐ ๋ธŒ๋ฃจํŠธํฌ์‹ฑ์˜ ์ „ํ˜•์  ํŒจํ„ด์ž„
  • 500 ์—๋Ÿฌ์˜ ๊ธ‰์ฆ — ์ต์Šคํ”Œ๋กœ์ž‡ ์‹œ๋„๋Š” ๋Œ€๊ฐœ ์‹คํŒจ๋ฅผ ๋จผ์ € ๋‚จ๊น€. ์ด๋ฏธ์ง€ ๋ณ€ํ™˜ ๊ด€๋ จ ์˜ˆ์™ธ(ImageProcessing::Error, MiniMagick ๊ด€๋ จ ์ŠคํƒํŠธ๋ ˆ์ด์Šค)๊ฐ€ ํ‰์†Œ๋ณด๋‹ค ๋Š˜์—ˆ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ ์› ์š”์ฒญ๊นŒ์ง€ ์—ญ์ถ”์ ํ•ด์•ผ ํ•จ
  • ์›น ์„œ๋ฒ„ ํ”„๋กœ์„ธ์Šค์—์„œ ํŒŒ์ƒ๋œ ์˜ˆ์ƒ ๋ฐ– ์ž์‹ ํ”„๋กœ์„ธ์Šคconvert, magick์€ ์ •์ƒ์ด์ง€๋งŒ ๊ทธ ๋ฐ‘์—์„œ sh, curl, wget, bash๊ฐ€ ๋œฌ๋‹ค๋ฉด ๊ทธ๊ฑด ์‚ฌ๊ณ ์ž„. EDR์ด ์žˆ๋‹ค๋ฉด ์ด ๋ถ€๋ชจ-์ž์‹ ๊ด€๊ณ„๋ฅผ ๋ฃฐ๋กœ ๋ฐ•์•„๋‘๋Š” ๊ฒŒ ๊ฐ€์žฅ ํ™•์‹คํ•œ ํƒ์ง€ ์ง€์ ์ž„
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„์—์„œ ๋‚˜๊ฐ€๋Š” ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์•„์›ƒ๋ฐ”์šด๋“œ ์—ฐ๊ฒฐ — ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์„œ๋ฒ„๊ฐ€ ์™ธ๋ถ€๋กœ ๋จผ์ € ๋ง์„ ๊ฑธ ์ด์œ ๋Š” ๊ฑฐ์˜ ์—†์Œ

4. ์™„ํ™” — ํŒจ์น˜ ์™ธ์— ๊ฒน์ณ ๋‘˜ ๋ฐฉ์–ด์ธต

ํŒจ์น˜๊ฐ€ 1์ˆœ์œ„์ธ ๊ฑด ๋‹น์—ฐํ•˜์ง€๋งŒ, ๋‹ค์Œ์— ๋˜ ๋น„์Šทํ•œ ๊ฒฐํ•จ์ด ๋‚˜์™€๋„ ๋ฒ„ํ‹ธ ์ˆ˜ ์žˆ๊ฒŒ ๊ตฌ์กฐ๋ฅผ ๋ฐ”๊ฟ” ๋‘๋Š” ๊ฒŒ ์ง„์งœ ์†Œ๋“์ž„.

  • ๋ณ€ํ™˜ ์˜ต์…˜ ํ—ˆ์šฉ ๋ชฉ๋ก ๊ณ ์ •: Rails์—๋Š” ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅํ•œ ๋ณ€ํ™˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ œํ•œํ•˜๋Š” ์„ค์ •์ด ์žˆ์Œ. ์„œ๋น„์Šค๊ฐ€ ์‹ค์ œ๋กœ ์“ฐ๋Š” ๋ฆฌ์‚ฌ์ด์ฆˆ·ํฌ๋งท ๋ณ€ํ™˜ ๋ช‡ ๊ฐ€์ง€๋งŒ ๋‚จ๊ธฐ๊ณ  ๋‚˜๋จธ์ง€๋Š” ์ „๋ถ€ ๋ง‰์•„ ๋‘๋ฉด, ๋ฏธ์ง€์˜ ์˜ต์…˜ ์•…์šฉ์€ ๋Œ€๋ถ€๋ถ„ ๋ฌธํ„ฑ์—์„œ ๋Š๊น€
  • ์‚ฌ์ „ ์ •์˜๋œ variant๋งŒ ํ—ˆ์šฉ: URL๋กœ ์ž„์˜ ๋ณ€ํ™˜์„ ๋ฐ›์ง€ ๋ง๊ณ , ์„œ๋ฒ„๊ฐ€ ์ •ํ•œ ํ”„๋ฆฌ์…‹(thumb, medium, large)๋งŒ ์ด๋ฆ„์œผ๋กœ ๋ฐ›๊ฒŒ ์„ค๊ณ„ํ•˜๋ฉด ๊ณต๊ฒฉ์ž๊ฐ€ ์กฐ์ž‘ํ•  ๊ฐ’ ์ž์ฒด๊ฐ€ ์‚ฌ๋ผ์ง. ๊ฐœ์ธ์ ์œผ๋กœ ๊ฐ€์žฅ ํšจ๊ณผ ์ข‹์€ ๊ตฌ์กฐ ๋ณ€๊ฒฝ์ด๋ผ๊ณ  ๋ด„
  • ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ๊ฒฉ๋ฆฌ: ๋ณ€ํ™˜ ์ž‘์—…์„ ๋ณ„๋„ ์›Œ์ปค·๋ณ„๋„ ์ปจํ…Œ์ด๋„ˆ๋กœ ๋นผ๊ณ , ๋„คํŠธ์›Œํฌ ์•„์›ƒ๋ฐ”์šด๋“œ๋ฅผ ์ฐจ๋‹จํ•˜๊ณ , ์ฝ๊ธฐ ์ „์šฉ ํŒŒ์ผ์‹œ์Šคํ…œ์— ๋น„ํŠน๊ถŒ ๊ณ„์ •์œผ๋กœ ๋Œ๋ฆผ. RCE๊ฐ€ ๋‚˜๋”๋ผ๋„ ์–ป๋Š” ๊ฒŒ ์—†๋Š” ํ™˜๊ฒฝ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ž„
  • ImageMagick ์ •์ฑ… ํŒŒ์ผ ์†๋ณด๊ธฐ: policy.xml์—์„œ ์“ฐ์ง€ ์•Š๋Š” ์ฝ”๋”(MSL, MVG, HTTPS, EPHEMERAL, URL ๋“ฑ)๋ฅผ ๋ง‰์•„ ๋‘๋Š” ๊ฒƒ์€ ์˜ค๋ž˜์ „๋ถ€ํ„ฐ ์ •์„์ด์—ˆ๊ณ  ์ง€๊ธˆ๋„ ์œ ํšจํ•จ
  • WAF๋Š” ๋ณด์กฐ ์ˆ˜๋‹จ์œผ๋กœ: Active Storage ๊ฒฝ๋กœ์— ๋Œ€ํ•ด ํŒŒ๋ผ๋ฏธํ„ฐ ๊ธธ์ด ์ƒํ•œ์„ ๊ฑฐ๋Š” ์ •๋„๋Š” ์‹œ๊ฐ„์„ ๋ฒŒ์–ด ์คŒ. ๋‹ค๋งŒ ์„œ๋ช…๊ฐ’ ํ˜•ํƒœ๋ฅผ ํ‰๋‚ด ๋‚ธ ์šฐํšŒ๋Š” ์–ผ๋งˆ๋“ ์ง€ ๊ฐ€๋Šฅํ•˜๋‹ˆ WAF๋งŒ ๋ฏฟ๊ณ  ํŒจ์น˜๋ฅผ ๋ฏธ๋ฃจ๋Š” ๊ฑด ๊ธˆ๋ฌผ์ž„

5. ์ด ์‚ฌ๊ฑด์—์„œ ๋‚จ๊ธธ ๊ตํ›ˆ

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

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

์ฃผ๋ง์— ์‹œ๊ฐ„ ๋‚ด์„œ ์šฐ๋ฆฌ ์„œ๋น„์Šค์˜ rails routes ํ•œ ๋ฒˆ ๋ฝ‘์•„ ๋ณด์‹œ๋ฉด ์ข‹๊ฒ ์Œ. ์ƒ๊ฐ๋ณด๋‹ค ์—ด๋ ค ์žˆ๋Š” ๊ฒฝ๋กœ๊ฐ€ ๋งŽ์•„์„œ ๋†€๋ž„ ์ˆ˜๋„ ์žˆ์Œ. ์ ๊ฒ€ํ•ด ๋ณด์‹œ๊ณ  ์˜์™ธ์˜ ๋ฐœ๊ฒฌ์ด ์žˆ์—ˆ๋‹ค๋ฉด ๋Œ“๊ธ€๋กœ ๊ณต์œ ํ•ด ์ฃผ์„ธ์š”. ๊ฐ™์ด ์ฑ™๊ฒจ ๋ณด์•„์š”!

728x90
๋ฐ˜์‘ํ˜•