experimental_taintObjectReference
taintObjectReference
๋ฅผ ์ฌ์ฉํ๋ฉด user
๊ฐ์ฒด์ ๊ฐ์ ํน์ ํ ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ์ ์กํ๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
experimental_taintObjectReference(message, object);
ํค, ํด์ ๋๋ ํ ํฐ์ด ์ ๋ฌ๋๋ ๊ฒ์ ๋ฐฉ์งํ๋ ๋ฐฉ๋ฒ์ taintUniqueValue
๋ฅผ ์ฐธ๊ณ ํ์ธ์.
๋ ํผ๋ฐ์ค
taintObjectReference(message, object)
ํด๋ผ์ด์ธํธ๋ก ์ ๋ฌ๋์ง ์์์ผ ํ ๊ฐ์ฒด๋ฅผ taintObjectReference
์ ํจ๊ป ํธ์ถํ์ฌ React์ ๋ฑ๋กํฉ๋๋ค.
import {experimental_taintObjectReference} from 'react';
experimental_taintObjectReference(
'ํ๊ฒฝ ๋ณ์๋ ํด๋ผ์ด์ธํธ๋ก ์ ๋ฌํ์ง ๋ง์ธ์.',
process.env
);
๋ ๋ง์ ์์ ๋ฅผ ์๋์์ ๋ณผ ์ ์์ต๋๋ค.
๋งค๊ฐ๋ณ์
-
message
: ๊ฐ์ฒด๊ฐ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ์ ๋ฌ๋ ๋ ํ์ํ ๋ฉ์์ง. ๊ฐ์ฒด๊ฐ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ์ ๋ฌ๋ ๋ ๋ฐ์ํ๋ ์๋ฌ ๊ฐ์ฒด์ ํฌํจ๋์ด ๋ํ๋๋ ๋ฉ์์ง์ ๋๋ค. -
object
: ์ค์ผ(taint)๋ ๊ฐ์ฒด. ํจ์์ ํด๋์ค ์ธ์คํด์ค๋object
๋ก์taintObjectReference
์ ์ ๋ฌ๋ ์ ์์ต๋๋ค. ํจ์์ ํด๋์ค๋ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ์ ๋ฌ๋์ง ์๋๋ก ์ด๋ฏธ ๋งํ์์ง๋ง React์ ๊ธฐ๋ณธ ์๋ฌ ๋ฉ์์ง ๋์message
์ ์ค์ ํ ๋ฉ์์ง๋ฅผ ๋ณด์ฌ์ค ์ ์์ต๋๋ค. ํ์ ๋ฐฐ์ด(Typed Array)์ ์ธ์คํด์ค๋ฅผobject
๋ก์taintObjectReference
์ ์ ๋ฌํ๋ฉด ๊ฐ์ ํ์ ๋ฐฐ์ด์ ๋ค๋ฅธ ์ธ์คํด์ค๊ฐ ์ค์ผ๋์ง ์์ต๋๋ค.
๋ฐํ๊ฐ
experimental_taintObjectReference
๋ undefined
๋ฅผ ๋ฐํํฉ๋๋ค.
์ฃผ์์ฌํญ
- ์ค์ผ๋ ๊ฐ์ฒด๋ฅผ ๋ค์ ์์ฑํ๊ฑฐ๋ ๋ณต์ ํ๋ฉด ์ค์ผ๋์ง ์์ ๊ฐ์ฒด๊ฐ ์๋ก ๋ง๋ค์ด์ง๋๋ค. ์๋ก ๋ง๋ค์ด์ง ๊ฐ์ฒด๋ ๋ฏผ๊ฐํ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ค์ผ๋
user
๊ฐ์ฒด๊ฐ ์๋ค๊ณ ํ ๋,const userInfo = {name: user.name, ssn: user.ssn}
ํน์{...user}
๋ฅผ ์คํํ๋ฉด ์ค์ผ๋์ง ์์ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.taintObjectReference
๋ ๊ฐ์ฒด๊ฐ ๋ณ๊ฒฝ๋์ง ์์ ์ํ์์ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ๊ทธ๋๋ก ์ ๋ฌ๋๋ ๊ฒ๋ง ๋ฐฉ์งํฉ๋๋ค.
์ฌ์ฉ๋ฒ
์ฌ์ฉ์ ๋ฐ์ดํฐ๊ฐ ์๋ํ์ง ์๊ฒ ํด๋ผ์ด์ธํธ๋ก ์ ๋ฌ๋๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ
ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์๋ ๋ฏผ๊ฐํ ๋ฐ์ดํฐ๋ฅผ ๋ด์ ๊ฐ์ฒด๊ฐ ์ ๋ฌ๋์ด์๋ ์ ๋ฉ๋๋ค. ์ด์์ ์ผ๋ก, ๋ฐ์ดํฐ ํ์น ํจ์๋ ํ์ฌ ์ฌ์ฉ์๊ฐ ์ ๊ทผํ ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ๋ ธ์ถํ๋ฉด ์ ๋ฉ๋๋ค. ํ์ง๋ง ๋ฆฌํฉํ ๋ง ๋์ค ๊ฐ๋ ์ค์๊ฐ ๋ฐ์ํ๊ธฐ๋ ํฉ๋๋ค. ๋ฐ์ดํฐ API์์ ์ฌ์ฉ์ ๊ฐ์ฒด๋ฅผ โ์ค์ผ(taint)โ์์ผ์ ์ด๋ฌํ ์ค์๋ฅผ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
import {experimental_taintObjectReference} from 'react';
export async function getUser(id) {
const user = await db`SELECT * FROM users WHERE id = ${id}`;
experimental_taintObjectReference(
'user ๊ฐ์ฒด ์ ์ฒด๋ฅผ ํด๋ผ์ด์ธํธ๋ก ์ ๋ฌํ์ง ๋ง์ธ์.' +
'ํ์ํ๋ค๋ฉด ์ผ๋ถ ํน์ ํ ํ๋กํผํฐ๋ง ๋ฝ์์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.',
user,
);
return user;
}
์ด์ ๋๊ตฐ๊ฐ ์ด ๊ฐ์ฒด๋ฅผ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ์ ๋ฌํ๋ ค๊ณ ํ๋ฉด ์ ๋ฌ๋ ์๋ฌ ๋ฉ์์ง์ ํจ๊ป ์๋ฌ๊ฐ ๋ฐ์๋ฉ๋๋ค.
Deep Dive
๋ฏผ๊ฐํ ๋ฐ์ดํฐ์ ์ ๊ทผํ ์ ์๋ ์๋ฒ ์ปดํฌ๋ํธ ํ๊ฒฝ์ ์คํํ๊ณ ์๋ค๋ฉด ๊ฐ์ฒด๋ฅผ ๊ทธ๋๋ก ์ ๋ฌํ ๋ ์ฃผ์๋ฅผ ๊ธฐ์ธ์ฌ์ผ ํฉ๋๋ค.
// api.js
export async function getUser(id) {
const user = await db`SELECT * FROM users WHERE id = ${id}`;
return user;
}
import { getUser } from 'api.js';
import { InfoCard } from 'components.js';
export async function Profile(props) {
const user = await getUser(props.userId);
// DO NOT DO THIS
return <InfoCard user={user} />;
}
// components.js
"use client";
export async function InfoCard({ user }) {
return <div>{user.name}</div>;
}
์ด์์ ์ผ๋ก, getUser
๋ ํ์ฌ ์ฌ์ฉ์๊ฐ ์ ๊ทผํ ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ๋
ธ์ถํ์ง ์์์ผ ํฉ๋๋ค. user
๊ฐ์ฒด๊ฐ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ์ ๋ฌ๋๋ ๊ฒ์ ๋ฐฉ์งํ๋ ค๋ฉด ์ฌ์ฉ์ ๊ฐ์ฒด๋ฅผ โ์ค์ผ(taint)โ์์ผ์ผ ํฉ๋๋ค.
// api.js
import {experimental_taintObjectReference} from 'react';
export async function getUser(id) {
const user = await db`SELECT * FROM users WHERE id = ${id}`;
experimental_taintObjectReference(
'user ๊ฐ์ฒด ์ ์ฒด๋ฅผ ํด๋ผ์ด์ธํธ๋ก ์ ๋ฌํ์ง ๋ง์ธ์. ' +
'ํ์ํ๋ค๋ฉด ์ผ๋ถ ํน์ ํ ํ๋กํผํฐ๋ง ๋ฝ์์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.',
user,
);
return user;
}
์ด์ ๋๊ตฐ๊ฐ user
๊ฐ์ฒด๋ฅผ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ์ ๋ฌํ๋ ค๊ณ ํ๋ฉด ์ค์ ํ ์๋ฌ ๋ฉ์์ง์ ํจ๊ป ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค.