원티드 프리온보딩 4월

원티드에서 운영하는 프리온보딩 4월차의 두번째 강의를  듣고 정리하는글입니다

많은 설명들을 해주셨지만 그중에서 제일궁금했던건 useEffect를 사용안해도 된다라는글을 보고 설명을 들어서입니다

https://react.dev/learn/you-might-not-need-an-effect

 

You Might Not Need an Effect – React

The library for web and native user interfaces

react.dev

리액트 공식문서에서도  useEffect가 필요하지 않을수도 있다 라고 글이나와있어서입니다

일단 프리온보딩 4월에서의 강사님께서 해주신말씀들중엔 useEffect를 아예 사용하지말라는 의견보다는 적재적소에 맞게 사용을해야한다 라고 해주셨습니다

그러면서 useEffect와 useLayoutEffect , useRef 에대해 설명해주셨습니다

글에대해 다 다뤄보기엔 말로 해주신부분이라 기억하고있는 부분을 작성해보려합니다

 

useEffect와 useLayoutEffect의 차이

 

https://medium.com/@jnso5072/react-useeffect-%EC%99%80-uselayouteffect-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C-e1a13adf1cd5

 

[React] useEffect 와 useLayoutEffect 의 차이는 무엇일까?

React 가 웹 프레임워크 시장에서 대세가 되면서, 많은 사람들이 웹 어플리케이션을 제작하기 위해 React 를 사용하고 있습니다. 특히, 2018년 10월의 React Conf 에서 발표된 React Hooks 가 등장함에 따라

medium.com

위의 블로그에서 내용을 가져왔습니다

 

useEffect

useEffect 는 컴포넌트들이 render 와 paint 된 후 실행됩니다. 

비동기적(asynchronous) 으로 실행됩니다.

paint 된 후 실행되기 때문에, useEffect 내부에 dom 에 영향을 주는 코드가 있을 경우 사용자 입장에서는 화면의 깜빡임을 보게됩니다

 

useLayoutEffect

useLayoutEffect 는 컴포넌트들이 render 된 후 실행되며, 그 이후에 paint 가 됩니다.

이 작업은 동기적(synchronous) 으로 실행됩니다.

paint 가 되기전에 실행되기 때문에 dom 을 조작하는 코드가 존재하더라도 사용자는 깜빡임을 경험하지 않습니다.

 

이외에도 useLayoutEffect의 경우 useEffect보다 먼저 실행되는걸 아래의 사진에서 알수있게되었습니다

로컬호스트에서 실행한 리액트 웹
로컬호스트 콘솔에서 확인한 console.log

useLayoutEffect 는 동기적으로 실행되고 내부의 코드가 모두 실행된 후 painting 작업을 거칩니다.

따라서 로직이 복잡할 경우 사용자가 레이아웃을 보는데까지 시간이 오래걸린다는 단점이 있어,

기본적으로는 항상 useEffect 만을 사용하는 것을 권장하는데 에시로는 

  • 데이터 fetch
  • event handler
  • state reset

등 작업은 항상 useEffect를 써야한다고합니다

 

useLayoutEffect의 경우는 state값이 존재하고 해당 state의 조건이 첫 paninting시 다르게 렌더링 할경우 useEffect를 사용하게도면 처음에 0이보여지고 re-rendering이 일어나 화면이 깜빡거리기때문에 이런경우엔 useLayoutEffect를 사용하는것이 바람직하다고 합니다

 

그리고 강사님이 useEffect의 사용이 줄어들어 된다는 이유는 useRef를 사용하여 줄어든다고 하였습니다

useRef의 경우 저장은 하나 렌더링이 필요하지않은경우 데이터를 저장해둘시에 사용한다고 하셨습니다 ( 예 : webRTC 방 유지 등 )

useRef의 사용법

제가 사용했던 useRef는 웹페이지의 주소에서 쿼리값을 가져오거나 DOM요소를 선택해야할때 사용하였습니다

이외에도 강사님이 저장하고 렌더링이 필요하지않을때에는 useRef에 저장한다고 하셔서 이에대한 글을 찾아 아래의 글을 가져오게되었습니다

 

