2023.04.27 TIL

0

TIL

목록 보기
19/37
post-thumbnail

오늘의 나는 무엇을 잘했을까?

도커를 처음부터 배워서 내가 사용할 수 있는 환경을 드디어 만들어 냈다. 문서화를 통해 방법과 개념을 정리해볼 예정이다.

오늘의 나는 무엇을 배웠을까?

리액트 훅

  • 커스텀 훅 반복되는 작업들을 함수로 빼고 싶은데, 그 안에서 리액트 내장 훅들을 사용할 필요가 있다면 커스텀 훅을 만들면 된다.
    // custom hook
    
    import {useState} from "react";
    
    export default const useAsync = (asyncFunc) =>{
    	const [pending, setPending] = useState(false);
    	const [error, setError] = useState(null);
    
    	const wrappedFunction = async(...args) =>{
    		try {
    			setError(null);
    			setPending(true);
    			return await asyncFunc(...args);
    		} catch (error) {
    			setError(error);
    		} finally {
    			setPending(false);
    		}
    	}	
    	return [pending, error, wrappedFunction];
    }
    
    // custom hook 사용처
    function App(){
    	const [pending, error, getReviewsAsync] = useAsync(getReviews);
    
    	...
    	const handleLoad = (options)=>{
    		let result = getReviewsAsync(options);
    		if (!result) {
    			return;
    		}
    		//result를 가지고 할
    		//setItems[..]등의 작업
    	}
    }

    useCallback 훅

    • 컴포넌트 내에 정의된 일반 함수는 컴포넌트가 재렌더링 될 때마다 새로 만들어진다. 따라서 불필요하게 다시 생성된다는 비효율 뿐만 아니라, 이 함수가 useEffect의 디펜던시 배열에 추가되어야 할 때, 매 렌더링마다 새로운 값을 가지게 되어 useEffect가 무한루프에 빠지는 현상 또한 발생한다.

    • 이 문제를 해결할 수 있는 훅이 useCallback훅이다.

      const handleLoad = useCallback(함수, 디펜던시 리스트);
    • 디펜던시 리스트는 이 함수가 언제 새로 생성될 지 기준을 정해주는 요소들이담긴 배열이다. useEffect의 디펜던시 배열과 마찬가지로 요소들의 값이 바뀌면 그 때 함수가 새로 생성되게 된다.

    • 디펜던시 리스트에 추가해야 할 것들은 해당 함수가 외부에서 참조하는 값들이다. 그런데 setState와 같은 리액트에서 제공하는 외부 훅들은 수동으로 추가해줄 필요가 없고, 직접 정의한 함수들이나 변수들만 넣어주면 된다. 주의할 점은 useCallback 디펜던시에 들어가는 값들또한 렌더링 마다 새로 생성되고 있는지 확인해봐야 한다는 점이다. 만약 그렇게 되고 있다면 그 디펜던시 값 또한 useCallback또는 useMemo로 처리해줘야 useCallback이 제대로 사용될 수 있다.

전역 데이터 다루기

사이트의 언어 설정처럼 전역적으로 사용하는 데이터를 전역데이터라고 하는데, 이 전역 데이터를 스테이트로 만들어 사용하려면 이 데이터를 사용하는 모든 컴포넌트에게 prop drilling을 통해 번거롭게 내려줘야 한다. 이런 현상을 해결하기 위해 리액트에서 제공하는 것이 바로 React Context이다.

다음은 Context를 직접 개발한 개발자의 Context에 대한 summary이다.

Context:
Summary: adds this.context which you can think of as implicit props, which are passed automatically down the ownership or hierarchy.

