Coder Social home page Coder Social logo

why's Introduction

why's People

Contributors

saseungg avatar

Watchers

 avatar

why's Issues

npm과 yarn 차이는 뭘까?

패키지를 관리하는 툴인 npm, yarn 둘의 차이점이 궁금했다.

npm, yarn은 뭔데?

  • 패키지 관리 툴
  • 둘은 호환이 가능하다.

npm

  • Node.js의 기본 패키지 매니저
  • 패키지를 순차적으로 설치

yarn

  • 페이스북이 npm의 단점을 보완하고자 만든 패키지 매니저 (보완성, 속도 보완)
  • 패키지 병렬적 설치로 속도면에서 npm보다 빠르다.

결론

yarn이 npm보다 속도, 보완면에서 더 좋다고하지만 npm도 속도, 보완면에서 많이 개선이 되서 차이는 크게 없다고 한다. yarn은 단점으로 디스크 공간 점유율이 높다고 하니 취향껏 사용하면 될듯!

같이 보면 좋을 자료

npm? yarn? 그 차이가 뭐길래...

StrictMode를 쓰는 이유는 뭘까?

cra를 쓰면 index.js 파일에 있는 StrictMode는 무엇이고 왜 쓸까?

StrictMode란?

  • 웹 애플리케이션 내의 잠재적인 문제를 알아내기 위한 도구
  • Fragment와 같이 UI를 렌더링하지 않으며, 자손들에 대한 부가적인 검사와 경고를 활성화한다.
  • StrictMode는 개발 모드에서만 활성화되기 때문에, 프로덕션 빌드에는 영향을 끼치지 않는다.

예시

import React from 'react';

function ExampleApplication() {
  return (
    <div>
      <Header />
      <React.StrictMode>
        <div>
          <ComponentOne />
          <ComponentTwo />
        </div>
      </React.StrictMode>
      <Footer />
    </div>
  );
}
  • Header와 Footer 컴포넌트는 StrictMode 검사가 이루어지지 않음
  • ComponentOne과 ComponentTwo는 각각의 자손까지 검사가 이루어진다.

StrictMode 검사항목

  • 함수가 순수한지 판별 가능

    • 랜덤 메서드가 있을 경우 리렌더링할때마다 값이 바뀔것이다. StrictMode를 통해 두번 실행하면서 함수가 순수한지 판별할 수 있음
  • 예상치 못한 부작용 검사

리액트 공식문서에 나오는 추가 항목들은 아직 와닿지는 않아서 적진 않겠다.

같이 읽어보면 좋을 문서

리액트 공식문서
페이스북 리액트 레포 strict모드 관련 이슈

json파일을 public 폴더에 넣어야하는 이유

리액트에서 json파일을 만들고 fetch를 통해 데이터를 불러오는 과정에서 경로 인식 문제가 있었고 public에서만 인식이 되는지에 대해 의문이 생겼다.

문제 상황

src 폴더

src 폴더 안에 data/data.json 파일을 넣어 데이터를 fetch 해줬다.
image
image
주소가 일치하지 않을 때 나오는 304에러가 나오며 VM570:1 Uncaught (in promise) SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON 해당 에러가 나오는데 마찬가지로 경로가 일치하지 않았을 때 등장하는 에러이다.

public 폴더

image
image
public폴더로 옮겨주니 데이터가 잘 들어온다.

결론

찾아보니 대부분 public 폴더 안에 넣어서 관리했다. 나는 여기서 궁금해졌다.

왜 public은 되고 다른 폴더들은 인식이 안되지??

json 파일을 src폴더, 루트 위치에 넣었을 때 경로 인식 문제가 발생하는 것은 프로젝트 구조와 서버 동작방식에 관련이 있었다.
public 폴더는 정적 파일을 호스팅하기 위한 공용 디렉토리이다. 따라서 정적 데이터는 public에서 관리되어야한다! 동적 파일들을 관리하는 src 폴더에 json 파일을 넣고 불러오니 인식을 못했던 것이었다!

부모 컴포넌트에서 state를 전부 관리하는 것이 과연 좋을까?

이슈 9와 이어지는 문제

코드 예시

상위 컴포넌트에서 state를 전부 정의하고 있다. 핸들러를 전부 정의하고 카운터 함수에 props로 전달해주고 있다.
그럼 카운터 함수에서 state를 정의하는 것과의 차이가 무엇이고 뭐가 효율적일까?
아래의 질문을 보고 생각해보자.