https://powerku.tistory.com/entry/React-useRef-DOM-%EC%9A%94%EC%86%8C%EC%97%90-%EC%A0%91%EA%B7%BC%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8A%94-Hook

 

[React] - useRef() DOM 요소에 접근할 수 있는 Hook

useRef() useRef는 React Hook API 중의 하나입니다. DOM 요소에 접근하거나, 상태값을 저장할 때 사용하는 API입니다. 내부 current 변수에 저장하게 됩니다. document.getElementById와 비슷한 역할을 하게 됩니다.

powerku.tistory.com

useRef는 React Hook API 중의 하나입니다

DOM요소에 접근하거나, 상태값을 저장할때 사용하는 API이며 내부 current 변수에 저장한다고 합니다

 

'자유일지' 카테고리의 다른 글

줌클론코딩 보면서 기록했던 글  (0) 2022.06.03
2022/03/17  (0) 2022.03.18
2022/03/12 깃모음  (0) 2022.03.18
2022/03/15  (0) 2022.03.18
2022/03/16  (0) 2022.03.18

노마드코드 타입스크립트 강의를 보면서 정리한 글입니다 

노마드 첼린지 타입스크립트를 진행하고 있으며 오늘은 5일차입니다

 

 

정리

TypeScript 를 활용한 객체지향 프로그래밍

 

배우는 이유 : TypeScript가 객체지향 코드를 더 안전하고 좋게 만들도록 도와주는 기능을 제공함

 

객체 지향 프로그래밍이란?

https://insidelamp.tistory.com/72

 

코드스테이츠 블로깅 다섯번째 객체 지향 프로그래밍 ( OOP )

객체지향 프로그래밍이란? ( OOP ) 객체 지향 프로그래밍은 컴퓨터 프로그래밍 페러다임 중 하나로 프로그래밍에서 필요한 데이터를 추상회시켜 상태와 행위를 가진 객체를 만들고 그 객체들 간

insidelamp.tistory.com

타입스크립트에서 클래스 선언과 객체 생성방법

자바스크립트에서 constructor 함수를 만들고 사용하는 방법

 

 

타입스크립트에서는 파라미터를 써주기만 한다면 Constructor 함수를 만들어줍니다

 

위의 자바스크립트로 클래스를 만들어줄때 this를 사용하여 만들어줘야했지만 TypeScript는  위와같이 사용해주면 됩니다 

 

타입스크립트에서는 private 혹은 public poperty 를 만들 수 있습니다

모든 객체향 프로그래밍 언어들이 가지고있는 특징이지만 private 혹은 public 부분이 JavaScript에서는 보이지가 않습니다 

( JavaScript 로 컴파일 되면서 private 부분과 public 부분이 사라짐 )

타입스크립트의 private, public 키워드는 작성한 코드를 보호해주기위해 사용합니다  ( JavaScript 에서는 사용되지 않음)

 

 

위의 사진을 보시면 타입스크립트에서는 private으로 선언한 firstName을 보호해주는것을 보실 수 있습니다

JavaScript 에서는 private 나 public 같은 보호가 제공되지않습니다 

 

타입스크립트와 객체 지향 프로그램이 가지고있는 훌륭한점은 추상 클래스 라고합니다 

 

추상클래스란? 

  • 다른곳에서 상속만 받을 수 있는 클래스
  • 직접 새로운 인스턴스를 만들수는 없음

👆 추상클래스를 사용하여 User의 property를 상속받은 사진

👆 추상클래스를 사용하여 직접 User의 인스턴스를 생성하여 오류가 뜬 사진

위와 같이 사용해서 추상 메소드를 만들 수 있습니다

메소드란 클래스안에 존재하는 함수를 의미합니다

추상클래스 안에서는 추상 메소드를 만들 수 있습니다

  • 메소드를 구현하면 안되고 메소드의 call signature만 적어줘야합니다

추상 메소드는 추상클래스를 상속받는 모든 것들이 구현을 해야하는 메소드를 의미합니다

상속받을 property를 privite로 만든다면 클래스를 상속하였을지라도 클래스의 property 에 접근할수없습니다 

 

