Implement Child Client

WRP์˜ ๋‘ ๊ฐ€์ง€์˜ ํ†ต์‹  ๋ฐฉ๋ฒ•

Web์—์„œ WRP๋ฅผ ์ด์šฉํ•œ ํ†ต์‹ ์„ ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋„ค์ดํ‹ฐ๋ธŒ ์•ฑ์ด ์ œ๊ณตํ•˜๋Š” ์ „์—ญ ๊ฐ์ฒด ์‚ฌ์šฉ: ์•ฑ๊ณผ ์›น๋ทฐ๊ฐ€ ํ†ต์‹ ํ•  ๋•Œ ์›น๋ทฐ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
  • iframe์˜ postMessage ์‚ฌ์šฉ: ์•ฑ๊ณผ ์›น๋ทฐ๊ฐ€ ํ†ต์‹ ํ•˜๋Š” ์ƒํ™ฉ์„ ๋ชจ๋ฐฉํ•ด์•ผ ํ•˜๋Š” ํ…Œ์ŠคํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ์— ์ ํ•ฉํ•œ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ด๋ฒˆ ์˜ˆ์ œ์—์„œ๋Š” iframe์œผ๋กœ ์•ฑ๊ณผ ์›น๋ทฐ๋ฅผ ๋ชจ๋ฐฉํ•˜๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์•ฑ๊ณผ ์›น๋ทฐ ์‚ฌ์ด์˜ ๊ด€๊ณ„๋ฅผ iframe ๋‚ด์—์„œ๋Š” ๋ถ€๋ชจ ์œˆ๋„์šฐ(parent window)-์ž์‹ ์œˆ๋„์šฐ(child window; iframe ๋‚ด๋ถ€์˜ ์œˆ๋„์šฐ)๋กœ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฒˆ ์„น์…˜์—์„œ๋Š” ์ž์‹ ์œˆ๋„์šฐ์— ํด๋ผ์ด์–ธํŠธ๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด๊ณ , ๋‹ค์Œ ์„น์…˜์—์„œ ๋ถ€๋ชจ ์œˆ๋„์šฐ์— ์„œ๋ฒ„๋ฅผ ๊ตฌํ˜„ํ•จ์œผ๋กœ์จ iframe ์˜ˆ์ œ๋ฅผ ์™„์„ฑํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ž์‹์— ํด๋ผ์ด์–ธํŠธ(๊ฒŒ์ŠคํŠธ) ๋งŒ๋“ค๊ธฐ

์ผ๋‹จ ์ ๋‹นํ•œ Client.tsx๋ฅผ ์ค€๋น„ํ•ด์ค๋‹ˆ๋‹ค. ์•ž์„œ ๋งŒ๋“  proto์™€ generated ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ์žˆ๋Š” ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ๋ผ๊ณ  ๊ฐ€์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

import React from "react";

const Client = () => {
  return (
    <>
      <div>Hello world!</div>
    </>
  );
};

export default Client;

ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” useClientImpl hook์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

importํ•œ ํ›„ clientImpl์„ ์ค€๋น„ํ•ด์ฃผ์„ธ์š”.

import React from "react";
+ import { useClientImpl } from "@pbkit/wrp-jotai/parent";

const Client = () => {
+  const clientImpl = useClientImpl();
  return (
    <>

useClientImpl์„ client๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ์— ํ•„์š”ํ•œ ์†Œ์ผ“๊ณผ ์ฑ„๋„ ๊ฐ™์€ ์ €์ˆ˜์ค€ ์ž์›๋“ค์„ ๋งŒ๋“  ๋’ค, clientImpl์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

client๋Š” ์–ด๋–ค ๊ฒƒ(์„œ๋น„์Šค)์„ ์–ด๋–ป๊ฒŒ(ํ†ต์‹  ๋ฐฉ๋ฒ•) ๋ณด๋‚ผ์ง€ ์•Œ์•„์•ผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. clientImpl์€ ํ†ต์‹  ๋ฐฉ๋ฒ•(WRP ์ฑ„๋„)์— ๋Œ€ํ•œ ์ •๋ณด๋งŒ ์•Œ๊ณ  ์žˆ๋Š” client์˜ ์ผ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ์„œ๋น„์Šค๊ฐ€ ๋‹ด๊ณ  ์žˆ๋Š” ๋ฉ”์†Œ๋“œ ์ •๋ณด๋“ค์„ ๋„ฃ์–ด์ฃผ๋ฉด ์™„์„ฑ๋œ client๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์„œ๋น„์Šค ์ •๋ณด๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ด์ „ ๋‹จ๊ณ„์—์„œ ์ƒ์„ฑํ•œ ์ฝ”๋“œ์—์„œ ์–ป์–ด์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import React, { useMemo } from "react";
import { useClientImpl } from "@pbkit/wrp-jotai/parent";
+ import { createServiceClient } from '../generated/services/pbkit/wrp/example/WrpExampleService';

const Client = () => {
  const clientImpl = useClientImpl();
+  const serviceClient = useMemo(() => {
+    if (!clientImpl) return;
+    return createServiceClient(clientImpl);
+  }, [clientImpl]);
  return (
    <>

์ƒ์„ฑ๋œ ์„œ๋น„์Šค ์ฝ”๋“œ์—์„œ createServiceClient๋ฅผ ์ด์šฉํ•ด serviceClient๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. serviceClient๋ฅผ ์ž…๋ ฅํ•ด๋ณด๋ฉด ์šฐ๋ฆฌ๊ฐ€ ์ •์˜ํ•œ ๋‘ rpc๊ฐ€ ์ถ”๋ก ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!

์ด์ œ ๋ฒ„ํŠผ์„ ์ถ”๊ฐ€ํ•˜๊ณ , ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ GetTextValue๋ฅผ ํ˜ธ์ถœํ•œ ๋’ค ๋ฐ›์€ ๊ฐ’์œผ๋กœ ๊ฒฐ๊ณผ๋ฅผ ๋„์›Œ ๋ด…์‹œ๋‹ค.

const Client = () => {
+  const [result, setResult] = useState<string>();
  const clientImpl = useClientImpl();
  const serviceClient = useMemo(() => {
    if (!clientImpl) return;
    return createServiceClient(clientImpl);
  }, [clientImpl]);
+   const onClick = async () => {
+     setResult((await serviceClient?.getTextValue({}))?.text);
+   };
  return (
    <>
+       <button onClick={onClick}>Click me!</button>
+       {result && <p>Result: {result}</p>}
    </>
  );
};

๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ๋ณด๋ฉด ๊ฒฐ๊ณผ๋กœ undefined๊ฐ€ ๋œจ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. rpc๋ฅผ ์ œ๊ณตํ•˜๋Š” ์„œ๋ฒ„(ํ˜ธ์ŠคํŠธ)๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋‹น์—ฐํ•œ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. ์ด์ œ ํ˜ธ์ŠคํŠธ๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด๋ฒˆ ์„น์…˜์—์„œ ๊ตฌํ˜„ํ•œ ๋‚ด์šฉ์„ ์•„๋ž˜์—์„œ ํ™•์ธํ•ด๋ณด์„ธ์š”!