Qwik: κ°€μž₯ λΉ λ₯Έ λ‘œλ”©μ†λ„μ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ ν”„λ ˆμž„μ›Œν¬

NaHCoH
  • #FrontEnd
  • #Qwik
  • #Framework
  • #Performance

μ•ˆλ…•ν•˜μ„Έμš”. μ›λ”μ›”μ—μ„œ ν”„λ‘ νŠΈμ—”λ“œ κ°œλ°œμ„ ν•˜κ³ μžˆλŠ” ν™©ν˜Έμ°¬μž…λ‹ˆλ‹€.

μ΄λ²ˆμ—λŠ” builder.ioμ—μ„œ λ§Œλ“€μ–΄λ‚Έ Qwik Framework에 λŒ€ν•œ μ†Œκ°œλ₯Ό ν•΄λ³ΌκΉŒ ν•©λ‹ˆλ‹€.

Qwik은 2021년에 졜초둜 pre-release, μ˜¬ν•΄ 5월에 1.0.0이 릴리즈된 λ‚˜λ¦„? λ”°λˆλ”°λˆν•œ ν”„λ ˆμž„μ›Œν¬μž…λ‹ˆλ‹€.

κ°œλ°œνŒ€ λ‚΄λΆ€μ—μ„œλ„ μž‘λ…„μ— Qwik의 정보λ₯Ό 같이 κ³΅μœ ν•œ νžˆμŠ€ν† λ¦¬κ°€ μžˆλ„€μš”.

Qwik Framework?

Qwik은 React.js, Vue.js와 같은 μ›Ή ν”„λ ˆμž„μ›Œν¬μž…λ‹ˆλ‹€.

Qwikμ• μ„œ κ°€μž₯ κ°•μ μœΌλ‘œ 뽑고 μžˆλŠ” 뢀뢄은, λ‘œλ”©μ‹œμ˜ μ΅œμ†Œ 크기의 μžλ°”μŠ€ν¬λ¦½νŠΈμ™€ κ°€μž₯ λΉ λ₯Έ μ†λ„μž…λ‹ˆλ‹€.

Qwik is a new kind of web framework that can deliver instant loading web applications at any size or complexity.
Your sites and apps can boot with about 1kb of JS (regardless of application complexity), and achieve consistent performance at scale.

단 1kb의 μžλ°”μŠ€ν¬λ¦½νŠΈλ§ŒμœΌλ‘œ νŽ˜μ΄μ§€μ˜ 졜초 기동이 κ°€λŠ₯ν•˜λ‹€κ³  ν•˜λ„€μš”. 이λ₯Ό κ°€λŠ₯ν•˜κ²Œ ν•˜λŠ”κ²ƒμ€ λ‹€λ₯Έ ν”„λ ˆμž„μ›Œν¬μ™€ Qwik의 λ™μž‘ λ°©μ‹μ˜ μ°¨μ΄μž…λ‹ˆλ‹€.

κΈ°μ‘΄ ν”„λ ˆμž„μ›Œν¬λŠ” 졜초 κΈ°λ™μ‹œ ν•΄λ‹Ή νŽ˜μ΄μ§€μ— ν•„μš”ν•œ λͺ¨λ“  jsνŒŒμΌμ„ λ‘œλ“œν•˜κ³ , κ·Έ νŒŒμΌλ“€μ΄ λ‘œλ“œλ˜κΈ° μ „κΉŒμ§€λŠ” μ‚¬μš©μžκ°€ νŽ˜μ΄μ§€λ₯Ό ν™•μΈν• μˆ˜ μ—†μŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ Qwik은 μ΅œμ†Œν•œμ˜ jsνŒŒμΌλ§Œμ„ κ°€μ Έμ˜€κ³ , ν•„μš”ν• λ•Œ κ·Έ λ™μž‘μ„ μœ„ν•œ μ΅œμ†Œν•œμ˜ jsνŒŒμΌμ„ κ·Έλ•Œκ·Έλ•Œ κ°€μ Έμ˜΅λ‹ˆλ‹€.

직접 ν™•μΈν•΄λ³΄μž

μ‹€μ œλ‘œ λ™μΌν•˜κ²Œ λ™μž‘ν•˜λŠ”μ§€ μ•Œμ•„λ³΄κΈ°μœ„ν•΄ react와 qwik λ²„μ „μ˜ λ‹€μŒκ³Ό 같은 κ°„λ‹¨ν•œ Counterλ₯Ό λ§Œλ“€μ–΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

λ¨Όμ € reactμž…λ‹ˆλ‹€.

