Feliz: Feliz๋ฅผ ์ถ”์ƒ API๋กœ ๋งŒ๋“ค๊ธฐ

์— ๋งŒ๋“  2020๋…„ 12์›” 19์ผ  ยท  15์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: Zaid-Ajaj/Feliz

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

  1. F#์€ UI๋ฅผ ์„ ์–ธํ•˜๋Š” ํ›Œ๋ฅญํ•œ ์–ธ์–ด์ž…๋‹ˆ๋‹ค.
  2. ์›น ๊ด€๋ จ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ชจ๋“  F# ๊ฐœ๋ฐœ์ž๋Š” ๊ณ ์œ ํ•œ DSL์„ ์ž‘์„ฑํ•˜์—ฌ UI๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.
  3. Feliz๋Š” React ์›น UI๋ฅผ ์„ ์–ธํ•˜๋Š” ํ›Œ๋ฅญํ•œ API/DSL์ž…๋‹ˆ๋‹ค.

3์—์„œ "React"๋ฅผ ์ œ๊ฑฐํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”? ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋งŽ์€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Feliz๋Š” ํ‘œ์ค€์ด ๋˜์–ด ์œ„ ๋ชฉ๋ก์—์„œ 2๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ Feliz๋กœ ์ž‘์„ฑ๋œ ๋Œ€๋ถ€๋ถ„์˜ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ž๋™์œผ๋กœ ๋‹ค๋ฅธ ๋ Œ๋”๋ง ์—”์ง„๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ด๊ฒƒ์€ ๋˜ํ•œ #285์—์„œ ๋…ผ์˜๋œ Fable.React ์ข…์†์„ฑ์„ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(Fable.React๋Š” ํ˜ธํ™˜์„ฑ์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด IViewElement๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค)
  • ์ด๊ฒƒ์€ ๋˜ํ•œ Fable.React์™€ ๊ฐ™์ด ๋ชจ๋“  ๊ณณ์—์„œ #if FABLE_COMPILER ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ ๋„ ์„œ๋ฒ„์ธก Feliz ๋ Œ๋”๋Ÿฌ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์„ ๋” ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์–ด๋”˜๊ฐ€์— ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ Fable์—์„œ ์ง์ ‘ ํ”„๋ก ํŠธ์—”๋“œ ๋ Œ๋”๋Ÿฌ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŽ ๋ฆฌ์ฆˆ๋งŒ ์“ฐ๋ฉด ์ข‹์„ํ…๋ฐ

์—˜๋ฆฌ๋ฒ ์ดํ„ฐ ํ”ผ์น˜๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ์ด๊ฒƒ์ด ์ข‹์€ ์กฐ์น˜๋ผ๊ณ  ์ƒ๊ฐ๋˜๋ฉด ๊ตฌํ˜„์— ๋Œ€ํ•ด ๋…ผ์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์•„์ง ์•„๋ฌด๊ฒƒ๋„ ์‹œ๋„ํ•˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ ๊ทธ๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์ง€๋งŒ ๋‚ด๊ฐ€ ์—ผ๋‘์— ๋‘” ๊ฒƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

type IViewElement = interface end
type IViewProp = interface end

// Later renderers can inherit these interfaces
type ReactElement = inherit IViewElement

// The basic renderer interface contains few methods
type IHTML =
    abstract renderNative: tagName: string * props: IViewProp seq

// Most of the helpers would be extensions to the interface
type IHTML with
    member this.div(props: IViewProp seq) = this.renderNative("div", props)
    ...

// Then we have different implementations
module Feliz.React

type ReactHTML() =
    interface IHTML with
        member _.RenderNative(tag, props, children) = ...

let Html = Feliz.ReactHTML()

// Consumer code
open Feliz.React

Html.div [...]

์ธํ…”๋ฆฌ์„ผ์Šค๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ๊ณ  ์ธํ„ฐํŽ˜์ด์Šค ๋Œ€์‹  ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์•„์ด๋””์–ด๋ฅผ ์–ป์œผ์…จ์œผ๋ฉด ํ•ฉ๋‹ˆ๋‹ค. ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜๋‚˜์š”?

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

@alfonsogarciacaro ๋Œ€๋‹จํ•ด ๋ณด์ด๋„ค์š”. #262์—์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด Fable.React์—์„œ Feliz๋กœ ์ „ํ™˜ํ•œ ํ›„ ๋‚ด๊ฐ€ ์ •๋ง ์ •๋ง ๊ทธ๋ฆฌ์›Œํ•˜๋Š” ์œ ์ผํ•œ ๊ฒƒ์€ '๊ทธ๋ƒฅ ์ž‘๋™ํ•˜๋Š”' SSR์ž…๋‹ˆ๋‹ค. Feliz์™€ Feliz.ViewEngine์€ ๋ชจ๋‘ ๋†€๋ผ์šด ํ”„๋กœ์ ํŠธ์ด์ง€๋งŒ ๋‘ ๊ฐœ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ๊ฐ€ ์žˆ์œผ๋ฉด ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์ด ์–ด๋ ค์›Œ์ง‘๋‹ˆ๋‹ค. ifdefs๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋Š” ifdefs๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ์ฝ”๋“œ์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์œ ์ผํ•œ ๋ฐ ์–‘์ชฝ ์„ธ๊ณ„ ์ฝ”๋“œ. ๊ทธ ๊ฒฉ์ฐจ๋ฅผ ์ค„์ด๋Š” ๊ฒƒ์€ ๋ฌด์—‡์ด๋“  Feliz ๋ฐ .Net ์„œ๋ฒ„๋กœ ์ž‘์—…ํ•  ๋•Œ ์‚ถ์˜ ์งˆ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

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