const CountPage = () => {
  const [topCount, setTopCount] = useState(0);
  const [bottomCount, setBottomCount] = useState(0);

  const handleTopCount = function () {
    setTopCount(prev => prev + 1);
  };

  const handleBottomCount = function () {
    setBottomCount(prev => prev + 1);
  };

  return (
    <div>
      <h2>
        {`TOTAL COUNT : ${topCount + bottomCount}`}
        {topCount + bottomCount > 10 && '🔥'}
      </h2>
      <Counter count={topCount} handleClick={handleTopCount} />
      <Counter count={bottomCount} handleClick={handleBottomCount} />
    </div>
  );
}

고민해보자 🧐

  1. Counter가 2개가 아니라 10개라면?
    하위 컴포넌트의 갯수가 지금처럼 2개가 아니라 10개 이상으로 많아진다면 상위 컴포넌트에 동일한 코드가 많아질 것이다.
    각각의 카운터 컴포넌트에 들어가는 카운트숫자를 카운트 컴포넌트 개수만큼 useState를 선언해주어야한다. 중복 코드가 많아짐.

  2. Counter 컴포넌트 자체로 재사용이 가능한가?
    숫자를 증가시키는 업데이트 기능과 현재 카운트를 카운트 컴포넌트가 아닌 상위 컴포넌트에서 관리하고 있어 카운트 컴포넌트 자체로는 재사용이 불가하다. 해당 카운트 컴포넌트를 사용할 때마다 다른 상위 컴포넌트에서 매번 상태값과 증가하는 코드를 가지고 있어야한다.
    counter 컴포넌트 자체로 독룁된 재사용성이 높은 컴포넌트라고 볼 수 없다.

결론 : 서로 독립적이고 재사용가능한 컴포넌트들로 구성되어야 하는 것이 리액트 컨셉에도 맞다.

Position 설정 값은 같은데 왜 컴포넌트 위치가 다르게 표시될까?

profile 카드를 만들던 중 position 값을 똑같이 줬음에도 컴포넌트 위치가 다르게 표현되어 원인을 파악하고자 했다.

문제 화면 및 코드

두개의 컴포넌트의 new 박스 위치가 다르다. css 값은 동일한데 뭐가 문제일까? 일단 해당 화면에 대한 코드이다.

// Avatar 컴포넌트
const Avatar = ({ image, isNew }) => {
  return (
    <div className='avatar'>
      <img className="image" src={image} alt="avatar" />
      {isNew && <span className="new">NEW</span>}
    </div>
  );
};
// Profile 컴포넌트
const Profile = ({ image, name, title, isNew }) => {
  return (
    <div className="profile">
      <Avatar image={image} isNew={isNew}/>
      <h1>{name}</h1>
      <span>{title}</span>
    </div>
  );
};
// App에서 Profile과 Avatar 컴포넌트를 선언했음
    <>
      <Profile image={image} isNew={isNew} />
      <Avatar image={image} isNew={isNew} />
    </>
.avatar {
  position: relative;
}

.image {
  width: 200px;
  height: 200px;
  border-radius: 100%;
}

.new {
  width: 50px;
  border-radius: 10px;

  padding: 5px;
  position: absolute;
  top: 20px;
  left: 80px;

  text-align: center;
  background-color: rgb(160, 250, 244);
}

왜 둘의 new 박스의 위치가 다를까?
position은 동일한 위치에 있을 것인데 다르게 나오는지 이해가 안갔다.

원인

원인은 avatar의 사이즈값이다.
avatar 사이즈값을 지정하지 않으니 Profile 컴포넌트 내에서 avatar 컴포넌트를 선언함으로써 avatar의 사이즈값이 커졌다.

.avatar {
  position: relative;
  width: 200px;
  height: 200px;
}

.image {
  width: 200px;
  height: 200px;
  border-radius: 100%;
}

이미지랑 동일한 사이즈값으로 변경하니 해결!

이미지를 가운데로 오게 하기 위해 avatar에 maring: auto;를 주고 top, left-> right로 설정값을 수정하면 아래와 같이 표시된다!

최종 코드

.avatar {
  position: relative;
  width: 200px;
  height: 200px;
  margin: auto;
}

.image {
  width: 200px;
  height: 200px;
  border-radius: 100%;
}

.new {
  width: 50px;
  border-radius: 10px;

  padding: 5px;
  position: absolute;
  top: 25px;
  right: 5px;

  text-align: center;
  background-color: rgb(160, 250, 244);
}

useMemo로 캐쉬된 값은 메모리에 어느 시점에 삭제될까?

useMemo는 캐쉬된 값이 메모리에 저장되는데 어느 시점에 메모리에서 삭제되는지 궁금해졌다.

useMemo는 useMemo가 사용된 컴포넌트가 언마운트 됐을 때 메모리에서 삭제되며, 마운트가 유지될 경우 메모리에 계속 남아있는다.
따라서 useMemo로 많은 값을 캐쉬했을 경우 차지하는 메모리 공간이 많아지므로 무분별한 useMemo 사용은 지양하는 것이 좋다.

