โ ๋๊ธฐ(๊ธฐ๋ค๋ฆฌ์) vs ๋น๋๊ธฐ(๊ธฐ๋ค๋ฆฌ์ง ๋ง์)
- ๋น๋๊ธฐ ์คํ: ์๋ฒ ์ปดํจํฐ์ ์์ ์ด ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์๋ ํต์ ์ผ๋ก ์๋ฒ์ ์์ฒญ(๋ฑ๋ก, ์์ , ์ญ์ ๋ฑ)์ด ์ ์ฅ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋ค๋ฅธ ์์ ์ ์งํํ๋ค.
- ๋๊ธฐ ์คํ: ์๋ฒ ์ปดํจํฐ์ ์์ ์ด ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ ํ ๋ค์ ์์ ์ ์คํํ๋ ํต์ ์ด๋ค.
๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ๊ธฐ ์ํด์ ๋ธ๋ผ์ฐ์ ์์ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ๋ฉด API์์ฒญ์ ๋ฐ์ ๋ฐฑ์๋ ์ปดํจํฐ๋
๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ์ฌ ๋ธ๋ผ์ฐ์ ์ ์๋ต์ ๋๋ ค์ค๋ค.
์ด ๋, ๊ฒ์๊ธ์ ๋ฑ๋ก ํ ๊ฒ์๊ธ์ ๋ถ๋ฌ์์ ๋ ๊ฒ์๊ธ์ด ๋ถ๋ฌ์์ง์ง ์๋ ๊ฒฝ์ฐ๊ฐ ์๋ค.
์ด๋ฌํ ๋ฌธ์ ๋ ๊ฒ์๊ธ ๋ฑ๋ก ์์ฒญ ํ ๋ฐฑ์๋ ์ปดํจํฐ์ ์์ฒญ์ ์ ์กํ๊ณ ๋ฐ์ดํฐ๊ฐ ์ฒ๋ฆฌ๋ ํ ๊ฒ์๊ธ ๋ถ๋ฌ์ค๊ธฐ ๊ณผ์ ์ด ์คํ๋์ด์ผ ํ๋๋ฐ,
๋ฐ์ดํฐ ์ฒ๋ฆฌ ์ด์ ์ ๊ฒ์๊ธ ๋ถ๋ฌ์ค๊ธฐ ๊ณผ์ ์ด ์คํ๋์ด์ ธ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ด๋ค.
์ด๋ฌํ ์คํ ๋ฐฉ์์ ๋น๋๊ธฐ ์คํ์ด๋ผ๊ณ ํ๋ค.
๋ฐ๋ผ์ ๊ฒ์๊ธ ๋ฑ๋ก ํ ๋ถ๋ฌ์์ ๋ ๊ฒ์๊ธ์ด ๋ถ๋ฌ์์ง์ง ์๋ ์ค๋ฅ์ ์ง๋ฉดํ ๊ฒ์ฒ๋ผ ๋น๋๊ธฐ ์คํ ๋ฐฉ์์ด ์๋ ๋ค๋ฅธ ํต์ ๋ฐฉ์์ ์ฌ์ฉํด์ผํ ๊ฒฝ์ฐ๊ฐ ์๋๋ฐ,
์ด ๋ ์ฌ์ฉํ๋ ๊ฒ์ด ๋๊ธฐ ์คํ ๋ฐฉ์์ด๋ค.
๋๊ธฐ ์คํ ๋ฐฉ์์ ๋ฑ๋ก ์์ฒญ์ ํ๊ฒ ๋๋ฉด ๋ฑ๋ก ๊ณผ์ ์ด ๋ชจ๋ ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ ค์ค ํ ๊ฒ์๊ธ ๋ถ๋ฌ์ค๊ธฐ ๊ณผ์ ์ด ์คํ๋๊ธฐ ๋๋ฌธ์ ๋ฌธ์ ์์ด ์์ ์ด ๊ฐ๋ฅํ๋ค.๊ทธ๋ ๋ค๋ฉด ๋น๋๊ธฐ๋ ์ธ์ ์ฐ๋๊ฑธ๊นโ
์์ฒญ๋ค์ด ์๋ก ๊ธฐ๋ค๋ฆด ํ์๊ฐ ์์ ๋ ์ฐ์ธ๋ค!
์ฆ, ์ฌ๋ฌ ๊ฐ์ง ์์ฒญ์ ๋์์ ์ฒ๋ฆฌํด ์ค ๋์ ์ฌ์ฉ๋๋ค!
์๋ฅผ ๋ค์ด, ๊ฒ์์ ๋ค์ด๋ฐ์ผ๋ฉด์ ์นดํกํ๋ ๊ฒ ๋ํ ๋น๋๊ธฐ์ด๋ค.โ VSCODE์์ ๋น๋๊ธฐ
<REST-API์์ ๋๊ธฐ/๋น๋๊ธฐ ์คํ>
- ๋น๋๊ธฐ ํต์
function ํจ์์ด๋ฆ() { const data = axios.get('https://koreanjson.com/posts/1') console.log(data) // Promise }
์ ์ฝ๋๋ ์์ฒญ๋ ์๋ต์ ๊ฐ์ ธ์ ๋ฐ์ดํฐ์ ์ ์ฅํ๊ณ , ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ์ฐฝ์ ์ฐ์ด์ฃผ๋๋ก ์์ฑ๋ ์ฝ๋์ด๋ค.
REST-API์์ ๋ฐ์ดํฐ์ ์์ฒญ๊ณผ ์๋ต์ ์ํด axios๋ฅผ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ ํต์ ์ ์ฌ์ฉํ๊ณ ,
์ฝ๋๋ ์๋จ์์๋ถํฐ ์คํ๋๋ฉด์ ๋ฐฑ์๋ ์ปดํจํฐ์ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ๊ณ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ ์๋ต์ ์ค๋ค.
์ด ๋, ํด๋น ์ฝ๋๋ฅผ ์คํํ๊ฒ ๋๋ฉด ์ฝ์์ฐฝ์๋ ๋ฆฌํด๋ Promise ๊ฐ์ฒด๊ฐ ๋ณด์ฌ์ง๊ฒ ๋๋ค.
์ฐธ๊ณ PROMISE
- ๋๊ธฐ ํต์ (async/awiat)
async function ํจ์์ด๋ฆ() { const data = await axios.get('https://koreanjson.com/posts/1') console.log(data) // {id: 1, title: "์ ๋น์ ๋ชฉ์ ์ด๋ ํ๋์ด ...", ...} }
๋น๋๊ธฐ ์คํ ๋ฐฉ์์์ ๋๊ธฐ ์คํ ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝํด์ฃผ๊ธฐ ์ํด์๋ async/awiat์ด ํ์ํ๋ค.
await๋ ๊ผญ async์ ํจ๊ป ์์ฑ๋์ด์ผ ํ๋คโ๏ธ
์ ์ฝ๋์ ๊ฐ์ด ์์ฑํ๋ฉด await์ด ์์ฑ๋ ๋ถ๋ถ์ ์ฝ๋ ์คํ์ด ์์ ํ ์๋ฃ๋๊ธฐ ์ ๊น์ง๋ ํ๋จ์ ์ฝ๋๋ก ์คํ์ด ๋์ด๊ฐ์ง ์๋๋ค.
์์ ํ ์๋ฃ๋ ํ ์์ฑ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๊ธฐ ๋๋ฌธ์ ํด๋น ์ฝ๋๋ฅผ ์คํํ๋ฉด ์ฝ์ ์ฐฝ์ ์ฐ๋ฆฌ๊ฐ ๋ถ๋ฌ์ค๊ณ ์ ํ๋ ๋ฐ์ดํฐ๊ฐ ์ ๋ณด์ฌ์ง๋ ๊ฒ์ ์ ์ ์๋ค.
๊ฐ๋งํ ๊ธฐ๋ค๋ฆฌ๊ณ ๋ฃ๋ ๊ฒ์ ์คํํ์ง ๋ง๋ผ!
๋ฐ์์ฌ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ณ ๊ทธ ํ์ ๋ฐ์์ค๋ฉด ๋ฐ์ดํฐ๋ฅผ ์ง์ด๋ฃ๊ฒ ๋๋ค.
โบ ์ค์ตํด๋ณด๊ธฐ
import axios from "axios"; import ๋๋ง์ํ์ด์ง from "../../section01/01-01-example"; export default function RestGetPage() { //js function onClickAsync() { const result = axios.get("https://koreanjson.com/posts/1"); console.log(result); //Promise } //ํจ์ ์ค๋ณต ์ ์ธ ๋ฌธ์ ๋ก ํ์ดํํจ์๋ก ๋ฐ๊ฟ! // async function onClickSync(){ // const result = await axios.get("https://koreanjson.com/posts/1") // console.log(result) //์ ๋๋ก ๋ ๊ฒฐ๊ณผ =>{ title : "..." } // console.log(result.data.title) //์ ๋น์ ๋ชฉ์ ์ด๋... // } const onClickSync = async () => { const result = await axios.get("https://koreanjson.com/posts/1"); console.log(result); //์ ๋๋ก ๋ ๊ฒฐ๊ณผ =>{ title : "..." } console.log(result.data.title); //์ ๋น์ ๋ชฉ์ ์ด๋... }; return ( //jsx <div> <button onClick={onClickAsync}>REST-API(๋น๋๊ธฐ)์์ฒญํ๊ธฐ</button> <button onClick={onClickSync}>REST-API(๋๊ธฐ)์์ฒญํ๊ธฐ</button> <๋๋ง์ํ์ด์ง /> </div> ); }
โ ย Fragments
React์์ DOM์ ๋ณ๋์ ๋ ธ๋๋ฅผ ์ถ๊ฐํ์ง ์๊ณ ์ฌ๋ฌ ์์์ ๊ทธ๋ฃนํ ํ ์ ์๋ ํ๊ทธ๋ก,
์ฌ์ฉ ์ key๊ฐ ์๋ค๋ฉด<></>
์ฒ๋ผ ๋น ํ๊ทธ๋ก ์ฌ์ฉํ ์ ์์ง๋ง,
๋ง์ฝ key๊ฐ ์๋ค๋ฉด<Fragment></Fragment>
๋ฌธ๋ฒ์ผ๋ก ๋ช ์์ ์ผ๋ก ์ ์ธํด์ค์ผ ํ๋ค.
โ๏ธย ์๋ฐ์คํฌ๋ฆฝํธ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋๊ธฐ์ฒ๋ฆฌ ๋ฐฉ์์ด์ง๋ง,
์ธ๋ถ ์ค์นํ๋ก๊ทธ๋จ์ ๋๋ถ๋ถ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํด๋์ด์ ์คํ์์ ๋น๋๊ธฐ๋ก ์คํ๋๋ค.
โ ํธ์ด์คํ ์ด๋โ
์ธํฐํ๋ฆฌํฐ๊ฐ ๋ณ์์ ํจ์์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ ์ธ ์ ์ ๋ฏธ๋ฆฌ ํ ๋นํ๋ ๊ฒ
์ฝ๊ฒ ๋งํด, ๋ณ์์ ์ ์ธ๊ณผ ์ด๊ธฐํ๋ฅผ ๋ถ๋ฆฌํ์ฌ ์ ์ธ๋ง ์ฝ๋์ ์ต์๋จ์ผ๋ก ๋์ด์ฌ๋ ค์ฃผ๋ ๊ฒ์ด๋ค.
๋ฐ๋ผ์, ๋ณ์๋ฅผ ์ ์ํ๋ ์ฝ๋๋ณด๋ค ์ฌ์ฉํ๋ ์ฝ๋๊ฐ ์์ ๋ฑ์ฅํ ์ ์๋ค.
๋ณ์ ์ ์ธ ๋ฐฉ์ ์ค์ var๋ ์ด๋ฏธ ์ ์ธ๋ ๋ณ์๋ฅผ ๋ค์ ์ ์ธํ ์ ์๊ธฐ ๋๋ฌธ์ ์ฆ ํธ์ด์คํ ์ด ์ผ์ด๋ฌ๊ธฐ ๋๋ฌธ์ ํ์ฌ๋ ์ฌ์ฉํ์ง ์๋ ๋ณ์ ์ ์ธ ๋ฐฉ์์ด๋ค.
- ๋ณ์ ์ ์ธ ๋ฐฉ์(var)์ ํธ์ด์คํ
console.log(num); // ํธ์ด์คํ ํ var ์ ์ธ์ผ๋ก ์ธํด undefined ์ถ๋ ฅ var num; // ์ ์ธ num = 6; // ์ด๊ธฐํ
๋ณ์ ์ ์ธ ์ ์ด๊ธฐํ๋ฅผ ์ ์ธํ ์ ์ธ๋ง ํธ์ด์คํ ํ๋ค.
๋ณ์๋ฅผ ๋จผ์ ์ฌ์ฉํ๊ณ ๊ทธ ํ์ ์ ์ธ ๋ฐ ์ด๊ธฐํ๊ฐ ๋ํ๋๋ฉด ์ฌ์ฉํ๋ ์์ ์ ๋ณ์๋ ๊ธฐ๋ณธ ์ด๊ธฐํ ์ํ์ธ undefined์ด๋ค.
let๊ณผ const๋ก ์ ์ธํ ๋ณ์๋ ํธ์ด์คํ ์ด ๋๊ธด ํ์ง๋ง,
var์๋ ๋ฌ๋ฆฌ undefined๋ก ๋ณ์๋ฅผ ์ด๊ธฐํ ํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ณ์ ์ ์ธ ์ ์ ๋จผ์ ์ฌ์ฉํ๊ฒ๋๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ฒ ๋๋ค.
- ํจ์(function)์ ํธ์ด์คํ
catName('ํด๋ก์ด') function catName(name) { console.log('์ ๊ณ ์์ด์ ์ด๋ฆ์' + name + '์ ๋๋ค')' }// '์ ๊ณ ์์ด์ ์ด๋ฆ์ ํด๋ก์ด์ ๋๋ค'
ํจ์๋ ์ฝ๋๋ฅผ ์คํํ๊ธฐ ์ ์ ํจ์ ์ ์ธ์ ๋ํ ๋ฉ๋ชจ๋ฆฌ('ํด๋ก์ด')๋ถํฐ ํ ๋น๋์ด,
ํจ์๋ฅผ ํธ์ถํ๋ ์ฝ๋๋ฅผ ํจ์ ์ ์ธ ์์ ๋ฐฐ์นํ ์ ์๋ค.
์ด๋ฌํ ํน์ง ๋๋ฌธ์const
๋ฅผ ์ฌ์ฉํ ํ์ดํํ ํจ์ ์ ์ธ ๋ฐฉ์์ ํตํด ์์ํ์ง ๋ชปํ ์๋ฌ๋ฅผ ๋ฐฉ์งํ ์ ์๋ค.
์ฆ, ํ์ดํํจ์๋ฅผ ์ฐ๊ฒ ๋๋ฉด ๋ณ์์ ์ค๋ณต์ ์ธ์ ๋ง์์ค๋คโ๏ธ
playground ์์ ์ค์ตํ๋ ๋ด์ฉ์ ์ฝ๋๋ฅผ vscode์์ ์ ์ฉํ๊ธฐ ์ํด์๋ apollo-client๋ผ๋ ๋๊ตฌ๊ฐ ํ์ํ๋ค.
apollo-client๋ฅผ ์ค์น ํ ์ฌ์ฉํ๊ธฐ ์ํ ์ฒ์ 1๋ฒ ์ ํ ์ด ํ์ํ๋ฐ,
์ค์นํ ๋๊ตฌ๋ค์ ์ ํ ํ๋ ์์น๋ ์ผ๋ฐ์ ์ผ๋ก _app.js ์ ์๋ค.
_app.js์ ์๋์ ๊ฐ์ด ์์ฑํด์ค๋ค.
index.js๊ฐ ํ์ด์ง๋ก ์ธ์๋์ด ์คํ๋๊ธด ํ์ง๋ง,
์ฌ์ค์ index.js(ํ์ด์ง)๊ฐ ์คํ๋๋ ๊ฒ์ด ์๋ index.js๊ฐ app.js๋ก ํฉ์ณ์ ธ์ app.js๊ฐ ์คํ๋๋ ๊ฒ์ด๋ค.
import { ApolloClient, ApolloProvider, InMemoryCache } from "@apollo/client"; // InMemoryCache์ ์์์ ์ฅ export default function App({ Component }) { const client = new ApolloClient({ uri: "http://backend-example.codebootcamp.co.kr/graphql", cache: new InMemoryCache(), //์ปดํจํฐ์ ๋ฉ๋ชจ๋ฆฌ(rem)์ ๋ฐฑ์๋์์ ๋ฐ์์จ ๋ฐ์ดํฐ ๋ชจ๋ ์์์ ์ฅ! }); return ( <div> <div> ==== ์ฌ๊ธฐ๋ _app.js ์ปดํฌ๋ํธ ์์๋ถ๋ถ</div> <ApolloProvider client={client}> <Component /> </ApolloProvider> <div> ==== ์ฌ๊ธฐ๋ _app.js ์ปดํฌ๋ํธ ๋ง์ง๋ง๋ถ๋ถ</div> </div> ); }
ํ์ด์ง์ปดํฌ๋ํธ๋ ๋ถ๋ฌ์์ ์กฐ๋ฆฝ์ด ๊ฐ๋ฅํ๋ค (์๋? ํ์ด์ง๋ ํ๋์ ์ปดํฌ๋ํธ ์ด๊ธฐ ๋๋ฌธ์ ๋ถํ์ด๋ผ ์๊ฐํ ์ ์๋ค!) -> ์ด์ฒ๋ผ ํ์ด์ง์ปดํฌ๋ํธ ๋ค๋ฅธ ํ์ผ์ ์๋ ๊ฒ์ด ์คํ๋๋ค.
์ปดํฌ๋ํธ ๋๋ฌธ์ ์ด๋ค ํ์ด์ง๋ฅผ ์ ์ํด๋ ๋ณด์ด๊ฒ ๋๋ค.
APP ์ปดํฌ๋ํธ์ ๋ชจ๋ ๊ฒ ํฉ์ณ์ ธ์ ์คํ์ด ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
(๋๋ง์ ํ์ด์ง๊ฐ ๋ถ๋ ค์์ ํฉ์ณ์ง๋ค.)
๊ฒฐ๋ก โ๏ธ
Component ์๋ฆฌ์ index.js๊ฐ ๋ค์ด์ค๊ฒ ๋๊ณ index.js๊ฐ ํฉ์ณ์ง app.js๊ฐ ์คํ๋์ด ์ต์ข ์ ์ผ๋ก ์ฐ๋ฆฌ ๋์ ๋ณด์ด๋ ๊ฒ!
- playground์์ ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ๋ ค๋ mutation์ด ์ ๋๋ก ์๋ํ๋์ง ํ์ธํ๋ค.
- ์ ๋๋ก ์๋ํ๋ค๋ฉด, graphql mutation์ ์คํํ๋ ค๋ ํ์ด์ง ์๋จ์์, apollo-client ์ ๋๊ตฌ๋ค์ ๋ถ๋ฌ์จ๋ค.
// graphql ์์ฒญ์ ํ์ํ ๋๊ตฌ ๋ถ๋ฌ์ค๊ธฐ import { useMutation, gql } from '@apollo/client'
- javascript ์ ๋ ฅ ๋ถ๋ถ์ playground์ ์ฝ๋๋ฅผ ๋ณต์ฌํ์ฌ ์๋์ ๊ฐ์ด gql`` ์ฌ์ด์ ๋ถ์ฌ๋ฃ์ด ๋ณ์/์์๋ฅผ ๋ง๋ค์ด ์ค๋ค.
import { useMutation, gql } from "@apollo/client"; const ๋์๊ทธ๋ํํ์์ธํ = gql` mutation { CREATE_BOARD( writer: "123", title: "hi", contents: "you" ){ _id number message } } `;
4.gql ๋ณ์/์์๋ฅผ ํ์ฉํ์ฌ, useMutation์ ๋ง๋ค์ด ์ค๋ค.
//mutation ์ฝ๋ ์์ฑ const [๋์ํจ์(๋ณ์๋ช )] = useMutation(๋์๊ทธ๋ํํ์์ธํ );
-> ๋ณดํต API ์ด๋ฆ๊ณผ ๋ง์ถฐ์ ์ฌ์ฉํ๋๊ฒ ์ผ๋ฐ์ ์ด๋ฏ๋ก API ์ด๋ฆ๊ณผ ํต์ผํด์ ์ ์ด์ฃผ๋ ๊ฒ์ด ์ข๋คโ๏ธ
5. ๊ฒ์๋ฌผ ๋ฑ๋ก ๋ฒํผ์ ํด๋ฆญํ์ ๋ ์คํ๋๋ ํจ์์์ mutation ์ฝ๋๋ฅผ ์คํํด์ค๋ค.const onClickSubmit = () => { const result = ๋์ํจ์(); console.log(result); }; //ํ ์ค์ผ ๋๋ (๊ดํธ) ํ์์์ return <button onClick={onClickSubmit}>Graphql-API ์์ฒญํ๊ธฐ</button>; }
6. ๊ฒ์๋ฌผ์ด ์ ์์ ์ผ๋ก ๋ฑ๋ก๋๋์ง ํ์ธํ๋ค.
๊ทธ๋ฌ๋ ์ ๊ฐ์ ์ฝ๋๋ ํญ์ ๊ฐ์ ๊ฒ์๋ฌผ์ด ๋ฑ๋ก๋๋ค๋ ๋ฌธ์ ์ ์ด ์๊ณ , ์ด๋ฅผ ํ๋์ฝ๋ฉ ํ๋ค๋ผ๊ณ ํ๋ค.
๋ฐ๋ผ์, CREATE_BOARD ๋ถ๋ถ์ ๋ณ๊ฒฝํ ํ์๊ฐ ์๋ค.(CREATE_BOARD๋ฅผ ๋๋ฌธ์๋ก ๋ฐ๊ฟ์ค์ผ ํ๋ค ๊ด๋ก๊ฐ์ ๊ฒ)
ํ์ง๋ง ์ฐ๋ฆฌ๋ ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ๋๋ก ์์ฑํด์ค์ผ ํ๊ธฐ๋๋ฌธ์ ์ ๋ ฅ ๊ฐ์ด ๋งค๋ฒ ๋ฐ๋์ด์ผ ํ๋ค!
input์ onChange๋ฅผ ์ด์ฉํด ์ ๋ ฅ๋ฐ์ ๊ฐ์ state์ ์ ์ฅ๋์๋ ๊ฒ์ฒ๋ผ,
์ ๋ ฅ๋ฐ์ ๊ฐ์ state์ ์ ์ฅํ๊ณ variables($)์ ๋ฃ์ด์ค๋ค.import { useMutation, gql } from "@apollo/client"; // graphql ์ฝ๋ const CREATE_BOARD = gql` mutation createBoard($writer: String, $title: String, $contents: String) { createBoard(writer: $writer, title: $title, contents: $contents) { _id number message } } `;
-> createBoard($ writer:String, $ title:String,$contents:String)์ ํ์ ๊ฒ์ฌ(ํ์ธ)์ฉ์ ์ ๊ฒฝ์์จ๋ ๋จ.
ํ์ง๋ง ์ฐ์ง ์์ผ๋ฉด ์๋ฌ๊ฐ ๋๋ค.//mutation ์ฝ๋ export default function GraphqlMutationPage() { const [๋์ํจ์] = useMutation(CREATE_BOARD); const onClickSubmit = () => { const result = ๋์ํจ์({ variables($): { //variables๊ฐ $์ญํ ์ ํ๋ค. writer: "์ฒ ์", title: "์ ๋ชฉ", contents: "๋ด์ฉ" }, }); console.log(result); }; //ํ ์ค์ผ ๋๋ (๊ดํธ) ํ์์์ return <button onClick={onClickSubmit}>Graphql-API ์์ฒญํ๊ธฐ</button>; }
์ฆ, graphql์ ์ ๋ ฅํ ๋ฐ์ดํฐ๋ ์ต์ข ์ ์ผ๋ก ๋ฑ๋กํ๊ธฐ ๋ฒํผ์ ๋๋ ์ ๋, ์คํ๋๋ onClickSubmit ํจ์์์ ์คํ๋๋ mutation ์์ ๋ฃ์ด ์ฃผ์ด์ผ ํ๋ค.
โ๏ธmutation์ ๋ณด๋ด์ค์ผ ํ ๊ฐ์ ์ง์ ์ ๋ ฅํ๋ ๋ฐฉ์(3๋ฒ, 5๋ฒ ๊ณผ์ )์ โํ๋์ฝ๋ฉโ์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
7. ๋ง์ฝ ์ด๋ ๊ฒ ํด๋ ๊ณ์ ๋๊ฐ์ ๋ฐ์ดํฐ๋ง ๋ค์ด๊ฐ๋ค๋ฉด?//mutation ์ฝ๋ export default function GraphqlMutationPage() { const [writer, setWriter] = useState(""); ------->๋ณ๊ฒฝ const [title, setTitle] = useState(""); ------->๋ณ๊ฒฝ const [contents, setContents] = useState(""); ------> ๋ณ๊ฒฝ const [๋์ํจ์] = useMutation(CREATE_BOARD); const onClickSubmit = () => { const result = ๋์ํจ์({ variables: { //variables๊ฐ $์ญํ ์ ํ๋ค($๋ถ์ฌ์ผ ๋ณ์๋ผ๋ ๊ฑธ ์๋ค.) write: writer, -------------->๋ณ๊ฒฝ title: title,-------------->๋ณ๊ฒฝ contents: contents,------------>๋ณ๊ฒฝ }, }); console.log(result); }; //ํ ์ค์ผ ๋๋ (๊ดํธ) ํ์์์ return <button onClick={onClickSubmit}>Graphql-API ์์ฒญํ๊ธฐ</button>; }
-> variables์ ๋ค์ด๊ฐ๋ ๋ฐ์ดํฐ๋ฅผ ๊ณ ์ ๋ ๊ฐ์ด ์๋, state๋ก ๋ณ๊ฒฝํ๋ฉด ์ต์ข ์ ์ธ ์ฝ๋๊ฐ ์์ฑ๋๋ค
rest-API ๋๋ graphql-API ๋ฅผ ์ฌ์ฉํด์ ์์ฒญ์ ๋ํ ์๋ต์ผ๋ก ๋ฐ์ ๊ฐ์ฒด(JSON)๋ฅผ ๋ณ์์ ๋ด์์ ์ฌ์ฉํ ์ ์๋ค.
์๋ต ๊ฒฐ๊ณผ๋ฅผ ๋ณ์์ ๋ด์์ ์ฌ์ฉํ๋ ค๋ฉด!
ํต์ ์ด ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผ ํ๋๋ฐ,
์ด ๋ async / await๋ฅผ ํ์ฉํ์ฌ ๊ธฐ๋ค๋ฆด ์ ์๋ค.
<๊ธฐ๋ณธํ์>// ๋น๋๊ธฐ ํต์ function ํจ์๋ช () { // ์๋ฒ์ ์์ฒญํ๋ ์ฝ๋ } // ๋๊ธฐ ํต์ async function ํจ์๋ช () { await // ์๋ฒ์ ์์ฒญํ๋ ์ฝ๋ } ------------------------------------------------------ // ํ์ดํ ํจ์์ธ ๊ฒฝ์ฐ async ์ ์์น๋ฅผ () ์์ ์ ๋ ฅํ๋ค. const ํจ์๋ช = async () => { await // ์๋ฒ์ ์์ฒญํ๋ ์ฝ๋ }
// mutation์ ๋๊ธฐ์ ์ฒ๋ฆฌ async function onClickSubmit(){ const result = await createBoard({ variables: { writer: writer, title: title, contents: contents, } }); // ๊ฒฐ๊ณผ๋ฌผ ํ์ธํ๊ธฐ console.log(result); } return <button onClick={onClickSubmit}>Graphql-API ์์ฒญํ๊ธฐ</button>
import { useMutation, gql } from "@apollo/client"; import { useState } from "react"; const ๋์๊ทธ๋ํํ์์ธํ = gql` mutation createBoard($writer: String, $title: String, $contents: String) { createBoard(writer: $writer, title: $title, contents: $contents) { _id number message } } `; export default function GraphqlMutationPage() { const [writer, setWriter] = useState(""); const [title, setTitle] = useState(""); const [contents, setContents] = useState(""); const [๋์ํจ์] = useMutation(๋์๊ทธ๋ํํ์์ธํ ); const onClickSubmit = async () => { const result = await ๋์ํจ์({ variables: { //variables๊ฐ $์ญํ ์ ํ๋ค. writer: writer, title: title, contents: contents, }, }); console.log(result); }; function onChangeWriter(event) { setWriter(event.target.value); } function onChangeTitle(event) { setTitle(event.target.value); } function onChangeContents(event) { setContents(event.target.value); } //ํ ์ค์ผ ๋๋ (๊ดํธ) ํ์์์ return ( <div> ์์ฑ์: <input type="text" onChange={onChangeWriter} /> ์ ๋ชฉ: <input type="text" onChange={onChangeTitle} /> ๋ด์ฉ: <input type="text" onChange={onChangeContents} /> <button onClick={onClickSubmit}>Graphql-API ์์ฒญํ๊ธฐ</button> </div> ); }
import { useMutation, gql } from "@apollo/client"; const CREATE_PRODUCT = gql` mutation createProduct( $seller: String $createProductInput: CreateProductInput! ) { createProduct(seller: $seller, createProductInput: $createProductInput) { _id number message } } `; export default function GraphqlMutationPage() { const [createProduct] = useMutation(CREATE_PRODUCT); const onClickSubmit = async () => { const result = await createProduct({ variables: { //variables๊ฐ $์ญํ ์ ํ๋ค. seller: "์ฒ ์", createProductInput: { name: "mouse", detail: "good mouse", price: 2000, }, }, }); console.log(result); }; //ํ ์ค์ผ ๋๋ (๊ดํธ) ํ์์์ return <button onClick={onClickSubmit}>Graphql-API ์์ฒญํ๊ธฐ</button>; }
- URL : ๋คํธ์ํฌ ์์์ ์น ํ์ด์ง, ์ด๋ฏธ์ง, ๋์์ ๋ฑ์ ํ์ผ์ด ์์นํ ์ ๋ณด๋ฅผ ๋ํ๋ธ๋ค.
- URN(Uniform Resource Name) : ๋ฆฌ์์ค์ name์ ๊ฐ๋ฆฌํค๋๋ฐ ์ฌ์ฉ๋๋ค.
- URI : URL๊ณผ URN์ ํฌํจํ๋ ๊ฐ๋
- " # ": ๋ง์ฝ ํ์ด์ง ์ ์ํ์๋ง์ ํ๋จ์ผ๋ก ๊ฐ๊ณ ์ถ๋ค๋ฉด (์ฃผ์)#footer
[์ฐธ๊ณ ] URL, URI, URN
๋ฐ์ดํฐ ํต์ ๊ณผ์ ์ด ์๋ค๋ฉด ์ค๋ฅ๋ฐ์ ์ ์ฝ์์ฐฝ์์ ๋ฌธ์ ๋ฅผ ํ์ธํ ์ ์์ง๋ง, ๋ฐ์ดํฐ ํต์ ๊ณผ์ ์ด ์๊ธด๋ค๋ฉด ์ฝ์์ฐฝ์์๋ ํ์ธํ ์ ์๋ ๋ฌธ์ ๋ค์ด ๋ฐ์ํ๋ค.
๋งค๋ฒ ์์ ํ๊ณ refresh ํ๋ ๊ฒ์ ์๋ชป๋ ๋ฐฉ๋ฒ!
๋ธ๋ผ์ฐ์ ์์ ๋ฐ๊พธ๊ณ ๋์ ์ฝ๋๋ก ์ ์ฉํด์ผ ํ๋ค.
Request, Response, Preview ํค๋๋ฅผ ๊ฐ๊ฐ ํ์ธํ์ฌ ์ด๋ค ๋ฌธ์ ๊ฐ ๋ฐ์ํ์๋์ง ์ง์ ํ์ธํ๊ณ ์์ ํ ์ ์๋ค.<ํด๊ฒฐ๋ฐฉ๋ฒ>
1. HTML/ CSS ์์ ๋ฐ์ํ์ ์
- ๊ฐ๋ฐ์ ๋๊ตฌ element ํญ์ ํ์ธ ํ ๊ฒ
- vs ์ฝ๋๋ ์ต์ข ์!
2. ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๋ฌธ์ ๊ฐ ์์ ์
- ๋จผ์ ์ฝ์ ์ฐฝ์์ ํ์ธํด๋ณธ๋ค.
- ๋ฒํผ ํด๋ฆญํ๊ณ ๋คํธ์ํฌ๋ก ํ์ธํ๊ธฐ
3. ๋คํธ์ํฌ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ ์
- request์ response์ ์ก์์ ์ ๋๋์ง ํ์ธ
- payroad๋ก ๋ด๊ฐ ์ด๋ค ๊ฑธ ๋ณด๋๋์ง ํ์ธํ ์ ์๋ค.
(vscode๋ก ์์ ํ ๊ฒ์ด๋ ํ์ ํ์ธํ ๊ฒ!)
JSX
import { Wrapper, Title, Wrapper_input, Wrapper_info, Name, Input, Password, Wrapper_title, Subtitle, Sub_Input, Wrapper_content, Content, Content_input, Wrapper_address, Address_title, AddressZip, Address_Input, Search_btn, Address, Wrapper_youtube, Youtube_title, Youtube_Input, Wrapper_image, Img_title, UploadBox, UploadBtn, Box, Plus, Text, Wrapper_mainSet, Main_title, Radio, RadioButton, RadioLabel, Wrapper_register, RegisterBtn, Color, } from "./css"; import { useState } from "react"; import { useMutation, gql } from "@apollo/client"; const CREATE_BOARD = gql` mutation createBoard($writer: String, $title: String, $contents: String) { createBoard(writer: $writer, title: $title, contents: $contents) { _id number message } } `; export default function freeBoardFrom() { const [TheName, setName] = useState(""); const [ThePassword, setPassword] = useState(""); const [TheSubtitle, setSubtitle] = useState(""); const [TheContent, setContent] = useState(""); const [NameError, setNameError] = useState(""); const [PasswordError, setPasswordError] = useState(""); const [SubtitleError, setSubtitleError] = useState(""); const [ContentError, setContentError] = useState(""); function onChangeName(event) { setName(event.target.value); } function onChangePassword(event) { setPassword(event.target.value); } function onChangeSubtitle(event) { setSubtitle(event.target.value); } function onChangeContent(event) { setContent(event.target.value); } const [client] = useMutation(CREATE_BOARD); const Signup = async () => { //๊ฐ์ ํ๊ธฐ if (TheName === "") { //์ด๋ฆ์ด ๋น๊ฐ์ด๋ผ๋ฉด setNameError("์ด๋ฆ์ ์ ๋ ฅํด์ฃผ์ธ์"); } else { setNameError(""); } if (ThePassword === "") { setPasswordError("๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํด์ฃผ์ธ์"); } else { setPasswordError(""); } if (TheSubtitle === "") { setSubtitleError("์ ๋ชฉ์ ์ ๋ ฅํด์ฃผ์ธ์"); } else { setSubtitleError(""); } if (TheContent === "") { setContentError("๋ด์ฉ์ ์ ๋ ฅํด์ฃผ์ธ์"); } else { setContentError(""); } if ( TheName !== "" && ThePassword !== "" && TheSubtitle !== "" && TheContent !== "" ) { alert("๊ฒ์๊ธ์ด ๋ฑ๋ก๋์์ต๋๋ค."); const result = await client({ variables: { //variables๊ฐ $์ญํ ์ ํ๋ค. writer: TheName, title: TheSubtitle, contents: TheContent, }, }); console.log(result); } }; return ( <Wrapper> <Title>๊ฒ์๋ฌผ๋ฑ๋ก</Title> <Wrapper_input> <Wrapper_info> <Name>์์ฑ์</Name> <Input type="text" placeholder="์ด๋ฆ์ ์ ์ด์ฃผ์ธ์" onChange={onChangeName} /> <Color>{NameError}</Color> </Wrapper_info> <Wrapper_info> <Password>๋น๋ฐ๋ฒํธ</Password> <Input type="password" placeholder="๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํด์ฃผ์ธ์" onChange={onChangePassword} /> <Color>{PasswordError}</Color> </Wrapper_info> </Wrapper_input> <Wrapper_title> <Subtitle>์ ๋ชฉ</Subtitle> <Sub_Input type="text" placeholder="์ ๋ชฉ์ ์์ฑํด์ฃผ์ธ์" onChange={onChangeSubtitle} /> <Color>{SubtitleError}</Color> </Wrapper_title> <Wrapper_content> <Content>๋ด์ฉ</Content> <Content_input type="text" placeholder="์ ๋ชฉ์ ์์ฑํด์ฃผ์ธ์" onChange={onChangeContent} /> <Color>{ContentError}</Color> </Wrapper_content> <Wrapper_address> <Address_title>์ฃผ์</Address_title> <AddressZip> <Address_Input type="text" placeholder="07250"></Address_Input> <Search_btn>์ฐํธ๋ฒํธ ๊ฒ์</Search_btn> </AddressZip> <Address /> <Address /> </Wrapper_address> <Wrapper_youtube> <Youtube_title>์ ํ๋ธ</Youtube_title> <Youtube_Input type="text" placeholder="๋งํฌ๋ฅผ ๋ณต์ฌํด์ฃผ์ธ์." </Youtube_Input> </Wrapper_youtube> <Wrapper_image> <Img_title>์ฌ์ง์ฒจ๋ถ</Img_title> <UploadBox> <UploadBtn> <Box> <Plus>+</Plus> <Text>Upload</Text> </Box> </UploadBtn> <UploadBtn> <Box> <Plus>+</Plus> <Text>Upload</Text> </Box> </UploadBtn> <UploadBtn> <Box> <Plus>+</Plus> <Text>Upload</Text> </Box> </UploadBtn> </UploadBox> </Wrapper_image> <Wrapper_mainSet> <Main_title>๋ฉ์ธ์ค์ </Main_title> <Radio> <RadioButton type="radio" id="youtube" name="radio-button" /> <RadioLabel>์ ํ๋ธ</RadioLabel> <RadioButton type="radio" id="image" name="radio-button" /> <RadioLabel>์ฌ์ง</RadioLabel> </Radio> </Wrapper_mainSet> <Wrapper_register> <RegisterBtn onClick={Signup}>๋ฑ๋กํ๊ธฐ</RegisterBtn> </Wrapper_register> </Wrapper> ); }
Image
- ์ปดํฌ๋ํธ๋ ๋ฐ๋์ ์์ชฝ์ ๋ฃ์ด์ค์ผ ํ๋ค.!
- ๋ธ๋ผ์ฐ์ ํ๊ฒฝ์ ๋ฐ๋ผ var์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ์๋ค.
const๋ก ๋ง๋ค์์ง๋ง var๋ก ๋ฐ๊ฟ์ค ํ์๊ฐ ์๋ค.
๊ทธ๋์ ์๋ ๋ธ๋ผ์ฐ์ ์์๋ ์๋ํ ์ ์๊ฒ๋ ํด์ค!- ํจ์จ์ ์ธ ์ฒ๋ฆฌ๋ ๋น๋๊ธฐ๋ก ํ๊ณ
์ด์ฉ ์ ์๋ ๋ถ๋ถ๋ง ๋๊ธฐ๋ก ํ๋ค.- ์ญ์ฌ๋์() ์ค๋ฐ๊ฟ
- apollo๋ก ์ธํ , ์ปดํฌ๋ํธ๋ ์ ์
- ์๋ฐ์คํฌ๋ฆฝํธ์์ ์ ๊ณตํด์ฃผ๋ ๊ธฐ๋ฅ๋ค (axios๋ฑ) ๋๋ถ๋ถ์ ๋น๋๊ธฐ๋ก ์๋์ ํ๋ค.
- async / await ๋น๋๊ธฐ๋ฅผ ๋๊ธฐ๋ก ๋ฐ๊ฟ์ฃผ๋ ๋ช ๋ น์ด
- npmjs.com ๋จ์ด ๋ง๋ค์ด๋์ ๊ธฐ๋ฅ ๋ค์ด๋ก๋ ๊ฐ๋ฅ
- ๋ชจ๋ ํ์ด์ง์์ graph-ql์ ๊ฐ๋ฅํ๊ฒ ํ๊ณ ์ถ์ ๋ ์ค์ ํ๋ ๋ฒ
app.js ->๋ชจ๋ ํ์ด์ง ๊ณตํต ์ค์ ํ์ผ- ์ค๋ฅ๋ฐ์ ์ ๋ฐ๋์ ํด๋น ๋ฌธ๊ตฌ ์ฝ์ด์ ํผ์ ํด๊ฒฐํด๋ณด๋ ค๊ณ ๋ ธ๋ ฅํ ๊ฒ!
Q.package.json์์ ์ค์น๋ apollo ํ๋ก๊ทธ๋จ๋ง ์ญ์ ๊ฐ ๋๋ ๊ฒฝ์ฐ๊ฐ ์๋์ง?
A. ๊ทธ๋ฐ ๊ฒฝ์ฐ๋ ๊ฑฐ์ ์์ง๋ง ๋ค์ ๋ฒ์ ๋ ๊ทธ๋ฐ๋ค๋ฉด apollo๋ง ์ ์ฒด์ ์ผ๋ก ๊น ์ ์๋ ํ๋ก๊ทธ๋จ์ด ์๋ค๊ณ ํ์ ์ ๋ฉํ ๋๊ป์ ์๋ ค๋ฌ๋ผ๊ณ ํ์ จ๋ค.
์ง์ง ๋ง์ ์์ ๋ฐฐ์ด ๊ฒ ๊ฐ์ ์ค๋์ ์์ ์ด์๋ค.
API๊ฐ ๋ ์ข ๋ฅ๋ก ๋๋์ด ์๋ค๋ ๊ฒ๋ ์ฒ์ ์์๊ณ ,
์ค์ ๋ก ์ ์ฉํด๋ณด๋ฉฐ ๊ฐ๊ฐ์ ์ฐจ์ด์ ์ ๋ํด ์ ์ ์๋ ์๊ฐ์ด์๋ค.
๋๊ธฐ์ ๋น๋๊ธฐ, ๊ทธ๋ฆฌ๊ณ promise์ ๊ด๋ จํ ๋ด์ฉ์
์ง๋ ์จ๋ผ์ธ ํ๋ฆฌ์บ ํ ๋ ์งํํ๋ ์ ์ด ์์ด์
๋ ธ์ ์ ์ด์ฌํ ์ ๋ฆฌํด ๋์๋๋ฐ, ํจ๊ป ๋ณด๋ ๋์์ด ์ ๋๋ ๊ฒ ๊ฐ๋ค!
์ด๋์ ์ค๋ ๋ฐฐ์ด ๊ฒ์ ์ค๋ ์ ๋ฆฌํด์ผ ํ๋ ๊ฒ,,
์ด์ฌํ ๊ณผ์ ๋ฅผ ํ๋ ์ค์ package.json์์ ์ค์น๋ apollo๊ฐ ์ญ์ ๊ฐ ๋์ด ์๊พธ๋ง ๋คํธ์ํฌ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
์ค์น๋ ํ๋ก๊ทธ๋จ์ด ์ญ์ ๊ฐ ๋์์ ๊ฒ์ด๋ผ๊ณค ์๊ฐ๋ ๋ชปํ๋๋ฐ,
package.json์ ํน์๋ ๊ฐ๋ดค๋๋ apolloํ๋ก๊ทธ๋จ๋ง ๊น๋ ค์์ง ์์๋ฐ,,
๋ถ๋ช ๊ฑด๋ ์ ์ด ์๋ ๊ฒ ๊ฐ์๋ฐ,,ใ ใ
์ฌ์ค์น ํ ์๋ํ์ง๋ง ์ฌ์ ํ ๋๊ฐ์๋ค
๊ฒฐ๊ตญ ์ฐฝ์ ๋ค ๋๊ณ ์ด์ด์ ๋ค๋ฅธ ํ์ผ์ ๋ณต์ฌํด ๋ฃ์ด์ ํ๋ ํด๊ฒฐ์ด ๋์๋ค,,
์ด๊ฑธ๋ก ์๊ฐ์ ๊ฝค๋ ์ก์ ๋จน์ด๋ฒ๋ ค์ฏคใ
๊ทธ๋๋ ํ์ด๋ถ๋ค๊ป์ ์๊ทธ๋ฐ๊ฑด์ง ์์์ ๊ฐ์ด ๊ณ ๋ฏผํด์ฃผ์๊ณ ๋์์ฃผ์๋ ๋ฐ๋์
๊ธ๋ฐฉ ํด๊ฒฐํ ๊ฒ ๊ฐ๋ค! ๊ฐ์ฌํ ๋ง์๐
์ง๋ 3์ผ์ฐจ๋ณด๋ค๋ ์ค๋์ด ์ง์ค์ด ์ข ์ ๋์ด์ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ๊ฑด ๊ธ๋ฐฉ ํ์ง๋ง,
์ด๋ฐ์ HTML๊ณผ CSS๋ฅผ ์ง๋๋ฐ ์๊ฐ์ด ๋ง์ด ๊ฑธ๋ ธ๋ค,,
๋นจ๋ฆฌ ํด๋ฒ๋ฆฌ๊ณ ๊ธฐ๋ฅํ๊ณ ์ถ์๋ ใ ใ ,,,
๊ฐ์๋ก ๋๋ ๊พธ๋ฏธ๋ ๊ฒ๋ณด๋ค ์์ง์ด๊ฒ๋ ๋ง๋๋ ๊ฑธ ๋ ์ข์ํ๋ค๋ ๊ฒ ๋๊ปด์ง๋ค,,ใ ใ
ํ์ง๋ง ๋๋ 1px ํ๋ํ๋ ์ ๊ฒฝ์ฐ๋ ํ๋ก ํธ์ธ๊ฑธ?!
๊ฒฐ๊ตญ์ ์์ฑ๋ ๋ชจ์ต์ ๋ณด๊ณ ์ผ ๋ง๋ ๋
๋ด์ผ์ด๋ฉด ๋ฒ์จ ํ์ฃผ์ ๋ง์ง๋ง ๋ ์ด๋ค,,
ํ๋ฃจ๊ฐ ์์ฃผ ๊ธฐ์ผ~~~๊ฒ ๋๊ปด์ก ํ๋ฃจํ๋ฃจ์์ง๋ง
์ ์ง๋์จ ๋ด๊ฐ ์๋์ค๋ฝ๋ค peace -