์•ˆ๋…•ํ•˜์„ธ์š” @alfonsogarciacaro , ์†”์งํžˆ ๋งํ•ด์„œ ์ €๋Š” ์ด๊ฒƒ์ด ์ข‹์€ ์ƒ๊ฐ์ด๋ผ๊ณ  _๊ธฐ์–ต_ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ก ์ ์œผ๋กœ๋Š” ์ดํ•ด๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. Fable์—์„œ HTML์šฉ ํ‘œ์ค€ API๋ฅผ ๊ตฌ์ถ•ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ๋Š” ์ž˜ ๋ฒˆ์—ญ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ๋ช‡ ๊ฐ€์ง€ ์ด์œ ์ž…๋‹ˆ๋‹ค.

  • ํ˜„์žฌ API๋Š” ํ‘œ์ค€์ด ์•„๋‹ˆ๋ฉฐ ์‚ฌ์‹ค ๋งค์šฐ ๋…๋‹จ์ ์ž…๋‹ˆ๋‹ค. ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์€ ์—ฌ์ „ํžˆ โ€‹โ€‹์ „์ฒด ๋‹จ์ผ ๋ชฉ๋ก๊ณผ prop.children ์ข‹์•„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์™„์ „ํžˆ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.
  • ํ˜„์žฌ API๋Š” React ์ „์šฉ์ด๋ผ๋Š” ๊ฐ€์ • ๋•Œ๋ฌธ์— "๋‹จ์ˆœ"ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. ์ถ”์ƒํ™”ํ•˜๋ ค๋ฉด Feliz ์Šคํƒ€์ผ API๋ฅผ ์ž‘์„ฑ/๋ณต์ œํ•˜๋Š” ๋Œ€์•ˆ์ด ๋” ์‰ฌ์šด ์†”๋ฃจ์…˜์ผ ์ˆ˜ ์žˆ๋Š” ๋งŽ์€ ์ž‘์—…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฆฌ์†Œ์Šค๋ฅผ ๋ถ„์‚ฐ์‹œํ‚ค๋Š” ๊ฒƒ๋ณด๋‹ค React ์ฃผ๋ณ€์˜ ๋„๊ตฌ๋ฅผ ๊ฐœ์„ ํ•˜๋Š” ๋ฐ ์ง‘์ค‘ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. Feliz๋Š” "์™„๋ฃŒ"์™€๋Š” ๊ฑฐ๋ฆฌ๊ฐ€ ๋ฉ€๊ณ , ๋ฌธ์„œ, ์ƒ˜ํ”Œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜, ๋” ๋‚˜์€ ํ…Œ์ŠคํŠธ ์Šคํ† ๋ฆฌ ๋“ฑ๊ณผ ๊ด€๋ จํ•˜์—ฌ ์—ฌ์ „ํžˆ ํ•ด์•ผ ํ•  ์ผ์ด ๋งŽ์Šต๋‹ˆ๋‹ค.

@Zaid ๋‹ต๋ณ€ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ๋‚˜๋Š” ๋‹น์‹ ์˜ ์ถ”๋ก ์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๊ฒฝ์Ÿํ•˜๋Š” DSL์ด ๋„ˆ๋ฌด ๋งŽ๋‹ค๋Š” ๊ฒƒ์ด ์—ฌ์ „ํžˆ ์œ ๊ฐ์ด์ง€๋งŒ ๋‹น์‹ ์ด ๋งํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋‹ค๋ฅธ ์†”๋ฃจ์…˜์ด ์žˆ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹œ๊ฐ„์ด ๋œ๋‹ค๋ฉด ํ”„๋กœํ† ํƒ€์ž…์„ ์ž‘์„ฑํ•˜์—ฌ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

BTW, ์—ฌ๊ธฐ์—์„œ ๋ช‡ ๊ฐ€์ง€ ์ž‘์—…์„ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. https://github.com/alfonsogarciacaro/Feliz.Engine/blob/main/src/HtmlEngine.fs

๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ํ…Œ์ŠคํŠธํ•˜์ง€ ์•Š์•˜์ง€๋งŒ ๋ชจ๋“  unbox ๋ฐ ์œ ์‚ฌํ•œ ํŠธ๋ฆญ์„ ์ œ๊ฑฐํ–ˆ์œผ๋ฏ€๋กœ ์›์น™์ ์œผ๋กœ ์ด ์ธํ„ฐํŽ˜์ด์Šค ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ชจ๋“  ๋ Œ๋”๋Ÿฌ์™€ "์ž‘๋™ํ•ด์•ผ" ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด React ๋ Œ๋”๋Ÿฌ๋ฅผ @dbrattli Feliz.ViewEngine๊ณผ ๊ฒฐํ•ฉํ•˜๊ณ  Feliz๋กœ SSR์„ ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ๋งŒ๋“œ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

ํŒŒ์•…/๊ณ ๋ คํ•ด์•ผ ํ•  ๋ช‡ ๊ฐ€์ง€ ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ธํ…”๋ฆฌ์„ผ์Šค