처음 든 생각은 가비지 컬렉터가 일정 시점에 지워주는가 아닐까했었는데 그런건 아니다!

Node.js는 프레임워크일까?

강의를 듣던 중 Node.js 관련 설명 부분에서 "JavaScript runtime environment (framework) that executes JavaScript code outside a web browser javascript everywhere" 이 부분을 보고 그럼 노드도 프레임워크인가라는 궁금증이 들었다.

https://dev.to/educative/what-is-nodejs-a-beginners-introduction-to-javascript-runtime-1iki

https://velog.io/@ktaewon98/Node-Node-JS%EB%8A%94-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC%EC%9D%BC%EA%B9%8C-NO
바로 위 블로그는 아니라고 나와서 잘 모르겠지만 일단 프레임워크가 아닌건 확실함 .

추가적으로 알게되면 업데이트 하자

업데이트 함수(setState)를 props로 전달하는 것이 왜 안좋을까?

setState를 그대로 전달하는건 외부에 데이터 변경의 주도권을 넘겨주는 것과 같다. 콜백함수로 감싸서 넘기고 자식 컴포넌트가 적절한 시점에 호출만 하도록 하는 것이 좋다. 그럼 호출하는 입장은 그 기능의 세부 로직은 알지 못하기 때문이다.

결론 : 데이터의 주도권을 지키면서 컴포넌트 간의 협력을 가능하게 하는 것이 좋다.

예시

화면 기록 2023-09-04 오후 5 04 27

버튼을 누르면 카운트가 1씩 증가하고 카운터를 두개 선언했을 당시 각각의 카운터의 토탈 합산을 알 수 있도록 카운터를 만들어보자.
각각의 카운터의 토탈 카운트는 공유하지만 개별의 카운트 숫자는 각각 다르게 동작한다.

Bad Case

const CountPage = () => {
  const [count, setCount] = useState(0);

  return (
    <div className="pageLayout">
      <p className="header">Total Count : {count}</p>
      <Count set={setCount} total={count} />
      <Count set={setCount} total={count} />
    </div>
  );
};
const Count = ({ set, total }) => {
  const [count, setCount] = useState(0);

  const handleClickIncrease = () => {
    setCount((prev) => prev + 1);
    set((prev)=>prev+1);
  };

  return (
    <div className="container">
      <p className="count">
        {count}
        <span className="total">/{total}</span>
      </p>
      <button className="countButton" onClick={handle}>
          +1
      </button>
    </div>
  );
};

set 함수를 하위 컴포넌트에게 넘겨줌으로써 데이터를 변경하는 권한을 자식에게 넘겨줌.
목적은 숫자를 1씩 증가시키는 것인데 하위 컴포넌트에서 마이너스를 처리한다던지 변경할 수 있는 권한을 넘겨주는 것이다.

Good Case

const CountPage = () => {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount((prev) => prev + 1);
  };

  return (
    <div className="pageLayout">
      <p className="header">Total Count : {count}</p>
      <Count onIncrease={handleClick} total={count} />
      <Count onIncrease={handleClick} total={count} />
    </div>
  );
};
const Count = ({ onClick, total }) => {
  const [count, setCount] = useState(0);

  const handleClickIncrease = () => {
    setCount((prev) => prev + 1);
    onClick();
  };

  return (
    <div className="container">
      <p className="count">
        {count}
        <span className="total">/{total}</span>
      </p>
      <button className="countButton" onClick={handle}>
          +1
      </button>
    </div>
  );
};

상위 컴포넌트 핸들러안에 set함수를 정의한 후 핸들러를 넘겨준다.

Object.is()와 === 차이점

리액트 공식문서에서 React는 Object.is 비교 알고리즘을 사용하여 각 의존성을 이전 값과 비교합니다. 라는 문구를 보고 궁금증이 들었다.

Object.is()란?

  • 두 값이 같은 값인지 비교하는 자바스크립트 메서드. (불리언 값으로 반환)
Object.is(value1, value2);

Object.is()와 === 차이점

=== (일치 연산자)

NaN === NaN; // false
+0 === -0; // true

Object.is()

Object.is(NaN,NaN); // true
Object.is(+0,-0); // false

=== 같은 경우 NaN과 부호있는 0을 비교했을 경우 값이 위와 같이 나타난다. Object.is는 보다 정확한 연산을 위해 만들어진 메서드로 두 값이 정확하게 같은 값인지를 확인한다.

리액트에서 Object.is()를 사용하는 이유는 NaN, -0, +0과 같은 특수한 숫자 비교 경우에서 더 정확하고 예상대로 비교를 수행하기 위해서!

같이 읽어보면 좋을 문서

useState에서 Object.is와 prevState 이해하기
MDN 공식문서

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.