Backend/RubyOnRails

[๋ฒˆ์—ญ] General Ruby on Rails Problems and Takeaways(์ผ๋ฐ˜์ ์ธ Ruby On Rails ๋ฌธ์ œ ๋ฐ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•)

Seyun(Marco) 2024. 1. 19. 23:15
728x90

๐Ÿ’ก ์›๋ณธ ๊ธ€ : https://blog.appsignal.com/2021/07/07/general-ruby-on-rails-problems-and-takeaways.html

 

General Ruby on Rails Problems and Takeaways | AppSignal Blog

In this last part of the Rails Patterns and Anti-patterns series, I'll be going over the most common problems I've encountered while building and shipping Ruby on Rails applications.

blog.appsignal.com

 

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

์—ฌ๊ธฐ์„œ ์‚ดํŽด๋ณผ ์ƒ๊ฐ๋“ค์€ ์ฝ”๋“œ์˜ ๊ฑฐ์˜ ๋ชจ๋“  ๊ณณ์— ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ MVC ํŒจํ„ด๊ณผ ๊ด€๋ จ๋œ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ผ๋ฐ˜์ ์ธ ์ƒ๊ฐ๋“ค๋กœ ๋ด์ฃผ์‹œ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค. Rails MVC์™€ ๊ด€๋ จ๋œ ํŒจํ„ด ๋ฐ ์•ˆํ‹ฐ ํŒจํ„ด์— ๊ด€์‹ฌ์ด ์žˆ๋‹ค๋ฉด Model(๋ฒˆ์—ญ), View(๋ฒˆ์—ญ), Controller(๋ฒˆ์—ญ) ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŒ…์„ ํ™•์ธํ•ด๋ณด์„ธ์š”.

๊ทธ๋Ÿผ ์ด์ œ ์ผ๋ฐ˜์ ์ธ ๋ฌธ์ œ์™€ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด๊ธฐ์ ์ธ ๊ฐ์ฒด์™€ ๋””๋ฏธํ„ฐ์˜ ๋ฒ•์น™

๋””๋ฏธํ„ฐ์˜ ๋ฒ•์น™์€ ๋””๋ฏธํ„ฐ ํ”„๋กœ์ ํŠธ์—์„œ ์—ฌ๋Ÿฌ ์‚ฌ๋žŒ๋“ค์ด ํ•จ๊ป˜ ์ž‘์—…ํ•˜๋ฉด์„œ ๊ทธ ์ด๋ฆ„์„ ์–ป์€ ํœด๋ฆฌ์Šคํ‹ฑ ์ž…๋‹ˆ๋‹ค. ์ด ๋ฒ•์น™์€ ๊ฐ์ฒด๊ฐ€ ํ•œ๋ฒˆ์— ํ•˜๋‚˜์˜ ๋ฉ”์„œ๋“œ๋งŒ ํ˜ธ์ถœํ•˜๊ณ  ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ์˜ ํ˜ธ์ถœ์„ ์—ฐ์‡„์ ์œผ๋กœ ํ•˜์ง€ ์•Š๋Š”๊ฒƒ์ด ์ข‹๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์‹ค์ œ๋กœ ์˜๋ฏธํ•˜๋Š” ๋ฐ”๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

# Bad
song.label.address

# Good
song.label_address

์ด์ œ song ๊ฐ์ฒด๋Š” ๋” ์ด์ƒ address๊ฐ€ ์–ด๋””์„œ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€ ์•Œ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. address๋Š” label ๊ฐ์ฒด์˜ ์ฑ…์ž„์ž…๋‹ˆ๋‹ค. ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ํ•œ ๋ฒˆ๋งŒ ํ•˜๊ณ , ๊ฐ์ฒด๋ฅผ ์ด๊ธฐ์ ์œผ๋กœ ๋งŒ๋“ค์–ด ์ „์ฒด ์ •๋ณด๋ฅผ ๊ณต์œ ํ•˜์ง€ ์•Š๊ณ  helper ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ณต์œ ํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

Rails์—์„œ๋Š” helper ๋ฉ”์„œ๋“œ ์ž์ฒด๋ฅผ ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์—†์ด delegate ํ—ฌํผ๋ฅผ ์‚ฌ์šฉํ• ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

def Label < ApplicationModel
  belongs_to :song

  delegate :address, to: :song
end

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