Html ๊ฐ€ Feliz์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜๋  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‚ด ์ธํ…”๋ฆฌ์„ผ์Šค๊ฐ€ ํŽ‘ํ‚คํ•ด ๋ณด์ธ๋‹ค๋Š” ์‚ฌ์‹ค์ด ๋งค์šฐ ๊ธฐ์˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

let Html = HtmlEngine(renderer)

๊ทธ๊ฒƒ์€ ๋” ์‚ฌ์†Œํ•œ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

๋ฒˆ๋“ค ํฌ๊ธฐ

์šฐ๋ฆฌ๋Š” ์ด๊ฒƒ์ด ํ˜„์žฌ์™€ ๊ฐ™๊ฑฐ๋‚˜ ๋” ์ข‹๊ธฐ๋ฅผ ๋ถ„๋ช…ํžˆ ์›ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ์ปดํŒŒ์ผ๋Ÿฌ ์ง€์‹œ๋ฌธ์— ๋ž˜ํ•‘๋œ Feliz.HtmlEngine ์˜ ํ”Œ๋Ÿฌ๊ทธ์ธ์ผ๊นŒ์š”? ์ด ์†”๋ฃจ์…˜์€ ์›น ์„œ๋ฒ„๊ฐ€ Fable์— ์˜์กดํ•˜๋„๋ก ๋งŒ๋“ค ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ธฐํƒ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

ํ˜„์žฌ ์ˆ˜ํ–‰๋˜๊ณ  ์žˆ๋Š” SSR์˜ ๊ฐ€์žฅ ํฐ ๋ฌธ์ œ ์ค‘ ํ•˜๋‚˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋‹จ์ˆœํžˆ ์ž‘๋™ํ•˜์ง€ ์•Š๊ณ  ์ž‘๋™ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(์˜ˆ Feliz.Bulma / Feliz.Bulma.ViewEngine )๋„ ์กฐ์ •์ด ํ•„์š”ํ•˜์ง€ ์•Š๋Š” ํ•œ ์—ฌ์ „ํžˆ ์กฐ์ •์ด ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€ ์œ ์‚ฌํ•œ ์ฐธ์กฐ๋ฅผ ์œ„ํ•ด ๋‘˜ ๋‹ค์— ๋Œ€ํ•œ ์ถ”์ƒ API๋ฅผ ๋นŒ๋“œํ•˜์‹ญ์‹œ์˜ค.

๋Œ€์•ˆ

์—ฌ๊ธฐ์„œ ๊ทผ๋ณธ์ ์ธ ๋ฌธ์ œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์˜๋„ํ•œ ์ฒซ ๋ฒˆ์งธ ํŽ˜์ธํŠธ๋ฅผ ์™„์ „ํžˆ ์—๋ฎฌ๋ ˆ์ดํŠธํ•˜๊ณ  ์‹ถ์„ ๋•Œ SSR์„ ์ง์ ‘ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ์‹คํ˜„ ๊ฐ€๋Šฅํ•˜์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ์—๊ฒŒ ์ •๋ง๋กœ ํ•„์š”ํ•œ ๊ฒƒ์€ .NET์„ ์œ„ํ•œ ReactDOMServer ์™€ ๊ฐ™์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด๊ฒƒ์— ๋Œ€ํ•ด ๋„ˆ๋ฌด ๊นŠ์ด ํŒŒ๊ณ  ๋“ค์ง€ ๋Š”

@Shmew ์˜ ์˜๊ฒฌ์— ๊ฐ์‚ฌํ•˜๊ณ  ๋Šฆ๊ฒŒ ๋‹ต์žฅ์„

  • Intellisense : ํ , ์ถ”์ƒ API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋งŒ ์ž‘์„ฑํ–ˆ์ง€๋งŒ ์ž๋™ ์™„์„ฑ ๋ฌธ์ œ๋Š” ๋ณด์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ํ™•์ธํ•ด ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ์ •์  ์œ ํ˜•์— ์•ก์„ธ์Šคํ•˜๋Š” ๋Œ€์‹  ๊ฐ’์— ์•ก์„ธ์Šคํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ดœ์ฐฎ์„ ๊ฒƒ์ด๊ณ  ๋งŽ์€ ๊ฒฝ์šฐ์— ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ฃผ์š” ๋‹จ์ ์€ ์•„๋งˆ๋„ open type ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • ๋ฒˆ๋“ค ํฌ๊ธฐ : ์ด๊ฒƒ๋„ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ํฌ๋ง์€ ํด๋ž˜์Šค ๋ฉค๋ฒ„๊ฐ€ ํŠธ๋ฆฌ๋ฅผ ํ”๋“ค ์ˆ˜ ์žˆ๊ณ  ์ž˜ ์ถ•์†Œํ•  ์ˆ˜ ์žˆ๋Š” ๋ถ„๋ฆฌ๋œ ํ•จ์ˆ˜๋กœ Fable์— ์˜ํ•ด ์ปดํŒŒ์ผ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋งŽ์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ถˆํ–‰ํžˆ๋„ ์ƒ์„ฑ๋œ ์ฝ”๋“œ๋Š” #284 ์ดํ›„์™€ ๊ฐ™์ด ๋ฉ‹์ง€๊ฒŒ ๋ณด์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ๊ธฐํƒ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ : ์˜ˆ, ์ถ”์ƒ API์˜ ์ด์ ์„ ์–ป์œผ๋ ค๋ฉด ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์กฐ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ตœ์†Œํ•œ์˜ ๋ณ€๊ฒฝ์œผ๋กœ ๋ฐ”๋ž๋‹ˆ๋‹ค.
  • ๋Œ€์•ˆ : TBH, Fable.React์˜ (๊ธฐ์—ฌ๋œ) ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ๋งค์šฐ ๋ณต์žกํ•ด ๋ณด์ด์ง€๋Š” ์•Š์ง€๋งŒ(๊ธฐ๋ณธ์ ์œผ๋กœ ์ƒ์„ฑ๋œ html ํƒœ๊ทธ์— ์ผ๋ถ€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ) SSR์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. React.NET๊ณผ ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์‰ฌ์šด์ง€ ์—ฌ๋ถ€. Feliz์—๋Š” .NET์—์„œ ๋ฐœ์ƒํ•˜๋Š” Fable ํŠธ๋ฆญ(์ฃผ๋กœ ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์บ์ŠคํŠธ)์ด ํฌํ•จ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— Feliz์—์„œ๋„ ootb๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์‚ฌ์‹ค, ์ด๊ฒƒ์„ ์œ„ํ•ด ๋‚˜๋Š” SSR ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ _beyond React_ :wink:์—์„œ๋„ ์ƒ๊ฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด F# ์„œ๋ฒ„์˜ html ์ƒ์„ฑ๊ธฐ๋Š” React์™€ ๋ฐ˜๋“œ์‹œ ํ˜ธํ™˜๋  ํ•„์š”๋Š” ์—†๊ณ  ๋‹ค๋ฅธ ๋ Œ๋”๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ํ”„๋ก ํŠธ์—”๋“œ์— ๋Œ€ํ•ด ๋ฐ˜์‘ํ•ฉ๋‹ˆ๋‹ค.