Context를 사용하면 번거롭게 prop으로 데이터를 넘겨주지 않고도 여러 컴포넌트가 데이터를 사용할 수 있다. 위의 다국어 기능을 예시로 들면 특정 언어를 사용하는 상황(맥락)을 하나의 Context로 만들어 범위를 지정해줘야 한다. 해당 전역 데이터를 사용할 컴포넌트들이 묶여 있는 범위이다. 이 범위는 <Context.Provider />라는 컴포넌트의 자식 컴포넌트들이 해당된다. 이렇게 묶어줘야 한다.

  • createContext 사용법

    // src/contexts/LocaleContext.js
    import {createContext} from "react";
    
    const LocaleContext = createContext();
    
    export default LocaleContext;
    
    // app.js
    import LocaleContext from "src/contexts/LocaleContext.js";
    
    function App(){
    	...
    	return (
    		<LocaleContext.Provider value={"ko"}> //Provider에 value prop으로 컨텍스트에 공유할 전역 상태를 전달한다.
    			...
    		</LocaleContext.Provider>
    	);
    }
    
    //컨텍스트 전역 데이터 사용하는 컴포넌트 속
    function ReviewList(){
    	const locale = useContext(LocaleContext);
    
    	return (
    		...
    		<p>현재 언어: {locale}</p> //현재언어: ko
    		...
    	);
    }
  • context값에 사용자가 바꿀 수 있는 스테이트 사용하기

    //app.js
    function App(){
    	const [locale, setLocale] = useState('ko');
    	return (
    		<LocaleContext.Provider value={locale}> 
    			...
    			<LocaleSelect value={locale} onChange={setLocale} />
    			...
    		</LocaleContext.Provider>
    	);
    }
    
    //LocaleSelect.js
    function LocaleSelect({value, onChange}){
    	const handleChange = (e)=>{onChange(e.target.value)};
    
    	return (<select value={value} onChange={handleChange}>
    		<option value="ko">한국어</option>
    		<option value="en">English</option>
    	</select>);
    }
  • Context 모듈화하기

    • 위의 코드는 한 가지 문제점이 있는데, 다른 개발자가 LocalContext를 App에서 말고 다른 곳에서 쓰고 싶을 때 코드를 일일히 다 옮겨야 한다는 것이다. 그리고 컨텍스트에 사용되는 값을 스테이트로 사용할 때 모듈화를 해 놓으면 해당 스테이트는 항상 컨텍스트를 통해서만 바꿀 수 있다. 모듈화를 통해 이 컨텍스트를 쓰고 싶은 컴포넌트에 편하게 가져와 쓸 수 있게 해보자.

      //LocaleContext.js
      import { createContext, useState } from "react";
      
      const LocaleContext = createContext();
      
      export function LocaleProvider({ defaultValue = 'ko', children }) {
      	const [locale, setLocale] = useState(defaultvalue);
      
      	return (
      		<LocaleContext.Provider
      			value={{
      				locale,
      				setLocale,
      			}}
      		>
      			{children}
      		</LocaleContext.Provider>
      	);
      }
      
      export function useLocale() {
      	const context = useContext(LocaleContext);
      	
      	if (!context) {
      		throw new Error('반드시 LocaleProvider 안에서 사용해야 합니다');
      	}
      	return context.locale;
      }
      
      export function useSetLocale() {
      	const context = useContext(LocaleContext);
      	
      	if(!context) {
      		throw new Error('반드시 LocaleProvider 안에서 사용해야 합니다');
      	}
      	return context.setLocale;
      }
      
      //app.js
      function App(){
      	...
      	return (
      		...
      		<LocaleProvider defaultValue={"ko"}>
      		...
      		</LocaleProvider>
      	);
      }

docker

dockerfile

 FROM node:16-alpine
 # 경로 설정
 WORKDIR /app
 
 COPY package.json .
 # 명령어 실행 (의존성 설치)
 RUN npm install
 
 COPY . .
 # 5174번 포트 노출(vite 프로젝트용 포트)
 EXPOSE 5174
 
 CMD ["npm", "run", "dev"]

vite.config.ts

 // https://vitejs.dev/config/
 export default defineConfig({
   plugins: [react()],
   server: {
     host: true,
     port: 8000, // 이렇게 설정해두면 로컬에서 5173포트가 아닌 8000포트로 접속하면 된다. 
 		//도커에서는 5174포트로 접속이 가능해진다. 
   },
 });

