2021-01-23(Sat)

ํ•ญ๋ชฉ

๋‚ด์šฉ

ํ•™์Šต ๋‚ ์งœ

2021-01-23(ํ† )

ํ•™์Šต ์‹œ๊ฐ„

10:00~24:00

ํ•™์Šต ๋ฒ”์œ„ ๋ฐ ์ฃผ์ œ

Backbone, Swagger

ํ•™์Šต ๋ชฉํ‘œ

Backbone์˜ View ๊ด€๋ฆฌ ํ…Œํฌ๋‹‰์„ ํ™•์ธํ•œ๋‹ค. Swagger ์‚ฌ์šฉ๋ฒ•์„ ์ตํ˜€๋ณธ๋‹ค.

๋™๋ฃŒ ํ•™์Šต ๋ฐฉ๋ฒ•

eunhkim๋‹˜๊ณผ ์•„ํ‹ฐํด์„ ๊ณต์œ ํ•˜๊ณ , ํŒ€ ํ”„๋กœ์ ํŠธ์— ์ ์šฉ์‹œ ์ฒ˜๋ฆฌํ•ด์•ผํ•  ์ด์Šˆ๋“ค์— ๋Œ€ํ•ด ์–˜๊ธฐ๋‚˜๋ˆด๋‹ค.

์ƒ์„ธ ํ•™์Šต ๋‚ด์šฉ

๋ฐฑ๋ณธ์„ ๋‹ค๋ฃฐ ๋•Œ ํ•˜๊ธฐ ์‰ฌ์šด 8๊ฐ€์ง€ ์‹ค์ˆ˜์™€ Rendering Views in Backbone.js Isn't Always Simple ์•„ํ‹ฐํด, ๊ทธ๋ฆฌ๊ณ  Assigning backbone subviews mad even cleaner๋ฅผ ์ฝ์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์™œ ์ด๋ฒคํŠธ ์œ„์ž„์„ ํ•ด์•ผํ•˜๋Š”๊ฐ€?๋ฅผ ์ฝ์—ˆ๋‹ค.

๋ฐฑ๋ณธ์„ ๋‹ค๋ฃฐ ๋•Œ ํ•˜๊ธฐ ์‰ฌ์šด 8๊ฐ€์ง€ ์‹ค์ˆ˜

์‹ค์ˆ˜1) ๋ฐฑ๋ณธ ์ž์ฒด์˜ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด์ง€ ์•Š๋Š”๋‹ค.

์ƒ๊ฐ๋ณด๋‹ค ์˜์กด์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” underscore ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž์ฒด์˜ ๊ธฐ๋Šฅ์ด ํ›Œ๋ฅญํ•˜๋‹ค. ๋ฐฑ๋ณธ์˜ ์†Œ์Šค์ฝ”๋“œ๋Š” ์ปคํ”ผ ํ•œ ์ž” ํ•˜๋ฉฐ ๋ณผ ์ˆ˜ ์žˆ์„๋งŒํผ ๊ฐ„๋‹จํ•˜๋‹ค. ์ดˆ๋ณด ์ฝ”๋”๋“ค์€ ์ด๋Ÿฐ ์ž˜ ์ž‘์„ฑ๋œ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด์„œ ๋ฐฐ์šธ ์ˆ˜ ์žˆ๋‹ค.

์‹ค์ˆ˜2) ์ด๋ฒคํŠธ์— ์ง์ ‘ ๋ฐ˜์‘ํ•ด์„œ ๋ทฐ์—์„œ DOM ์š”์†Œ๋ฅผ ์ง์ ‘ ๋ณ€๊ฒฝ์‹œํ‚จ๋‹ค.

๊ฐ€๋ น ์•„๋ž˜ ์ฒ˜๋Ÿผ ์ฝ”๋”ฉํ•  ์ˆ˜ ์žˆ๋‹ค.

var AudioPlayerControls = Backbone.View.extend({
  events: {
    โ€˜click .btn-play, .btn-pauseโ€™: function(event) {
      $(event.target).toggleClass(โ€˜btn-play btn-pauseโ€™)
    }
  },
  // ...
})