๋””๋ฏธํ„ฐ์˜ ๋ฒ•์น™๊ณผ ๋งค์šฐ ์œ ์‹œํ•œ ๋˜ ๋‹ค๋ฅธ ์•„์ด๋””์–ด๋Š” ๋‹จ์ผ์ฑ…์ž„์›์น™(SRP)์ž…๋‹ˆ๋‹ค. ์ด ์›์น™์€ ๋ชจ๋“ˆ, ํด๋ž˜์Šค ๋˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์‹œ์Šคํ…œ ํ•œ ๋ถ€๋ถ„์„ ์ฑ…์ž„์ ธ์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์€ ๋ง๋กœ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ™์€ ์ด์œ ๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ํ•ญ๋ชฉ์„ ํ•œ๊ตฐ๋ฐ๋กœ ๋ชจ์๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์ด์œ ๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ํ•ญ๋ชฉ์€ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

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

๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ณ  LOC๋ฅผ ๋Š˜๋ฆด ๋•Œ ์‚ฌ๋žŒ๋“ค์€ ์ข…์ข… ๋น ๋ฅธ ํ•ด๊ฒฐ์ฑ…์„ ์ฐพ๋Š” ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ๋น ๋ฅธ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

LOC๋ž€?

LOC๋Š” Lines of Code์˜ ์•ฝ์ž๋กœ, ์ฝ”๋“œ์˜ ๊ธธ์ด๋‚˜ ๋ณต์žก๋„๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ง€ํ‘œ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. LOC๊ฐ€ ๋งŽ์œผ๋ฉด ์ฝ”๋“œ๊ฐ€ ๋” ๋ณต์žกํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์•„๋Š” ๋‚จ์ž (Ruby Gem์ด ํ•„์š”ํ•˜์‹  ๊ฐ€์š”?)

Rails๊ฐ€ ํ™”์ œ๊ฐ€ ๋˜๋˜ ์‹œ์ ˆ์—๋Š” ์˜คํ”ˆ์†Œ์Šค ํ˜‘์—…์ด ๋ถ์„ ์ด๋ฃจ๋ฉด์„œ ์ƒˆ๋กœ์šด Ruby Gem์ด ๊ณณ๊ณณ์—์„œ ๋“ฑ์žฅํ–ˆ์Šต๋‹ˆ๋‹ค.(์š”์ฆ˜์€ ๋ชจ๋“  ์ƒˆ๋กœ์šด JavaScript ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋“ฑ์žฅํ•˜๋Š” ๊ฒƒ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ ๊ทœ๋ชจ๋Š” ํ›จ์”ฌ ์ž‘์ง€๋งŒ์š”.)

๐Ÿ‘† ๋ชจ๋“ˆ ๊ฐฏ์ˆ˜์˜ ์ •๋ณด

์–ด์จ‹๋“ , ์ผ๋ฐ˜์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐ ํ•  ์ˆ˜ ์žˆ๋Š” Gem์„ ์ฐพ๋Š” ๊ฒƒ์ด์˜€์Šต๋‹ˆ๋‹ค.

์ด ๋ฐฉ๋ฒ•์ด ์ž˜๋ชป๋œ ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ, Gem์„ ์„ค์น˜ํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ•˜๊ธฐ ์ „์— ๋ช‡ ๊ฐ€์ง€ ์กฐ์–ธ์„ ๋“œ๋ฆด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๋จผ์ € ์Šค์Šค๋กœ์—๊ฒŒ ์•„๋ž˜์™€ ๊ฐ™์€ ์งˆ๋ฌธ์„ ํ•ด๋ณด์„ธ์š”.

  • Gem์˜ ๊ธฐ๋Šฅ ์ค‘ ์–ด๋–ค ๋ถ€๋ถ„์„ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•˜์‹œ๋‚˜์š”?
  • ๋” ‘๋‹จ์ˆœ’ํ•˜๊ฑฐ๋‚˜ ๋” ์ตœ์‹ ์˜ ์œ ์‚ฌํ•œ Gem์ด ์žˆ๋‚˜์š”?
  • ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์„ ์‰ฝ๊ณ  ํ™•์‹คํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‚˜์š”?

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

์ œ๊ฐ€ ๊ณ ๋ คํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ์š”์†Œ๋Š” ํ•ด๋‹น Gem ์ €์žฅ์†Œ๊ฐ€ ์–ผ๋งˆ๋‚˜ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ๋Š”์ง€, ์ฆ‰ ํ™œ๋™์ค‘์ธ ๋ฉ”์ธํ…Œ์ด๋„ˆ๊ฐ€ ์žˆ๋Š”์ง€? ๋งˆ์ง€๋ง‰์œผ๋กœ ๋ฆด๋ฆฌ์ฆˆ๊ฐ€ ์ด๋ฃจ์–ด์ง„ ์‹œ๊ธฐ๋Š” ์–ธ์ œ์ธ์ง€? ํ™•์ธํ•ด๋ณด์„ธ์š”.

