Pixi.js: ํ™œ์„ฑ WebGL ์ปจํ…์ŠคํŠธ๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์Šต๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2015๋…„ 12์›” 11์ผ  ยท  29์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: pixijs/pixi.js

๋‚˜๋Š” pixi.js, three.js ๋“ฑ์˜ ์—ฌ๋Ÿฌ ๊ฐœ๋ณ„ ์‹คํ—˜์„ ๋กœ๋“œํ•˜๋Š” React์™€ ํ†ตํ•ฉ๋œ ์•ฑ์„ ๋งŒ๋“ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. iframe์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹คํ—˜์„ ๋กœ๋“œํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์Šค์Šค๋กœ ์ •๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ƒˆ๋กœ์šด ์‹คํ—˜์— ๋Œ€ํ•œ ํƒ์ƒ‰์ด ์žˆ์„ ๋•Œ๋งˆ๋‹ค ๋ Œ๋”๋Ÿฌ๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๊ณ  ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ ํŒŒ๊ดดํ•ฉ๋‹ˆ๋‹ค.

๋”๋ฏธ ์ฝ”๋“œ

if renderer
    renderer.destroy(true);
    renderer = null

renderer = new PIXI.autoDetectRenderer ......

๋‚ด webgl ๋ Œ๋”๋Ÿฌ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฒญ์†Œํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ ๊ฐ™์ง€๋งŒ 16ํŽ˜์ด์ง€๊ฐ€ ๋กœ๋“œ๋œ ํ›„ WARNING: Too many active WebGL contexts. Oldest context will be lost. ๊ฒฝ๊ณ ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ๊ฒฝ๊ณ ๋งŒ ํ‘œ์‹œ๋˜๋ฏ€๋กœ ๋ฐ์Šคํฌํƒ‘์—์„œ๋Š” ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์ง€๋งŒ ipad์—์„œ๋Š” ์ถฉ๋Œํ•ฉ๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ €์™€ ๋ฉ”์‹œ์ง€๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค: X A problem occurred with this web page, so it was reloaded. .

๋‚˜๋Š” threejs์™€ ๊ทธ๋“ค์ด ์ด์— ๋Œ€ํ•œ ์†”๋ฃจ์…˜์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„๋ณด๊ณ  ์žˆ์—ˆ๊ณ  ๋‹ค์Œ ์ฝ”๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์–ด๋ฆฌ์„์€ ์ง“์„ ํ•˜๊ณ  ์žˆ๋Š” ๊ฑธ๊นŒ?

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์ข‹์€ ํ•ด๊ฒฐ์ฑ…์„ ์ฐพ์€ ๊ฒƒ ๊ฐ™์•„์š”. ์ด๋ฅผ ํ†ตํ•ด ์„œ๋กœ์— ๋Œ€ํ•ด ์•Œ ํ•„์š”๊ฐ€ ์—†๊ณ  React๊ฐ€ DOM์„ ์†Œ์œ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์ง€๋„ ์˜ค๋ฒ„๋ ˆ์ด React ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ปจํ…์ŠคํŠธ ์†์‹ค์„ ๊ฐ•์ œํ•˜๊ธฐ ์œ„ํ•ด ์ด ๊ธฐ์ˆ  ์„ ์‚ฌ์šฉ

gl.getExtension('WEBGL_lose_context').loseContext();

์ „์ฒด ์˜ˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

var document = require('global/document');
var PIXI = require('pixi.js');

// I want to keep this canvas / renderer around. For example, this might be a bottom layer PIXI / React map overlay.
var canvas1 = document.createElement('canvas');
document.body.appendChild(canvas1);
createRenderer(0xff0000, canvas1);

function createRenderer(color, canvas) {
  canvas = canvas || document.createElement('canvas');
  var renderer = new PIXI.WebGLRenderer(800, 600, {view: canvas});
  var stage = new PIXI.Container();
  var graphics = new PIXI.Graphics();
  graphics.beginFill(color, 0.5);
  graphics.drawCircle(0, 0, 200);
  graphics.endFill();
  stage.addChild(graphics);
  renderer.render(stage);
  return {renderer: renderer, stage: stage, graphics: graphics};
}

// Simulate frequent adding / removing of lots of PIXI / React map overlays on top.
for (var i = 0; i < 16; i++) {
  var canvas = document.createElement('canvas');
  document.body.appendChild(canvas);
  var scene = createRenderer(0x00ff00, canvas);
  // Uncomment to see that the original canvas isn't removed.
  /* scene.renderer.currentRenderTarget.gl
      .getExtension('WEBGL_lose_context').loseContext(); */
  scene.renderer.destroy();
  scene.stage.removeChild(scene.graphics);
  document.body.removeChild(canvas);
}