์ด ๊ฒฝ์šฐ DOM ์š”์†Œ์˜ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ์ถ”์ ํ•˜๋Š”๋ฐ ๋ณต์žก๋„๊ฐ€ ์ฆ๊ฐ€ํ•œ๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด๋‹ค.

๋ทฐ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ๋Š” ๋ชจ๋ธ์„ ๋ณ€๊ฒฝ์‹œํ‚ค๊ณ , ๋ทฐ๋Š” ๋ชจ๋ธ์˜ ๋ณ€๊ฒฝ์— ๋ฐ˜์‘ํ•˜๋„๋ก ํ•˜์ž. ์•„๋ž˜์ฒ˜๋Ÿผ!

var AudioPlayerControls = Backbone.View.extend({
  events: {
    โ€˜click .btn-play, .btn-pauseโ€™: function(event) {
      this.model.set(โ€˜playingโ€™, !this.model.get(โ€˜playingโ€™))
    }
  },
  initialize: function() {
    this.listenTo(this.model, โ€˜changeโ€™, this.render)
    this.render()
  },
  // ...
})

์ด๋ฅผ ํ†ตํ•ด ํ˜„์žฌ ์ด๋ฒคํŠธ ์ƒํƒœ๋ฅผ ์ถ”์ ํ•  ์ˆ˜ ์žˆ๊ณ , DOM ์š”์†Œ๋ฅผ ๊ตฌ์กฐ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค. ์• ์ดˆ์— ๋ฐฑ๋ณธ์˜ ์„ค๊ณ„๋Š” ์ด๋ฒคํŠธ์— ์˜ํ•ด ๋ณต์žกํ•œ DOM ๊ฐ์ฒด๊ฐ€ ์ง์ ‘ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์„ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๊ณ ์•ˆ๋œ ์ธก๋ฉด์ด ํฌ๋‹ค. ๐Ÿ˜บ

์‹ค์ˆ˜3) ๋ Œ๋”๋ง ๋น„์šฉ์„ ๊ณผ์†Œํ‰๊ฐ€ํ•œ๋‹ค.

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

var AudioPlayerPlaylist = Backbone.View.extend({
  template: _.template(โ€˜<ul> <% _.each(musics, function(m) { %> <li><%- m.title %></li> <% }) %> </ul>โ€™),
  initialize: function() {
    this.listenTo(this.collection, โ€˜addโ€™, this.render)
  },
  // ...
})

๋งค add ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ๋ Œ๋”๋ง์ด ๋˜๋Š” ๊ตฌ์กฐ์ด๋‹ค. ๊ทธ๋Ÿผ ๋ชจ๋ธ๋„ ๋งค add ์ด๋ฒคํŠธ๋งˆ๋‹ค ์ถ”๊ฐ€๋˜๊ฒŒ๋˜๊ณ , ๋ชจ๋ธ์ด ๋น„๋Œ€ํ•ด์ง€๋ฉฐ ์ƒ๊ธฐ๋Š” ์„ฑ๋Šฅ ์ €ํ•˜๋Š” ์œ ์ € ๊ฒฝํ—˜์„ ํ•ด์น  ์ˆ˜ ์žˆ๋‹ค. ์Œ.. ์ด๋Ÿฐ ๊ตฌ์กฐ๋ณด๋‹ค๋Š” ์•„๋ž˜์ฒ˜๋Ÿผ ๋ฐฐ์น˜ ๋‹จ์œ„๋กœ ๋ Œ๋”๋งํ•˜๊ฒŒ ์ˆ˜์ •ํ•ด๋ณด์ž.

this.listenTo(this.collection, โ€˜addโ€™, _.debounce(_.bind(this.render), 128))

์—ฌ์ „ํžˆ add ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ํšŸ์ˆ˜๋งŒํผ model์ด ์ƒ์„ฑ๋˜๋Š”๊ฑด ๋งˆ์ฐฌ๊ฐ€์ง€์ด์ง€๋งŒ, underscore.js ์˜ _.debounce ๋ฉ”์„œ๋“œ ๋•์— ๋งˆ์ง€๋ง‰ add ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  ๋‚˜์„œ 128 milliseconds๋งŒํผ ๊ธฐ๋‹ค๋ฆฐ ํ›„ ํ•œ๊บผ๋ฒˆ์— ๋ Œ๋”๋งํ•  ๊ฒƒ์ด๋‹ค. ๋ฌผ๋ก  ์ด๋Ÿฐ ๋ฐฉ๋ฒ• ๋ง๊ณ ๋„ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•์€ ๋งŽ์„ ๊ฒƒ์ด๋‹ค.

