헬스체크
- 김은수
- 한남/성수 쇼핑 했습니다. 봄 옷을 샀어요. 제가 좋아하는 편집샵이 요쪽에 있어서 ㅎ
- tonywack 너무 맛있지!! 이쁜 옷들은 이미 다 품절..ㅜ
- 환승연애3 ⇒ 재밌네요…ㅎㅎ
- 2가 명작이긴해요 ㅋㅋ
- 김영현
- 감기..에 걸렸다ㅜㅜ 굉장히 독했다. 부상 투혼(?)
- 감기도.. 경험이다?(?)
- 지금은 많이 괜찮아졌다!
- 다들 감기 조심…ㅎ
- 백준원
- 감기..ㅜㅜ
- 지금은 괜찮아졌다. 다행!
- 건강 잘 챙기시기 바랍니다.
- 신종욱
- 건강은 했는데(?) 잠을 잘 못잤다. 피로가 누적ㅜ 방학때 많이 잤다!
- 어떻게 쉬셨나요? ㅎ
- 하루는 푹 자고 운동도 가고 친구들도 만나서 맛있는 것도 먹고 알차게 잘 쉬었다!!!!
- 이예진
- 아픈건 없었다(다행!)
- 방학때 하루는 놀자!! 하루종일 놀았다. 온천 사우나! 수원에 북수원온천!?! 잘 꾸며놓은 찜질방?!
질문
1. 브랜치 분기
dev — b1L b2b2 에서 작업하고 b1←b2으로 PR을 보낸상태에서 새로운 이슈가 생겨서 새로운 브랜치로 이어서 작업하고 싶다면 b2에서 분기해오는게 맞나요?dev — b1L b4L b2L b3이렇게?? 그럼 b2←b3 PR 먼저 머지하고 이전의 b1←b2 머지인가요?
1) b4 작업이 먼저 끝남
- init - b1 -b4
- b2 작업이 끝났어요
- init - b1 - b4 - b2 - b3
가장오래된ㄱ ㅓ(b1) 먼저
b4가 있는경우? 예외적으로, b1먼저하지 않고, b2,fv4에겐 b1이 dev인거처럼.
b4작업이 먼저끝났으면 먼저 b1으로
2. 객체 타입 명시
const publishIngame = (destination: string, payload: object) => {
이렇게했었는데
object
보단 명확하게 타입을 지정하고 싶다!일단, payload로 와야 하는 형식이 정해져있다.
{"currentScore": 0 }
{ "word": '단어'}
{ "currentRound" : 123 }
이렇게 세개!- 인덱스시그니처
enum PubEndPoint { CURRENTSCORE = 'currentScore', WORD = 'word', CURRENTROUND = 'currentRound', } const publishIngame = ( destination: string, payload: { [key in PubEndPoint]: number | string; }
혹은
payload: {} as [key in 'currentScore'| 'word' | 'currentRound' ]: number | string;
- 제네릭
const publishIngame = <T>(destination: string, payload: T) => { -> 좁히는게 추가로 필요함
- 옵셔널
const publishIngame = ( destination: string, payload: { currentScore?: number; word?: string; currentRound?: number; } ) => {
- 옵셔널인데 타입선언으로
export type PayloadType = | { currentScore: number } | { word: string } | { currentRound: number }; ... const publishIngame = (destination: string, payload: PayloadType) => {
export type PayloadType = | { currentScore: number } | { word: string } | { currentRound: number }; ... const publishIngame = (destination: string, payload: PayloadType) => { if (payload.currentScore) { console.log(`currentScore: ${payload.currentScore}`); } if (payload.word) { console.log(`word: ${payload.word}`); } else { console.log('else') } // 패턴 매칭(pattern matching) match(payload) .with({ currentScore: P.number }, () => console.log(`currentScore: ${payload.currentScore}`)) .with({ word: P.string }, () => console.log(`word: ${payload.word}`)) .otherwise(() => console.log('else')); }
정답은 없지만 멘토님생각으론 4번 혹은 1번
3. ref로 관리하기
“ref.current 가 변경되어도 컴포넌트를 리렌더링 하지 않는다”
zustand store Ver.
const { wordsStore, setWordStore, setSubmittedWord } = useWordsStore(); useEffect(() => { if (ingameRoomRes.submittedWord) { const submittedWord: WordQuestionType = {}; submittedWord[ingameRoomRes.submittedWord] = -1; setSubmittedWord(submittedWord); } }, [ingameRoomRes.submittedWord]); useEffect(() => { if (checkIsEmptyObj(wordsStore)) { const words: WordQuestionType = {}; for (const idx in ingameRoomRes.questions) { words[ingameRoomRes.questions[Number(idx)].question] = Number(idx); } setWordStore(words); } }, [ingameRoomRes.questions]); return ( <> <IngameHeader /> <div className='grow'> <div className='flex flex-col items-center justify-around h-[60rem]'> <div className='h-[25rem] grid grid-rows-[repeat(8,minmax(0,1fr))] grid-cols-[repeat(14,9rem)] text-[1.6rem] p-4 box-content bg-gray-10 rounded-2xl'> {!checkIsEmptyObj(wordsStore) && Object.entries(wordsStore).map((w, i) => { return ( <WordCell key={i} rd={i % 3}> {w[1] >= 0 ? w[0] : ' '} </WordCell> ); })} </div>.
의문점) 전역상태로서 여러 컴포넌트에 쓰이고 있는 건 아닌데 zustand store를 쓰는게 맞을까 ?..
ref Ver.
const { wordsStore, setWordStore, setSubmittedWord } = useWordsStore(); const testRef = useRef<WordQuestionType>({}); useEffect(() => { if (ingameRoomRes.submittedWord) { const submittedWord: WordQuestionType = {}; submittedWord[ingameRoomRes.submittedWord] = -1; setSubmittedWord(submittedWord); testRef.current = { ...testRef.current, ...submittedWord }; } }, [ingameRoomRes.submittedWord]); useEffect(() => { if (checkIsEmptyObj(wordsStore)) { const words: WordQuestionType = {}; for (const idx in ingameRoomRes.questions) { words[ingameRoomRes.questions[Number(idx)].question] = Number(idx); } setWordStore(words); testRef.current = words; } }, [ingameRoomRes.questions]); return ( <> <IngameHeader /> <div className='grow'> <div className='flex flex-col items-center justify-around h-[60rem]'> <div className='h-[25rem] grid grid-rows-[repeat(8,minmax(0,1fr))] grid-cols-[repeat(14,9rem)] text-[1.6rem] p-4 box-content bg-gray-10 rounded-2xl'> {!checkIsEmptyObj(wordsStore) && Object.entries(testRef.current).map((w, i) => { return ( <WordCell key={i} rd={i % 3}> {w[1] >= 0 ? w[0] : ' '} </WordCell> ); })} </div>
문제점 ) testRef.current 자체로는 갱신되어도 리렌더링을 만들지 않아서, 결국 화면에 그리기 위해서는 리렌더링을 시키는 state가 추가로 필요한것 같다. (위 코드의 wordsStore 는 임시..)
부모에서 원본저장해서 같이 넘겨주기
혹은 백엔드횽님들…
우선 최선의 방법을 생각하고, 다양한 시각을 생각해보는것도 !
4. useEffect의 올바른 사용법?
- 컴포넌트가 마운트 되었을 때 한번만 실행시키고 싶어서 useEffect의 dependency 배열에 빈배열을 두기
- 1번의 경우를 제외하고는 dependency array에 의존되는 값들을 다 넣는게 맞을까요?!
- eslint 도구를 이용하면 dependency 배열에 빠진 값들을 알려주는데 빠진 값들을 다 넣는게 맞을까요?!
- → 맞을 수도 있고? 아닐 수도 있다!
- 대부분의 경우 린트룰을 따르는 게 맞을 확률이 높지만, 개발자의 의도에 따라 의존하는 값을 넣으면 된다.


- 사이드 이펙트를 제어하기 위해 useEffect는 탈출구 처럼 쓰인다고 들었습니다. 적절한 사용은 좋지만 과한 사용을 지양해야 한다고 들었는데 어떠한 경우에 어떻게 써야 하는지 아직은 잘 모르겠습니다.
- best case는 없지만 worst case는 있다!
부모 컴포넌트와 자식 컴포넌트에서 동일한 상태를 쓴다면 useEffect대신 리프팅업을 쓰자!
useEffect를 2번 사용할 수도 있는지?! 3개 이상부터는 warning
useEffect 내부에 작성한 코드의 반은 Effect 밖에 작성할 수 있다!! (아마도..!)ㅈㅈㄷ