Skip to main content

Browser operating principles + React principles

image

  • Creating DOM(Document Object Model)

    • Lifecycle Method: DOMContentLoaded, load, beforeunload, unload
    1. DOMContentLoaded
      • Occurs immediately after completion of the DOM tree.
      • No Wait for assets like img, css etc
    <script>
    function ready() {
    alert("DOM is ready!");

    // size is 0X0 as it is not loaded
    alert(`img size: ${img.offsetWidth}x${img.offsetHeight}`);
    }

    document.addEventListener("DOMContentLoaded", ready);
    </script>

    <img id="img" src="https://en.js.cx/clipart/train.gif?speed=1&cache=0" />
    • If multiple script tags exist => DOMCcontentLoaded runs after all scripts run (reason: DOMcontentLoaded may have logic related to DOM manipulation)
    <!-- b => c => a -->

    <script>
    document.addEventListener("DOMContentLoaded", () => {
    alert("DOM is ready!");
    });
    // a
    </script>

    <script
    src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.3.0/lodash.js"
    >
    // b
    </script>

    <script>
    // c
    alert("๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋กœ๋”ฉ์ด ๋๋‚˜๊ณ  ์ธ๋ผ์ธ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹คํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค.");
    </script>
    • Scripts created dynamically with document.createElement ('script')
      • and added to web pages do not prevent DOMCentLoaded.
      • if script location after CSS loading link tag - Script tag will not run until CSS loading is complete - Therefore, DOMCcontentLoaded runs after style loading too (reason: Possible use of style-affected properties during JS like img, offsetTopโ€ฆ)
    1. load => Executed when all external resources such as img and CSS are loaded
    2. beforeunload / => Occurs when a user leaves the page !https://blog.kakaocdn.net/dn/bwVtza/btrMI23XIp7/f7LpqlCEGumD6kfIPvEsg0/img.png
    3. unload (the last thing to do when you really leave) => Occurs when a user leaves the page
    // only document
    window.addEventListener("DOMContentLoaded", (event) => {
    console.log("DOMContentLoaded");
    });

    // after resources (css, images)
    window.addEventListener("load", (event) => {
    console.log("load");
    });

    // before unload
    window.addEventListener("beforeunload", (event) => {
    console.log("beforeunload");
    });

    // resource is being unloaded
    window.addEventListener("unload", (event) => {
    console.log("unload");
    });
  • Creating CSSOM(Cascade Style Sheet Object Model)

    • DOM + CSS = CSSOM => DOM + CSSOM = Render Tree image
    • display:none applied to DOM => including to Final Render Tree
    • visibility: hidden / opacity: 0 => including to Final Render Tree(Element exists, but not visible) image

    Parsing HTML, CSS, JS(= Synchronous Parsing)โ€‹

    • at facing tag while parsing HTML โ‡’ simultaneously parsing HTML, CSS

      => CSS doesnโ€™t change DOM structure

    • JS can change DOM structure, then if you face script tag, then stop parsing HTML parse and start JS parse

    No blocking if you use defer, async(= Asynchronous Parsing)โ€‹

    • async

      • JS assets is downloaded at background environment
      • JS assets is loaded async, JS parsing is after HTML parsing
        • JS runs with HTML parsing pause
      • if thereโ€™s multiple async, running order is on itโ€™s own terms
      <script
      async
      src="https://javascript.info/article/script-async-defer/long.js"
      ></script>
      <script
      async
      src="https://javascript.info/article/script-async-defer/small.js"
      ></script>

      <!-- small.js is run first before long.js -->
      • DOMContentLoadedย event, async script is not waiting each other.
      1. If the async script is downloaded after the page is configured, DOMCcontentLoaded may occur before the async script is executed,
      2. If the async script is short and is downloaded before the page configuration is finished, or if the script is cached, DOMCcontentLoaded can also occur after the async script is executed.
    • defer

      • JS download runs in the background
      • JS load is asynchronous, JS execution is synchronized (HTML parsing is completed)
      • Executed before the DOMCcontentLoaded event occurs
      <!-- a -->
      <p>...content after script...</p>

      <!-- b -->
      <script
      defer
      src="https://javascript.info/article/script-async-defer/long.js?speed=1"
      ></script>

      <!-- see now! -->
      <!-- c -->
      <p>...script after content...</p>

      <!-- order a => c => b -->
      • The above script runs and the below script runs (small.js, a small script, is download before long.js, a long script)
      <!-- a -->
      <script
      defer
      src="https://javascript.info/article/script-async-defer/long.js"
      ></script>
      <!-- b -->
      <script
      defer
      src="https://javascript.info/article/script-async-defer/small.js"
      ></script>

      <!-- b runs after a is completed -->
      • if src in script is not exists, then defer property is ignored(inline script tag is ignored)
      <!-- defer is not applied -->
      <script defer>
      document.addEventListener("DOMContentLoaded", () =>
      alert("DOM is ready after running `defer`script")
      ); // (2)
      </script>

      <!-- defer is applied -->
      <script
      defer
      src="https://javascript.info/article/script-async-defer/long.js?speed=1"
      ></script>
  • Creating Render Tree = DOM + CSSOM

  • Run โ€œLayoutโ€ process

    • Each node in the render tree => Calculate which viewport and where it should be placed
      • Relative properties such as %, vh, vw are converted to px
  • Run โ€œPaintโ€ process

    • draw each node in the render tree as a real pixel on the monitor
      • When reflow occurs, paint must occur

        However, if there are properties that affect the layout, such as background-color, visibility, etc., do not need to reflow => Therefore, only paint is performed

    • Property that neither Layout nor Paint occurs
      • transform, opacitiy, cursor, orphans, perspective etc
      • Rendering is faster than the 'Paint Only' property (absolutely reduced operations)

        => If possible, it is recommended to use properties that do not cause Repaint or Reflow.

      • Different rendering engines in your browser(chrome, safari, firefox etc) might have different steps to process CSS properties