위의 코드는 Player에서 User를 상속받지만 Player에서는 nickname에 접근할수없는것을 볼수있습니다

 

위의 코드에서는 보호하기위한 방법이 2가지만 있는게 아니라서라고 합니다 

 

privite로 코드에 작성되어 있다면 작성된 property 들은 인스턴스 밖에서 접근할수 없으며, 다른 클래스에서도 접근할수없습니다

 

private는 말그대로 개인적인것을 말하며 User클래스의 인스턴스나 메소드에 접근할수있으나 추상클래스 ( getFullname )  의 경우 인스턴스화 할 수 없습니다

 

만약 코드가 외부로부터 보호는 되지만 다른 자식클래스에서는 사용되기를 원한다면 private를 사용하면 안되고 protected를 사용해야합니다 

 

protected를 사용 시 클래스 밖에서는 사용이 불가능하지만 User를 상속하면 User.nickname에 접근할 수 있습니다

 

 

'공부한것들 정리' 카테고리의 다른 글

타입스크립트 강의 정리 - 1  (0) 2022.12.14

노마드코드 타입스크립트 강의를 보면서 정리한 글입니다 

강의 링크 

https://nomadcoders.co/typescript-for-beginners/lobby

 

Typescript로 블록체인 만들기 – 노마드 코더 Nomad Coders

Typescript for Beginners

nomadcoders.co

정리

  • call signatures ( 호출 서명)
  • overloading ( 과부하 )

 

call signatures ( 단축키라고 볼 수 있음)

call signatures 란 함 수 위에 마우스를 올렸을때 뒤에 나오는 글들을 의미합니다 

 

 👆 위의 사진과 같이 plusFunction 함수에 마우스를 올렸을경우 나오는 글중  ( a: number, b: number ) => number 를 의미합니다 

 

call signatures는 함수를 호출할때 어떻게 호출하는지와 함수의 반환 타입에대해 알려줍니다 

함수가 어떻게 구현되는지를 알려주는게아니며 인자 ( arguments )의 타입과 함수의 반환타입을 알려줍니다

 

함수의 call signature 타입을 만드는방법은 

type Add = (a:number, b: number) => number;

const add:Add = (a,b) => a + b

위와 같이 작성해준다면 타입스크립트에게 타입이 number라고 말해줄 필요가없어집니다

왜냐

 

하면 타입스크립트는 add의 타입을  Add의 타입이라고 알고있기 때문입니다 

 

위와같이 작성한다면 함수를 구현하기전에 타입을 만들 수 있고 함수가 어떻게 작동하는지 서술이 가능해집니다

 

리액트 사용 시 props로 함수를 보내게되면 타입스크립트한테 함수가 어떻게 작동하는지 설명해줘야하는데 위와같이 사용시 함수의 반환값만 설명해주면됨

1. 프로그램을 디자인하면서 타입을 먼저생각함

2. 그 다음 코드를 구현함

아래의 add:Add 부분은 타입스크립트가 이미 알고있기때문에 타입을 추가로 작성해줄 필요없음

만약 위와같이 반환값을 number타입이 아닌 다른타입을 작성 시 타입스크립트에서 void의 반환값을 반환하지 않는다고 말해줍니다

void는 함수인데 아무것도 반환하지않는다고 말해주는것입니다

 

overloading ( 오버로딩  :  과부하 )

function overloading 이나 method overloading 라고도 부름

 

오버로딩은 함수가 서로 다른 여러개의 call signatures를 가지고 있을때 발생시킵니다

 

만약 위와같이 Add  함수가 있다면 Add 함수는 1번모양을 부를 수도 있고 2번모양을 부를 수도있습니다

파라미터 a에 마우스를 올리게되면 a의 타입은 number라고 말해주며 b의 타입은 string라고 될 수있고 number 타입이라고 될수있다합니다

위와 같이 타입스크립트는 파라미터인 b가  string 가 될수 있고 number가 될수있는데 string와 number는 더할수 없다합니다

위의 문제는 위와같이 해결이 가능합니다

하지만 위의 방식은 매우 소수의 함수만 이런방식으로 할수있어 의미가 없다고 합니다