PIXI๊ฐ€ ์ž์ฒด "destroy" ๋ฉ”์†Œ๋“œ์— ์ด๊ฒƒ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ• ๊นŒ์š”?

๋ชจ๋“  29 ๋Œ“๊ธ€

@andrevenancio
๋‚˜๋Š” ์›”์š”์ผ์ด๋‚˜ ํ™”์š”์ผ ์ดํ›„๋กœ ๋งŒ ์‚ฌ์šฉํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— Pixi์— ๋Œ€ํ•œ ์ „๋ฌธ๊ฐ€๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ํ•œ ๋ฒˆ์— ํ•˜๋‚˜๋งŒ ์•ก์„ธ์Šคํ•ด์•ผ ํ•œ๋‹ค๋Š” ์•„์ด๋””์–ด๋กœ ๋งŽ์€ ์‹คํ—˜( ์ด์™€ ๊ฐ™์€ )์œผ๋กœ ์ธํ•ด ์—ฌ๋Ÿฌ ๋ Œ๋”๋Ÿฌ์™€ ์บ”๋ฒ„์Šค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๊ธ€๋กœ๋ฒŒ ๋ Œ๋”๋Ÿฌ ๋˜๋Š” ๋‹ค๋ฅธ ๋ Œ๋”๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹คํ—˜์„ ๋ฐฐ์—ด๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ํ‘œ์‹œํ•ด์•ผ ํ•  ๋•Œ ๊ฐ ์‹คํ—˜์˜ ์Šคํ…Œ์ด์ง€๋ฅผ ๋ Œ๋”๋Ÿฌ๋กœ ์ „๋‹ฌํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

var renderer = PIXI.autoDetectRenderer({blah});
var experiments = [];
experiments.push(experiment1);
experiments.push(experiment2);
experiments.push(experiment3);

var currentExperiment = $('#experminetSelector').val();
renderer.render(experiments[currentExperiment]);

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ Œ๋”๋Ÿฌ๋ฅผ ํ•œ ๋ฒˆ๋งŒ ๋งŒ๋“ค๊ณ  ๊ฐ ์‹คํ—˜์˜ ๋‹จ๊ณ„๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์—ฌ๋Ÿฌ ์‹คํ—˜ ํŽ˜์ด์ง€๊ฐ€ ์•„๋‹Œ ํ•œ ํŽ˜์ด์ง€๋งŒ ๋ Œ๋”๋งํ•˜๊ณ  ๋ชจ๋“  ์‹คํ—˜์ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

๋ฉด์ฑ… ์กฐํ•ญ: ์ €๋Š” pixi๋ฅผ ์ฒ˜์Œ ์‚ฌ์šฉํ•˜๊ณ  ์ด๊ฒƒ์„ ์‹œ๋„ํ•˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ ๋งˆ์ผ๋ฆฌ์ง€๊ฐ€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๊ฐœ๋ฐœ์ž๊ฐ€ ์กฐ์‚ฌํ•˜๊ฑฐ๋‚˜ ์ง€์นจ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ์ผ์ข…์˜ ๋ฒ„๊ทธ๋ฅผ ๋ฐœ๊ฒฌํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋“ค๋ฆฝ๋‹ˆ๋‹ค.

๋‹จ์ผ ๋ Œ๋”๋Ÿฌ์™€ ์—ฌ๋Ÿฌ ์žฅ๋ฉด์„ ๊ฐ–๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. 1๊ฐœ์˜ ๋ Œ๋”๋Ÿฌ === 1๊ฐœ์˜ ์บ”๋ฒ„์Šค ์š”์†Œ.

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

๊ฒŒ๋‹ค๊ฐ€.... ์ด๊ฒƒ์€ ํ•ด๊ฒฐ์ฑ… ์ž์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ ๋ฌธ์ œ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค... .destroy() ๋ฉ”์„œ๋“œ๊ฐ€ ์‹ค์ œ๋กœ webgl ์ปจํ…์ŠคํŠธ์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ํŒŒ๊ดดํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด... ์š”์ ์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? :(

์•ผ ์นœ๊ตฌ! ์ปจํ…์ŠคํŠธ๊ฐ€ ํŒŒ๊ดด๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ํŒŒ๊ดด ๊ธฐ๋Šฅ์ด ์ •ํ™•ํžˆ ํ•ด์•ผ ํ•  ์ผ์„ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋ฐ ์ „์ ์œผ๋กœ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. :)

