โ† ๋ชฉ๋ก์œผ๋กœ
Building Context-Query Library

๋™๊ธฐ

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

  • Props
  • ์ „์—ญ์ƒํƒœ
  • Context API
  • React Query

Props๋Š” ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ•์ด์ง€๋งŒ, ์ปดํฌ๋„ŒํŠธ์˜ ๊นŠ์ด๊ฐ€ ๊นŠ์–ด์ง€๋ฉด ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์–ด๋ ค์›Œ์ง‘๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ Prop Drilling์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์ „์—ญ์ƒํƒœ๋Š” ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
์†์‰ฝ๊ฒŒ ์ƒํƒœ๋ฅผ ์ •์˜ํ•˜๊ณ  ๊ณต์œ  ํ•  ์ˆ˜ ์žˆ์œผ๋‚˜, ์ปดํฌ๋„ŒํŠธ ์‚ฌ์ดํด์— ๋ฒ—์–ด๋‚˜๋ฏ€๋กœ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด์„œ ์ˆ˜๋™์œผ๋กœ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Context API๋Š” ํŠน์ • ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ ๋‚ด์—์„œ ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
์ปดํฌ๋„ŒํŠธ์˜ ๋ผ์ดํ”„์‚ฌ์ดํด์— ๋”ฐ๋ผ ์ƒํƒœ๊ฐ€ ๊ด€๋ฆฌ๋˜์„œ ํŽธํ•˜์ง€๋งŒ Context์˜ ์ผ๋ถ€ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

React Query๋Š” ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—†์œผ๋ฉด ์ž๋™์œผ๋กœ ์ƒํƒœ๋ฅผ ์‚ญ์ œํ•˜๋Š” ์ตœ์ ํ™”๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ React Query์˜ ์ฃผ๋œ ๋ชฉ์ ์€ ์„œ๋ฒ„์˜ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๊ฐ ๋ฐฉ๋ฒ•์—๋Š” ํŠน์ง•์ด ์กด์žฌํ•˜๋Š”๋ฐ ์ œ๊ฐ€ ์›ํ•˜๋Š” ์š”๊ตฌ์‚ฌํ•ญ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ์ปดํฌ๋„ŒํŠธ ๋ผ์ดํ”„์‚ฌ์ดํด์— ๋”ฐ๋ผ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌ - ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ฌ๋ผ์ง€๋ฉด ์ƒํƒœ๋„ ์‚ฌ๋ผ์ง€๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  2. ๋ฆฌ๋ Œ๋”๋ง ์ตœ์ ํ™” - ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์œผ๋ฉด ๋ฆฌ๋ Œ๋”๋ง ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ฒฐ๊ตญ Context API์™€ React Query์˜ ๊ฐ ์žฅ์ ์„ ๊ฒฐํ•ฉํ•œ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ Context Query๋ฅผ ๊ฐœ๋ฐœํ•˜์˜€์Šต๋‹ˆ๋‹ค.

Context Query ๊ตฌ์กฐ

Context Query๋Š” ๋ชจ๋…ธ๋ ˆํฌ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์œผ๋ฉฐ ์ฝ”์–ด ํŒจํ‚ค์ง€์™€ ์ฝ”์–ด ํŒจํ‚ค์ง€๋ฅผ ์ด์šฉํ•ด ๊ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‚˜ ํ”„๋ ˆ์ž„์›Œํฌ์— ๋งž๊ฒŒ ๊ฐœ๋ฐœ ํ•  ์ˆ˜ ์žˆ๋„๋ก,
์–ด๋Œ‘ํ„ฐ ํŒจํ„ด์„ ์ด์šฉํ•ด ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํ˜„์žฌ๋Š” ๋ฆฌ์•กํŠธ๋งŒ ์ง€์›ํ•˜์ง€๋งŒ ์ถ”ํ›„ ํ™•์žฅ์„ฑ์„ ์—ผ๋‘ํ•œ ์•„ํ‚คํ…์ฒ˜์ž…๋‹ˆ๋‹ค.

์ฝ”์–ด ํŒจํ‚ค์ง€๋Š” ์Šคํ† ์–ด ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์Šคํ† ์–ด๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ฐ˜ํ™˜ ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์˜ต์ €๋ฒ„ ํŒจํ„ด์„ ์ด์šฉํ•˜์—ฌ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ ๋  ๋•Œ ๋“ฑ๋ก๋œ ๋ฆฌ์Šค๋„ˆ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋ฆฌ์•กํŠธ ํŒจํ‚ค์ง€๋Š” ์Šคํ† ์–ด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๊ฐ ์ปค์Šคํ…€ ํ›…์—์„œ ์ƒํƒœ๋ฅผ ๊ตฌ๋…ํ•˜๊ณ  ๋ฆฌ์Šค๋„ˆ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰ ๋  ๋•Œ ๋ฆฌ์•กํŠธ์˜ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๋Š” ๊ตฌ์กฐ๋กœ ๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜๊ณผ ์„ฑ๋Šฅ ์ตœ์ ํ™”

๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜์„ ๋†’์ด๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ๊ฐ€์ง€๋ฅผ ๊ณ ๋ คํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ์ค‘ ํ•˜๋‚˜๊ฐ€ Context ์™ธ๋ถ€์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๊ด€ํ•œ๊ฒƒ์ž…๋‹ˆ๋‹ค
Context Query๋Š” ๊ฒฐ๊ตญ Context API์˜ Provider๋กœ ๊ตฌ์„ฑ๋˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž…๋‹ˆ๋‹ค. ์ด๋Š” Provider๋กœ ์ดˆ๊ธฐ๊ฐ’์„ Props๋กœ ์ „๋‹ฌ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์ฒ˜์Œ์—๋Š” ์ด๋Ÿฐ ๋ฐฉํ–ฅ์œผ๋กœ ๊ฐœ๋ฐœ์„ ์‹œ์ž‘ํ–ˆ์ง€๋งŒ ์„ฑ๋Šฅ ์ตœ์ ํ™” ๋ฌธ์ œ์— ๋ถ€๋”ช์ณค์Šต๋‹ˆ๋‹ค.
props๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ๋ฆฌ์•กํŠธ์—์„œ๋Š” ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ชจ๋‘ ๋ฆฌ๋ Œ๋”๋ง ํ•˜๋Š” ๋ฌธ์ œ์˜€์Šต๋‹ˆ๋‹ค. ์„ฑ๋Šฅ์„ ์ตœ์ ํ™” ํ•˜๋ฉด์„œ ๊ฐœ๋ฐœ์ž๊ฐ€ Provider ์™ธ๋ถ€์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ดˆ๊ธฐํ™” ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋Š” Store์˜ ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค. Provider๋กœ Props๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š๊ณ  Store์— ์ง์ ‘์ ์œผ๋กœ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ๊ทธ์— ๋”ฐ๋ผ ์ƒํƒœ๋ฅผ ๊ตฌ๋…ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์—๊ฒŒ ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹์ด์˜€์Šต๋‹ˆ๋‹ค.
์ด๋Š” Props๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐœ์ƒ์‹œํ‚ค์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ฐœ๋ฐœ์ž๊ฐ€ ์ƒํƒœ๋ฅผ ์‰ฝ๊ฒŒ ๊ตฌ๋… ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ๋…ํ•˜๊ณ ์ž ํ•˜๋Š” ์ƒํƒœ์˜ ๊ฐ ํ‚ค๊ฐ’์„ ๋ฐฐ์—ด๋กœ ์ „๋‹ฌํ•˜์—ฌ ๋‹ค์ค‘ ๋˜๋Š” ๋‹จ์ผ๋กœ ์ƒํƒœ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ Context Query๋ฅผ ๋งŒ๋“ค๊ณ  ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์„ ๊ฒฐ์ •ํ•  ๋•Œ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ์™ธ๋ถ€์—์„œ ์„ ์–ธํ•˜์—ฌ ํ•„์š”ํ•œ ๊ณณ์— ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ์‹์„ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.
์ด๋Š” Zustand ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ฒ˜๋Ÿผ ๋น„์Šทํ•œ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ContextQuery๋ฅผ ์ƒ์„ฑํ•˜๋ฉด Provider์™€ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋Š” ํ›…์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

Provider์™€ ์ปค์Šคํ…€ ํ›…์€ ๋‚ด๋ถ€์ ์œผ๋กœ ํ•˜๋‚˜์˜ ์Šคํ† ์–ด๋ฅผ ๊ณต์œ ํ•˜๋ฏ€๋กœ Provider์™€ ํ›…์„ ๊ฐ™์ด ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ๋™์ผํ•œ ์ƒํƒœ๋ฅผ ์กฐ์ž‘ํ•˜๊ณ  ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์ž„์„ ์ธ์ง€์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

Context Query ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ๋ฐฉ๋ฒ•

createContextQuery ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ์ดˆ๊ธฐ๊ฐ’์„ ์ „๋‹ฌํ•˜๊ณ  ์ด์— ๋”ฐ๋ผ ํƒ€์ž…์ด ์ž๋™์œผ๋กœ ์ถ”๋ก ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์‹ค ์ œ๋„ค๋ฆญ์€ ์„ ์–ธํ•  ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค. ์ œ๋„ค๋ฆญ์€ ๋ช…์‹œ์ ์ธ ์„ ์–ธ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฐ˜ํ™˜๋œ Provider๊ณผ useํ›…์— ๋ณ„์นญ์„ ๋ถ€์—ฌํ•˜์—ฌ ๊ตฌ๋ถ„์ด ์ž˜๋˜๊ฒŒ ํ•˜๊ณ  ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ํ›…์—์„œ ์ œ๊ณตํ•˜๋Š” ํ•จ์ˆ˜๋Š” ๋ฆฌ์•กํŠธ์˜ useState ํ›…์˜ setter ํ•จ์ˆ˜์™€ ๋™์ผํ•˜๊ฒŒ ๋™์ž‘ํ•˜๋ฏ€๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์€ ๊ธˆ๋ฐฉ ์ตํž ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