👆위와 같이 config에 마우스를 올리게되면 config는 위에 선언하였던 string과 Config를 인자로 받을수있습니다

 

오버로딩은 위와같이 패키지나 라이브러리를 디자인할때 많이 사용합니다

핵심은 어쩔땐 type Push 안의 path가 string일때 보내줄수있고 config가 오브젝트일때도 보내줄수있게 됩니다

위와같이 사용시 타입스크립트는 내부에서 그 타입을 체크해서 보내줍니다

 

오버로딩에 대해 알아야 할 한가지가 더있는데 다른 여러개의 argument를 가지고있을때 발생하는 효과입니다

위의 상황은 똑같은 1개의 argument가 있고 타입이 틀릴경우 입니다 

만약 위와같이 argment의 가짓수가 틀리다면 타입스크립트에서 아래의 문제를 해결해달라 요청합니다

다른 개수의 파라미터를 가지게 되면, 나머지 파라미터도 타입을 지정해줘야 합니다

위의 경우는 파라미터의 개수가 다를때 일어나는 경우입니다 

이 의미는 마지막 c는 추가파라미터인 옵션이라는 뜻이 됩니다 

그래서 추가적으로 타입을 줘야하고 이 파라미터는 선택사항이라는것을 알려줘야합니다

위와같이 c가 있다면 a+b+c를 해주고 c가없을경우엔 a+b가 반환됩니다

'공부한것들 정리' 카테고리의 다른 글

타입스크립트 강의 정리 - 2  (0) 2022.12.16

메인프로젝트 통합으로 정리하며 디버깅 및 피드백받은 글들을 정리하려 합니다 ( version 3)

  • 메인프로젝트 깃허브
  • 마무리 피드백 받은 부분
  • 피드백 수정중 발견한 오류 디버깅과 진행하면서 발생한 오류 디버깅

 

메인프로젝트 깃허브 와 배포되어있는 사이트

https://github.com/codestates-seb/seb40_main_013

 

GitHub - codestates-seb/seb40_main_013: 가구 유통 플랫폼 집가구싶다🏡

가구 유통 플랫폼 집가구싶다🏡. Contribute to codestates-seb/seb40_main_013 development by creating an account on GitHub.

github.com

https://dailydaily.shop/

 

Daily, daily

 

dailydaily.shop

 

 

마무리 피드백 받은 부분

  • 로그인, 회원가입 글자 마우스 올라갈경우 크기 달라짐
    • 마우스가 올라가 있지않을경우엔 글자의 두께의 css설정이없고 올라갈경우 글자의 두께의 설정이 있어 이 부분을 제거하여 수정하였습니다
  • 로그인 시 블링킹이 티가 많이남
    • 해당 부분의 문제는 수정을 완료하였고 아래의 디버깅에서 다뤄보고자 합니다
  • 로그인, 회원가입 페이지 반응형 320px 까지 구현
    • 로그인 페이지와 회원가입 페이지가 프로젝트 초기에 만들게 됬고 이전에는 반응형을 390px까지 대응으로 진행해서 390px로 적용하였지만 이후 피드백을 받아 반응형을 320px까지 대응하기로하여 이부분을 수정하였습니다 
  • 회원가입 페이지의 경우 react-hook-form 사용하여 리팩토링 추천
    • 프로젝트 완료까지 시간이 얼마 남지않아 프로젝트 완료후 개인적으로 리팩토링 해볼예정입니다
  • 상품상세에 상세설명 / 부분 | 로 변경 
    • 해당 문제의 부분을 아래와 같이 수정하였습니다

👆 피드백 변경전의 화면

👆 피드백 변경후의 화면

 

  • 상품 상세에 옵션 안누르면 장바구니 안눌리게 alert 
    • sweetalert을 이용하여 옵션을 누르지 않은경우 옵션을 선택해주세요 를 띄우도록 만들어줬습니다 
  • 판매등록 게스트 로그인에서만 보이게설정

👆일반로그인 할경우의 화면

👆 판매 권한이 있는 게스트로 로그인한 화면

  • 상품옵션의 수량이 다떨어졌지만 요청이 안오도록 변경
    • 재고수량이 0일경우 아래사진의 alert추가하였습니다