@Shmew ๋Œ“๊ธ€ ๊ฐ์‚ฌํ•˜๊ณ  ๋Šฆ๊ฒŒ ๋‹ต์žฅํ•ด์„œ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค

์ฒœ๋งŒ์—์š”. ๊ฑฑ์ • ๋งˆ์„ธ์š”!

Intellisense: ํ , ์ถ”์ƒ API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋งŒ ์ž‘์„ฑํ–ˆ์ง€๋งŒ ์ž๋™ ์™„์„ฑ์—๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ํ™•์ธํ•ด ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ์ •์  ์œ ํ˜•์— ์•ก์„ธ์Šคํ•˜๋Š” ๋Œ€์‹  ๊ฐ’์— ์•ก์„ธ์Šคํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ดœ์ฐฎ์„ ๊ฒƒ์ด๊ณ  ๋งŽ์€ ๊ฒฝ์šฐ์— ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ฃผ์š” ๋‹จ์ ์€ ์•„๋งˆ๋„ ๊ฐœ๋ฐฉํ˜• ์œ ํ˜•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค, ๋‚˜๋Š” ๋งค์šฐ ๋ช…ํ™•ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. Intellisense๋Š” ๊ดœ์ฐฎ์ง€๋งŒ Html ๊ฐ€ ๋‹ค๋ฅธ ์ƒ‰์ƒ์ด๋ผ๋Š” ์‚ฌ์‹ค์ž…๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ๋งํ–ˆ๋“ฏ์ด, ์ •๋ง ๋งˆ์ด๋„ˆ ๐Ÿ˜…. ์šฐ๋ฆฌ๊ฐ€ open type ํ•  ์ˆ˜ ์—†๋‹ค๋Š” ์‚ฌ์‹ค์€ ์‚ฌ์‹ค ์กฐ๊ธˆ ๋” ํฐ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ผ๋ถ€ ์‚ฌ๋žŒ๋“ค ์ด ๋ชจ๋“  ๊ฒƒ์„ ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋กœ ์ง€์ •ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๊ทธ๊ฒƒ์„

๋ฒˆ๋“ค ํฌ๊ธฐ: ์ด๊ฒƒ๋„ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ํฌ๋ง์€ ํด๋ž˜์Šค ๋ฉค๋ฒ„๊ฐ€ ํŠธ๋ฆฌ๋ฅผ ํ”๋“ค ์ˆ˜ ์žˆ๊ณ  ์ž˜ ์ถ•์†Œํ•  ์ˆ˜ ์žˆ๋Š” ๋ถ„๋ฆฌ๋œ ํ•จ์ˆ˜๋กœ Fable์— ์˜ํ•ด ์ปดํŒŒ์ผ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋งŽ์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ถˆํ–‰ํžˆ๋„ ์ƒ์„ฑ๋œ ์ฝ”๋“œ๋Š” #284 ์ดํ›„์™€ ๊ฐ™์ด ๋ฉ‹์ง€๊ฒŒ ๋ณด์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

interop ํ•จ์ˆ˜๊ฐ€ ์ด๋ฏธ ์ธ๋ผ์ธ๋˜์ง€ ์•Š์•˜์Œ์„ ๊นจ๋‹ซ์ง€๋„ ๋ชปํ•˜๊ณ  ์ด๋ฏธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ธ๋ผ์ธํ–ˆ์Šต๋‹ˆ๋‹ค. ์ „์ฒด Html ๋ชจ๋“ˆ์€ ๋ชจ๋‘ ์ธ๋ผ์ธ ๋ž˜ํผ์ด๊ธฐ ๋•Œ๋ฌธ์— JS์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ˆ˜ํ–‰๋˜๋Š” ๊ฒฝ์šฐ์™€ ๋น„๊ตํ•˜์—ฌ ๋ฒˆ๋“ค ํฌ๊ธฐ ์ฆ๊ฐ€๊ฐ€ ์—†๋‹ค๋Š” ์‚ฌ์‹ค์— ๋Œ€ํ•ด ๋” ๋งŽ์ด ์ด์•ผ๊ธฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๋” ์ด์ƒ ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ตฌ์ฒด์ ์ธ ํด๋ž˜์Šค๋กœ.

