๋์์ ์ ํ ์ดํ ๊ฐ์ฅ์ ๊ทธ๋ฆฌ์ ๊ฒ์ Fable.React
๋์ ์๋ค๋ ๊ฒ์
๋๋ค Feliz/Feliz.ViewEngine
, SSR์ ๊ณ ํต์
๋๋ค. ์๋ํ ์ ์์ง๋ง ์ฃผ์๊ฐ ํ์ํ๊ณ ..์ ์๋ํ๊ณ ์ฝ๋๋ฅผ ๋ณด๊ธฐ ํํ๊ฒ ๋ง๋ญ๋๋ค.
Fable.React
์์๋ ๋จ์ํ ํจ์๋ฅผ ํธ์ถํ๊ณ ๋ชจ๋ ๊ฒ์ SSR๋ก ์ฒ๋ฆฌํ ์ ์์์ต๋๋ค. "๊ทธ๋ฅ ์๋ํฉ๋๋ค." ๊ทธ๋ฆฌ๊ณ SSR๋ฟ๋ง ์๋๋ผ ํจ์ฌ ๋ ๋์ ํ
์คํธ๋ฅผ ํ๊ณ ์ด์ํ ํ๋์ ์ฐพ๋ ๋ฐ ๋์์ด ๋์์ต๋๋ค.
Feliz
์์๋ ๊ทธ ๊ฒฝํ์ ํ๊ฒ ๋์ด ๋๋จํ ๊ฐ์ฌํฉ๋๋ค. ๋ชจ๋ ํ์ผ(๋๋ ๋ ๋ค๋ฅธ ๋ค์์คํ์ด์ค์ ๋ค๋ฅธ ๋ฌธ์ ์ธํธ๊ฐ ์๋ Isomorphic ์ฌ์ฉ)์์ #if FABLE_COMPILER
์ ๋ณต์ก์ฑ๊ณผ ์ถํจ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์จ๊ฒจ์ ธ ์์ด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ธ ์ ์์ด์ผ ํ๋ค
open Feliz
AspNetCore์์๋ ์๋ํ๋๋ก ํฉ๋๋ค.
ํนํ Fable.Remoting
์ ํจ๊ป SSR์ ๋ํ ๊ธฐ๋ณธ ์ง์์ด Feliz/AspNetCore ์คํ์ ๊ฐ์น๋ฅผ ํฅ์์ํค๊ณ ์ผ๋ฐ์ ์ผ๋ก Full Stack F# ์คํ ๋ฆฌ์ ํฌ๊ฒ ๋์์ด ๋ ๊ฒ์ด๋ผ๊ณ ๋ฏฟ์ต๋๋ค.
์ด๋ป๊ฒ ์๊ฐํด?
๋ค, ์ ๋ ๊ทธ ์์ด๋์ด์ ๋ฐ๋ํ์ง ์์ต๋๋ค. ๋ํ ๋๊ธฐํ๋ฅผ ์ ์งํฉ๋๋ค.
@l3m๋ , ์ ๋ ์ด ์์ด๋์ด๊ฐ ์ ๋ง ๋ง์์ ๋ค์ด์. ๋ฌผ๋ก "
์ง๊ธ ๊ฐ์ฅ ์ข์ ์ ์ถฉ์์ SSR ๋ถ๋ถ์ Fable.React๋ฅผ ์ฌ์ฉํ๊ณ ๋๋จธ์ง ๋ถ๋ถ์ Feliz๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ Feliz/Feliz.ViewEngine์ ๊ณ์ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค.
Feliz์ ๋ํ ํ์ฌ ๊ณํ์ ์ฌ์ ํ โโ์์ํ React ์ง์ ๋ฐ ์ํ๊ณ์ ์ด์ ์ ๋ง์ถ๋ ๊ฒ์ ๋๋ค. ์ ์ ํ Svg ์ง์ #251, Fable 3์ ์ ์ ํ ๋น ๋ฅธ ์๋ก ๊ณ ์นจ ์ง์(#157 ๋ฐ #260) ๋ฐ ๋ชจ๋ ์ฅ์ (๋ฌธ์)์ผ๋ก ๋ ๋ง์ ์ ์ฒด ๊ตฌ์ฑ ์์ ๊ตฌํ , ์ ๋ฑ)
@Zaid-Ajaj ํ , ์ดํดํ ์ ์๋ ์ด์ ์ง๋ง ์ด ์ ๊ทผ ๋ฐฉ์์์ ๋ด๊ฐ ๋ณด๋ ๋ฌธ์ ๋ ๋ชจ๋ ์ข ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ SSR์ ๊ตฌํํ์ง ์๋๋ค๋ ๊ฒ์ ๋๋ค. Feliz์ ์๋ค๋ฉด ๋ชจ๋ ์ข ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์๋ ์์ ๊ฒ์ ๋๋ค.
์ด๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ค์์ ์๋ฏธํฉ๋๋ค. Feliz๋ ์ฅ๋๊ฐ์ด ์๋ ํ๋ก์ ํธ(SSR์ด ์ค์ ๋ก ํ์ํ ๊ฒฝ์ฐ)์ SSR๊ณผ ํจ๊ป ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ถ๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ง์ ์์ด ์์ํ Feliz๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋ ํฐ ํ๋ก์ ํธ์ ๊ฒฝ์ฐ ๋ ๋๋ฌธ ๊ฒฝ์ฐ์ธ ๊ฒ์ฒ๋ผ ๋ณด์ ๋๋ค.
์ฐ๋ฆฌ๋ฅผ ์ํด Feliz๊ฐ ์๋ SSR์ ์ถ๊ฐ ์ข ์์ฑ์ ์ฌ์ฉํด์ผ ํ ๋๊น์ง ์๋ํ๊ณ Feliz๊ฐ ์ ๊ณตํ์ง ์์ผ๋ฉด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฑ์๊ฐ ์์ ์ ์ํํ๋๋ก ์ค๋ํ๊ธฐ ์ด๋ ค์ด ๊ฒ ๊ฐ์ต๋๋ค.
๋ค, ๊ฝค ์ค๋๋ ฅ ์๋ ์ฃผ์ฅ์ ๋๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ด๋ฏธ ๊ตฌ์กฐํ๋ ๋ฐฉ์์ผ๋ก ์ธํด ํผ๋์ ์๋นํ ์ค์ผ ์ ์๋ค๊ณ ์๊ฐ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด ๋ชจ๋ ์์(๋๋ ๋๋ค์)๋ ๋๋ถ๋ถ์ ์์ฑ ๋ฑ๊ณผ ๋์ผํ ๋์ผํ 2-3๊ฐ์ ํจ์๋ฅผ ํธ์ถํฉ๋๋ค. ๋ฐ๋ผ์ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ํด๋น ์์ค์์ ์์ ์ด ํ์ํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๋ด๊ฐ ์ ์์ง ๋ชปํ๋ ๋ณด๊ธฐ ์์ง์์ ์ํ๋ ๋ช ๊ฐ์ง ํน๋ณํ ์์ ์ด ์์ต๋๋ค. ์๋ง๋ @dbrattli ๊ฐ ๊ทธ/์ด ์ฃผ์ ์ ๋ํด
๋ค, ์ ๋ ๊ณ ํต์ ๋๋ผ๊ณ ์์ต๋๋ค . ๋๋ถ๋ถ ๋ค๋ฅธ ๋ค์์คํ์ด์ค๋ก ์ธํด ํ์ผ ์ ์ฒด์ ๋ง์ #if FABLE_COMPILER
๋ฐ์ํฉ๋๋ค. ๊ทธ๋ฌ๋ Ionide๊ฐ์ ์จ์ด ๋ํ ReactElement
Feliz.ViewEngine์ด ๊ฐ์ ์๋ค๋ ReactElement
Fable.React์. Feliz์์ ๋ชจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(์: Feliz.MaterialUI
๋ฅผ .ViewEngine์ผ๋ก ์ด์ํ๊ณ ๋๊ธฐํ ์ํ๋ก ์ ์งํ๋ ๊ฒ์ ๊ณ ํต์ค๋ฌ์ธ ๊ฒ์
๋๋ค. Feliz.Bulma.ViewEngine์ ์ต์ ์ํ๋ก ์ ์งํ๋ ๊ฒ์ ์ด๋ฏธ ํฌ๊ธฐํ ๊ฒ ๊ฐ์ต๋๋ค.
ํ ๋ฆฌ ์ฆ ์ฝ๋ ์๋ฒ ์ธก์ ์ฌ์ฉํ์ฌ ์ฃผ์ ๋ฌธ์ ๋ ์๋ฅผ ๋ง์ด ์ฌ์ฉํ๋ค๋ ๊ฒ์
๋๋ค unbox<string>(value)
๋์ string value
. ์ฌ๊ธฐ์ ์ฑ๋ฅ ์ด๋์ด๋ ๋ฌด์์
๋๊น? ์ฐจ์ด์ ์ ์จ๊ธฐ๊ธฐ ์ํด ์ธ๋ผ์ธ ํจ์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๊น? ์๋ฒ ์ธก์์ ๋ค๋ฅด๊ฒ ์ฒ๋ฆฌํด์ผ ํ๋ !!e?value <> !!value then e?value
๊ฐ์ Fable.Core.JsInterop ํญ๋ชฉ๋ ์์ต๋๋ค.
Feliz.ViewEngine์ ReactElement
๋ฅผ HTML๋ก ๋ค์ ๊ตฌ๋ฌธ ๋ถ์ํ๋ ๊ฒ์ด ์ฝ์ง ์๊ธฐ ๋๋ฌธ์ ์์ฒด ๋ฐ์ดํฐ ๋ชจ๋ธ๋ ์ฌ์ฉํฉ๋๋ค. ๋ฐ๋ผ์ !FABLE_COMPILER
๋ Interop.fs์์ ViewEngine ์ ํ์ ์์ฑํ ์ ์๋ค๋ฉด ์ข์ ๊ฒ์
๋๋ค. ViewEngine ์ ํ์ ์ฌ์ ํ ReactElement์์ ์์ ํ ์ ์์ผ๋ฏ๋ก ์๋ช
์ด ๋์ผํ๊ฒ ์ ์ง๋ฉ๋๋ค.
๊ทธ๋์ ๊ฐ๋ฅํ๋ค๊ณ ์๊ฐํ์ง๋ง Feliz ์์ฒด์ ์ฝ๊ฐ์ ๋ณ๊ฒฝ๊ณผ ์ฝ๊ฐ์ #if FABLE_COMPILER
๊ฐ ํ์ํฉ๋๋ค. ๊ทธ๋ฌ๋ @Zaid-Ajaj๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ณํฉ ์์ด๋์ด์ ๋ํด ์น์ธ๋ ์์น์ ์ ๊ณตํ ๋๊น์ง๋ ๊ทธ๋ฌํ ๋
ธ๋ ฅ์ ์์ํ์ง ์์ ๊ฒ์
๋๋ค..
์๋ฅผ ๋ค์ด unbox<string>(value)
๋ ์ฌ์ฉํ๋ Feliz.Bulma ์ ๋ํด์๋ ์ ์ฌํ ๋ณ๊ฒฝ์ด ํ์ํ์ง๋ง ์์
๋ฐฉ๋ฒ์ ๋ํ ๊ณตํต ๊ถ์ฅ ์ฌํญ์ด ์๋ค๋ฉด ์ข
์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๊ฒฐ๊ตญ์๋ ์๋ํ ๊ฒ์
๋๋ค.
๊ฐ๋ฅํ ๊ฒฝ์ฐ unbox<string>
์ฌ์ฉํ๋ ์ด์ ๋ฅผ ๋ณด๋ ค๋ฉด ๋ค์์ ๊ณ ๋ คํ์ธ์.
box
/ unbox
๋ JS์ด๊ธฐ ๋๋ฌธ์ ์ปดํ์ผ ์์ ์ง์์ง๋๋ค.
string i
ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ปดํ์ผ๋ฉ๋๋ค.
// fable-library
export function int32ToString(i: number, radix?: number) {
i = i < 0 && radix != null && radix !== 10 ? 0xFFFFFFFF + i + 1 : i;
return i.toString(radix);
}
// Calling site
import { int32ToString } from "fable-library/Util.js";
export const test = int32ToString(1);
unbox<string> 1
ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ปดํ์ผ๋ฉ๋๋ค.
export const test = 1;
๋ฐ๋ผ์ ๋ชจ๋ ์ ๋ ฅ์ ๋ํ ์ ํ์ ์ฌ์ฉํ๋ 10๊ฐ์ ์์ฑ์ด ์์ง๋ง ์ค์ ํํ์ด ๋ฌธ์์ด์ธ ๊ฒฝ์ฐ ํด๋น ์์ฑ์ ํด๋น ๊ตฌ์ฑ ์์๋ฅผ ๋ค์ ๋ ๋๋ง ํ ๋ฉ๋๋ค . ์ด๊ฒ์ ๋จ์ผ ์ธ์คํด์ค์ ์คํ ๋น์ฉ์ ์์ฒญ๋๊ฒ ์์ง๋ง, ์ ์ฌ์ ์ผ๋ก ์๋ฐฑ ๊ฐ์ ๊ตฌ์ฑ ์์์ ๊ฑธ์ณ ์๋ ๊ฐ ๊ตฌ์ฑ ์์์ 1-20๊ฐ๋ฅผ ๊ฐ์ง ์ ์๋ ๊ฒฝ์ฐ ์ด๋ฌํ ํธ์ถ ์ฌ์ดํธ์์ ๊ณ์ฐ์ ์ค์ด๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
์ด์ ์ด์ ๋ํ ์๋ฃจ์ ์ ์ค์ ๋ก ๋งค์ฐ ๊ฐ๋จํฉ๋๋ค.
let inline unboxStr o =
#if FABLE_COMPILER
unbox<string> o
#else
string o
#endif
๊ทธ๋ฐ ๋ค์ unbox<string>
์์ ์ฐพ๊ธฐ ๋ฐ๊พธ๊ธฐ๋ฅผ ์ํํฉ๋๋ค.
Fable 3์๋ ์๋นํ ์ฌ์์ฑ์ด ํฌํจ๋ ๊ฐ๋ฅ์ฑ์ด ๋๊ธฐ ๋๋ฌธ์ ์์์ ์ธ๊ธํ @Zaid-Ajaj์ ๋ค๋ฅธ ๋ฌธ์ ๋ฅผ ์์ ํ๋ ๋์ ์ด ์์ ์ ์ํํ ์ ์ ํ ์๊ธฐ๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ฐ๋ฆฌ๋ ์ด๊ฒ์ ํ๊ธฐ๋ฅผ ์ํ ๊ฒ์ ๋๋ค. (๋๋ @Zaid-Ajaj๊ฐ SSR์ ๋ฐ๋ํ์ง ์๋๋ค๊ณ ๋งํ๋ ๊ฒ์ด ๋งค์ฐ ์์ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์๋ง์ ์คํ๊ฒํฐ๊ฐ ๊ทธ์ ์ฝ๋ ๋ฒ ์ด์ค ์ ์ฒด์ ์์์ง๋ ๊ฒ์ ๋ฐ๋ํ๋ ๊ฒ๋งํผ), ๊ทธ๋ฆฌ๊ณ ์ ๋ ๊ทธ๊ฒ์ด ๊ฐ์ฅ ๊ณ ํต์ค๋ฝ์ง ์์ ๊ฒ์ด๋ผ๊ณ ๋ฏฟ์ต๋๋ค. /๊ทธ ๊ธฐ๊ฐ ๋์ ์ฒ์๋ถํฐ SSR์ ์ผ๋์ ๋๊ณ ์๋ฃํ๋ค๋ฉด ์ง์ ๋ถํฉ๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
Fable 3์๋ ์๋นํ ์ฌ์์ฑ์ด ํฌํจ๋ ๊ฐ๋ฅ์ฑ์ด ๋๊ธฐ ๋๋ฌธ์ ์์์ ์ธ๊ธํ @Zaid-Ajaj์ ๋ค๋ฅธ ๋ฌธ์ ๋ฅผ ์์ ํ๋ ๋์ ์ด ์์ ์ ์ํํ ์ ์ ํ ์๊ธฐ๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ฐ๋ฆฌ๋ ์ด๊ฒ์ ํ๊ธฐ๋ฅผ ์ํ ๊ฒ์ ๋๋ค. (๋๋ @Zaid-Ajaj๊ฐ SSR์ ๋ฐ๋ํ์ง ์๋๋ค๊ณ ๋งํ๋ ๊ฒ์ด ๋งค์ฐ ์์ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์๋ง์ ์คํ๊ฒํฐ๊ฐ ๊ทธ์ ์ฝ๋ ๋ฒ ์ด์ค ์ ์ฒด์ ์์์ง๋ ๊ฒ์ ๋ฐ๋ํ๋ ๊ฒ๋งํผ), ๊ทธ๋ฆฌ๊ณ ์ ๋ ๊ทธ๊ฒ์ด ๊ฐ์ฅ ๊ณ ํต์ค๋ฝ์ง ์์ ๊ฒ์ด๋ผ๊ณ ๋ฏฟ์ต๋๋ค. /๊ทธ ๊ธฐ๊ฐ ๋์ ์ฒ์๋ถํฐ SSR์ ์ผ๋์ ๋๊ณ ์๋ฃํ๋ค๋ฉด ์ง์ ๋ถํฉ๋๋ค.