๋˜ํ•œ Gem์˜ ์ข…์†์„ฑ๋„ ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํŠน์ • ๋ฒ„์ „์˜ ์ข…์†์„ฑ์— ์ข…์†๋˜๋Š” ๊ฒƒ์„ ์›์น˜ ์•Š๋Š”๋‹ค๋ฉด ํ•ญ์ƒ “Gemfile.spec” ํŒŒ์ผ์„ ํ™•์ธํ•˜์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค. ๋ฃจ๋น„ Gem์˜ ๋ฒ„์ „ ์ง€์ • ๋ฐฉ๋ฒ• ๋ฌธ์„œ๋ฅผ ํ™•์ธํ•ด๋ณด์„ธ์š”.

Gem์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐ ํ•˜๋Š” ๋™์•ˆ ์ œ๊ฐ€ ์ ‘ํ•œ ๊ด€๋ จ๋œ ๋ถ€๋ถ„์ด ์žˆ๋Š”๋ฐ, ๋ฐ”๋กœ Rails/Ruby ์„ธ๊ณ„์— ์ ์šฉ๋˜๋Š” ‘Not Invented Here’(NIH) ํ˜„์ƒ์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ ์„ธ์…˜์—์„œ ๊ทธ ๋‚ด์šฉ์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์„ธ์ƒ์— ์—†๋˜ ๋ฐœ๋ช…ํ’ˆ(๊ฒฐ๊ตญ ๋ฃจ๋น„ ๋ณด์„์ด ํ•„์š”ํ•œ๊ฒƒ์ผ๊นŒ์š”?)

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

๋•Œ๋•Œ๋กœ NIH๋ฅผ ๊ฒฝํ—˜ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์€ ์ผ์ด ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ์‹œ์ค‘์— ๋‚˜์™€ ์žˆ๋Š” ๋‹ค๋ฅธ ํ•ด๊ฒฐ์ฑ…๋ณด๋‹ค ๊ฐœ์„ ํ•œ๋‹ค๋ฉด ์‚ฌ๋‚ด ํ•ด๊ฒฐ์ฑ…์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์ข‹์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•ด๊ฒฐ์ฑ…์„ ์˜คํ”ˆ์†Œ์Šคํ™”ํ•˜๊ธฐ๋กœ ํ•ด๊ฒฐํ–ˆ๋‹ค๋ฉด ๋”์šฑ ์ข‹์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (Ruby On Rails, React๋ฅผ ์‚ดํŽด๋ณด์„ธ์š”.) ํ•˜์ง€๋งŒ ์ด๋ฅผ ์œ„ํ•ด ๋ฐ”ํ€ด๋ฅผ ์žฌ๋ฐœ๋ช…ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๊ทธ๋ ‡๊ฒŒ ํ•˜์ง€ ๋งˆ์„ธ์š”. ๋ฐ”ํ€ด ์ž์ฒด๋Š” ์ด๋ฏธ ๊ฝค ํœผ๋ฅญํ•ฉ๋‹ˆ๋‹ค.

์ด ์ฃผ์ œ๋Š” ์ƒ๋‹นํžˆ ๊นŒ๋‹ค๋กœ์šด ์ฃผ์ œ์ด๋ฏ€๋กœ ์ด๋Ÿฐ ์ƒํ™ฉ์— ์ฒ˜ํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์งˆ๋ฌธ์„ ์Šค์Šค๋กœ์—๊ฒŒ ํ•ด๋ณด์„ธ์š”.

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

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

๊ทผ๋ฌด์ค‘์ธ ์ธ๋ช…๊ตฌ์กฐ์›(๊ณผํ•œ rescue exception)

์‚ฌ๋žŒ๋“ค์€ ์›๋ž˜ ๋ชฉํ‘œํ–ˆ๋˜ ๊ฒƒ๋ณด๋‹ค ๋” ๋งŽ์€ ์˜ˆ์™ธ๋ฅผ rescue๋ฅผ ํ•˜๋Š” ๊ฒฝํ–ฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์ฃผ์ œ๋Š” ์•ž์˜ ์ฃผ์ œ๋ณด๋‹ค ์šด์˜์›์น™๊ณผ ๋” ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ผ๋ถ€ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์ƒ์‹์ ์ธ ๋‚ด์šฉ์ผ ์ˆ˜ ์žˆ์ง€๋งŒ, ์ฝ”๋“œ์—์„œ ๊ฐ€๋” ๋ณผ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.