👆 판매상품의 재고가 없을경우 품절이 보여지는 화면

  • 상품추가쪽 메인selectBox 선택시 서브 selectBox 의 기본값이 보여지는데  상품등록할경우 값이 비어져있음
    • 메인카테고리 선택할경우 서브카테고리쪽의 첫번째 요소를 상태를 업데이트하여 문제를 해결하였습니다
  • 로컬서버에서 테스트한 토큰이 배포서버에서 사용될경우 500에러를 일으키는 문제
    • 배포 서버와 로컬서버의 접근권한 토큰이 달라지기 때문에 axios의 인터셉터를 활용하여 해당메세지가 뜰경우 로그인 요청하는 alert를 추가해줬습니다 

피드백 수정중 발견한 오류 디버깅 과 진행하면서 발생한 오류 디버깅

 

 

데이터 업데이트할때 새로고침하는 문제 

👆 위의사진은 로그인시 블링킹이 일어나는현상과 동일한 사진입니다

문제점

로그인을하여 jwt토큰을 웹저장공간에 저장하여 사용자의 정보가 담겨있는 토큰을 가지고 요청을했지만 토큰이 없어 빈화면이나옵니다

새로고침을 할경우 제대로된 데이터가 보여지는것을 보실 수 있습니다

블링킹이란 화면이 깜빡이는것을 말합니다 

새로고침을하게되면 사용자에게 빈화면을 잠깐 보여주게되며 로그인할경우 토큰값을 받아오기위해 새로고침을 넣어줬습니다

이로인해 블링킹 현상이 너무 눈에 띄어 이부분을 해결해야 했습니다

 

적용전 코드

const jwtToken = localStorage.getItem("Authorization");

export const getAllReview = createAsyncThunk(
  "review/allGet",
  async ({ count, setTotalpage }) => {
    return Apis.get(
      `members/mypage/reviews?page=${count}&size=20&sort=createdAt%2CDESC`,
      {
        headers: {
          Authorization: `${jwtToken}`,
          "Content-Type": "application/json",
        },
      }
    )
      .then((res) => {
        setTotalpage(res.data.pageInfo?.totalPages);
        return res.data;
      })
      .catch((err) => {
        console.log(err);
      });
  }
);

 

해결방법

👆위의 사진은 새로고침을 하지않아도 정보를 받아오는 성공한 화면입니다

 

문제점은 jwt토큰을 받오는부분을 선언하였지만 생각처럼 받아오지 않는다는것이었습니다

콘솔로그를 활용하여 어디에서 문제인지 파악하였고 문제를 발견하였습니다

사용자가 화면에 들어오게된다면 로그인을 할경우 토큰이 담아 요청할시 사용해야했지만 사용자가 로그인을 하기도전에 아무런값이 담겨있지않아 undefined가 담기게 되어 이 부분이 문제점으로 확인하였습니다

이 부분을 해결하기위해 api 요청시 헤더부분에 로컬스토리지않에있는 토큰을 받아 사용하게 만들어줘서 해결하였습니다

 

 

적용후 코드

export const getAllReview = createAsyncThunk(
  "review/allGet",
  async ({ count, setTotalpage }) => {
    return Apis.get(
      `members/mypage/reviews?page=${count}&size=20&sort=createdAt%2CDESC`,
      {
        headers: {
          Authorization: `${localStorage.getItem("Authorization")}`,
          "Content-Type": "application/json",
        },
      }
    )
      .then((res) => {
        setTotalpage(res.data.pageInfo?.totalPages);
        return res.data;
      })
      .catch((err) => {
        console.log(err);
      });
  }
);

 

 

옵션 셀렉트박스를 새로만들었지만 자식 li 컴포넌트들이 부모의 크기를 못가져옴  ( position: absolute 사용 미숙 )

 

👆부모의 속성을 자식이 받아오지 못하는 문제의 화면