๊ธฐํƒ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ: ์˜ˆ, ์ถ”์ƒ API์˜ ์ด์ ์„ ์–ป์œผ๋ ค๋ฉด ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์กฐ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ตœ์†Œํ•œ์˜ ๋ณ€๊ฒฝ์œผ๋กœ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ด๊ฒƒ์˜ ๋ฌธ์ œ๋Š” ๋ชจ๋“  ๋‚ด๋ถ€๊ฐ€ JS ์ „์šฉ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋„ค์ดํ‹ฐ๋ธŒ ๋ฐ˜์‘ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ œ๋Œ€๋กœ ์ž‘๋™ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋Œ€์•ˆ: TBH, Fable.React์˜ (๊ธฐ์—ฌ๋œ) ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ๊ทธ๋‹ค์ง€ ๋ณต์žกํ•ด ๋ณด์ด์ง€๋Š” ์•Š์ง€๋งŒ(๊ธฐ๋ณธ์ ์œผ๋กœ ์ƒ์„ฑ๋œ html ํƒœ๊ทธ์— ์ผ๋ถ€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ) SSR์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. React.NET๊ณผ ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์‰ฌ์šด์ง€ ์—ฌ๋ถ€. Feliz์—๋Š” .NET์—์„œ ๋ฐœ์ƒํ•˜๋Š” Fable ํŠธ๋ฆญ(์ฃผ๋กœ ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์บ์ŠคํŠธ)์ด ํฌํ•จ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— Feliz์—์„œ๋„ ootb๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋„ค, ๊ฐ„๋‹จํ•œ ๊ฒฝ์šฐ์—๋Š” ์ž‘๋™ํ•˜์ง€๋งŒ Feliz.MaterialUI ์ผ๋ถ€ ๊ตฌ์„ฑ ์š”์†Œ์™€ ๊ฐ™์ด ๋” ๋ณต์žกํ•œ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์ดํ•ดํ•œ ๋ฐ”์— ๋”ฐ๋ฅด๋ฉด React SSR์€ node.js์—์„œ ์™„๋ฃŒ๋  ๋•Œ ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ReactDOMServer ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ์‹ค์ œ๋กœ ํŽ˜์ด์ง€์˜ ์ฒซ ๋ฒˆ์งธ ํŽ˜์ธํŠธ์ธ ์ „์ฒด ๋ฌธ์ž์—ด์„ ๋ฑ‰์–ด๋‚ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‚ด ์ดํ•ด๋Š” React.NET ๊ฐ€ ์ •ํ™•ํžˆ ๊ทธ๊ฒƒ์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด node.js ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ž˜ํ•‘ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Feliz ์ฝ”๋“œ๋Š” ์ด๋ฏธ ์ด์™€ ๊ฐ™์€ ๊ฒƒ์„ ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์ด ์‹ค์ œ๋กœ ๋งค์šฐ ์‰ฌ์šธ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ์„ธ์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Fable compiles F# React 
-> node.js process imports and returns html string 
-> web server caches output 
-> web server serves page

๋ฐ˜์‘์„ ๋„˜์–ด์„œ

์ด๊ฒƒ์€ ํ›Œ๋ฅญํ•œ ์š”์ ์ด๋ฉฐ, React ๋˜๋Š” ๊ธฐํƒ€ ์š”์†Œ ์—†์ด ์ˆœ์ˆ˜ํ•œ HTML์„ ๋ Œ๋”๋งํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ํ™•์‹คํžˆ ์›ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ €๋Š” ์ด ์•„์ด๋””์–ด๋ฅผ ์‹คํ—˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ ์ œ ์ง„ํ–‰ ์ƒํ™ฉ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: https://github.com/alfonsogarciacaro/Feliz.Engine

์•„์ง ํ•ด์•ผ ํ•  ์ผ์ด ์žˆ๊ณ  ๋ช‡ ๊ฐ€์ง€ ์˜๊ตฌ์‹ฌ์ด ์žˆ์ง€๋งŒ ์ด๋ฏธ ์ž‘๋™ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ Feliz API์˜ ๋Œ€๋ถ€๋ถ„์„ ๋‹ค๋ฃจ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ ์•ฝ๊ฐ„์˜ ์ˆ˜์ •์„ ๊ฐ€ํ•ด์•ผ ํ•ด์„œ ํŽ ๋ฆฌ์ฆˆ๋ฅผ ์ด๋Ÿฐ๊ฑธ๋กœ ๋Œ€์ฒดํ•˜๊ธฐ ํž˜๋“ ๊ฒŒ ์‚ฌ์‹ค์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Feliz์˜ ์ถ”์ƒ ๋ฒ„์ „์€ ๋งŽ์€ ๊ฐ€๋Šฅ์„ฑ์„ ์—ด์–ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ์ „ํžˆ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ช‡ ๊ฐ€์ง€ ์˜ˆ:

  1. Sutil๊ณผ ๊ฐ™์€ ๋‹ค๋ฅธ ํ”„๋ก ํŠธ์—”๋“œ ํ”„๋ ˆ์ž„์›Œํฌ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ: https://github.com/davedawkins/Sutil/pull/15
  2. SASS ๋Œ€์‹  CSS๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ: https://github.com/alfonsogarciacaro/Feliz.Engine/blob/main/samples/Feliz.Css/Feliz.Css.fs
  3. ์ •์  html ์ƒ์„ฑ์— ์‚ฌ์šฉ: https://github.com/alfonsogarciacaro/Feliz.Engine/blob/main/samples/Feliz.StaticHtml/Feliz.StaticHtml.fs
  4. Snabbdom๊ณผ ๊ฐ™์€ ๋‹ค๋ฅธ ๊ฐ€์ƒ ๋” ๊ตฌํ˜„๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. https://github.com/alfonsogarciacaro/Feliz.Engine/blob/main/samples/Feliz.Snabbdom/Feliz.Snabbdom.fs