์‹ค์ˆ˜4) ์“ฐ๊ณ ๋‚œ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋“ค์„ ๋‚จ๊ฒจ๋‘”๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ํ”ํžˆ ํ•˜๋“ฏ on() ๋ฉ”์„œ๋“œ๋กœ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ”์ธ๋“œํ•˜๋ฉด off() ๋ฉ”์„œ๋“œ๋กœ ์–ธ๋ฐ”์ธ๋“œํ•˜์ง€ ์•Š์€ ์ƒํƒœ์—์„œ ์ฐธ์กฐ๋ฅผ ์žƒ์œผ๋ฉด ๋ฉ”๋ชจ๋ฆฌ๋ฆญ์˜ ์›์ธ์ด ๋œ๋‹ค. Backbone์ด ์ œ๊ณตํ•˜๋Š” listenTo() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ž. ๊ทธ๋Ÿผ remove() ๋ฉ”์„œ๋“œ๋ฅผ ๋ชจ๋ธ์— ์ ์šฉํ•˜๋ฉด ์•Œ์•„์„œ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋„ ์ œ๊ณต๋œ๋‹ค.

์‹ค์ˆ˜ 5) ๋‹จ์ผ ๋ทฐ ์ž‘์„ฑ

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

์‹ค์ˆ˜ 6) ๋ฐฑ๋ณธ์„ Non-RESTful APIs ์—๋„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๊ฐ„๊ณผํ•œ๋‹ค.

๋ฐฑ๋ณธ์—์„œ ํ”„๋ก ํŠธ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ๋ฅผ ์—ฐ๊ฒฐ์‹œ์ผœ์ฃผ๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” Sync๋‹ค. ์ด ์ปดํฌ๋„ŒํŠธ๋Š” ์˜ค๋ฒ„๋ผ์ด๋“œํ•  ์ˆ˜ ์žˆ๋Š” ๋งŽ์€ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๋ฐฑ์—”๋“œ ๋Œ€์‹  localStorage์™€ ์—ฐ๊ฒฐ์‹œํ‚ค๋Š” ์‹์œผ๋กœ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๋ฉด localStorage์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

์‹ค์ˆ˜ 7) ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋ธ ๋Œ€์‹  ๋ทฐ์— ์ €์žฅํ•œ๋‹ค.

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

์ด๋ ‡๊ฒŒ ์…‹ํŒ…ํ•˜์ง€ ์•Š์œผ๋ฉด? ์‹ค์ˆ˜๊ฐ€ ์ƒ๊ธฐ๊ธฐ ์‰ฝ๋‹ค.

์‹ค์ˆ˜ 8) ์ด๋ฒคํŠธ ์œ„์ž„ ๋Œ€์‹  jQuery์˜ .On() ๋ฉ”์†Œ๋“œ๋ฅผ ์“ด๋‹ค.

