-
์ฑ์ฉ ๊ณผ์ ๋ฅผ ํ๊ฑฐ๋, ์ทจ์ ํด์ ํ์ฌ๊ฐ ์๊ธฐ๊ณ ๋๋ฉด ์ ์ญ ์ํ ๊ด๋ฆฌ ํด์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ ๊ฑฐ๋ค. (์ด๋ง์ด๋งํ props drilling์ผ๋ก ๋ชจ๋ ๊ฑธ ํด๊ฒฐํ์ง ์์ ๊ฑฐ๋ผ๊ณ ์๊ฐ....) ๊ทธ๋์ ๋ฆฌ์กํธ๋ฅผ ํ๋ฉด์ redux, recoil ๊ฐ์ ์ ์ญ ์ํ ํด์ ์๊ณ ์๋ ๊ฒ ํ์๋ผ๊ณ ์๊ฐํ๋๋ฐ,
๋๋ ์ ๊ทธ๋์ ์ฌ์ฉํ์ง ์์๋์ง?์๋ฌดํผ ์ด๋ฒ์๋ ๋ฆฌ๋์ค๋ฅผ ํ์๋ก ์ฌ์ฉํ๋ ๊ณผ์ ์๊ณ , ์ด์ ์๋ Context API๋ ๋ฆฌ๋์ค ํํ ๋ฆฌ์ผ (์ ๋์ง๋ง)์ ํตํด ์ฌ์ฉํด ๋ดค๊ธฐ ๋๋ฌธ์ ๊ทธ๋ฅ ๊ฑฑ์ ์ ๋์ง ์์๋ค!์ฐ์ ์ด๋ฒ์๋ ๊ณผ์ ๋ณ๊ฒฝ ์ฌํญ์ด ๋ง์๊ธฐ ๋๋ฌธ์ ์กฑ๊ธ ์ ์ ์ด ์์๊ณ ... swit ๊ณผ์ ๋ ํ๋กํ ํ์ ์ด ์์๊ธฐ ๋๋ฌธ์ ๋์์ธ์ ์ด๋ป๊ฒ ํ์ง ์๊ฐํ๋ค๊ฐ swit์ ์ด๋ฏธ ์ ์ฌ์ฉ๋๊ณ ์๋ ๋ฉ์ ์ ์ด๊ธฐ ๋๋ฌธ์~ ์น ๋ฒ์ ๋์์ธ์ ์ฐธ๊ณ ํ๋ฉด ๋๊ฒ ๋ค๊ณ ์๊ฐํ๋ค.
(๋์์ธ์ด๋ผ๋ ์ฝ๊ฒ ๊ฐ์ ๋ง์ธ๋ ๋ง๊ณ ์ ํผ๊ทธ๋ง ์ฌ์ฉ์ด๋ผ๋ ์ง ๋์์ธ์ ์ ์ฒด์ ์ผ๋ก ์กฐ๊ธ ์์ ์์์ ๊ทธ๋ฌ๋ ๊ทธ๋ ๊ฒ ํํผํ ๊ฒ์ด ๋์ค์ ํ์ค๋ก ์ผ์ด๋ฉ๋๋ค)๊ทธ๋ฆฌ๊ณ ๋ฆฌ๋์ค๋ฅผ ์ฌ์ฉํ ๊ฑด์ง ๋ฆฌ๋์ค ํดํท์ ์ฌ์ฉํ ๊ฑด์ง๋ ํ์ํ ๋ ๋งํ์๋๋ฐ, C์ธ์ด๋ถํฐ ๋ฐฐ์ด ์ ๊ณต์ ์ ์ฅ์์๋ ์ญ์ ์ด๋ ค์ด ๊ฑธ ๋จผ์ ๋ฐฐ์ ๋ด์ผ ๋ค์์ ๋ฐฐ์ธ ๊ฒ๋ ์ฝ๊ณ ...... (๋ง์น C๋ ์๋ฐ ๋ฐฐ์ฐ๋ค๊ฐ ํ์ด์ฌ์ ์ฒ์ ๋ฐฐ์ ์ ๋ ์ฌ์ ๋ ๊ฒ์ฒ๋ผ) ๊ทธ๋์ ๋ฆฌ๋์ค๋ฅผ ์ฌ์ฉํด ๋ณด๊ณ ์ถ์๋ค. ํ์ ๋ถ๋ค์ด ์ข์์ ๊ทธ๋ ๊ฒ ํด ์ฃผ์ จ๋ค. ๋ด ์๊ฒฌ๋ง์ ์๋์๊ฒ ์ง?
์๊ตฌ ์ฌํญ์ ๋ณธ์ธ์ด ์์ฑํ ๋ฉ์์ง๋ ์์ * ํ์๊ฐ ๋ถ๋๋ค๊ณ ํด์ ๊ฐ๋จํ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ด ์์ด์ผ๊ฒ ๋ค~ ํ๊ณ , ์ด๋ฅผ ํ์ด์ด๋ฒ ์ด์ค๋ก ๊ตฌํํ์๊ณ ํ์ ์ ์กฐ๊ธ ์ค๋ฒ์คํ์ด ์๋๊ฐ ์ถ์์ผ๋ ๋คํํ๋ localStorage + redux ์กฐํฉ์ผ๋ก ์ ํด๊ฒฐํ๋ค.
์๋ฌดํผ ์์~
1. useFetch & json-server
์ ์ค์ท์ ๋ณด์ด๋ ๊ฒ์ฒ๋ผ ์ฌ์ดํธ์ ์ ์ํ๋ฉด 5๋ช ์ด ๋ ๋ค๊ณ ์๋ ์ฑํ ์ด ๋ฏธ๋ฆฌ ์ถ๋ ฅ๋์ด์ผ ํ๋ค. ์ด๋ฅผ ์ํด ๋ชฉ ๋ฐ์ดํฐ๋ฅผ ์ฐ๋ฆฌ๊ฐ ๋ง๋ค๊ณ ์ ๋ฒ์ ์ฌ์ฉํ๋ json-server๋ฅผ ์ฌ์ฉํ๋ ๊ฒ ์ด๋ ๋~ ์ ์ํ๋๋ฐ ๊ด์ฐฎ์ ๊ฒ ๊ฐ๋ค๊ณ ํด์ ์ ๋ฒ๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์งํํ๋ค.
๊ทธ๋ฆฌ๊ณ custom hook์ ์ฌ์ฉํ๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค ์ถ์ด์ useFetch ํ ์ ๋จผ์ ์์ฑํ๊ณ ์งํํ๊ฒ ๋์๋ค.
import { useEffect, useState } from 'react'; const useFetch = (url) => { const [state, setState] = useState(); useEffect(() => { const request = async () => { const json = await (await fetch(url)).json(); console.log(json); }; request(); }, []); return state; }; export default useFetch;
2. ๋ฉ์์ง ๋ต์ฅ ๊ธฐ๋ฅ
ํ์ ์ ํ๊ธฐ ์ ์๊ตฌ ์ฌํญ์ ์ดํด๋ณด๋๊น ๋ฉ์์ง ์ ๋ ฅ, ๋ต์ฅ, ์ญ์ ๋ถ๋ถ์ ๊ตฌํํด์ผ ํ๋ค. ๊ทผ๋ฐ ์ด ๋ถ๋ถ์ด ๋ญ๊ฐ ํ์ ํ ๋ ๋ฑ๋ฑ ๋๋ ์ง ๋ถ๋ถ์ด ์๋๋ผ ์กฐ๊ธ ๊ณค๋ํ ๊ฒ ๊ฐ์์ redux store ๋ถ๋ถ์ ๊ฐ์ด ์์ฑํ๊ณ ์งํํ๊ธฐ๋ก ํ๋ค.
import { createStore } from 'redux'; export const FETCH = 'FETCT'; export const ADD_MESSAGE = 'ADD_MESSAGE'; export const REPLY_MESSAGE = 'REPLY_MESSAGE'; export const REMOVE_MESSAGE = 'REMOVE_MESSAGE'; export const addMessage = (userId, userName, profileImage, content) => ({ type: ADD_MESSAGE, userId, userName, profileImage, content, }); export const replyMessage = () => ({ type: REPLY_MESSAGE }); export const removeMessage = () => ({ type: REMOVE_MESSAGE }); const initialState = []; const todoReducer = (state = initialState, action) => { switch (action.type) { case FETCH: return (state = action.value); case ADD_MESSAGE: return state.concat({ userId: action.userID, userName: action.userName, profileImage: action.profileImage, content: action.content, date: new Date(), }); default: return state; } }; const store = createStore(todoReducer); export default store;
๋์ถฉ ์ด~~ ๋ ๊ฒ Fetch๋ถํฐ ๋จผ์ ํด ๋ณด๊ธฐ.
๋๋ ๋ฆฌ๋์ค๋ฅผ ์ฌ์ฉํ ํ๋ก์ ํธ๋ ์ฒ์์ด์ด์ ๊ทธ๋ฌ๋์ง๋ ๋ชจ๋ฅด๊ฒ ๋๋ฐ, fetch ํ๋ ๊ฒ๋ถํฐ ๊ฝค ์ค๋ ๊ฑธ๋ ธ๋ ๊ฒ ๊ฐ๋ค. ^^ ๊ทธ์น๋ง ํด๊ฒฐ ๋ชป ํ๋ ์ค๋ฅ๋ ์๋ค๊ณ ๋ด๊ฐ ๋ ํด๋! ๋ด๊ฐํด๋!
๊ทธ๋ฆฌ๊ณ ๋ด๊ฐ ๋งก์ ๋ต์ฅ ๊ธฐ๋ฅ์ ๋ต์ฅ ๋ฒํผ์ ๋๋ฅด๋ฉด ํด๋นํ๋ ๋ฉ์์ง๋ฅผ ๋ณด๋ธ ์ฌ๋, ๋ฉ์์ง ๋ด์ฉ, (ํ์ ) ์ด๋ ๊ฒ ์ธ ๊ฐ์ง๋ฅผ ์ ๋ ฅ์ฐฝ์ ์๋ ์ ๋ ฅํ๋ ๊ธฐ๋ฅ์ด์๋ค. ์ด ๊ธฐ๋ฅ์ ๋ฒํผ์ ๋๋ฅด๋ฉด
`${๋ณด๋ธ ์ฌ๋}\n${๋ฉ์์ง}\n(ํ์ )\n`
์ด๋ฐ ๋ฌธ์์ด์ redux๋ก ๊ด๋ฆฌํ๊ณ , ์ ๋ ฅ์ฐฝ์์ ๋ถ๋ฌ์ค๋๋ก ํ๋ค. ์ฒดํฌ๋ฐ์ค์ ์น์ฌ์ ๊ทธ๋ฌ๋์ง ๋ชฐ๋ผ๋ ๋๋ฆ ์ฌ์ ์...3. ์ ๋ ฅ์ฐฝ์ ๋ง์ถฐ์ ์คํฌ๋กค ๋ด๋ฆฌ๊ธฐ
์ด๋ฐ์์ผ๋ก ์ ๋ ฅ์ฐฝ์ด ์ปค์ง๋ฉด ์ ๋ ฅํ ์ฑํ ๋ ์ฌ๋ผ๊ฐ๊ฒ ๋ง๋ค๊ณ ์ถ์๋ค. ์๋๋ฉด ์ค์์ด ๊ทธ๋ ๊ฒ ์๊ฒผ์.... ๊ทธ๋ฌ๋๊น ์ฐ๋ฆฌ๊ฐ ์ํ๋ ์๊ตฌ์ฌํญ ์ค ํ๋์์.
๊ทธ๋ฐ๋ฐ ๊ธฐ์กด ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๋ ์ปดํฌ๋ํธ์ ๋ฉ์์ง๋ฅผ ์ ๋ ฅํ๋ ์ปดํฌ๋ํธ๊ฐ ๋ถ๋ฆฌ๋์ด ์์ด์ ์ด๋ป๊ฒ ํ๋ฉด ๋์ ์ฐ๊ฒฐ์ํฌ ์ ์์๊น...... ๊ณ ๋ฏผ์ ๋ง์ด ํ๋ค!
๊ทธ๋์ ๋ด๊ฐ ์๊ฐํ ๋ฐฉ๋ฒ์ ๋ฉ์์ง ์ถ๋ ฅํ๋ Div์ useRef๋ฅผ ์ด์ด ์ฃผ๋ ๊ฑด๋ฐ, ๊ทธ๊ฑธ ์์์์ ์ ์ํ๊ณ , ๋ฉ์์ง ์ถ๋ ฅ ์ปดํฌ๋ํธ์ ์ ๋ ฅ ์ปดํฌ๋ํธ์ ๋ชจ๋ ์ ๋ฌํ๋ค.
const Main = () => { const MsgBoxRef = useRef(); return ( <Messages MsgBox={MsgBoxRef} /> <NewMessage MsgBox={MsgBoxRef} /> ) }
์ด๋ฐ ์์ผ๋ก! (Messages๊ฐ ์ถ๋ ฅ ๋ด๋น์ด๊ณ NewMessage๊ฐ ์ ๋ ฅ ๋ด๋น)
๊ทธ๋ฆฌ๊ณ Messages์์๋ ๋ฉ์์ง๋ค์ ๊ฐ์ธ๋ ์ ์ฒด div์ MsgBox๋ฅผ ์ฐ๊ฒฐํด ์ค๋ค.
const Messages = (props) => { return ( <S.StyledMessages ref={props.MsgBox}> // ์๋ต ) }
์ ๋ ฅ์ฐฝ ๋ฐ์ค ํฌ๊ธฐ์ ๋ฐ๋ผ Messages์ ์ถ๋ ฅ div ์คํฌ๋กค์ ๋งจ ๋ฐ์ผ๋ก ๋ด๋ฆฌ๋ ํจ์๋ NewMessage ์ปดํฌ๋ํธ์์ ์ ์ํด ์คฌ๋ค.
const scrollHandler = () => { MsgBox.current.scrollTo({ top: MsgBox.current.scrollHeight, }); }; useEffect(() => { scrollHandler(); }, [scrollHeight]);
์ด๋ฐ ์์ผ๋ก ์ ๋ฌ๋ฐ์ MsgBox์ ์คํฌ๋กค์ ๊ฐ์ฅ ๋ฐ์ผ๋ก ๋ด๋ฆฌ๊ณ , ์ ๋ ฅ์ฐฝ์ ๋์ด๊ฐ ๋ด๊ฒจ ์๋ scrollHeight๊ฐ ๋ณํ ๋๋ง๋ค scrollHandler๋ฅผ ์คํํ๋๋ก ์์ฑํด ์ฃผ๋๊น ์๋์.
4. ์ ๋ ฅ์ฐฝ ์์ ์ ์ก ๋ฒํผ
์ด๊ฑด ๋ง๊ฐ ๊ธฐํ์ด ์์ด์ ์ ๋นํ ํํํ๊ณ ์ ์ถํ ๊ฑด๋ฐ, ์ถ์ํ๋ฉด ์ ๋ฒํผ์ด ์ ๋ ฅ์ฐฝ์ ๋น๋๊ฐ๋ค...... ๐คฆ๐ป ๋ฌผ๋ก ์๋ํ๋ ๊ฑด ์ฌ๋ฌ ๋ฐฉ๋ฒ์ด ์๋ค.
1. input ์ฐฝ absolute, button๋ absolute ์ค์ ํ๊ธฐ
์ด๊ฑด ์ถ์ํด๋ ๋ฒํผ์ด input ์ฐฝ ์์ ์ ! ์์ ํ! ์๋๋ฐ ๋ฌธ์ ๊ฐ ๋ญ๋๋ฉด 3๋ฒ์์ ์ด ์ ๋ ฅ์ฐฝ์ ๋ง์ถฐ ์คํฌ๋กค ๋ด๋ฆฌ๋ ๊ฒ ์ ๋๋ค.
2. input ์ฐฝ relative, button๋ง absolute ์ค์ ํ๊ธฐ
์ ์ค์ท์ด ์ด๋ ๊ฒ ์ค์ ํ ๊ฒฐ๊ณผ๋ค. ์คํฌ๋กค์ด ๋ ์ฐ์ ์์๋ผ๊ณ ์๊ฐํ๊ณ , ์ถ์๋ง ์ ํ๋ฉด ๋ฒํผ์ด ์ ์์ผ๋๊น(...) ์ผ๋จ์ ์ด๋ ๊ฒ ์ค์ ํ๋ค.
๊ทธ๋ฆฌ๊ณ ํด์๋๋ง๋ค ๋ฒํผ ์์น๋ ์ฝ๊ฐ ๋ฌ๋๋๋ฐ, ์ด๊ฑด ๋ฒํผ ์คํ์ผ์ rem์ผ๋ก ํ๊ณ , input์์๋ px๋ก ์ค์ ํด์ ์กฐ๊ธ ๋ฌ๋๋ ๊ฒ ๊ฐ๋ค. ๋๊ฐ์ด px๋ก ๋ฐ๊พธ๋๊น ์ฌ๊ฐํ๊ฒ ๋ค๋ฅด์ง ์์๋ค.
์์ ํ๋ก์ ํธ๋ถํฐ ๋ฆฌํฉํ ๋ง ํ๊ณ ์์ด์ ์ข ํ์์์ง๋ง ์๋ ์๋ฌดํผ ๋ฆฌํฉํ ๋ง ๋์์ด๋ค.
+ 22.04.01
textarea์ button์ ๋ถ๋ชจ์ธ div์ form์ align-items ๊ฐ์ center์์ flex-end๋ก ๋ฐ๊พธ๋ฉด์ ์ํ๋ ๋๋ก ์ด๋ค ํด์๋์์๋ ๋ฒํผ์ด ์ธํ ์ฐฝ ์์ ๋ค์ด๊ฐ๋๋ก ๊ตฌํํ๋ค. ์ด๋ป๊ฒ ์์๋๋ ํ๋ฉด, textarea์ height๊ฐ ๋์ด๋๋ฉด textarea๊ฐ div์ ๊ฝ ์ฐจ๊ฒ ๋์์ผ๋ ์ด๊ธฐ์๋ div์ ์ ๋ ฌ์ center๋ก ์ค์ ํ๊ธฐ ๋๋ฌธ์ textarea์ ์ฌ๋ฐฑ์ด ์๊ฒผ์๊ณ , ๊ทธ ๋๋ฌธ์ ๋ฒํผ์ position์ absolute๋ก ์ค์ ํ๊ณ bottom ๊ฐ์ 0์ผ๋ก ์ฃผ์์ ๋ textarea์์ ์ด์ง ๋น๊ปด๋๊ฐ๊ฒ ๋ ๊ฒ์ด๋ค. ํ์ฐธ ๋์ ๋ด ๋จธ๋ฆฌ๋ฅผ ์ํ๊ฒ ํ๋ ์ฅ๊ณ ์๋ ์์ ๋ฅผ ๋๋์ด ํด๊ฒฐํด์ ๋ฟ๋ฏํ๋ค!
absolute์ relative ๋ฌธ์ ์ธ ์ค ์์๋๋ฐ ํ ๊ฐ์ง ๋ฌธ์ ์ focus๋ฅผ ๋ง์ถ๋ ๊ฒ ์๋๋ผ ์ฌ๋ฌ ์์ธ์ ๋ชจ๋ ์ดํด์ผ ์๋ฌ๋ฅผ ํด๊ฒฐํ ์ ์๋ค๋ ๊ฑธ ๋ค์๊ธ ๊นจ๋ซ๊ฒ ๋๋ค.
์ด๊ฒ ๋๋ค!
๊ทธ๋๋ ์ ๊ณผ์ ์ ๋นํ๋ฉด ์ฝ๊ฒ ๋๊ปด์ ธ์ ์งง์ ์๊ฐ์ ๊ต์ฅํ ์ฑ์ฅ์ ํด๋๊ตฌ๋! ์ถ์๋ค. ๊นํ๋ธ์ ์ด์ ๊ด๋ฆฌ๋ ํ์๋๋ฐ, ์ ์ฌ์ฉํ๋ฉด ํ๋ก์ ํธ ์ผ์ ๊ด๋ฆฌ์ ์ ์ฉํ์ ํ ๋ฐ ์ง๊ธ ์๊ฐํด ๋ณด๋ ์์ฝ๋ค. ์ด๋์ฏค ๋๋ ๋ฐฐํฌ๋ ๊ฑฐ์ ๊ธฐ๋ณธ์ด ๋ผ์ Netlify๋ฅผ ํตํ ๋ฐฐํฌ๋ ์์ฃผ ์์ํ๊ฒ ํ์๋ ๊ธฐ์ต์ด. ใ ใ ๋ฆฌ๋์ค๋ ๋ ํฐ ํ๋ก์ ํธ์์ ์ฌ์ฉํด ๋ณด๊ณ ์ถ๋ค. ๊ฐ๋ ์ฑ ์๋ ๋ฆฌ๋์ค ์ฝ๋ ์์ฑํ๋ ๊ฒ ์๊ทผ ๊น๋ค๋กญ๊ณ ์ด๋ ค์ด ๊ฒ ๊ฐ๋ค.
์ ์ฒด ์ฝ๋๋ ์ฌ๊ธฐ์ ํ์ธํด ์ฃผ์ธ์. ๐ฅฐ
'ETC' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