์ด๊ฒƒ๋“ค์€ ๋ชจ๋‘ ์ดˆ์•ˆ์ด์ง€๋งŒ ์ž‘๋™ ์ค‘์ด๋ฉฐ ๋งค์šฐ ์ ์€ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋” ์ค‘์š”ํ•œ ๊ฒƒ์€ ์ด๋“ค ๋ชจ๋‘๊ฐ€ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฌธ์„œํ™”๋˜๊ณ  ์นœ์ˆ™ํ•œ API๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ ํ™•์žฅ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ด๋Ÿฌํ•œ ๋ชจ๋“ (๋ฐ ํ–ฅํ›„) ์•ฑ๊ณผ ํ˜ธํ™˜๋˜๋Š” BulmaEngine์„ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 2. ๋ฐ 3์˜ ๊ฒฝ์šฐ ์ฆ๋ถ„ ์ปดํŒŒ์ผ์ด .NET๋ณด๋‹ค ํ›จ์”ฌ ๋น ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— Fable์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง€๋งŒ Feliz.Engine์€ .NET๊ณผ ํ˜ธํ™˜๋˜๋ฏ€๋กœ(๋ชจ๋“  unbox ) ๊ฐ„๋‹จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. F# .NET ์„œ๋ฒ„์™€ ํ˜ธํ™˜๋˜๋„๋ก ํ•˜๊ณ  HTML ์ƒ์„ฑ๊ธฐ๋ฅผ React์™€ ํ˜ธํ™˜๋˜๋„๋ก ๋งŒ๋“œ๋Š” ๋ฐ ๋งŽ์€ ์ž‘์—…์ด ํ•„์š”ํ•˜์ง€ ์•Š๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

@Zaid-Ajaj๋Š” ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์„ธ์š”? ๋‚˜๋Š” ์ด๋ฏธ ํ˜„์žฌ Feliz React API๋ฅผ ๋Œ€์ฒดํ•˜๋Š” ์•„์ด๋””์–ด๋ฅผ ํฌ๊ธฐํ–ˆ์Šต๋‹ˆ๋‹ค ๐Ÿ˜… ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๊ฒƒ์ด "Feliz family"(์•„๋งˆ๋„ ์ด repo์— ์žˆ์Œ)์— ์†ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์‹ญ๋‹ˆ๊นŒ? ์ด๋ฆ„์ด ๊ดœ์ฐฎ์Šต๋‹ˆ๊นŒ, ์•„๋‹ˆ๋ฉด ๋‹ค๋ฅธ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

์•ˆ๋…•ํ•˜์„ธ์š” @alfonsogarciacaro , ์ด๋ฒˆ ์ฃผ์— ์ด ์ƒ˜ํ”Œ์„ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ณ  ํ™•์‹คํžˆ ๋Œ์•„์˜ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค ๐Ÿ˜„

์•ˆ๋…•ํ•˜์‹ญ๋‹ˆ๊นŒ,

์ฝ”๋“œ๋ฅผ ๋น ๋ฅด๊ฒŒ ์‚ดํŽด๋ณด์•˜๋Š”๋ฐ ์ด ์ถ”์ƒ ๋ฒ„์ „์ด ๋ฒˆ๋“ค ํฌ๊ธฐ์— ์•ฝ๊ฐ„์˜ ์˜ํ–ฅ์„ ๋ฏธ์น  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ์˜ ํŽ ๋ฆฌ์ฆˆ์˜ ํŠน์ง• ์ค‘ ํ•˜๋‚˜๋ผ๋Š” ์ ์„ ์ง€์ ํ•˜๊ณ  ์‹ถ์—ˆ๋‹ค.