๋‚˜๋Š” ๋ฐฉํ™ฉํ•ฉ๋‹ˆ๋‹ค, ๋‹น์‹ ์€ autodetectRenderer ์žˆ์Šต๋‹ˆ๊นŒ? ๋ธŒ๋ผ์šฐ์ €๊ฐ€ webGL์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๊ฐ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ƒ์„ฑํ•œ ํ…Œ์ŠคํŠธ ์ปจํ…์ŠคํŠธ๊ฐ€ ํŒŒ๊ดด๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€ ์ •๋ณด: webgl ์ปจํ…์ŠคํŠธ๋ฅผ ํŒŒ๊ดดํ•  ์ˆ˜ ์—†์œผ๋ฉฐ ๊ฐ€๋น„์ง€ ์ˆ˜์ง‘๋ฉ๋‹ˆ๋‹ค(๋ญ”๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ํ•œ?)

๋‚˜๋Š” ์šฐ๋ฆฌ๊ฐ€ ๋ณด์œ ํ•˜๊ณ  ์žˆ๋Š” ์ฐธ์กฐ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ์„ ํƒ์ ์œผ๋กœ ์บ”๋ฒ„์Šค ์š”์†Œ(์ปจํ…์ŠคํŠธ ์ •๋ฆฌ์— ํ•„์š”ํ•จ)๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ์ •๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์€ ๋ธŒ๋ผ์šฐ์ €์— ๋‹ฌ๋ ค ์žˆ์Šต๋‹ˆ๋‹ค. ์ปจํ…์ŠคํŠธ๊ฐ€ ๋ˆ„์ถœ๋˜๊ฑฐ๋‚˜ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์›ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋น ๋ฅด๊ฒŒ ์ƒ์„ฑ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์†”์งํžˆ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ ๋„๊ตฌ๋Š” ์ด์™€ ๊ฐ™์€ ์ปจํ…์ŠคํŠธ ์ฃผ๋ณ€์˜ ๋ˆ„์ถœ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๊นŒ? ๊ทธ๊ฒŒ ๋„์›€์ด ๋ ๊นŒ์š”? ๋ญ”๊ฐ€ ์ปจํ…์ŠคํŠธ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋“ค๋ฆฝ๋‹ˆ๋‹ค. ์ปจํ…์ŠคํŠธ์— ๋Œ€ํ•œ js ์ฐธ์กฐ ๋˜๋Š” ๊ธฐ๋ณธ ์บ”๋ฒ„์Šค์— ๋Œ€ํ•œ js ์ฐธ์กฐ?

์ด๊ฒƒ์ด ๋‚ด๊ฐ€ ์–ด๋–ค ์ผ์ด ์žˆ์–ด๋„ ์—ฌ์ „ํžˆ iframe์„ ์‚ฌ๋ž‘ํ•˜๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค.

@GoodBoyDigital ์ €๋Š” ์ด๋ ‡๊ฒŒ autodetectRenderer ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

<strong i="9">@renderer</strong> = new PIXI.autoDetectRenderer canvas.width, canvas.height, { view: canvas, antialias: false, backgroundColor: 0xffffff }

๋‚˜๋Š” ์ง€๊ธˆ ์ด๊ฒƒ์„ ์ฃผ์ฐจํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์†”๋ฃจ์…˜์„ ์ฐพ์•˜์„ ๋•Œ ํ•ด๊ฒฐ์ฑ…์ด ๋ฌด์—‡์ธ์ง€ ์•Œ๋ ค์ค„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ ์ปจํ…์ŠคํŠธ๋ฅผ ๊ฐ•์ œ๋กœ ์žƒ์–ด ๋ฒ„๋ฆฌ๋ฉด ๊ฐ€๋น„์ง€ ์ˆ˜์ง‘์ด ๊ฐ•์ œ๋กœ ์ฒญ์†Œํ•  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. :)

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

์–ด๋–ค ์ง„์ „์ด ์žˆ์Šต๋‹ˆ๊นŒ?

๋ถ„๋ช…ํžˆ ์ €๋Š” Phaser๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง€๋งŒ Pixi์˜ renderer.destroy ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

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

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