npm create vite@latest react --template react-ts
function App() {
  const [count, setCount] = useState(0)

  return (
    <div style={{display: 'flex', justifyContent: 'center', alignItems: 'center', gap: '0.5rem'}}>
      <button onClick={() => setCount(count => count - 1)}>minus</button>
      <div>{count}</div>
      <button onClick={() => setCount(count => count + 1)}>plus</button>
    </div>
  )
}

λ‹€μŒμ€ qwikμž…λ‹ˆλ‹€.

npm create qwik@latest
export default component$(() => {
  const count = useSignal(0);

  return (
    <div style={{display: 'flex', justifyContent: 'center', alignItems: 'center', gap: '0.5rem'}}>
      <button onClick$={() => count.value--}>minus</button>
      <div>{count}</div>
      <button onClick$={() => count.value++}>plus</button>
    </div>
  );
});

그럼 이제 κ°œλ°œμžλ„κ΅¬ λ„€νŠΈμ›Œν¬νƒ­μ„ μ—΄μ–΄μ„œ js둜 ν•„ν„°λ₯Ό κ±Έκ³  ν•œλ²ˆ 확인해보면

μƒˆλ‘œκ³ μΉ¨ν–ˆμ„λ•Œ, react의 λ‘œλ”©λ˜λŠ” js 파일.

μƒˆλ‘œκ³ μΉ¨ν–ˆμ„λ•Œ, qwik의 λ‘œλ”©λ˜λŠ” js 파일.
qwikμ—μ„œλŠ” viteμ—μ„œ λ³΄λ‚΄μ£ΌλŠ” client, envλ₯Ό μ œμ™Έν•˜κ³ λŠ” 아무 js νŒŒμΌλ„ λΆˆλŸ¬μ˜€μ§€ μ•ŠλŠ”λ‹€.

생각보닀 λΆˆλŸ¬μ˜€λŠ” js파일의 μ–‘κ³Ό 크기에 ν™•μ—°ν•˜κ²Œ 차이가 λ³΄μ΄λŠ”κ±Έ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. λ¬Όλ‘  ν˜„μž¬ νŽ˜μ΄μ§€κ°€ 큰 κΈ°λŠ₯이 μžˆλŠ”κ±΄ μ•„λ‹ˆκ³  μ‹€μ œλ‘œ js둜 λ²ˆλ“€λ§λ˜λŠ” λ‚΄μš©λ„ λ§Žμ§€ μ•Šμ•„ νŽ˜μ΄μ§€ λ‘œλ”©μ— 큰 차이가 μ—†μ–΄λ³΄μΌμˆœ μžˆμ§€λ§Œ μˆ˜λ§Žμ€ κΈ°λŠ₯이 λ“€μ–΄κ°€λ©΄μ„œ νŽ˜μ΄μ§€ λ‘œλ”© μ†λ„λŠ” 점점 λŠλ €μ§€κ³  μ‚¬μš©μžμ˜ μ΄νƒˆμœ¨λ‘œ μ΄μ–΄μ§€κ²Œ λ©λ‹ˆλ‹€.

Qwik이 μ΄λ ‡κ²Œ 졜초 λ‘œλ”©μ‹œμ˜ js μ‚¬μ΄μ¦ˆλ₯Ό 쀄인 방법은, 졜초 νŽ˜μ΄μ§€λ₯Ό λ‘œλ”©ν•˜λŠ”λ° ν•„μš”ν•˜μ§€ μ•Šμ€ μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό λ‘œλ”©ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. 저희가 λ§Œλ“  μΉ΄μš΄ν„°μ•±μ—μ„œ νŽ˜μ΄μ§€ λ‘œλ”©μ„ ν•˜λŠ” μ‹œμ κΉŒμ§€λŠ” button에 λΆ™μ–΄μžˆλŠ” 이벀트 λ¦¬μŠ€λ„ˆλŠ” ν•„μš”ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μ‚¬μš©μžκ°€ ν΄λ¦­ν•˜μ§€ μ•ŠμœΌλ©΄ 쓸일 μ—†λŠ” λ‚΄μš©μ΄κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

Qwik은 κ°€λŠ₯ν•œ λͺ¨λ“ κ²ƒμ„ λΉ„λ™κΈ°λ‘œ μ²˜λ¦¬ν•˜κ³ , κΌ­ ν•„μš”ν•œ λ™μž‘μ΄ μ•„λ‹Œ 경우 ν•΄λ‹Ή μ½”λ“œκ°€ μ‚¬μš©λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— reactμ—μ„œλŠ” plus, minus λ²„νŠΌμ„ λˆŒλŸ¬λ„ 아무 λ³€ν™”κ°€ μ—†μ§€λ§Œ qwikμ—μ„œλŠ” ν•΄λ‹Ή λ²„νŠΌμ„ λˆ„λ₯΄λŠ” μ¦‰μ‹œ κ·Έ λ²„νŠΌμ„ ν΄λ¦­ν–ˆμ„λ•Œ λ°œμƒν•΄μ•Ό ν•˜λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ μ½”λ“œλ₯Ό 뢈러였고 호좜이 λλ‚˜λ©΄ μ‹€ν–‰ν•˜κ²Œ λ©λ‹ˆλ‹€.