๊ฐ€์ƒ๋”(Virtual DOM) ํŠน์ง•โ€‹

  • ํ˜„์žฌ ๋”์˜ ๋ณต์‚ฌ๋ณธ์ธ ๊ฐ€์ƒ๋” A์™€, ๋ณ€๊ฒฝ์ด ์žˆ๋Š” ๊ฐ€์ƒ๋” B(๋ฉ”๋ชจ๋ฆฌ์— ์ƒˆ๋กœ ์ƒ์„ฑ)๋ฅผ ๋น„๊ต(ํœด๋ฆฌ์Šคํ‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ๋น„๊ต) => ์ฐจ์ด์ ์˜ ๋ชจ๋“  ๋ถ€๋ถ„์„ ์ผ๊ด„์ ์œผ๋กœ, ๋ฆฌ์•กํŠธ๊ฐ€ ์‹ค์ œ DOM์— ๋ฐ˜์˜ํ•œ๋‹ค
  • ๋ฐฐ์น˜(batch) => DOM ์—…๋ฐ์ดํŠธ๋ฅผ ์ผ๊ด„์ ์œผ๋กœ ์ฒ˜๋ฆฌ => ์‹ค์ œ ๋”์˜ ๋ฆฌ๋ Œ๋”๋ง ์—ฐ์‚ฐ์„ ์ตœ์†Œํ™”(์—ฐ์‡„์  ๋ฆฌํ”Œ๋กœ์šฐ, ๋ฆฌํŽ˜์ธํŠธ ๋ฐœ์ƒ ๋ง‰์Œ)

์ž‘์€ ๊ทœ๋ชจ์˜ ๋ ˆ์ด์•„์›ƒ(๋ฆฌํ”Œ๋กœ์šฐ)์ด ์—ฌ๋Ÿฌ๋ฒˆ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ๋ณด๋‹คโ€‹

ํฐ ๊ทœ๋ชจ์˜ ๋ ˆ์ด์•„์›ƒ์ด ํ•œ ๋ฒˆ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์€ ์„ฑ๋Šฅ์ƒ์˜ ํฐ ์ฐจ์ด๋ฅผ ๋‚˜ํƒ€๋ƒ„โ€‹

image

์—…๋ฐ์ดํŠธ ๋œ ๊ฐ€์ƒ๋”๊ณผ ์ด์ „ ๊ฐ€์ƒ๋”์„ ๋น„๊ต


์žฌ์กฐ์ •(Reconciliation)

  • ๋‹ค์Œ ๊ฐ€์ •์„ ํ†ตํ•ด => ์ „์ฒด DOM ํŠธ๋ฆฌ๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ์‹œ๊ฐ„์„(O(n^3))์—์„œ O(n)์œผ๋กœ ์ค„์ž„

    • ์„œ๋กœ ๋‹ค๋ฅธ ํƒ€์ž…์˜ ๋‘ ์—˜๋ฆฌ๋จผํŠธ๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด๋ƒ„(์—˜๋ฆฌ๋จผํŠธ๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋น„๊ต ์•ˆํ•จ)
    • key props๋ฅผ ํ†ตํ•ด => key๊ฐ€ ๊ฐ™์€ ๋…ธ๋“œ๋ผ๋ฆฌ ๋น„๊ตํ•จ
  • ๋น„๊ต ๋ฐฉ์‹

    • ๋™์ผํ•œ ๋ ˆ๋ฒจ์˜ ๋…ธ๋“œ๋“ค๋ผ๋ฆฌ๋งŒ ๋น„๊ต
    • ๊ฐ™์€ ์œ„์น˜์—์„œ ์—˜๋ฆฌ๋จผํŠธ ํƒ€์ž…์ด ๋‹ค๋ฅธ ๊ฒฝ์šฐ => ๊ธฐ์กด ํŠธ๋ฆฌ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ์ƒˆ๋กญ๊ฒŒ ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ ๋‹ค(๋‚ด๋ถ€ ์—˜๋ฆฌ๋จผํŠธ, ๋‚ด๋ถ€ ์ปดํฌ๋„ŒํŠธ ๋ชจ๋‘ ์ œ๊ฑฐ ํ›„ ๋‹ค์‹œ ์ƒˆ๋กœ ๋งŒ๋“ฌ)
    • ๊ฐ™์€ ์œ„์น˜์—์„œ ์—˜๋ฆฌ๋จผํŠธ์˜ ํƒ€์ž…์ด ๊ฐ™์€ ๊ฒฝ์šฐ => class๊ฐ€ ๋ณ€๊ฒฝ๋๋‹ค๋ฉด ๋ณ€๊ฒฝ๋œ attributes๋งŒ ์—…๋ฐ์ดํŠธํ•œ๋‹ค => ์ž์‹ ์—˜๋ฆฌ๋จผํŠธ๋“ค์— ๋น„๊ต์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์žฌ๊ท€์ ์œผ๋กœ ์ ์šฉ
    • ๊ฐ™์€ ์œ„์น˜์—์„œ '์—˜๋ฆฌ๋จผํŠธ = ์ปดํฌ๋„ŒํŠธ'์ด๊ณ , ํƒ€์ž…์ด ๊ฐ™์€๊ฒฝ์šฐ => ์ปดํฌ๋„ŒํŠธ ์ธ์Šคํ„ดํŠธ ์ž์ฒด๋Š” ์•ˆ๋ณ€ํ•จ(state ์œ ์ง€) + ๋ผ์ดํ”„์‚ฌ์ดํด ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•ด props๊ฐ€ ์—…๋ฐ์ดํŠธ๋จ => render ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์„œ ์ปดํฌ๋„ŒํŠธ ์ด์ „ ์—˜๋ฆฌ๋จผํŠธ ํŠธ๋ฆฌ์™€ ๋‹ค์Œ ์—˜๋ฆฌ๋จผํŠธ ํŠธ๋ฆฌ์— ๋Œ€ํ•ด ์žฌ๊ท€์ ์œผ๋กœ ์ ์šฉ
    • ์ž์‹ ๋…ธ๋“œ์— ๋Œ€ํ•œ ์žฌ๊ท€์  ์ฒ˜๋ฆฌ ์‹œ
      • => key๋ฅผ ์ด์šฉํ•ด ๋™์ผํ•œ key๋ฅผ ๊ฐ–๋Š” ์ž์‹๋“ค๋ผ๋ฆฌ๋งŒ ๋น„๊ตํ•œ๋‹ค => ๋”ฐ๋ผ์„œ ItemC ๋…ธ๋“œ๋งŒ ์ถ”๊ฐ€๋œ๋‹ค. (key๊ฐ€ ์—†์œผ๋ฉด ๋‘๋ฆฌ์ŠคํŠธ๋ฅผ ๋ชจ๋‘ ์ˆœํšŒํ•ด์•ผํ•จ)
      • => ์ธ๋ฑ์Šค๋ฅผ key๋กœ ํ•  ๊ฒฝ์šฐ =>ย ๋ฆฌ์ŠคํŠธ์˜ ๋ฐฐ์—ด์ด ์žฌ์ •๋ ฌ๋˜์ง€ ์•Š๊ฑฐ๋‚˜ last-child์—์„œ๋งŒ ์ถ”๊ฐ€, ๋ณ€๊ฒฝ, ์ œ๊ฑฐ๊ฐ€ ์ผ์–ด๋‚œ๋‹ค๋ฉด ์ธ๋ฑ์Šค๋ฅผ ํ‚ค๋กœ ์‚ฌ์šฉํ•ด๋„๋จ
      • => ํ•˜์ง€๋งŒ ๋ฆฌ์ŠคํŠธ ์ˆœ์„œ๊ฐ€ ๋ฐ”๋€Œ๋ฉด key๊ฐ€ ์ „๋ถ€ ๋ฐ”๋€Œ์–ด์„œ key์˜ ์˜๋ฏธ๊ฐ€ ์‚ฌ๋ผ์ง
    // before
    <ul>
    <li>ItemA</li>
    //๋น„๊ต๋Œ€์ƒ1
    <li>ItemB</li>
    //๋น„๊ต๋Œ€์ƒ2
    </ul>

    // after
    <ul>
    <li>ItemC</li>
    //๋น„๊ต๋Œ€์ƒ1 (ItemA -> ItemC ๋กœ ๋ณ€๊ฒฝ)
    <li>ItemA</li>
    //๋น„๊ต๋Œ€์ƒ2 (ItemB -> ItemA ๋กœ ๋ณ€๊ฒฝ)
    <li>ItemB</li>
    //๋น„๊ต๋Œ€์ƒ3 (ItemB ์ถ”๊ฐ€)
    </ul>

image

๋ Œ๋”๋ง ํŠธ๋ฆฌ ๋น„๊ต


์ฐธ๊ณ 

[React] Virtual DOM๊ณผ ๋ธŒ๋ผ์šฐ์ €์˜ ๋ Œ๋”๋ง ๊ณผ์ •

๋ธŒ๋ผ์šฐ์ €์˜ ๋™์ž‘๊ณผ์ •๋ถ€ํ„ฐ React๊นŒ์ง€

[React] ๊ฐ€์ƒ๋” Virtual DOM์ด๋ž€?

๋ชจ๋˜ JavaScript ํŠœํ† ๋ฆฌ์–ผ

[JavaScript] ๋ฌธ์„œ์˜ ๋กœ๋”ฉ๋˜๋Š” ์‹œ์  ์ด๋ฒคํŠธ ์ œ์–ดํ•˜๊ธฐ (ft. DOMContentLoaded, load, beforeunload, unload)