import { jsx, jsxs, Fragment } from 'solid-jsx/jsx-runtime';

/*@jsxRuntime automatic @jsxImportSource solid-jsx*/
const toc = [{
  "depth": 1,
  "value": "반응성",
  "children": [{
    "depth": 2,
    "value": "프리미티브 소개",
    "children": []
  }, {
    "depth": 2,
    "value": "작동 방식",
    "children": []
  }, {
    "depth": 2,
    "value": "고려 사항",
    "children": []
  }]
}];
function _createMdxContent(props) {
  const _components = Object.assign({
    h1: "h1",
    a: "a",
    p: "p",
    code: "code",
    pre: "pre",
    span: "span",
    h2: "h2",
    ol: "ol",
    li: "li"
  }, props.components);
  return jsxs(Fragment, {
    children: [jsxs(_components.h1, {
      id: "반응성",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#반응성",
        children: "#"
      }), "반응성"]
    }), "\n", jsx(_components.p, {
      children: "Solid의 데이터 관리는 모든 업데이트를 담당하는 일련의 유연한 리액티브 프리미티브들로 구축됩니다. MobX 또는 Vue와 유사한 접근 방식을 사용하지만, 가상 DOM을 사용하지 않습니다. 이펙트와 JSX 뷰 코드에서 리액티브 값에 접근하는 경우, 디펜던시는 자동으로 추적됩니다."
    }), "\n", jsxs(_components.p, {
      children: ["Solid의 프리미티브들은 주로 튜플을 반환하는 ", jsx(_components.code, {
        children: "create"
      }), " 함수를 호출하는 형태로 제공되며, 일반적으로 첫 번째 요소는 getter 이며, 두 번째 요소는 setter 입니다. 일반적으로 프리미티브 이름으로 getter만 참조합니다."]
    }), "\n", jsxs(_components.p, {
      children: ["다음은 ", jsx(_components.code, {
        children: "count"
      }), " 시그널 변경에 따라 자동 증가되는 카운터입니다."]
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-jsx",
        children: [jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { createSignal, onCleanup } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-js\""
        }), ";\r\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { render } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-js/web\""
        }), ";\r\n\r\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "App"
        }), " = (", jsx(_components.span, {
          className: "hljs-params"
        }), ") => {\r\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " [count, setCount] = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createSignal"
        }), "(", jsx(_components.span, {
          className: "hljs-number",
          children: "0"
        }), "),\r\n    timer = ", jsx(_components.span, {
          className: "hljs-built_in",
          children: "setInterval"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "setCount"
        }), "(", jsx(_components.span, {
          className: "hljs-title function_",
          children: "count"
        }), "() + ", jsx(_components.span, {
          className: "hljs-number",
          children: "1"
        }), "), ", jsx(_components.span, {
          className: "hljs-number",
          children: "1000"
        }), ");\r\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "onCleanup"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "hljs-built_in",
          children: "clearInterval"
        }), "(timer));\r\n\r\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "return"
        }), " ", jsxs(_components.span, {
          className: "xml",
          children: [jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "div"
            }), ">"]
          }), "{count()}", jsxs(_components.span, {
            className: "hljs-tag",
            children: ["</", jsx(_components.span, {
              className: "hljs-name",
              children: "div"
            }), ">"]
          })]
        }), ";\r\n};\r\n\r\n", jsx(_components.span, {
          className: "hljs-title function_",
          children: "render"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "xml",
          children: jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "App"
            }), " />"]
          })
        }), ", ", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "document"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "getElementById"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"app\""
        }), "));\n"]
      })
    }), "\n", jsxs(_components.h2, {
      id: "프리미티브-소개",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#프리미티브-소개",
        children: "#"
      }), "프리미티브 소개"]
    }), "\n", jsx(_components.p, {
      children: "Solid 는 시그널, 메모, 이펙트의 세 가지 주요 프리미티브들로 구성됩니다. 그 핵심은 메모와 이펙트를 래핑하여 시그널(및 메모)을 추적하는 옵저버 패턴입니다."
    }), "\n", jsx(_components.p, {
      children: "시그널은 가장 핵심적인 프리미티브입니다. 여기에는 값과 함께 get/set 함수를 포함하고 있어, 읽고 쓸 때 인터셉터할 수 있습니다."
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-js",
        children: [jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " [count, setCount] = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createSignal"
        }), "(", jsx(_components.span, {
          className: "hljs-number",
          children: "0"
        }), ");\n"]
      })
    }), "\n", jsx(_components.p, {
      children: "이펙트는 시그널 읽기를 래핑해서, 관련 시그널의 값이 변경될 때마다 재실행되는 함수입니다. 렌더링과 같은 사이드 이펙트를 생성하는데 유용합니다."
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-js",
        children: [jsx(_components.span, {
          className: "hljs-title function_",
          children: "createEffect"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "console"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "log"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"The latest count is\""
        }), ", ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "count"
        }), "()));\n"]
      })
    }), "\n", jsx(_components.p, {
      children: "마지막으로 메모는 캐시된 파생 값으로 시그널과 이펙트의 속성을 공유합니다. 관련 시그널을 추적하고, 변경시에만 다시 실행되며, 메모 자체도 추적 가능한 시그널입니다."
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-js",
        children: [jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " fullName = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createMemo"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsxs(_components.span, {
          className: "hljs-string",
          children: ["`", jsx(_components.span, {
            className: "hljs-subst",
            children: "${firstName()}"
          }), " ", jsx(_components.span, {
            className: "hljs-subst",
            children: "${lastName()}"
          }), "`"]
        }), ");\n"]
      })
    }), "\n", jsxs(_components.h2, {
      id: "작동-방식",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#작동-방식",
        children: "#"
      }), "작동 방식"]
    }), "\n", jsxs(_components.p, {
      children: ["시그널은 구독 목록을 보유하는 이벤트 이미터", "Emitter", "입니다. 시그널은 값이 변경될 때마다 구독자에게 알립니다."]
    }), "\n", jsx(_components.p, {
      children: "흥미로운 점은 이러한 구독이 발생하는 방식입니다. Solid는 자동 종속성 추적을 사용하며, 데이터가 변경되면 자동으로 업데이트됩니다."
    }), "\n", jsx(_components.p, {
      children: "이 비결은 런타임의 글로벌 스택에 있습니다. 이펙트 또는 메모는 개발자가 제공한 함수를 실행(또는 재실행)하기 전에 스택에 자신을 푸시합니다. 그런 다음 읽은 모든 시그널은 스택에 현재 리스너가 있는지 확인하고 있으면 리스너를 해당 구독에 추가합니다."
    }), "\n", jsx(_components.p, {
      children: "다음과 같이 생각할 수 있습니다:"
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-js",
        children: [jsx(_components.span, {
          className: "hljs-keyword",
          children: "function"
        }), " ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createSignal"
        }), "(", jsx(_components.span, {
          className: "hljs-params",
          children: "value"
        }), ") {\r\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " subscribers = ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "new"
        }), " ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Set"
        }), "();\r\n\r\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "read"
        }), " = (", jsx(_components.span, {
          className: "hljs-params"
        }), ") => {\r\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " listener = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "getCurrentListener"
        }), "();\r\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "if"
        }), " (listener) subscribers.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "add"
        }), "(listener);\r\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "return"
        }), " value;\r\n  };\r\n\r\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "write"
        }), " = (", jsx(_components.span, {
          className: "hljs-params",
          children: "nextValue"
        }), ") => {\r\n    value = nextValue;\r\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "for"
        }), " (", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " sub ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "of"
        }), " subscribers) sub.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "run"
        }), "();\r\n  };\r\n\r\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "return"
        }), " [read, write];\r\n}\n"]
      })
    }), "\n", jsx(_components.p, {
      children: "이제 시그널을 업데이트할 때마다 어떤 이펙트를 다시 실행할지 알 수 있습니다. 간단하고 효과적입니다. 실제 구현은 이보다 훨씬 더 복잡하지만, 실제 일어나는 일의 핵심은 위의 코드와 같습니다."
    }), "\n", jsx(_components.p, {
      children: "반응성의 작동방식을 더 자세히 이해하려면 다음 문서들을 참조하세요:"
    }), "\n", jsx(_components.p, {
      children: jsx(_components.a, {
        href: "https://dev.to/ryansolid/a-hands-on-introduction-to-fine-grained-reactivity-3ndf",
        children: "A Hands-on Introduction to Fine-Grained Reactivity"
      })
    }), "\n", jsx(_components.p, {
      children: jsx(_components.a, {
        href: "https://dev.to/ryansolid/building-a-reactive-library-from-scratch-1i0p",
        children: "Building a Reactive Library from Scratch"
      })
    }), "\n", jsx(_components.p, {
      children: jsx(_components.a, {
        href: "https://indepth.dev/posts/1289/solidjs-reactivity-to-rendering",
        children: "SolidJS: Reactivity to Rendering"
      })
    }), "\n", jsxs(_components.h2, {
      id: "고려-사항",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#고려-사항",
        children: "#"
      }), "고려 사항"]
    }), "\n", jsx(_components.p, {
      children: "반응성에 대한 이 접근 방식은 매우 강력하고 동적입니다. 조건문의 다른 분기 코드를 실행해서 종속성이 동적으로 변경되는 것을 처리할 수 있습니다. 또한 여러 단계의 간접 참조에서도 작동합니다. 추적 범위 내에서 실행되는 모든 함수도 추적됩니다."
    }), "\n", jsx(_components.p, {
      children: "하지만, 주의해야할 몇 가지 중요한 동작과 트레이드오프가 있습니다."
    }), "\n", jsxs(_components.ol, {
      children: ["\n", jsxs(_components.li, {
        children: ["\n", jsx(_components.p, {
          children: "모든 반응성은 직접 함수 호출 또는 getter/프록시 아래에 숨겨저 있는 속성에 접근할 때 트리거되는 함수 호출에서 추적됩니다. 즉, 리액티브 객체의 속성에 접근하는 위치가 중요합니다."
        }), "\n"]
      }), "\n", jsxs(_components.li, {
        children: ["\n", jsx(_components.p, {
          children: "제어 흐름의 컴포넌트와 콜백은 추적하지 않으며 한 번만 실행됩니다. 즉, 컴포넌트의 최상위 레벨에서 디스트럭쳐링하거나 로직을 수행해도 다시 실행되지 않습니다. 코드를 다시 평가하려면 다른 리액티브 프리미티브나 JSX 에서 시그널, 스토어, props에 접근해야 합니다."
        }), "\n"]
      }), "\n", jsxs(_components.li, {
        children: ["\n", jsx(_components.p, {
          children: "이 방법은 동기식으로만 추적합니다. 이펙트에 setTimeout 이나 다른 비동기 함수를 사용하는 경우, 나중에 비동기 실행되는 코드는 추적되지 않습니다."
        }), "\n"]
      }), "\n"]
    })]
  });
}
function MDXContent(props = {}) {
  const {wrapper: MDXLayout} = props.components || ({});
  return MDXLayout ? jsx(MDXLayout, Object.assign({}, props, {
    children: jsx(_createMdxContent, props)
  })) : _createMdxContent(props);
}

export { MDXContent as default, toc };
//# sourceMappingURL=reactivity-d3fa806f.js.map