interface UserData {
  name: string;
  email: string;
  preferences: {
    theme: "light" | "dark";
    notifications: boolean;
  };
}

export const {
  Provider: UserQueryProvider,
  useContextQuery: useUserQuery,ํŠน
  updateState: updateUserState,
  setState: setUserState,
} = createContextQuery<UserData>({
  name: "",
  email: "",
  preferences: {
    theme: "light",
    notifications: true,
  },
});

function UserProfilePage({ userId }: { userId: string }) {
  useEffect(() => {
    // Initialize state with external data
    const loadUserData = async () => {
      const userData = await fetchUserData(userId);
      updateUserState(userData); // Update entire state with fetched data
    };
    loadUserData();
  }, [userId]);

  return (
    <UserQueryProvider>
      <div className="user-profile">
        <UserInfoForm />
        <UserPreferencesForm />
        <SaveButton />
      </div>
    </UserQueryProvider>
  );
}

function UserInfoForm() {
  // Subscribe to user info fields only
  const [state, setState] = useUserQuery(["name", "email"]);

  return (
    <div className="user-info">
      <h3>Basic Information</h3>
      <div>
        <label>Name:</label>
        <input
          value={state.name}
          onChange={(e) =>
            setState((prev) => ({ ...prev, name: e.target.value }))
          }
        />
      </div>
      <div>
        <label>Email:</label>
        <input
          value={state.email}
          onChange={(e) =>
            setState((prev) => ({ ...prev, email: e.target.value }))
          }
        />
      </div>
    </div>
  );
}

Context Query๊ฐ€ ํ•„์š”ํ•œ ๊ณณ

๋ชจ๋“  ์ƒํƒœ๋ฅผ Context Query๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ๋งž์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ ์ ˆํ•˜๊ฒŒ ๋ชฉ์ ์— ๋”ฐ๋ผ ์ƒํƒœ ๊ด€๋ฆฌ ๋ฐฉ๋ฒ•์„ ์„ ํƒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿผ Context Query๊ฐ€ ๊ฐ€์žฅ ์ ํ•ฉํ•œ ์‹œ๊ธฐ๋Š” ์–ธ์ œ์ผ๊นŒ์š”?

๋ฐ”๋กœ Props Drilling ์—†์ด ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ๋กœ ์กฐํ•ฉ๋œ ํ•˜๋‚˜์˜ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ๋•Œ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์ „์—ญ ์ƒํƒœ๋‚˜ ๋ฆฌ์•กํŠธ ์ฟผ๋ฆฌ๋กœ ๊ด€๋ฆฌํ•˜๋ฉด ์˜ค๋ฒ„ ์—”์ง€๋‹ˆ์–ด๋ง์ด๊ณ 
Context API๋Š” ์ „์ฒด ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ์—๋Š” ์ ํ•ฉํ•˜๋‚˜ ์ž‘์€ ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ๋ฅผ ์œ„ํ•ด์„œ๋Š” ์ ํ•ฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  Context API๋Š” ์ƒ์„ฑํ•˜๊ธฐ์œ„ํ•ด ์ง์ ‘ ํ›…๊ณผ Provider๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฝ”๋“œ๊ฐ€ ๋งŽ์•„์ง‘๋‹ˆ๋‹ค.
๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ž‘๊ฒŒ, Props Drilling ์—†์ด ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•˜๋Š” ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

๋งŒ๋“ค๋ฉด์„œ ๋ฌด์—‡์ด ํž˜๋“ค์—ˆ๋‚˜

๊ธฐ์ˆ ์ ์ธ ๋‚œ์ด๋„๊ฐ€ ๋†’์€ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ฐ ๋ฌธ์ œ์— ๋ถ€๋”ชํž๋•Œ ์•„์ด๋””์–ด๋ฅผ ์ด์šฉํ•ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ฐœ๋ฐœ์ž๊ฐ€ ์†์‰ฝ๊ฒŒ ์ด์šฉํ•˜๋„๋ก ์„ค๊ณ„ํ•˜๋Š”๊ฒƒ ์—ญ์‹œ ์‰ฌ์šด ๊ณผ์ •์€ ์•„๋‹ˆ์˜€์Šต๋‹ˆ๋‹ค.

๋” ๊ฐœ์„ ํ•ด์•ผ ํ•  ์ ์€ ๋งŽ์ง€๋งŒ ๋ฒ„์ „์ด ์˜ฌ๋ผ๊ฐ€๋ฉด์„œ ๋งŽ์€ ์ด๋“ค์—๊ฒŒ ์ €์ฒ˜๋Ÿผ ๋™์ผํ•œ ๋ฌธ์ œ๋ฅผ ๋งŒ๋‚ฌ์„๋•Œ ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด ์†์‰ฝ๊ฒŒ ๊ฐœ๋ฐœ ํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค.

Github - https://github.com/load28/context-query