이미지 빌드 명령: docker build -t <imagename> .

컨테이너 실행 명령: docker run -t -d -p 5174:5174 --name <container-name> <image-name>

컨테이너 안의 쉘 실행 명령: docker exec -it <containername> /bin/sh

프론트엔드 개발자를 위한 Docker로 React 개발 및 배포하기

How to use React or Vue with Vite and Docker

특강

개념을 개념으로 공부하려하면 너무 어려워짐. 사용하는 맥락에서 필요성을 느끼는 것이 중요. → 문제 해결 관점에서 적용하는 과정으로 개념 공부. 던져야 하는 질문: 내가 결국 지금 어떤 문제를 해결하려고 하는거지?

회사마다 원하는 인재상이 다름 → 예) 토스는 ui/ux개선 경험이 있는 프론트엔드 개발자를 원함 → 여기 가고싶다면 이런 경험을 고민하는게 중요

링크드인에서 회사 인사이더를 찾아 연락해서 커피챗을 가져보면 회사에 대해 더 잘 알 수 있음→생각보다 응답률 높음

채용시장이 얼어붙어 있어서 나만의 강점을 보유하는 것이 중요

동작되고 운영되는 서비스를 빠르게 만들어 본 경험이 상당히 중요

내가 문제를 해결할 때 어떤 시퀀스를 따라가는가 고민이 필요

전문성이 높은 개발자일 수록 다른사람에게 도움을 요청을 많이한다. 애매한 덩어리로 된 요구사항을 잘 쪼개서 중요도를 나누는 과정이 필요한데, 이것은 다른 사람들에게 물어보면서 (기획자, 디자이너 등) 인사이트를 얻는다. 잘되고 있던, 잘 안되고 있던 자주 과정을 공유해라.

사용자가 있는 서비스를 만드는 것이 중요하다 → 그래야 프로젝트를 이력서에 쓸 때 스토리텔링, 문제해결 경험을 쌓을 수 있다.

내가 모르는 것 또는 설명해보려고 했더니 잘 안나오는 것들을 리스트업 해놓고 긴 시간에 걸쳐 완성하는 것도 좋다.

JD 잘 분석하기 : 리액트 개발 경험이 있으신분 → 리액트를 ‘잘’한 경험이 있으신 분 으로 해석하면 원하는 역량이 잘 보인다.

AI 개발 시대 → 나는 어떤 문제를 해결하고 싶은가, 어떤 문제를 해결할 수 있는가 고민하자.

devfolio : 개발자들이 토이프로젝트 올리는곳

글 잘쓰는것: 말하고자 하는 거 한문장 먼저 쓰고, 글을 써내려가면서 그 문장에 가까워지고 있나의 관점에서 체크하기.

예) Context API 쓰세요. → 글을 읽는 사람이 Context API를 쓰고 싶게 만들고 있나.

코테 문제 정할 때: 흰색 문제 - 딱 보면 시뮬레이션 되는 문제

회색 문제 - 아리까리 → 이것들을 집중적으로 공략해라. 많이 풀다보면 얘네가 흰색, 검은색이 회색으로 내려간다.

검은색 문제 - 아예 접근을 못하는 문제

같은 문제를 다른 방법으로 여러번 풀어보기 → 한 문제만 풀어도 학습이 몇 배로 된다.

학습하면서 피드백을 더 자주 꾸준하게 받는 시스템을 구축해보자.

오늘의 나는 어떤 어려움이 있었을까?

도커라이징 세팅이 생각보다 오래 걸려서 위클리 미션을 제대로 시작하지 못했다. 또한 context api에 대한 방대한 실습 양을 따라가기 버거웠다.

내일의 나는 무엇을 해야할까?

  • 위클리 미션 끝내기
  • 도커 세팅과 리액트 인풋 다루기 문서화 (블로그 포스팅)

0개의 댓글