์•ˆ๋…•ํ•˜์„ธ์š” @GoodBoyDigital ์ œ ๊ฒฝ์šฐ์—๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ธ/์•„์›ƒ์ด ์žˆ์–ด์„œ ํ•ญ์ƒ 2๊ฐœ์˜ ์ปจํ…์ŠคํŠธ๊ฐ€ ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค... ๊ทธ๊ฑด React์™€ ํ†ตํ•ฉํ•˜๊ณ  ์ „์ฒด pixi๋กœ ๋งŒ๋“ค์ง€ ์•Š๋Š” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค... ์–ด์จŒ๋“ , ์ด๊ฒƒ์ด ๋ฒ„๊ทธ์ธ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ง์— ๋”ฐ๋ฅด๋ฉด .. ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ปจํ…์ŠคํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค ... three.js์˜์ด ํ•ดํ‚น์ด ์ž‘๋™ํ•˜๋Š”์ง€์กฐ์ฐจ ๋ชจ๋ฆ…๋‹ˆ๋‹ค ... ur V4์—์„œ ์‹œ๋„ํ•˜๊ณ  pixi๋กœ 16 ๊ฐœ ์ด์ƒ์˜ ํƒญ์„ ์—ด์–ด๋ณด์‹ญ์‹œ์˜ค. https://github.com/mrdoob/three.js/blob/master/src/renderers/WebGLRenderer.js#L289

๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ ๋‚ด ์•ฑ์˜ ์•„ํ‚คํ…์ฒ˜๋ฅผ ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค... iframe FTW :)

์ข‹์€ ๋ฌผ๊ฑด ๋‚จ์ž! three.js ํŠธ๋ฆญ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

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

์ฆ‰, ์‚ฌ์šฉ์ž๊ฐ€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฏธ๋ฆฌ ์ž‘์„ฑ๋œ ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค.

์ข‹์€ ํ•ด๊ฒฐ์ฑ…์„ ์ฐพ์€ ๊ฒƒ ๊ฐ™์•„์š”. ์ด๋ฅผ ํ†ตํ•ด ์„œ๋กœ์— ๋Œ€ํ•ด ์•Œ ํ•„์š”๊ฐ€ ์—†๊ณ  React๊ฐ€ DOM์„ ์†Œ์œ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์ง€๋„ ์˜ค๋ฒ„๋ ˆ์ด React ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ปจํ…์ŠคํŠธ ์†์‹ค์„ ๊ฐ•์ œํ•˜๊ธฐ ์œ„ํ•ด ์ด ๊ธฐ์ˆ  ์„ ์‚ฌ์šฉ

gl.getExtension('WEBGL_lose_context').loseContext();

์ „์ฒด ์˜ˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

var document = require('global/document');
var PIXI = require('pixi.js');

// I want to keep this canvas / renderer around. For example, this might be a bottom layer PIXI / React map overlay.
var canvas1 = document.createElement('canvas');
document.body.appendChild(canvas1);
createRenderer(0xff0000, canvas1);

function createRenderer(color, canvas) {
  canvas = canvas || document.createElement('canvas');
  var renderer = new PIXI.WebGLRenderer(800, 600, {view: canvas});
  var stage = new PIXI.Container();
  var graphics = new PIXI.Graphics();
  graphics.beginFill(color, 0.5);
  graphics.drawCircle(0, 0, 200);
  graphics.endFill();
  stage.addChild(graphics);
  renderer.render(stage);
  return {renderer: renderer, stage: stage, graphics: graphics};
}

// Simulate frequent adding / removing of lots of PIXI / React map overlays on top.
for (var i = 0; i < 16; i++) {
  var canvas = document.createElement('canvas');
  document.body.appendChild(canvas);
  var scene = createRenderer(0x00ff00, canvas);
  // Uncomment to see that the original canvas isn't removed.
  /* scene.renderer.currentRenderTarget.gl
      .getExtension('WEBGL_lose_context').loseContext(); */
  scene.renderer.destroy();
  scene.stage.removeChild(scene.graphics);
  document.body.removeChild(canvas);
}

PIXI๊ฐ€ ์ž์ฒด "destroy" ๋ฉ”์†Œ๋“œ์— ์ด๊ฒƒ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ• ๊นŒ์š”?

์šฐ๋ฆฌ๊ฐ€ ์ปจํ…์ŠคํŠธ๋ฅผ ์†Œ์œ ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ œ ์ƒ๊ฐ์—๋Š” ํ˜„์žฌ ์šฐ๋ฆฌ๊ฐ€ ์†Œ์œ ํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค(v3).