์˜ˆ, ์˜ํ–ฅ์ด ์˜ˆ์ƒ๋ฉ๋‹ˆ๋‹ค. ๋ฌธ์ œ๋Š” ํฌ๊ธฐ๊ฐ€ ์–ผ๋งˆ๋‚˜ ๋˜๋Š”์ง€์ž…๋‹ˆ๋‹ค. :) ์ค‘๊ฐ„ ๊ทœ๋ชจ ์•ฑ์˜ ๊ฒฝ์šฐ ๋ˆˆ์— ๋„์ง€ ์•Š๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฌผ๋ก  ๋‘ ์Šคํƒ€์ผ ๋ชจ๋‘์—์„œ fulma-demo ๊ฐ™์€ ๊ฒƒ์ด ์žˆ์œผ๋ฉด ์ข‹์„ ๊ฒƒ์ด๋ฏ€๋กœ ์šฐ๋ฆฌ๋Š” ๋น„๊ตํ•˜๊ณ  ์ตœ์ ํ™” ๊ธฐํšŒ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Feliz ๋„์šฐ๋ฏธ๊ฐ€ ๋ฒˆ๋“ค ํฌ๊ธฐ์— ์–ด๋–ค ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ๋„ ํฅ๋ฏธ๋กœ์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ Feliz๊ฐ€ ์ƒ์„ฑํ•œ ์ฝ”๋“œ๋Š” ๋งค์šฐ ํ›Œ๋ฅญํ•˜๊ณ  ์ปดํŒŒ์ผ๋œ JSX์™€ ๋งค์šฐ ์œ ์‚ฌํ•˜์ง€๋งŒ ํ•จ์ˆ˜๋ฅผ ์ถ•์†Œํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ .createElement("div") ์™€ ๊ฐ™์€ ๋งŽ์€ ํ˜ธ์ถœ์˜ ์ค‘๋ณต์„ ์ค„์ด๋Š” ๋ฐฉ๋ฒ•์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(gzip์ด ์••์ถ•ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Œ ๊ทธ๋Ÿฌ๋‚˜ ์ด๋Ÿฌํ•œ ํ˜ธ์ถœ).

๋„ค, ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์—์„œ ์ด ๋ฉ‹์ง„ API/์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์— ๋ฐ˜๋Œ€ํ•˜๋Š” ์‚ฌ๋žŒ์ด ์žˆ์„ ๊ฑฐ๋ผ๊ณ ๋Š” ์ƒ์ƒ๋„ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋‚ด ์œ ์ผํ•œ ์ง„์งœ ๊ด€์‹ฌ์‚ฌ๋Š” ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ํ’ˆ์งˆ๊ณผ ์œ„์—์„œ ์„ค๋ช…ํ•œ ์ผ๋ถ€ ์ธ์ฒด ๊ณตํ•™์  ๋ฌธ์ œ์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€์˜€์Šต๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š” @alfonsogarciacaro , ์˜ˆ์ œ ์ฝ”๋“œ๋ฅผ ์ž˜ ๋ณด์•˜์Šต๋‹ˆ๋‹ค. css ์—”์ง„๊ณผ ์ •์  html ์—”์ง„์ด ๋ชจ๋‘ node.js ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— nodejs ์ „์šฉ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๋ผ๋Š” ์‚ฌ์‹ค์— ๋†€๋ž์Šต๋‹ˆ๋‹ค. ์•„์ด๋””์–ด๊ฐ€ ํฅ๋ฏธ๋กญ๊ธด ํ•˜์ง€๋งŒ ์œ„์˜ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋ฅผ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ œ ์ž์‹ ์„ ๋ณด๊ธฐ๋Š” ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

  • CssEngine์€ CSS๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. Feliz์— ๋‚ด์žฅ๋œ ๊ฒƒ๊ณผ ๊ฐ™์€ CSS/SASS ๋„๊ตฌ ์ฒด์ธ ๋˜๋Š” CSS-in-JS๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ FSS ๋˜๋Š” ๊ฐ์ •๊ณผ ๊ฐ™์€ ๋‹ค๋ฅธ CSS-in-JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ๋Š” ๋Œ€์กฐ์ ์œผ๋กœ ์ด์ ์ด ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? F#์—์„œ CSS๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์€ ์ž์ฒด์ ์œผ๋กœ ์ž‘๋™ํ•˜์ง€๋งŒ ๊ธฐ์กด ๋„๊ตฌ ์ฒด์ธ์— ์˜์กดํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์€ ์„ ํƒ์ด ๋  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— Feliz์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ฑฐ๋Œ€ํ•œ ์Šคํƒ€์ผ์‹œํŠธ๋ฅผ ์ปดํŒŒ์ผํ•˜๊ธฐ ์œ„ํ•ด) ํ˜„์žฌ ์ €๋Š” Feliz/React ๊ตฌ์„ฑ ์š”์†Œ์— CSS ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๋” ์„ ํ˜ธ
  • ์ •์  html ์—”์ง„: Feliz๋Š” ์ด๋ฏธ ๋…ธ๋“œ์™€ ๋ธŒ๋ผ์šฐ์ €์—์„œ ReactDOM ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ •์  html์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. Feliz.ViewEngine์€ dotnet์—์„œ ์ •์  HTML์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. API๋ฅผ ๊ณต์œ ํ•˜๋Š” ๊ฒƒ์ด ์•„์ด๋””์–ด๋ผ๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์ง€๋งŒ @Shmew๊ฐ€ ์–ธ๊ธ‰ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋‹ค๋ฅธ ๋ฌธ์ œ๋กœ ์ธํ•ด ์–ด๋ ค์›Œ์กŒ์Šต๋‹ˆ๋‹ค. ๋‘ ๊ฐ€์ง€๋ฅผ ๋ชจ๋‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ƒ์„ฑ๋œ ์ฝ”๋“œ์— ์˜ํ–ฅ์„
  • Snabbdom ์—”์ง„: ํฅ๋ฏธ๋กœ์šด ์˜ˆ์ด์ง€๋งŒ React์™€ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ƒํƒœ๊ณ„๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋Œ€์ฒด๋กœ ํฅ๋ฏธ๋กœ์šด ์šด๋™์ž…๋‹ˆ๋‹ค. ์†”์งํžˆ ๋งํ•ด์„œ ์ €๋Š” ์ƒˆ๋กœ์šด API์˜ ์—ด๋ ฌํ•œ ํŒฌ์ด ์•„๋‹ˆ๋ฉฐ ๊ฐœ์ธ์ ์œผ๋กœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ‘œ์ค€ํ™”ํ•˜๋Š” ๋Œ€์‹  React์—์„œ ๋” ๋งŽ์€ ๋ฌธ์„œ, ์˜ˆ์ œ ๋ฐ ๋ฐ”์ธ๋”ฉ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ˜„์žฌ ๊ฒฝํ—˜์„ ๊ฐœ์„ ํ•˜๋Š” ๋ฐ ์‹œ๊ฐ„์„ ํ• ์• ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ œ๊ฐ€ ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ์•ฝ๊ฐ„ ๋ถ€์ •์ ์œผ๋กœ ์ƒ๊ฐํ–ˆ๋‹ค๋ฉด ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ์•„๋งˆ ๋งŽ์€ ์ผ์„ ํ•˜์…จ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Feliz์™€ ๊ฐ™์€ ์ด๋ฆ„์€ ๋„์„œ๊ด€์—์„œ ์˜๊ฐ์„ ๋ฐ›์•˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒ๊ด€ ์—†์Šต๋‹ˆ๋‹ค.