๋ฐฑ๋ณธ์—์„œ ์ž์ฒด์ ์œผ๋กœ DOM ์ด๋ฒคํŠธ๋ฅผ ํ•ธ๋“ค๋งํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์“ฐ๋Š” ๊ฒƒ์ด ์“ฐ์ง€ ์•Š๋Š” ๊ฒƒ๋ณด๋‹ค ์ด์ ์ด ๋งŽ๋‹ค. ๊ฐ€๋ น jQuery์˜ .On() ๋ฉ”์„œ๋“œ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์ด๋ฒคํŠธ๋ฅผ ๋ฐ”์ธ๋”ฉํ•˜๋Š”๊ฒŒ ์‰ฝ๊ฒŒ ๋Š๊ปด์งˆ ์ˆ˜ ์žˆ์ง€๋งŒ ์žฅ๊ธฐ์ ์œผ๋กœ ๋ณด๋ฉด ๋ฒˆ๊ฑฐ๋กœ์›Œ์ง€๊ธฐ ์‰ฝ๋‹ค. ํ•ด๋‹น ์š”์†Œ๊ฐ€ DOM ์š”์†Œ๋กœ๋ถ€ํ„ฐ detach ๋˜๋ฉด jQuery๋Š” ์ž๋™์ ์œผ๋กœ ๋ชจ๋“  ์ด๋ฒคํŠธ ํ•ธ๋“ค๋ง์„ ๊บผ๋ฒ„๋ฆฐ๋‹ค. ์ด ๋œป์€ DOM ์š”์†Œ๊ฐ€ detach๋˜์—ˆ๋‹ค๊ฐ€ reattach๋  ๋•Œ๋งˆ๋‹ค ์ด๋ฒคํŠธ ๋ฐ”์ธ๋”ฉ์„ ์ƒˆ๋กœ ํ•ด์ค˜์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋œปํ•œ๋‹ค. ๋ฐ˜๋ฉด ๋ฐฑ๋ณธ์€ ์ด๋ฒคํŠธ๋ฅผ ๋ทฐ์˜ root ์š”์†Œ๋ฅผ ํ†ตํ•ด ๋ฐ”์ธ๋“œํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ทฐ์˜ DOM ์ž์‹ ์š”์†Œ๋“ค์ด ๋ณ€๊ฒฝ๋˜์–ด๋„ ์ƒˆ๋กœ ๋ฐ”์ธ๋”ฉํ•ด์ค„ ํ•„์š”๊ฐ€ ์—†๋‹ค.

Rendering Views in Backbone.js Isnโ€™t Always Simple

todo ๋กœ๋Š” ์‹ค์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ ์“ธ ์ˆ˜ ์žˆ์„๋งŒํผ ๊นŠ์ด์žˆ๊ฒŒ ๋ทฐ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ๊ตฌ์กฐ๋ฅผ ์•Œ๋ ค์ฃผ์ง€ ์•Š๋Š”๋‹ค. ์•„๋ž˜ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๋„๋ก ๋ทฐ๋ฅผ ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ์—ˆ๋‹ค.

  • ๋ Œ๋”๋ง์€ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ์—†์ด ์—ฌ๋Ÿฌ๋ฒˆ ๋ฐ˜๋ณต ๊ฐ€๋Šฅํ•ด์•ผํ•œ๋‹ค.

  • DOM์˜ ์ˆœ์„œ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ ํ…œํ”Œ๋ฆฟ์— ์„ ์–ธ๋˜์–ด์•ผ ํ•œ๋‹ค.

  • ๋ Œ๋” ํ•จ์ˆ˜๋ฅผ ๋ฐ˜๋ณตํ•ด์„œ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ๋„ ๋ทฐ์˜ ์ƒํƒœ๊ฐ€ ์œ ์ง€ํ•ด์•ผํ•œ๋‹ค.

  • ๋ Œ๋”๋ง์„ ๋‘ ๋ฒˆ ํ–ˆ์„ ๋•Œ ์“ธ๋ฐ ์—†์ด ์„œ๋ธŒ๋ทฐ๊ฐ€ ์ƒ์„ฑ๋˜๋ฉฐ ์„ฑ๋Šฅ์ด ๋‚ญ๋น„๋˜์ง€ ์•Š์•„์•ผํ•œ๋‹ค.

๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ์ฝ”๋“œ ์˜ˆ์‹œ