begin
  song.upload_lyrics
rescue
  puts 'Lyrics upload failed'
end

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

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

๋„ˆ๋ฌด ๋งŽ์€๊ฒƒ์„ ๋ฌป์Šต๋‹ˆ๋‹ค.(๋„ˆ๋ฌด ๋งŽ์€ SQL ์ฟผ๋ฆฌ)

์ด ์„ธ์…˜์—์„œ๋Š” ๋˜ ๋‹ค๋ฅธ ์›น ๊ฐœ๋ฐœ ๋ฌธ์ œ์ธ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฌธ์ œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ•œ๋ฒˆ์˜ ์š”์ฒญ์— ๋„ˆ๋ฌด ๋งŽ์€ SQL ์ฟผ๋ฆฌ๋กœ ์›น ์„œ๋ฒ„๋ฅผ ํญ๊ฒฉํ•˜๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ์–ด๋–ป๊ฒŒ ์ด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ• ๊นŒ์š”? ํ•˜๋‚˜์˜ ์š”์ฒญ์œผ๋กœ ์—ฌ๋Ÿฌ ํ…Œ์ด๋ธ”์—์„œ ์—ฌ๋Ÿฌ ๋ ˆ์ฝ”๋“œ๋ฅผ ๊ฐ€์ ธ์˜ค๋ ค๊ณ  ํ•  ๋•Œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ฐ€์žฅ ์ž์ฃผ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์€ ์•…๋ช… ๋†’์€ N+1 ์ฟผ๋ฆฌ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ ๋ชจ๋ธ์„ ์ƒ์ƒํ•ด๋ณด์„ธ์š”.

class Song < ApplicationRecord
  belongs_to :artist
end

class Artist < ApplicationRecord
  has_many :songs
end

ํ•œ ์žฅ๋ฅด์˜ ๋…ธ๋ž˜ ๋ช‡ ๊ณก๊ณผ ํ•ด๋‹น ์•„ํ‹ฐ์ŠคํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ:

songs = Song.where(genre: genre).limit(10)

songs.each do |song|
  puts "#{song.title} by #{song.artist.name}"
end

์ด ์ฝ”๋“œ ์กฐ๊ฐ์€ 10๊ณก์„ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ํ•˜๋‚˜์˜ SQL ์ฟผ๋ฆฌ๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ํ›„, ๊ฐ ๊ณก์˜ ์•„ํ‹ฐ์ŠคํŠธ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€ SQL ์ฟผ๋ฆฌ๊ฐ€ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด 11๊ฐœ์˜ ์ฟผ๋ฆฌ๊ฐ€ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.

๋” ๋งŽ์€ ๊ณก์„ ๋ถˆ๋Ÿฌ์˜ฌ ๊ฒฝ์šฐ ๋ชจ๋“  ์•„ํ‹ฐ์ŠคํŠธ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๋” ๋งŽ์€ ๋ถ€ํ•˜๊ฐ€ ๊ฑธ๋ฆฌ๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์ƒ์ƒํ•ด ๋ณด์„ธ์š”.

๋Œ€์•ˆ์œผ๋กœ Rails์˜ includes๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”:

songs = Song.includes(:artists).where(genre: genre).limit(10)

songs.each do |song|
  puts "#{song.title} by #{song.artist.name}"
end

includes ์ดํ›„์—, ์ด์ œ ํ‘œ์‹œํ•  ๋…ธ๋ž˜ ์ˆ˜์— ์ƒ๊ณผ์—†์ด ๋‘๊ฐœ์˜ SQL ์ฟผ๋ฆฌ๋งŒ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ •๋ง ๊น”๋”ํ•ฉ๋‹ˆ๋‹ค.

๋„ˆ๋ฌด ๋งŽ์€ SQL ์ฟผ๋ฆฌ๋ฅผ ์ง„๋‹จํ•  ์ˆ˜ ์žˆ๋Š” ํ•œ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€ ๊ฐœ๋ฐœํ•˜๋Š” ์ค‘์— ์žˆ์Šต๋‹ˆ๋‹ค. ๋™์ผํ•œ ํ…Œ์ด๋ธ”์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์œ ์‚ฌํ•œ SQL ์ฟผ๋ฆฌ ๊ทธ๋ฃน์ด ๋ณด์ด๋ฉด ๋ญ”๊ฐ€ ์ด์ƒํ•œ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ๋•Œ๋ฌธ์— ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์— SQL ๋กœ๊น…์„ ์‚ฌ์šฉํ•˜๋„๋ก ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ Rails๋Š” ์ฝ”๋“œ์—์„œ ์ฟผ๋ฆฌ๊ฐ€ ํ˜ธ์ถœ๋œ ์œ„์น˜๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” **verbose query logs**๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