@Zaid-Ajaj ์ƒ˜ํ”Œ์„ ํ™•์ธํ•ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ๋‚˜๋Š” ๋‹น์‹ ์˜ ์ •์ง์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. css ๋ฐ html ํ”„๋ฆฐํ„ฐ๋Š” Feliz.Engine์„ ์ž ์žฌ์  ์šฉ๋„์— ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ์‰ฌ์šด์ง€/์–ด๋ ค์šด์ง€๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ„๋‹จํ•œ ์˜ˆ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค(์ธ์‡„๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ์ฝ”๋“œ๋Š” 50์ค„์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค). ์ฆ๋ถ„ ์ปดํŒŒ์ผ์ด ํ›จ์”ฌ ๋น ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— Fable & node๋ฅผ ์‚ฌ์šฉํ–ˆ์ง€๋งŒ "์›์น™์ ์œผ๋กœ" .net์— ์‰ฝ๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Snabbdom ์–ด๋Œ‘ํ„ฐ๋Š” ๋˜ ๋‹ค๋ฅธ ๋น ๋ฅธ ์˜ˆ์ด๊ธฐ๋„ ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ๋งˆ์Œ์— ๋“ค๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ๊ฑด ๋˜ ๋‹ค๋ฅธ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. :)

์–ด์จŒ๋“ , ๋‚˜๋Š” ๋งˆ์นจ๋‚ด ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๊นจ๋œจ๋ฆฌ์ง€ ์•Š๊ณ  ํ˜„์žฌ Feliz React ์•ฑ์„ ์ถ”์ƒํ™”ํ•˜๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๊นจ๋‹ฌ์•˜์Šต๋‹ˆ๋‹ค. Feliz ๊ฐ™์€ API ๐Ÿ‘

@alfonsogarciacaro ๋Œ€๋‹จํ•ด ๋ณด์ด๋„ค์š”. #262์—์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด Fable.React์—์„œ Feliz๋กœ ์ „ํ™˜ํ•œ ํ›„ ๋‚ด๊ฐ€ ์ •๋ง ์ •๋ง ๊ทธ๋ฆฌ์›Œํ•˜๋Š” ์œ ์ผํ•œ ๊ฒƒ์€ '๊ทธ๋ƒฅ ์ž‘๋™ํ•˜๋Š”' SSR์ž…๋‹ˆ๋‹ค. Feliz์™€ Feliz.ViewEngine์€ ๋ชจ๋‘ ๋†€๋ผ์šด ํ”„๋กœ์ ํŠธ์ด์ง€๋งŒ ๋‘ ๊ฐœ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ๊ฐ€ ์žˆ์œผ๋ฉด ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์ด ์–ด๋ ค์›Œ์ง‘๋‹ˆ๋‹ค. ifdefs๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋Š” ifdefs๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ์ฝ”๋“œ์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์œ ์ผํ•œ ๋ฐ ์–‘์ชฝ ์„ธ๊ณ„ ์ฝ”๋“œ. ๊ทธ ๊ฒฉ์ฐจ๋ฅผ ์ค„์ด๋Š” ๊ฒƒ์€ ๋ฌด์—‡์ด๋“  Feliz ๋ฐ .Net ์„œ๋ฒ„๋กœ ์ž‘์—…ํ•  ๋•Œ ์‚ถ์˜ ์งˆ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์˜ˆ. ํ›Œ๋ฅญํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ฒฐ๊ตญ Feliz.Engine์ด Feliz์™€ ๋ช‡ ๊ฐ€์ง€ ์ฐจ์ด์  ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊นŒ๋‹ค๋กญ์Šต๋‹ˆ๋‹ค. ์ฆ‰, Feliz ์ž์ฒด์™€ ๊ฒฝ์Ÿํ•  Feliz.Engine React ๊ตฌํ˜„์„ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋ฏ€๋กœ ํ”ผํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค ;) ํ•˜์ง€๋งŒ ๋ฐ”๋ผ๊ฑด๋Œ€ ์šฐ๋ฆฌ๋Š” ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•ด๊ฒฐ์ฑ….

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