Concept

μœ„μ—μ„œ μ‚΄νŽ΄λ³Έ λ‚΄μš©μ„ κΈ°μ€€μœΌλ‘œ Qwik의 컨셉, κ·Έ κ°œλ°œμžλ“€μ΄ μ–΄λ–€κ±Έ μ€‘μ‹œν•˜κ³  μž‘μ—…μ„ ν–ˆλŠ”μ§€ μ•Œμ•„λ³΄λ €κ³  ν•©λ‹ˆλ‹€.

Delay Execution

μ΅œμ†Œν•œμ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ μ½”λ“œλ₯Ό λ‹€μš΄λ‘œλ“œν•˜λŠ”κ±Έλ‘œ, μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λΉ λ₯΄κ²Œ μ‹€ν–‰μ‹œν‚΅λ‹ˆλ‹€.
λ‘œλ”© μ‹œκ°„ ν–₯상을 μœ„ν•΄ 적은 μ–‘μ˜ μ½”λ“œλ₯Ό λ§Œβ‚©λ“€μ–΄λ‚΄λŠ”κ²Œ μ•„λ‹ˆλΌ ν•„μš”ν• λ•Œ μ½”λ“œλ₯Ό κ°€μ Έμ™€μ„œ μ‚¬μš©ν•˜λ©°, 이λ₯Ό μœ„ν•΄ Qwikμ—μ„œλŠ” λͺ¨λ“ κ²ƒμ„ λ ˆμ΄μ§€λ‘œλ“œλ‘œ λ™μž‘ν•˜κ²Œ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Resumability

Qwik은 기본적으둜 SSR을 지ν–₯ν•˜λŠ” ν”„λ ˆμž„μ›Œν¬μž…λ‹ˆλ‹€. 이 λ•Œ, μ„œλ²„μ—μ„œ μ„€μ •λœ μƒνƒœκ°€ ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ μ΄ˆκΈ°ν™”λ˜λŠ”κ²Œ μ•„λ‹Œ ν•΄λ‹Ή μƒνƒœλ₯Ό ν΄λΌμ΄μ–ΈνŠΈμ—μ„œλ„ κ·ΈλŒ€λ‘œ μœ μ§€ν•©λ‹ˆλ‹€.
λ‹€λ§Œ ν•˜μ΄λ“œλ ˆμ΄μ…˜μ€ ν˜„μž¬ νŽ˜μ΄μ§€μ— κ΄€λ ¨λ˜λŠ” λͺ¨λ“  μ»΄ν¬λ„ŒνŠΈ μ½”λ“œλ₯Ό λ‹€μš΄λ‘œλ“œν•΄μ•Όν•˜κ³ , μ„ΈλΆ€ μ»΄ν¬λ„ŒνŠΈ νŠΈλ¦¬μ™€ λ¦¬μŠ€λ„ˆλ₯Ό λ‹€μ‹œ λΉŒλ“œν•˜κΈ° μœ„ν•œ μ»΄ν¬λ„ŒνŠΈμ— μ—°κ΄€λœ ν…œν”Œλ¦Ώμ„ μ‹€ν–‰μ‹œμΌœμ•Όν•˜κΈ° λ•Œλ¬Έμ— λ Œλ”λ§μ— λ„ˆλ¬΄ λ§Žμ€ λΉ„μš©μ΄ λ°œμƒ, ν•˜μ΄λ“œλ ˆμ΄μ…˜μ„ ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

Reactivity