<DetailArticleOptionSpaceSelect clickSelect={clickSelect}>
    <DetailArticleOptionSpaceSelectDiv
      onClick={clickFunction}
      optionStock={optionStock}
    >
      {selectOptionColor}
      <div className="cur">
        <FiChevronDown className="button" />
      </div>
    </DetailArticleOptionSpaceSelectDiv>
    {clickSelect ? (
      <DetailArticleOptionSpaceSelectDivValueUl>
        {optionSelect?.map((option) => (
          <DetailArticleOptionSpaceSelectDivValueLi
            key={option?.optionId}
            value={option?.value}
            optionStock={option?.stock}
            onClick={() => {
              selectOption(
                option.optionId,
                option.color,
                option.stock
              ),
                clickFunction();
            }}
          >
            <>
              {option?.stock === 0 ? (
                <OptionDiv>
                  <OptionDivA optionStock={option?.stock}>
                    {option?.color}
                  </OptionDivA>
                  <OptionDivB>품절 </OptionDivB>
                </OptionDiv>
              ) : (
                <> {option?.color}</>
              )}
            </>
          </DetailArticleOptionSpaceSelectDivValueLi>
        ))}
      </DetailArticleOptionSpaceSelectDivValueUl>
    ) : (
      <DetailArticleOptionSpaceSelectDivValueUl></DetailArticleOptionSpaceSelectDivValueUl>
    )}
  </DetailArticleOptionSpaceSelect>
  
  
  
  
const DetailArticleOptionSpaceSelect = styled.div`
  border-top: 1px solid var(--color-gray);
  display: inline-block;
  width: 100%;
  height: 3rem;
  font-size: 1rem;
  border-bottom: 1px solid var(--color-gray);
`;
const DetailArticleOptionSpaceSelectDiv = styled.div`
  width: 100%;
  display: flex;
  justify-content: space-between;
  height: 46px;
  align-items: center;
  color: var(--font-navy);
  margin-left: 10px;
  position: relative;
  .button {
    font-size: 20px;
    margin-right: 10px;
  }
  .cur {
    cursor: pointer;
  }
`;

const DetailArticleOptionSpaceSelectDivValueUl = styled.ul`
  position: absolute;
  border: none;
  cursor: pointer;
  width: 100%;
`;
const DetailArticleOptionSpaceSelectDivValueLi = styled.li`
  text-decoration: none;
  color: var(--font-navy);
  padding: 15px 0px 15px 10px;
  display: block;
  border: none;
  &:nth-child(1) {
    border: none;
    border-top: 1px solid var(--color-gray);
    border-bottom: 1px solid var(--color-gray);
    background-color: white;
    &:hover {
      background-color: #f0f0f0;
    }
  }
  &:nth-child(2) {
    border: none;
    border-bottom: 1px solid var(--color-gray);
    background-color: white;
    &:hover {
      background-color: #f0f0f0;
    }
  }
`;

👆부모컴포넌트안에 자식컴포넌트를 넣어 css를 컨트롤하려 하였지만 실패한 코드

 

위의코드에서는 셀렉트박스의 사용을 위해 position의  relative 와 absolute 를 사용하였습니다

리액트를 공부하는동안 부모컴포넌트안에 자식컴포넌트를 만들게되면 자식컴포넌트는 부모컴포넌트의 css속성을 받아오는걸로 알고있었습니다

하지만 위의 사진처럼 부모안에 자식컴포넌트들이 있지만 자식컴포넌트들이 부모의 속성을 받아오지 않는다는것을 화면에서 확인하였습니다

문제점

이때의 문제는 부모속성을 바로위의 부모에게만 relative 적용했다는 것입니다

position의 absolute의 경우 relative가 없다면 요소의 기준을 전체의 HTML을 기준으로합니다

relative가 있는경우 relative가 적용된 컴포넌트를 기준으로 작동합니다 

 

해결방법

이때 해결한방법은 position의 absolute 사용하여 기준을 잡을경우 absolute는 모든 부모에 relative를 전부 사용하여 부모의 속성들을 전부 가져와야 한다는점입니다 

 

지금 현재  position의 absolute를 사용한부위는 li컴포넌트이며 부모는 ul과 div가 2개 감싸져있습니다

div2개와 ul에 전부  position의 relative 를 적용하여 이 문제를 해결하였습니다

 

👆부모의 속성을 자식이 받아와 성공적으로 보여지는 화면

 

+ Recent posts