isWebGLSupported()(source/core/utils/index.js) ํ•จ์ˆ˜์—์„œ ๋Œ€์ฒด
return !!(gl && gl.getContextAttributes().stencil);

~์™€ ํ•จ๊ป˜
var success = !!(gl && gl.getContextAttributes().stencil); gl.getExtension('WEBGL_lose_context').loseContext(); gl = undefined; return success;

๋‚˜๋ฅผ ์œ„ํ•ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค. Google ํฌ๋กฌ์—์„œ ๊ฐ€์žฅ ๋‘๋“œ๋Ÿฌ์กŒ์Šต๋‹ˆ๋‹ค. Firefox๋Š” ์–ด๋Š ์ชฝ์ด๋“  ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” WebGL ๋ฉ์ฒญํ•œ ์‚ฌ๋žŒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด ์ ‘๊ทผ ๋ฐฉ์‹์— ๋Œ€ํ•œ ์˜๊ฒฌ์„ ์ฃผ์‹œ๋ฉด ์ •๋ง ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ข‹์€ ํ˜ธ์ถœ์€ ํ™•์ธํ•  ๋•Œ ๊ฐ•์ œ๋กœ ์ปจํ…์ŠคํŠธ๋ฅผ ์žƒ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์šฐ๋ฆฌ๊ฐ€ ํ•ด๋‹น ์ปจํ…์ŠคํŠธ๋ฅผ ์†Œ์œ ํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ (100%) ์•Œ๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ข‹์€ ์•„์ด๋””์–ด์ž…๋‹ˆ๋‹ค.

์ด ๋ณ‘ํ•ฉ ๋˜์—ˆ์Šต๋‹ˆ๊นŒ? ์šฐ๋ฆฌ๋Š” ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ๊ฒช๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

ping @englercj ์ง€๊ธˆ ๋‹ซ์„ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

gl.getExtension('WEBGL_lose_context').loseContext() ๋Š” ๊ฒฝ๊ณ ๋ฅผ ํ‘œ์‹œํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์ง€๋งŒ ์‚ฌ์–‘์— ๋”ฐ๋ฅด๋ฉด WEBGL_lose_context.restoreContext() ๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ๊นŒ์ง€ ์ปจํ…์ŠคํŠธ ์†์‹ค์„ ์‹œ๋ฎฌ๋ ˆ์ดํŠธํ•  ๋ฟ์ด๋ฉฐ ์ฒ˜์Œ์— ์‹ค์ œ๋กœ ์†์‹ค๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋งŒ ์ปจํ…์ŠคํŠธ๋ฅผ ๋ณต์›ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. loss_context()๋Š” (์‚ฌ์–‘์— ๋”ฐ๋ผ) ์‹œ๋ฎฌ๋ ˆ์ด์…˜์ผ ๋ฟ์ด์ง€๋งŒ ์ด ์Šค๋ ˆ๋“œ( Public WebGL: WEBGL_lose_context์—์„œ ์šฐ๋ฆฌ๋Š” (๋ชจ์งˆ๋ผ ๊ฐœ๋ฐœ์ž Jeff Gilbert๋กœ๋ถ€ํ„ฐ))์—์„œ Firefox loseContext() ๊ฐ€ " ์ด ์ปจํ…์ŠคํŠธ์™€ ๊ทธ์ž์›" .

๋ฌธ์ œ๋Š” ๋‹ค๋ฅธ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ด๊ฒƒ์„ ๋‹ค๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Google ๊ฐœ๋ฐœ์ž(Ken Russell)๊ฐ€ ์ถ”์ฒœํ•˜๋Š” ์˜๊ฒฌ์ด ์žˆ์Šต๋‹ˆ๋‹ค. WebGLRenderingContext์—์„œ ๋ช…์‹œ์  delete* API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” GPU ๋ฆฌ์†Œ์Šค๋ฅผ ํ•ด์ œํ•˜์‹ญ์‹œ์˜ค.

๋‚˜๋Š” ์ด๊ฒƒ ์ค‘ ์–ด๋Š ๊ฒƒ๋„ ์‹คํ—˜ํ•˜์ง€ ์•Š์•˜๋‹ค๋Š” ๊ฒƒ์„ ์ธ์ •ํ•ด์•ผํ•˜์ง€๋งŒ ์–ด๋–ค ์†”๋ฃจ์…˜๋„ ๋ธŒ๋ผ์šฐ์ €์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