๋กœ๊ทธ๋ฅผ ๋ณด๋Š” ๊ฒƒ์ด ๊ท€์ฐฎ๊ฑฐ๋‚˜ ์ข€๋” ์‹ฌ๊ฐํ•œ ๊ฒƒ์„ ์›ํ•œ๋‹ค๋ฉด AppSignal’s ์„ฑ๋Šฅ ์ธก์ • ๋ฐ N+1 ์ฟผ๋ฆฌ ๊ฐ์ง€๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์„ธ์š”. ์ด๋ฅผ ํ†ตํ•ด ๋ฌธ์ œ๊ฐ€ N+1 ์ฟผ๋ฆฌ์—์„œ ๋น„๋กฏ๋˜์—ˆ๋Š”์ง€์— ๋Œ€ํ•œ ํœผ๋ฅญํ•œ ์ง€ํ‘œ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” ๊ทธ ๋ชจ์Šต์ž…๋‹ˆ๋‹ค.

 

์š”์•ฝ

์ด ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ ์‹œ๋ฆฌ์ฆˆ๋ฅผ ์ฝ์–ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. Rails์˜ ํŒจํ„ด๊ณผ ์•ˆํ‹ฐ ํŒจํ„ด์„ ์†Œ๊ฐœํ•˜๋Š” ๊ฒƒ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜์—ฌ ์ผ๋ฐ˜์ ์ธ ๋ฌธ์ œ์— ๋Œ€ํ•œ ๋งˆ์ง€๋ง‰ ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ์— ์ด๋ฅด์ง€๊นŒ์ง€ Rails MVC ํŒจํ„ด ๋‚ด๋ถ€์—์„œ ํŒจํ„ด์ด ๋ฌด์—‡์ธ์ง€ ์‚ดํŽด๋ณด๋Š” ์ด ํฅ๋ฏธ๋กœ์šด ์—ฌ์ •์— ํ•จ๊ป˜ ํ•ด์ฃผ์…”์„œ ๊ธฐ์ฉ๋‹ˆ๋‹ค.

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

์ด ์„ธ์ƒ(ํŠนํžˆ ์†Œํ”„ํŠธ์›จ์–ด ๊ณตํ•™)์€ ์ด์ƒ์ ์ด์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ˜๋“œ์‹œ ํŒจํ„ด๊ณผ ์•ˆํ‹ฐํŒจํ„ด์„ ๋ชจ๋‘ ๋งŒ๋‚˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๊ณ  ๊ฑฑ์ •ํ•  ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค.

ํŒจํ„ด๊ณผ ์•ˆํ‹ฐ ํŒจํ„ด์„ ๋งˆ์Šคํ„ฐํ•˜๋ฉด ํœผ๋ฅญํ•œ ์†Œํ”„ํŠธ์›จ์–ด ์—”์ง€๋‹ˆ์–ด๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํ™˜๋ฒฝํ•œ ํ•ด๊ฒฐ์ฑ…์€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฌํ•œ ํŒจํ„ด๊ณผ ํ‹€์„ ๊นจ์•ผ ํ•  ๋•Œ๋ฅผ ์•„๋Š” ๊ฒƒ์ด ์—ฌ๋Ÿฌ๋ถ„์„ ๋”์šฑ ํœผ๋ฅญํ•˜๊ฒŒ ๋งŒ๋“ค์–ด ์ค„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฐธ์—ฌํ•ด์ฃผ์‹œ๊ณ , ์ฝ์–ด์ฃผ์…”์„œ ๋‹ค์‹œ ํ•œ๋ฒˆ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๋‹ค์ŒํŽธ์—์„œ ๋˜ ๋งŒ๋‚˜์š”!

PS. Ruby Magic ๊ฒŒ์‹œ๋ฌผ์ด ๋ณด๋„๋˜๋Š” ๋Œ€๋กœ ์ฝ๊ณ  ์‹ถ์œผ์‹œ๋ฉด Ruby Magic ๋‰ด์Šค๋ ˆํ„ฐ๋ฅผ ๊ตฌ๋…ํ•˜์‹œ๊ณ  ๋‹จ ํ•˜๋‚˜์˜ ๊ฒŒ์‹œ๋ฌผ๋„ ๋†“์น˜์ง€ ๋งˆ์„ธ์š”!

728x90
728x90