Express.js CR GET //file Data GET app.get("/posts", async (req, res) => { res.json(posts); //JSONํ์์ผ๋ก ์๋ต๋ณด๋ด๊ธฐ }); app.get("/posts/:postId", (req, res) => { const postId = req.params.postId; const post = posts.find((post) => post.id === Number(postId)); res.json(post); }); //axios๋ก GET app.get("/todos", async (req, res) => { const response = await axios.get( "https://jsonplaceholder.typicode.com/to..
Next.js React Query React Query๋ฅผ ํตํด, useEffect์ data-fetch๋ฅผ ํ๋ฒ์ ํ ์ ์๋ค. useQuery({ queryKey: ["til", { category: "trending" }] }); //category์ธ์ page, sort๊ฐ์๊ฒ๋ ๊ฐ์ด ๋ฃ๋๋ค๊ณ ํ๋ค. โ๏ธ react query๋ ์๋ฒ์ ๋๊ธฐํ ํ๊ธฐ ๋๋ฌธ์, ๊ฐ๋์ local์ชฝ data๋ฅผ ๋ ๋ฆฌ๊ณ ์๋ก ๋ฐ์์ค๋ ์์
์ ํ๋ค๊ณ ํ๋ค. (invalidate) ๐๐ป key๋ฅผ ๊ตฌ๋ถํด, ์ ์ฒด ๋ฐ๊ตฌ๋๋ฅผ ์ด๊ธฐํํ๋ ๊ฒ์ด ์๋๋ผ til๋ง ์ด๊ธฐํ ํ๋ค. โqueryKey: ๋ถ์ํ๊ณ ์ ๋ฆฌํ๋ค. โqueryFn: fetch์ ๊ฐ์ ํจ์๋ฅผ ์ ์ํ๊ณ , fetch๋๋ฉด queryKey์ ๋ฐ๋ผ ๋ฐ์ดํฐ๋ก ์ ๋ฆฌ๋์ด ๋ค์ด๊ฐ๋ค. โจ Nex..
immer ๋ฐฐ์ด์ด๋, ๊ฐ์ฒด๊ฐ์ ๋ถ๋ณ์ฑ ํ์
์ ๊ฐ์ง state๋ฅผ ์
๋ฐ์ดํธ ํ๊ธฐ์ํด์ , ์คํ๋ ๋ ์ฐ์ฐ์ (...)๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค. ํ์ง๋ง depth๊ฐ ํฐ ๊ฐ์ฒด๋ฅผ ๊น์ ๋ณต์ฌ๋ฅผ ํ๊ธฐ์ ์คํ๋ ๋ ์ฐ์ฐ์๋ก ๊ฐ๋ฐ์ ์
์ฅ์์ ๊ต์ฅํ ํ๋ ์ผ์ด๋ค. โจimmer๋ฅผ ์ฌ์ฉํ๋ฉด, draft๋ฅผ ์ฃผ๋๋ฐ ๊น์ ๋ณต์ฌ๊ฐ ๋ ๊ฐ์ฒด์ด๋ค! [๊ธฐ์กด์ ๋ฐฉ์] else if (action.type === ADD_FRIEND) { const newFriend = action.payload; const newState = { ...state, friends: [...state.friends, newFriend] }; return newState; [immer] const newState = produce( (state, (draft) => { con..
NEXFLEX ๊ณผ์ โ๏ธ ์ค๋ ๋ฐฐ์ด context API๋ฅผ ํ์ฉํด์ ๋๋ค์์ ์์ ํ ์ ์๊ณ , ํค๋์ ๋๋ค์์ ๋์์ผํ๋ฉฐ ์ข์์๋ฒํผ๊ณผ ์ข์์ ์ทจ์ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ๊ฒ์ด์๋ค. HomePage์์ ์ข์์, ์ข์์ ์ทจ์๋ฅผ ๋๋ฅด๋ฉด ๋ง์ดํ์ด์ง์ ์ด์ ๊ฐ์ด ์ข์์ํ ์ํ ๋ชฉ๋ก๋ค์ด ๋ด๊ฒจ์ผํ๋ค. ๋ฌผ๋ก ์์ธํ์ด์ง์์๋ ์ข์์๊ฐ ๋ ์ํ๋ผ๋ฉด ํ์๋์ด์ผํ๋ค. ๐ ๊ฐ์ฌ๋์ ๋ฐฉ๋ฒ์ ์ ๋ฆฌํด ๋ฆฌํฉํ ๋ง ํด๋ณด์ ๐ ์ข์์ ๋ฒํผ์ ํ ๊ธ๋ก ๊ตฌํํ๋ฉฐ, likedMovies์ ์ ์ญ์ํ๋ฅผ ์
๋ฐ์ดํธ ํด์ผํ๋ค. {!likedMovies.some((likedMovie) => likedMovie.title === movie.title) ? : some()์ผ๋ก ์ข์์ํ ์ํ๋ค์ด ๋ด๊ธด likedMovie์ ํ์ฌ ํด๋ฆญ๋ movied๊ฐ ์ผ์น์ฌ๋ถ(boolean..
๋ฐฐ์ด ์ํ์ ๋ถ๋ณ์ฑ state ์ถ๊ฐ: ์ ์์๋ฅผ ๋ฐฐ์ด์ ์ถ๊ฐํ ๋๋ ์คํ๋ ๋ ์ฐ์ฐ์(... )๋ฅผ ์ฌ์ฉํด ๊ธฐ์กด ๋ฐฐ์ด์ ๋ณต์ฌํ๊ณ ์ ์์๋ฅผ ์ถ๊ฐ const [items, setItems] = useState(['์ฌ๊ณผ', '๋ฐ๋๋']); const addItem = (item) => { setItems([...items, item]); }; ์คํ๋ ๋ ์ฐ์ฐ์๋ก ์ด์ ์ items๋ฅผ ์๋ก์ด ๋ฐฐ์ด์ ๋ฃ๊ณ , ์๋ก์ด ์์๋ฅผ ๋ฎ์ด์ฐ๊ธฐ ํ์์ผ๋ก ์๋ก์ด ๋ฐฐ์ด์ ์์ฑํด state๋ฅผ ์
๋ฐ์ดํธ ํด์ค๋ค. โจ ์ ๊ฑฐ: ํน์ ์์๋ฅผ ์ ๊ฑฐํ ๋๋ filter ๋ฉ์๋๋ฅผ ์ฌ์ฉํด ํด๋น ์์๋ฅผ ์ ์ธํ ์ ๋ฐฐ์ด์ ์์ฑํด์. const [items, setItems] = useState(['์ฌ๊ณผ', '๋ฐ๋๋']); const removeItem = ..
SASS Sass(๋๋ Syntactically Awesome Stylesheets)๋ CSS์ ํ์ฅ๋ ๋ฌธ๋ฒ์ ์ ๊ณตํ๋ ์คํ์ผ ์ํธ ์ธ์ด์
๋๋ค. Sass๋ ๋ ๊ฐ๊ฒฐํ๊ณ ์ ์ง๋ณด์๊ฐ ์ฌ์ด CSS ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋๋ก ๋์์ฃผ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ์ฃผ๋ก CSS์ ๊ธฐ๋ฅ์ ํ์ฅํ๊ณ ์ค๋ณต์ ์ค์ด๋ฉฐ ๊ฐ๋
์ฑ์ ํฅ์์ํค๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. โ๏ธSASS๋ก ์์ฑํ๋ฉด CSS๋ก ๋ฐ๊ฟ์ฃผ๋ ์์
์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ, CRA๊ฐ ํด์ค๋ค๊ณ ํ๋ค. npm install -D sass #layout-header { background-color: yellowgreen; height: 80px; padding: 0 3rem; display: flex; align-items: center; .layout-header-logo { > a { font-..
โจํ์ฅ์์
2์ผ์ฐจ ๐๐ป Javascript(fetch) + React fetch const endpoint = "https://jsonplaceholder.typicode.com/todos/1"; fetch(endpoint).then(async (response) => { const data = await response.json(); console.log(data); }); const endpoint = "https://jsonplaceholder.typicode.com/todos/1"; fetch(endpoint) .then((response) => response.json()) .then((data) => console.log(data)); async function getToDo() { const..
โจํ์ฅ์์
1์ผ์ฐจ ๐๐ป Javascript SEO SEO๋ "Search Engine Optimization"์ ์ฝ์๋ก, ๊ฒ์ ์์ง ์ต์ ํ๋ฅผ ์๋ฏธํ๋ฉฐ, ์ด๋ ์น์ฌ์ดํธ๊ฐ ๊ฒ์ ์์ง์์ ๋์ ์์๋ฅผ ์ป์ ์ ์๋๋ก ์ต์ ํํ๋ ํ๋ก์ธ์ค๋ฅผ ๋งํฉ๋๋ค. ๊ฒ์ ์์ง์ ์ฌ์ฉ์๊ฐ ํน์ ํค์๋๋ก ๊ฒ์ํ ๋ ๊ฐ์ฅ ๊ด๋ จ์ฑ ๋์ ์นํ์ด์ง๋ฅผ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด ๋ค์ํ ๊ธฐ์ค์ ํ์ฉํฉ๋๋ค. ๐๐ป h1 ํ๊ทธ๋ ํ ํ์ด์ง๋น 1๊ฐ์ฉ ์ฌ์ฉํ๋ค. ๐๐ป imgํ๊ทธ์ alt๋ next.js์์ ์๋ฌ์ ์์ธ์ด ๋ ์ ์๊ณ , ์ ๊ทผ์ฑ SEO์ ์์์ ๋์ผ์ ์๋ค๊ณ ํ๋ค. ๐๐ป ์๋งจํฑ ํ๊ทธ ๋ํ SEO ์ต์ ํ ๋ฐฉ๋ฒ ์ค ํ๋์ด๋ค. ์ฒซ ํ์ฅ๊ฐ์ ์ค์ต์ด์๋ค! ์งง์ ์๊ฐ๋ด์ ๋์ผํ ํ์ด์ง๋ฅผ ๊ตฌํํ๋๋ผ ์ข ํ๋ค์์ง๋ง ๋คํํ ์ ์๊ฐ ๋ด์ ์์ฑํ ์ ์์๋ค. ์ฒซ ํ์์ดํ์ด..