μ–΄λ–€ μ»΄ν¬λ„ŒνŠΈκ°€ μ–΄λ–€ μƒνƒœλ₯Ό κ΅¬λ…ν•˜κ³  μžˆλŠ”μ§€λ₯Ό μ•Œκ²Œν•˜μ—¬ λ¦¬λ Œλ”λ˜λŠ” μ»΄ν¬λ„ŒνŠΈμ˜ 수λ₯Ό μ΅œμ†Œν™”ν•˜κ³ , μ΄λŠ” ν”„λ‘μ‹œλ₯Ό ν†΅ν•΄μ„œ κ΄€λ¦¬λ©λ‹ˆλ‹€.
λ˜ν•œ Qwik μ»΄ν¬λ„ŒνŠΈλŠ” λΆ€λͺ¨λΆ€ν„° μžμ‹μ˜ μˆœμ„œλŒ€λ‘œ λ Œλ”λ§μ„ ν•˜μ§€ μ•Šκ³  각각 λ³„κ°œμ˜ λ Œλ”λ§κ³Όμ •μ„ 거치며, μ΄λŠ” λΆ€λͺ¨μ˜ λ¦¬λ Œλ”λ§μœΌλ‘œ μΈν•œ μžμ‹μ˜ λ¦¬λ Œλ”λ§μ„ μ˜ˆλ°©ν•©λ‹ˆλ‹€.
이λ₯Όν†΅ν•΄, 객체등을 ν™œμš©ν•˜μ—¬ ν•˜λ‚˜μ˜ μƒνƒœλ‘œ κ΄€λ¦¬ν•˜κ³  μžˆμ–΄λ„, ν•΄λ‹Ή μ»΄ν¬λ„ŒνŠΈμ—μ„œ μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” κ°’μ˜ 변경은 λ¦¬λ Œλ”λ§μ„ λ°œμƒμ‹œν‚€μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μ•„λž˜ μ˜ˆμ œμ—μ„œ a값을 λ³€κ²½μ‹œμΌ°μ„λ•Œ, props둜 aλ₯Ό μ „λ‹¬λ°›λŠ” Child만 λ Œλ”λ§μ΄ λ‹€μ‹œ λ°œμƒν•˜κ³ , bλ₯Ό μ „λ‹¬λ°›λŠ” ChildλŠ” λ¦¬λ Œλ”λ§μ΄ λ°œμƒν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

export const Child = component$((props: { count: number }) => {
  return <span>{props.count}</span>;
});

export const MyApp = component$(() => {
  const store = useStore({ a: 0, b: 0, c: 0 });

  return (
    <>
      <button onClick$={() => store.a++}>a++</button>
      <button onClick$={() => store.b++}>b++</button>
      <button onClick$={() => store.c++}>c++</button>
      {JSON.stringify(store)}

      <Child count={store.a} />
      <Child count={store.b} />
    </>
  );
});

마치며

μ΄λ²ˆμ— μ œκ°€ 개인적으둜 μ£Όλͺ©ν•˜κ³  μžˆλŠ” μ°¨μ„ΈλŒ€ ν”„λ ˆμž„μ›Œν¬λΌ μƒκ°λ˜λŠ” Qwik.js에 λŒ€ν•΄μ„œ κ°„λ‹¨ν•œ μ†Œκ°œλ₯Ό ν•΄λ΄€μŠ΅λ‹ˆλ‹€.
ν˜„μž¬ νŒ€ λ‚΄ κ°œλ°œμžλ“€μ„ μœ„ν•œ qwik λ¬Έμ„œλ₯Ό μž‘μ„±ν•˜κ³  있으며, 좔후에 완성도λ₯Ό λ†’μ—¬μ„œ ν•΄λ‹Ή λ¬Έμ„œλ₯Ό κ³΅κ°œν•  수 μžˆλŠ” κΈ°νšŒκ°€ 있으면 μ’‹κ² μŠ΅λ‹ˆλ‹€.
λ˜ν•œ μ›λ”μ›”μ—μ„œλŠ” κ°„λ‹¨ν•œ ν”„λ‘œμ νŠΈλ₯Ό λŒ€μƒμœΌλ‘œ Qwik을 μ μš©ν•΄λ³΄λ € ν•˜κ³  있고, 이λ₯Ό 톡해 원더월이 κ΄€λ¦¬ν•˜κ³  μžˆλŠ” ν”„λ‘œμ νŠΈλ“€μ— λŒ€ν•΄μ„œ μ‚¬μš©μžλ“€μ— λ”μš± μΉœλ°€ν•œ μ„œλΉ„μŠ€κ°€ λ˜λŠ” κΈ°νšŒκ°€ 될수 μžˆμ„κ±°λΌ μƒκ°ν•©λ‹ˆλ‹€.

← λͺ©λ‘μœΌλ‘œ λŒμ•„κ°€κΈ°

Art Changes Life

λ…Έλ¨ΈμŠ€μ™€ ν•¨κ»˜ μ—”ν„°ν…Œν¬ 산업을 ν˜μ‹ ν•΄λ‚˜κ°ˆ 멀버λ₯Ό μ°ΎμŠ΅λ‹ˆλ‹€.

μ±„μš© 쀑인 곡고 보기