๋ก๊ทธ์ธ
์ ํ๋ฉด ๋ฐฑ์๋๋ก ๋ก๊ทธ์ธ api ์์ฒญ์ด ๋๊ณ , ๋ฐฑ์๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ์ ์ ๋ณด๊ฐ ์๋์ง ํ์ธํ๋ค. ๋ง์ฝ ํ์์ ๋ณด์ ๋ก๊ทธ์ธ ์ ๋ณด๊ฐ ์ผ์นํ๋ฉด ๋ฐฑ์๋ ์ปดํจํฐ์ ๊ฐ์ฒด(Session)๋ฅผ ๋ง๋ค์ด๋๊ณ ์ ๋ณด๋ฅผ ์ ์ฅํ๋ค.
๊ทธ ํ์ ํน์ ํ ์ธ์
์์ด๋
๋ฅผ ๋ถ์ฌํด์ ๋ธ๋ผ์ฐ์ ๋ก ๋ณด๋ด์ค๋ค. ์ ์ฅ ์ฅ์๋ก๋ state, ๋ณ์, ๋ธ๋ผ์ฐ์ ์ ์ฅ๊ณต๊ฐ(local storage), session storage, ์ฟ ํค ๋ฑ์ด ์๋ค.
๋ก๊ทธ์ธ(์ธ์ฆ) ํ์ fetchUser์ฒ๋ผ ํ์์ ๋ณด๋ฅผ ํ์ฉํ๊ธฐ ์ํด์๋ http header์ ๋ก๊ทธ์ธ ์ฆํ์ธ ์ธ์
์์ด๋๋ฅผ ๋ถ์ฐฉํด์ ๋ฐฑ์๋๋ก ๋ณด๋ด๊ฒ ๋๋ค(์ธ๊ฐ). ๋ฐฑ์๋์์๋ http header
์ ์ธ์
์์ด๋๊ฐ ๋ค์ด์์๋์ง ํ์ธํ๊ณ , session์ ์ ๋ณด๊ฐ ์๋์ง ์ฒดํฌํ๋ค. ๊ทธ ํ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ฐ์ ์์ฒญ๋ฐ์ ์ ๋ณด๋ฅผ ์ฐพ์์ ๋๋ ค์ค๋ค.
์ด ๋ฐฉ์์ ์ธ์ ์์ด๋๋ฅผ ํตํด ๋ณธ์ธ์ด ๋๊ตฐ์ง๋ ์๋ณํ ์ ์์ง๋ง, ์ฌ์ฉ์๊ฐ ๋ง์์ง๋ฉด, session์ ์ ์ฅํ๊ธฐ ์ํ ๋ฉ๋ชจ๋ฆฌ(RAM)์ด ๋ถ์กฑํด์ง๋ค. ์ด๋ฅผ ๋ณด์ํ๊ธฐ ์ํด์ ์ปดํจํฐ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ๊ทธ๋ ์ด๋(scale-up)ํด์ฃผ์๋ค.
๋ฐฑ์๋ ์ปดํจํฐ์ ์ฑ๋ฅ์ ์ ๊ทธ๋ ์ด๋ ํ์์๋ ๋ ๋ง์ ์ ์ ์ ์ ์์ด ๋์๋ค๋ฐ์ ์ผ๋ก ์ผ์ด๋๋ฉด, ์ฌ์ ํ ์๋ฒ์ ๋ถํ๋ฅผ ์ด๋ํ๋ค.
๊ทธ๋์ ๋์จ ๊ฒ์ด scale-out(์ํํ์ฅ๋ฐฉ์)
์ด๋ค. ๋ฐฑ์๋ ์ปดํจํฐ๋ฅผ ์ฌ๋ฌ ๋ ๋ง๋ จํด์ ๊ฐ์ ์๋ฒ๊ฐ ์คํ๋๊ฒ๋ ํ๋ ๋ฐฉ์์ด๋ค.
ํ์ง๋ง ๋ฐฑ์๋ ์ปดํจํฐ๋ฅผ ๋ณต์ฌํ ๋ ์ธ์ ๊น์ง scale out ๋์ง ์์์ ๊ธฐ์กด์ ๋ก๊ทธ์ธ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๋ ์ปดํจํฐ๊ฐ ์๋ ๋ค๋ฅธ ์ปดํจํฐ์ ๊ฐ๋ฉด ์ธ์ ํ ์ด๋ธ์ ์ ๊ทผํ ์ ์๊ฒ ๋์๋ค.
์์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ธ์
ํ
์ด๋ธ์ ๊ฐ์ ธ๋ค ๋์๋ค. ํ์ง๋ง ์ด ์ญ์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ธ์
ํ
์ด๋ธ์ ๋ถํ๊ฐ ์ง์ค๋์ด์ ๋๋ ค์ง๋ ๋ณดํ๋ฅ ํ์
์ ์ผ์ผ์ผฐ๋ค!
๋ฐ๋ผ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ชผ๊ฐ๋ ๋ฐฉ๋ฒ์ ๊ณ ์ํด๋๋ค.
์์งํํฐ์ ๋ ํน์ ์ํํํฐ์ ๋(์ค๋ฉ)์ ํตํด ์ชผ๊ฐ๊ณ , ์ ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์์ ๋ ํด๋น ๋ฐ์ดํฐ๊ฐ ์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐฉ์์ ํ์ฉํ๋ค. ๋ค๋ง ๋ฐ์ดํฐ๋ค์ด Disk์ ์ ์ฅ๋๋ฉด์ ์ธ๊ฐ๋ฅผ ํ ๋์๋ Disk IO๊ฐ ๋๋ฌด ๋ง์ด ๋ฐ์ํด์ ์ฒ๋ฆฌ์๋๊ฐ ๋๋ ค์ง๊ฒ ๋์๋ค.
๊ทธ๋์ ๋์จ ๊ฒ์ด Redis
์ด๋ค. Redis๋ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํด๋๋ ์์ ๋ฐ์ดํฐ ๋ฒ ์ด์ค๋ก, Redis์ sessioin table์ ๋๊ณ , ์ธ๊ฐ๋ฅผ ํ์ ๋์๋ ๋ฐ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ก ๊ฐ๋ ๊ฒ์ด ์๋๋ผ redis์ session table์์ ๊ฒ์ฆํ๊ณ , ๋ณธ ์ ์ ๋ฐ์ดํฐ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ฐ์ ๊ฐ์ ธ์จ๋ค. ์ด ๋ฐฉ์์ด ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ๋ฐฉ์ ์ค ํ ๊ฐ์ง ๋ฐฉ์์ด๋ค!
redis์๋ ์ ๊ทผํ์ง ์๋ ๋ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ด ์์๊น? ๋๋ํ ๊ฐ๋ฐ์๋ค์ด ๊ทธ๋ฐ ๋ฐฉ๋ฒ์ ์ฐพ์๋๋ค!
๋ฐ๋ก, ์ธ์
์์ด๋๋ฅผ redis์ ๋ง๋๋ ๊ฒ์ด ์๋๋ผ, ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋ฐฑ์๋๋ก ๊ฐ์ ธ์จ ํ ๊ฐ์ฒด๋ฅผ ๋ฌธ์์ด๋ก ๋ง๋ค์ด ์ํธํ์์ผ์ ์ํธํ๋ ํค(accessToken
)๋ฅผ ๋ธ๋ผ์ฐ์ ์ ๋๋ ค์ฃผ๋ ๋ฐฉ๋ฒ์ด๋ค.
์ก์ธ์คํ ํฐ
์ ๋ธ๋ผ์ฐ์ ์ state ๋ฑ์ ์ ์ฅํด ๋์๋ค๊ฐ ๋ธ๋ผ์ฐ์ ์์ ๋ฐฑ์๋๋ก api ์์ฒญํ ๋ ๋ค์ ์ก์ธ์คํ ํฐ์ ๋ณด๋ด์, ๋ฐฑ์๋์์ ๋ณตํธํ(์ํธ ํด๋
)ํด์ ์ฌ์ฉ์๋ฅผ ์๋ณํ ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๊ทผํ๊ฒ ๋๋ค.
์ด๋ฌํ ๋ฐฉ์์ JWT(Json Web Token) ๋ฐฉ์
์ด๋ผ๊ณ ํ๋ค. JWT ํ ํฐ์ ํด๋น ํ ํฐ์ด ๋ฐ๊ธ ๋ฐ์์จ ์๋ฒ์์ ์ ์์ ์ผ๋ก ๋ฐ๊ธ์ ๋ฐ์๋ค๋ ์ฆ๋ช
์ ํ๋ signature๋ฅผ ๊ฐ์ง๊ณ ์์ด์ ์ฌ์ฉ์์ ์ ๋ณด๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ด์ด๋ณด์ง ์๊ณ ๋ ์๋ณํ ์ ์๋ค.
JWT ๋ฐฉ์์์ ์ก์ธ์คํ ํฐ์ ์ ์ฅํ๋ ์ฅ์๋ ๋ณ์, ์ธ์ ์คํ ๋ฆฌ์ง, ๋ก์ปฌ ์คํ ๋ฆฌ์ง, ์ฟ ํค ๋ฑ์ด ์๋ค.
- ๋ณ์: ์๋ก๊ณ ์นจ ์ ์ญ์ (์ด๊ธฐํ)
- Session Storage: ๋ธ๋ผ์ฐ์ ๋ฅผ ๊ป๋ค ํค๋ฉด ์ด๊ธฐํ
- Local Storage: ๋ธ๋ผ์ฐ์ ๊ป๋ค ์ผ๋ ๋จ์์์
- ์ฟ ํค: ๋ธ๋ผ์ฐ์ ๊ป๋ค ์ผ๋ ๋จ์์์. ๋ง๋ฃ์๊ฐ ๋ถ์ฌ ๊ฐ๋ฅ(๋ง๋ฃ์๊ฐ ๋์ผ๋ฉด ์๋ ์ญ์ ). ๋ณด์๊ธฐ๋ฅ(httpOnly, Secure ๋ฑ) ๊ฐํ ๊ฐ๋ฅ, ์๋ฒ์ ์ฐ๋์ด ๊ฐ๋ฅ(์๋์ผ๋ก ์๋ฒ์ ๋ธ๋ผ์ฐ์ ๋ฅผ ์๋ค๊ฐ๋ค ํ ์ ์์)
๋ํ, JWT ํ ํฐ์ ์์ ๋ด์ฉ์ด ๋ค ๋ณด์ด๋ ํ ํฐ์ด๋ค. ๋ฐ๋ผ์ ์ค์ํ ๋ด์ฉ์ JWT ํ ํฐ ์์ ์ ์ฅํ์ง ์์์ผ ํ๋ค! JWT ํ ํฐ์ ๋ด์ฉ์ ๊ฐ์ถ๋ค๊ธฐ๋ณด๋ค๋, ๋ด์ฉ ์กฐ์์ ๊ธ์งํ๋ค.
๊ทธ๋ฌ๋ฉด ์ฌ์ฉํ๋ฉด ์๋๋ ๊ฒ ์๋๊ฐ? ๋ณด์์ ์ํด์ ํ ํฐ ๋ง๋ฃ์๊ฐ์ ์งง๊ฒ ์ฃผ์๋ค. ๊ทธ๋ฆฌ๊ณ ์กฐ์์ ๋ฏธ์ฐ์ ๋ฐฉ์งํ๊ธฐ ์ํด signature(ํ ํฐ์ ๋น๋ฐ๋ฒํธ)๋ฅผ ์ฌ์ฉํ๋ค. ๋ด์ฉ ์กฐ์์ ์ํด์๋ ์ด ๋น๋ฐ๋ฒํธ๋ฅผ ์์์ผ ํ๋ค. ํด๋น ๋น๋ฐ๋ฒํธ๋ ๋ฐฑ์๋์์ ์์ฑํ๋ฉฐ, ์ ์ ์๋ค.
๋ก๊ทธ์ธ์ ํ๊ณ , ๋ก๊ทธ์ธ ์ ๋ณด๋ฅผ fetch ํด์์ ๋ ๋ธ๋ผ์ฐ์ ์ ๋น๋ฐ๋ฒํธ๋ฅผ fetchํ ์ ์์ด์ผ ํ๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์๋ ๋น๋ฐ๋ฒํธ๋ฅผ ์์๋ผ ์ ์๊ฒ ํด๋์๊ธฐ ๋๋ฌธ์ด๋ค. ์ด๋ฌํ ๋ฏผ๊ฐ ์ ๋ณด๋ค์ ๋ฐฑ์๋์ ์ ์ฅํ ๋ ๊ทธ๋๋ก ์ ์ฅํด์๋ ์๋๋ค. ํดํน์ ์ํ์ฑ์ด ์๋ค.
JWT ๋ฐฉ์์ฒ๋ผ ๋ณตํธํ๊ฐ ๋๋ ์ํธํ. ์ํธํ์ ๋ณตํธํ ๋ชจ๋ ๊ฐ๋ฅ
์ํธํ๋ ๋์ง๋ง ๋ณตํธํ๋ ์๋๋ค. ๋ค๋์ผ
๋ฐฉ์์ ์ฌ์ฉํด์ ์๋ ์ ๋ณด๋ฅผ ์์๋ด๊ธฐ ์ด๋ ต๋๋ก ํด๋๋๋ค. ํ์ง๋ง ๊ทธ๋ผ์๋ ๋ฌด์ฐจ๋ณ๊ณต๊ฒฉ์ผ๋ก ํดํน ์ํ์ด ์์ ์ ์์ด์ ์ต๊ทผ์๋ Bcrypt Hash๋ผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉํด์ ๋ฐ์ดํฐ๋ฅผ ์ํธํํ๋ค.
HTTP HEADERS์ "Authorization"์ ๋ณด๋ด์ฃผ๋ฉด ๋๋ค. Bearer๋ ๊ด๋ก์ ์ฌ์ฉํ ๋ฟ ํ์๋ก ์ ์ด์ค์ผ ํ๋ ๊ฒ์ ์๋๋ค. ์ด ๋ถ๋ถ์ ๋ฐฑ์๋์ ์์ํด์ ์ฌ์ฉํ๋ฉด ๋๋ค.
์ด์ ํ์๊ฐ์
์ ๋จผ์ ํ ํ์ ๊ทธ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์ค์ ๋ก๊ทธ์ธ์ ํด๋ณด์๋ค. ๋ก๊ทธ์ธ์ ํ๋ฉด accessToken
์ ๋ฐ์์ค๋๋ฐ, ๋ฐ์์จ accessToken์๋ ์ ์ ๊ฐ ๋ก๊ทธ์ธ์ ํ ๊ธฐ๋ก์ด ์ ์ฅ๋์ด ์๋ค.
๋ฐ๋ผ์ ์ ์ ์ ๋ณด๋ฅผ ํ์ธํด์ผ ํ๋ API๋ฅผ ์ฌ์ฉํ ๋, accessToken
์ ์ฒจ๋ถํด์ ๋ณด๋ด๋ฉด ๋ฐฑ์๋์์ ์ ์ ์ ๋ณด๋ฅผ ํ์ธํ ํ์ ํด๋น API๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ํด์ค๋ค.
jwt.io ์ ์ ์ํด์ Encoded(์ํธํ) ๋ถ๋ถ์ ์์์ ๋ฐ์์จ accessToken์ ๋ฃ์ผ๋ฉด Decoded(๋ณตํธํ) ๋ถ๋ถ์ ํ ํฐ์ ๋ํ ์ ๋ณด๊ฐ ๋ชจ๋ ๋ณด์ธ๋ค.
๋ง์ฝ ๋๊ตฐ๊ฐ ํ ํฐ์ ์์๋ด์ ํด๋น ์ฌ์ดํธ์ ๋ฃ์ด๋ณธ๋ค๋ฉด ํ ํฐ์ ์ ๋ณด๋ฅผ ์ฝ๊ฒ ์์๋ผ ์ ์๋ค๋ ๊ฒ์ด๋ค! ๋ฐ๋ผ์ ์ค์ํ ๋ฐ์ดํฐ๋ JWT ํ ํฐ์ ์ ์ฅํ๋ฉด ์๋๋ค.
๊ทธ๋ ๋ค๋ฉด JWT ํ ํฐ์ ๋ณด์์ด ์ ํ ์๋๋ ๊ฒ ์๋๊ฐ..? ๊ทธ๋ ์ง๋ ์๋ค. JWT ํ ํฐ์ ํ ํฐ์ ๋ง๋ฃ์๊ฐ์ ์งง๊ฒ ์ค๋ค.
ํ์ง๋ง Decoded ์ ๋ณด์ ํ ํฐ์ ๋ง๋ฃ์๊ฐ์ด ๋ช ์๋์ด ์์ด์ ์ด๊ฒ ๋ํ ์กฐ์์ด ๊ฐ๋ฅํ๋ค.
ํ ํฐ ๋ง๋ฃ์๊ฐ๊น์ง ์กฐ์์ด ๊ฐ๋ฅํ๋ฉด ์ด๋กํ๋ ์ถ์๋ฐ, ์ด๋ฐ ์กฐ์์ ๋ฐฉ์งํ๊ธฐ ์ํด์ JWT๋ signature(ํ ํฐ์ ๋น๋ฐ๋ฒํธ)
๋ฅผ ์ฌ์ฉํ๋ค.
ํ ํฐ์ ๋ด์ฉ์ ์กฐ์ํ๊ธฐ ์ํด์๋ ํ ํฐ์ ๋น๋ฐ๋ฒํธ๋ฅผ ์์์ผ ํ๋ค๋ ๊ฒ์ด๋ค. ๋น๋ฐ๋ฒํธ๋ ๋ฐฑ์๋์์ ์์ฑํ๊ณ , ์ฐ๋ฆฌ๋ ์ ์ ์๋ค.
// login page
import {useMutation,gql} from "@apollo/client"
import {ChangeEvent} from "react"
cosnt LOGIN_USER = gql`
mutation loginUser($email:String){
loginUser(email: $email, password: $password){
accessToken
}
}
`
export default function LoginPage(){
const [email,setEmail]=useState("")
const [password,setPassword]=useState("")
const [loginUser] = useMutation<Pick<IMutation,'loginUser'>,IMutationLoginUserArgs>(LOGIN_USER)
// loginUser ํ์
์ถ๋ก ๋ถ๊ฐ๋ฅ -> ์์๋ ๋ฐ์์ฌ ํ์
์, ๋ค์๋ ๋ณด๋ด์ค ํ์
์์ฑ
const onChangeEmail = (event:ChangeEvent<HTMLInputElement>)=>{
setEmail(event.target.value)
}
const onChangePassword = (event:ChangeEvent<HTMLInputElement>)=>{
setPassword(event.target.value)
}
const onClickLogin = async()=>{
try{
cosnt result = await loginUser({
variables:{
email : email,
password : password
}
})
const accessToken = result.data?.loginUser.accessToken
}catch(error){
Modal.error({content : error.message})
}
}
return(
<div>
์ด๋ฉ์ผ : <input type="text" onchange={onChangeEmail}/> <br/>
๋น๋ฐ๋ฒํธ : <input type="password" onchange={onChangePassword}/>
<button onClick={onClickLogin}>๋ก๊ทธ์ธํ๊ธฐ!!</button>
</div>
)
}
accessToken
์ global state(Recoil)์ ์ ์ฅํ๊ธฐ์ ์ ์ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์ค๋ api๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด http header ๋ถ๋ถ์ accessToken ์ฒจ๋ถํด์ ์์ฒญํด์ผ ํ๋ค.
๋ค์๊ณผ ๊ฐ์ด ์ฝ๋๋ฅผ ์ถ๊ฐ ๋ฐ ์์ ํด์ฃผ๋ฉด ๋๋ค.
import { useRecoilState } from "recoil";
export default function LoginPage(){
const [accessToken, setAccessToken] = useRecoilState(accessTokenState)
const onClickLogin = async() => {
try{
const result = await loginUser({
variables: {
email: email,
password: password
}
})
const accessToken = result.data?.loginUser.accessToken
setAccessToken(accessToken)
router.push(`/loginsuccess`)
} catch(error) {
Modal.error({content: error.message})
}
}
}
// loginsuccess page
const FETCH_USER_LOGGED_IN = gql`
query fetchUserLoggedIn{
fetchUserLoggedIn{
email
name
}
}
`
export default function LoginSuccessPage(){
const {data} = useQuery<Pick<IQuery,"fetchUserLoggedIn">>(FETCH_USER_LOGGED_IN)
return(
<div>
{data?.fetchUserLoggedIn.name}๋ ํ์ํฉ๋๋ค.
</div>
)
}
header
์ ์ฐ๋ํ๊ธฐ//app.tsxํ์ผ
function MyApp({ component,pageProps }:AppProps){
const [accessToken,setAccessToken] = useState("")
const uploadLink = createUploadLink({
uri : "๋ฐฑ์๋ ์ฃผ์",
headers : { Authorization : `Bearer ${accessToken}` }
})
return (
<ApolloProvider client={client}>
<Component {..pageProps}/>
</ApolloProvider>
)
}
uploadLink์ ํ ํฐ์ ์ถ๊ฐํจ์ผ๋ก์จ ๋ชจ๋ ์ปดํฌ๋ํธ์์ ๋ก๊ทธ์ธ ๊ด๋ จ ํ ํฐ์ ์ถ๊ฐํด์ ๋ณด๋ด์ฃผ๋๋ก ๋ง๋ค์๋ค.
๋ก๊ทธ์ธ์ ํ ์ฌ๋๋ง ํ ํฐ์ ๊ฐ์ง๊ณ ์๊ฒ ๋๋ค. ์์ ํ ํฐ ์๋ฆฌ์ ํ ํฐ์ ์ฑ์ฐ๊ธฐ ์ํด์๋ ์ด๋ป๊ฒ ํด์ผ ํ ๊น?
Recoil์ accessToken์ ์ ์ฅํด๋๊ณ ์ฌ์ฉํ๊ณ ์ถ์ ์ปดํฌ๋ํธ ์ ์ฒด๋ฅผ ๊ฐ์ธ์ฃผ๊ณ ํ์ํ ๊ณณ์์ ๊บผ๋ด์ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค!
//app.tsxํ์ผ
import { RecoilRoot } from "recoil";
function MyApp({ component,pageProps }:AppProps){
return (
<RecoilRoot>
<ApolloSetting>
<Global styles={globalStyles} />
<Layout>
<Component {...pageProps} />
</Layout>
</ApolloSetting>
</RecoilRoot>
)
}
๊ธฐ์กด์ app.tsx์์ apollo setting ํด์คฌ๋ ๋ถ๋ถ์ ๋ฐ๋ก ํ์ผ์ ๋ง๋ค์ด์ ๋ถ๋ฆฌํ๋ค.
// Apollo Setting ๋นผ์ฃผ๊ธฐ
import { useRecoilState } from "recoil";
import { accessTokenState } from "../../../commons/store";
export default function ApolloSetting(props) {
const [accessToken,setAccessToken] =useRecoilState(accessTokenState)
const uploadLink = createUploadLink({
uri : "๋ฐฑ์๋ ์ฃผ์",
headers : { Authorization : "Bearer ๋ฐ์์จ ํ ํฐ" }
})
return (
<ApolloProvider client={client}>
{props.children}
</ApolloProvider>
)
}