์œ„ ์š”๊ตฌ์‚ฌํ•ญ์„ ์ถฉ์กฑ์‹œํ‚ค์ง€ ๋ชปํ•˜๋Š” ์˜ˆ์‹œ๋“ค์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  1. ํ…œํ”Œ๋ฆฟ์„ ๋ Œ๋”๋งํ•  ๋•Œ jQuery์˜ html() ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด์„œ ๋ Œ๋”๋งํ•œ๋‹ค.

    render : function () {
        this.$el.html(this.template(options));
        return this;
    }

    ์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•˜๋ฉด ์„œ๋ธŒ๋ทฐ๊ฐ€ ์—†์„ ๋•Œ๋Š” ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ ์„œ๋ธŒ๋ทฐ๋ฅผ ์ž‘์„ฑํ•  ๊ฒฝ์šฐ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค. html() ๋ฉ”์„œ๋“œ๊ฐ€ empty() ๋ฉ”์„œ๋“œ๋ฅผ ๋จผ์ € ํ˜ธ์ถœํ•ด์„œ jQuery ์ด๋ฒคํŠธ๋ฅผ ๋ชจ๋‘ unbind ํ•ด๋ฒ„๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์˜๋„์น˜์•Š๊ฒŒ this.events์— ์ •์˜๋œ ์ด๋ฒคํŠธ๋“ค์ด ๋ชจ๋‘ ์‚ฌ๋ผ์ ธ๋ฒ„๋ฆด ์ˆ˜ ์žˆ๋‹ค.

  2. ํ…œํ”Œ๋ฆฟ์„ ์“ฐ์ง€ ์•Š๋Š”๋‹ค.

    render : function () {
        this.$el.append(this.subview.render().$el);
        this.$el.append(this.anotherSubview.render().$el);
        return this;
    }

    ์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•˜๋ฉด DOM ๊ตฌ์กฐ๊ฐ€ ๋ Œ๋”๋ง ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ˆœ์„œ์— ์˜์กด์ ์ด๊ฒŒ ๋œ๋‹ค. ๊ฒฐ๊ตญ ํ”„๋กœ์ ํŠธ๊ฐ€ ์ปค์ง€๋ฉด ์ปค์งˆ ์ˆ˜๋ก DOM ๊ตฌ์กฐ ๊ด€๋ฆฌ๊ฐ€ ๋งค์šฐ ์–ด๋ ค์›Œ์ง„๋‹ค. ํ  ๊ฒฐ๊ตญ html() ๋ฉ”์„œ๋“œ๋ฅผ ์จ์•ผํ•œ๋‹ค๋Š” ๊ฑด๋ฐ.. ํ˜ผ๋ž€์Šค๋Ÿฝ์ง€ ์•Š์€๊ฐ€? ์ด๊ฑธ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์ด ์žˆ๊ธดํ•œ๋ฐ, ํ”ํžˆ๋“ค..

  3. ...์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋„ˆ๋ฌด ํฐ ๋ฐฉ๋ฒ•์„ ์“ด๋‹ค.

    render : function () {
        this.$el.$html(this.template());
    โ€‹
        this.subview        = new Subview();
        this.anotherSubview = new AnotherSubview();
    โ€‹
        this.$el.append(this.subview.render().$el);
        this.$el.append(this.anotherSubview.render().$el);
    โ€‹
        return this;
    }

    ๊ฒฐ๊ตญ render ํ•จ์ˆ˜๊ฐ€ ์ฝœ๋  ๋•Œ๋งˆ๋‹ค render ํ•จ์ˆ˜ ์•ˆ์—์„œ ์„œ๋ธŒ๋ทฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์„ ์“ฐ๊ณคํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ด ๊ฒฝ์šฐ render ํ•จ์ˆ˜๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์€ ์ผ์„ ์‹œํ‚ค๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋ƒฅ DOM ์ด๋ฒคํŠธ ํ•˜๋‚˜๋ฅผ rebindํ•˜๋ ค๊ณ  ํ•  ๋•Œ๋„ ์„œ๋ธŒ๋ทฐ๋ฅผ ํ•˜๋‚˜ํ•˜๋‚˜ ์ƒ์„ฑํ•ด์ค˜์•ผํ•  ์ˆ˜๋„ ์žˆ๋‹ค..

๊ทธ๋ž˜์„œ ํ•ด๊ฒฐ์ฑ…์€?

์‚ฌ์‹ค ํ•ด๊ฒฐ์ฑ…์€ ๊ฐ„๋‹จํ•˜๋‹ค. ๊ทธ๋ƒฅ html()๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ์„œ๋ธŒ๋ทฐ์˜ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ”์ธ๋“œํ•˜๊ธฐ ์œ„ํ•ด delegateEvents๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด delegateEvents๋Š” ๋ฐฑ๋ณธ์˜ setElement ํ•จ์ˆ˜์— ํฌํ•จ๋˜์–ด์žˆ์œผ๋‹ˆ ๊ทธ๋ƒฅ setElement ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์ž. ์•„๋ž˜์ฒ˜๋Ÿผ!

render : function () {
    this.$el.$html(this.template());
โ€‹
    this.subview.setElement(this.$('.subview')).render();
    this.anotherSubview.setElement(this.$('.another-subview')).render();
    return this;
}

๊ทธ๋Ÿฌ๋‚˜ ์ด๋Š” ๋„ˆ๋ฌด ๊ธธ๊ณ  ํŒŒ์‹ฑํ•˜๊ธฐ๋„ ์–ด๋ ต๋‹ค. ๊ทธ๋ž˜์„œ ์•„๋ž˜์ฒ˜๋Ÿผ ๋ฒ ์ด์Šค๋ทฐ์— assign์ด๋ผ๋Š” helper ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค๋ฉด ํ•œ๊ฒฐ ๊น”๋”ํ•ด์ง„๋‹ค.

render : function () {
    this.$el.html(this.template());
โ€‹
    this.assign(this.subview,        '.subview');
    this.assign(this.anotherSubview, '.another-subview');
    return this;
}

assign์€ ์•„๋ž˜์ฒ˜๋Ÿผ ์ •์˜๋œ๋‹ค.

assign : function (view, selector) {
    view.setElement(this.$(selector)).render();
}

์ž, ์ด์ œ ์ฒ˜์Œ ์š”๊ตฌ์‚ฌํ•ญ์ด ๋ชจ๋‘ ํ•ด์†Œ๋˜์—ˆ๋‹ค.

  • ๋ Œ๋”๋ง์€ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ์—†์ด ์—ฌ๋Ÿฌ๋ฒˆ ๋ฐ˜๋ณต ๊ฐ€๋Šฅํ•ด์•ผํ•œ๋‹ค.

    • setElement๋Š” DOM ์ด๋ฒคํŠธ๋ฅผ re-delegate ํ•˜๋ฏ€๋กœ ๋” ์ด์ƒ jQuery์˜ html( ๋ฉ”์„œ๋“œ๊ฐ€ ์„œ๋ธŒ๋ทฐ์˜ ์ด๋ฒคํŠธ๋ฅผ ๋‚ ๋ ค๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์„ ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†์–ด์ง„๋‹ค.

  • DOM์˜ ์ˆœ์„œ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ ํ…œํ”Œ๋ฆฟ์— ์„ ์–ธ๋˜์–ด์•ผ ํ•œ๋‹ค.

    • ใ…‡ใ…‡

  • ๋ Œ๋” ํ•จ์ˆ˜๋ฅผ ๋ฐ˜๋ณตํ•ด์„œ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ๋„ ๋ทฐ์˜ ์ƒํƒœ๊ฐ€ ์œ ์ง€ํ•ด์•ผํ•œ๋‹ค.

    • ๋ทฐ๊ฐ€ render ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ๋‹ค์‹œ ์ดˆ๊ธฐํ™”๋˜์ง„ ์•Š์œผ๋ฏ€๋กœ ๋ทฐ์˜ ์ƒํƒœ๊ฐ€ ์œ ์ง€๋œ๋‹ค.

  • ๋ Œ๋”๋ง์„ ๋‘ ๋ฒˆ ํ–ˆ์„ ๋•Œ ์“ธ๋ฐ ์—†์ด ๋˜‘๊ฐ™์€ ๋ Œ๋”๋งํ•˜๋Š” ๋‚ญ๋น„๊ฐ€ ์—†์–ด์•ผํ•œ๋‹ค.

    • ์ด ๋ฐฉ์‹๋Œ€๋กœ๋ผ๋ฉด render ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ์“ธ๋ฐ ์—†์ด ์„œ๋ธŒ๋ทฐ์˜ ์ƒ์„ฑ์ž ์ฝ”๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ผ์„ ์˜ˆ๋ฐฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Assigning Backbone Subviews Made Even Cleaner

์‹ฌ์ง€์–ด ์œ„์— ์ ์—ˆ๋˜ ๊ฒƒ์„ ์•„๋ž˜์ฒ˜๋Ÿผ ๊ฐ„์†Œํ™”์‹œํ‚ฌ ์ˆ˜๋„ ์žˆ๋‹ค.

render : function () {
    this.$el.html(this.template());
โ€‹
    this.assign({
        '.subview'             : this.subview,
        '.another-subview'     : this.anotherSubview,
        '.yet-another-subview' : this.yetAnotherSubview
    });
โ€‹
    return this;
}

๋‚ด๋ถ€ ๊ตฌํ˜„์€ ์•„๋ž˜์ฒ˜๋Ÿผ ๋˜์–ด์žˆ๋‹ค.

assign : function (selector, view) {
    var selectors;
โ€‹
    if (_.isObject(selector)) {
        selectors = selector;
    } else {
        selectors = {};
        selectors[selector] = view;
    }
โ€‹
    if (!selectors) return;
    _.each(selectors, function (view, selector) {
        view.setElement(this.$(selector)).render();
    }, this);
}

์€ํœผ๋‹˜๊ณผ์˜ ํƒ๊ตฌ ๊ฒฐ๊ณผ

  1. DOM ์š”์†Œ ๊ด€๋ จ ์ด๋ฒคํŠธ๋Š” setElement๋กœ ์œ„์ž„์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

  2. ์˜ฌ๋“œ DOM ์š”์†Œ์— ๋‹ด๊ฒผ๋˜ ์ด๋ฒคํŠธ๋Š” ์–ด๋–ป๊ฒŒ ๋˜๋Š”๊ฐ€? ์†Œ์Šค์ฝ”๋“œ๋ฅผ ๋ณด์ž! https://backbonejs.org/docs/backbone.html - listenTo ์ฒ˜๋Ÿผ ๋ชจ๋ธ์˜ ์ด๋ฒคํŠธ์— ๋ฐ”์ธ๋”ฉํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ๋“ค์€, ๋ทฐ ๊ฐ์ฒด๊ฐ€ ์‚ญ์ œ๋˜๊ธฐ ์ „๊นŒ์ง€๋Š” ๊ทธ๋Œ€๋กœ ๋‚จ์•„์žˆ๊ณ , ๊ทธ๋ž˜๋„ ๋ฌด๋ฐฉํ•˜๋ฏ€๋กœ ์ด ๊ฒฝ์šฐ์—” ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

    DOM ์š”์†Œ๋ฅผ jQuery์˜ html ๋ฉ”์„œ๋“œ๋กœ ๋ฐ”๊ฟ”๋ผ์šฐ๋ฉด empty() ํ•จ์ˆ˜๋ฅผ ์„ ํ–‰ํ˜ธ์ถœํ•˜๋ฏ€๋กœ, DOM ์š”์†Œ์— ์œ„์ž„๋œ ์ด๋ฒคํŠธ๋“ค์€ ํ™•์‹คํžˆ ์‚ญ์ œ๋œ๋‹ค. ํ•˜์ง€๋งŒ ์œ„์ž„๋˜์ง€ ์•Š์€ ์ด๋ฒคํŠธ๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ, ์‚ญ์ œ๋˜๋Š” ๊ฒƒ์ด ๋ณด์žฅ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ด๋Š” ์ œ๊ฑฐํ•˜๊ณ  html ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์•ผํ•œ๋‹ค.

  3. stopListening์„ ํ•  ๊ฒƒ์ธ๊ฐ€ ๋ง ๊ฒƒ์ธ๊ฐ€?

    el ์˜ต์…˜์œผ๋กœ ๊ธฐ์กด DOM ์š”์†Œ๋ฅผ ์ง€์ •ํ•˜๊ณ  ๋‚ด์šฉ์„ ๋ Œ๋”๋งํ•˜๋Š” ๋ทฐ์ด๋ƒ์— ๋”ฐ๋ผ์„œ ์ทจ๊ธ‰ ๋ฐฉ์‹์ด ๋‹ฌ๋ผ์ ธ์•ผ ํ•œ๋‹ค๋Š” ๊ฐ€์„ค๋กœ 1์ฐจ์ ์ธ ๋งค๋“ญ์„ ์ง€์—ˆ๋‹ค. ์ด๋ฒคํŠธ๋ผ๋Š” ๊ฒƒ์ด ํŠน์ •ํ•œ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ฌถ์ด๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—, ์„œ๋ธŒ ๋ทฐ๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š” ์Šˆํผ ๋ทฐ๊ฐ€ ํ…œํ”Œ๋ฆฟ์œผ๋กœ ์ƒˆ๋กญ๊ฒŒ ๊ตฌ์„ฑ๋œ๋‹ค๋ฉด ์„œ๋ธŒ ๋ทฐ๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ๊ฑธ์—ˆ๋˜ ๊ธฐ์กด DOM ์š”์†Œ๊ฐ€ ์‚ฌ๋ผ์ง€๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ. ๊ทธ๋ž˜์„œ ์„œ๋ธŒ ๋ทฐ์—์„œ el ์˜ต์…˜์„ ์‚ฌ์šฉํ–ˆ๋‹ค๋ฉด setElement ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ ์„œ๋ธŒ ๋ทฐ์˜ el์„ ๊ฐฑ์‹ ํ•ด์ฃผ์–ด์•ผ ํ•˜๊ณ , el ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด ์ƒˆ๋กœ ์ƒ์„ฑํ•œ ๋ฌธ์„œ์˜ ์ง€์ • ์˜์—ญ์— superView.selector.html(subView.render().$el)๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋ฐ”๋กœ ์‚ฝ์ž…ํ•˜๋ฉด ๋˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

ํ•™์Šต ๋‚ด์šฉ์— ๋Œ€ํ•œ ๊ฐœ์ธ์ ์ธ ์ดํ‰

๋ฐฑ๋ณธ์„ ๊ณต์‹๋ฌธ์„œ์™€ ์ฑ…์œผ๋กœ๋งŒ ํ•™์Šตํ–ˆ์„ ๋•Œ๋Š” ๋– ์˜ฌ๋ฆฌ์ง€ ๋ชปํ–ˆ๋˜ ์˜๋ฌธ๋“ค์ด ๋งŽ์•˜๋‹ค.

  1. ๋ฐฑ๋ณธ์˜ ๋ทฐ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ํŒจํ„ด์˜ ๋ฒ ์ŠคํŠธํ”Œ๋ž™ํ‹ฐ์Šค๋Š” ๋ฌด์—‡์ผ๊นŒ?

  2. SPA๋ฅผ ๊ตฌ์„ฑํ•  ๋•Œ ๋‹ค๋ฅธ ๋ทฐ๋กœ ์ „ํ™˜์‹œ ๊ธฐ์กด์— ์ƒ์„ฑํ•ด๋‘” ๋ทฐ ์ธ์Šคํ„ด์Šค๋Š” ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•ด์•ผํ•˜๋Š”๊ฐ€?

    1. SubView

    2. SubView์˜ ParentView

์ด๋Ÿฐ ์˜๋ฌธ์„ ํ’€๊ธฐ ์œ„ํ•ด ์ž๋ฃŒ๋ฅผ ์ฐพ๋Š” ์ค‘ ์€ํœผ๋‹˜ ๋•์— ์ข‹์€ ์•„ํ‹ฐํด์„ ์ฐพ์•„ ์ฝ์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์—ญ์‹œ ํ”„๋กœ์ ํŠธ๋ฅผ ํ•ด๋ด์•ผ ์ข‹์€ ์งˆ๋ฌธ์ด ์ƒ๊ธฐ๊ณ  ์งˆ ์ข‹์€ ์„ฑ์žฅ์œผ๋กœ ์ด์–ด์ง€๊ธฐ ์‰ฝ๋‹ค.

๋‹ค์Œ ํ•™์Šต ๊ณ„ํš

  • RESTful API

  • ํ˜‘์—… ๊ทœ์น™ ๋“ฑ ๊ด€๋ฆฌํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ํˆด ์ •ํ•ด๋ณด๊ธฐ

Last updated