ํฅ๋ฏธ๋กœ์šด FF ๊ตฌํ˜„ ๋…ธํŠธ. ์‹ค์ œ๋กœ ๊ฐœ๋ณ„ ๋ฆฌ์†Œ์Šค ์‚ญ์ œ์— ๋Œ€ํ•œ Ken์˜ ์กฐ์–ธ์€ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ FF๋Š” ๋งŽ์€ ์ธ๊ธฐ ์žˆ๋Š” ๋ธŒ๋ผ์šฐ์ € ์ค‘ ํ•˜๋‚˜์ด๋ฉฐ FF ๋™์ž‘๋„ ์˜ˆ๊ณ  ์—†์ด ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋Œ€์•ˆ์ด ์žˆ์„ ๋•Œ ๊ตฌํ˜„ ์„ธ๋ถ€ ์ •๋ณด์™€ ๊ฐ€์งœ ์‚ฌ์šฉ์ž ์—์ด์ „ํŠธ ๋ฌธ์ž์—ด ๋˜๋Š” ๋ธŒ๋ผ์šฐ์ € ์Šค๋‹ˆํ•‘ ๋ฐ ์ถ”๊ฐ€ ์ฝ”๋“œ ๊ฒฝ๋กœ์— ์˜์กดํ•˜๊ณ  ์‹ถ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ธŒ๋ผ์šฐ์ €๋ณ„๋กœ ํ…Œ์ŠคํŠธํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

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

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ์—ฌ๋Ÿฌ ์ปจํ…์ŠคํŠธ๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ์žฌ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. ํŽ˜์ด์ง€๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๊ฒฝ์šฐ ์ด์ „ ํŽ˜์ด์ง€์—์„œ ์ƒ์„ฑ๋œ ๋‚ด์šฉ์€ ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

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

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

์ด๊ฒƒ์€ ๋‹จ์ผ ํŽ˜์ด์ง€ ์•ฑ ๋‚ด์—์„œ PIXI๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๊ด€๋ จ๋œ ๋ฌธ์ œ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

PIXI.Application/PIXI.WebGLRenderer/PIXI.CanvasRenderer์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ €์žฅํ•˜๋ฉด ์บ”๋ฒ„์Šค ์š”์†Œ์˜ ์ธ์Šคํ„ด์Šค๋„ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, PIXI.Application์—์„œ HTMLCanvasElement์ธ view ์†์„ฑ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์บ”๋ฒ„์Šค ์š”์†Œ๋ฅผ ์‚ฝ์ž…ํ•˜๊ณ  AngularJS/React ์•ฑ์—์„œ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. PIXI์—์„œ ์˜ต์…˜์œผ๋กœ ์ „๋‹ฌํ•˜์—ฌ ์‚ฌ์šฉํ•  ์บ”๋ฒ„์Šค ์š”์†Œ๋ฅผ ๋ Œ๋”๋Ÿฌ์— ์•Œ๋ฆด ์ˆ˜ ์žˆ์ง€๋งŒ ์‚ฌ์šฉํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๋Œ€์‹  PIXI๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ์ž์ฒด ์บ”๋ฒ„์Šค ์š”์†Œ๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ํ—ˆ์šฉํ•˜๊ณ  ์ผ๋ถ€ DOM ์ปจํ…Œ์ด๋„ˆ์— appendChild๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

<div id="pixi-container"></div>
// maintain the reference to this Application even as your SPA view gets destroyed
const app = new PIXI.Application();

// Insert in the DOM or whatever the equivalent is in Angular
document.querySelector("#pixi-container").appendChild(app.view);

๋„ค, ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์‹œ๋„ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ๋Š” ์ „ํ˜€ ๋‚˜๋น  ๋ณด์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ข‹์•„, ๋ทฐ๋ฅผ ํŒŒ๊ดดํ•˜๋Š” ๋Œ€์‹  ๋ทฐ๋ฅผ ๋ถ„๋ฆฌํ–ˆ๋‹ค๊ฐ€ ๋‹ค์‹œ ์ถ”๊ฐ€ํ•˜๋ฉด ๋‚ด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋„์›€์„ ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์ด ์Šค๋ ˆ๋“œ๋Š” ๋‹ซํžŒ ํ›„ ์ตœ๊ทผ ํ™œ๋™์ด ์—†์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ž๋™์œผ๋กœ ์ž ๊ฒผ์Šต๋‹ˆ๋‹ค. ๊ด€๋ จ ๋ฒ„๊ทธ์— ๋Œ€ํ•œ ์ƒˆ ๋ฌธ์ œ๋ฅผ ์—ฌ์‹ญ์‹œ์˜ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