v19.2Latest

컴포넌트의 순수성 유지하기

일부 JavaScript 함수는순수합니다.순수 함수는 오직 계산만 수행하며 그 외에는 아무것도 하지 않습니다. 컴포넌트를 엄격하게 순수 함수로만 작성하면 코드베이스가 커질수록 당황스러운 버그와 예측 불가능한 동작의 전체 범주를 피할 수 있습니다. 그러나 이러한 이점을 얻으려면 따라야 할 몇 가지 규칙이 있습니다.

배울 내용
  • 순수성이 무엇이며 버그를 피하는 데 어떻게 도움이 되는지
  • 렌더링 단계에서 변경 사항을 배제하여 컴포넌트를 순수하게 유지하는 방법
  • Strict Mode를 사용하여 컴포넌트의 실수를 찾는 방법

순수성: 컴포넌트를 공식처럼 생각하기

컴퓨터 과학(특히 함수형 프로그래밍 세계)에서순수 함수는 다음과 같은 특성을 가진 함수입니다:

  • 자기 일만 합니다.호출되기 전에 존재했던 객체나 변수를 변경하지 않습니다.
  • 동일한 입력, 동일한 출력.동일한 입력이 주어지면 순수 함수는 항상 동일한 결과를 반환해야 합니다.

순수 함수의 한 가지 예를 이미 알고 있을 수 있습니다: 수학의 공식입니다.

이 수학 공식을 생각해 보세요:y= 2x.

만약x= 2라면y= 4입니다. 항상 그렇습니다.

만약x= 3라면y= 6입니다. 항상 그렇습니다.

만약x= 3이라면,y가 때로는 9–1, 또는2.5가 되지는 않습니다. 시간이나 주식 시장 상태에 따라 달라지지 않습니다.

만약y= 2x이고x= 3이라면,y항상 6이 될 것입니다.

이것을 JavaScript 함수로 만들면 다음과 같을 것입니다:

위 예제에서 double순수 함수입니다. 여기에 3을 전달하면6을 반환합니다. 항상 그렇습니다.

React는 이 개념을 기반으로 설계되었습니다.React는 여러분이 작성하는 모든 컴포넌트가 순수 함수라고 가정합니다.이는 여러분이 작성한 React 컴포넌트가 동일한 입력이 주어지면 항상 동일한 JSX를 반환해야 한다는 것을 의미합니다:

여러분이 drinkers={2}Recipe에 전달하면, 이 컴포넌트는2 cups of water항상 그렇습니다

만약 drinkers={4}를 전달하면, 이 컴포넌트는4 cups of water항상 그렇습니다

수학 공식과 마찬가지입니다.

컴포넌트를 레시피로 생각할 수 있습니다: 레시피를 따르고 조리 과정 중에 새로운 재료를 도입하지 않으면 매번 같은 요리를 얻을 수 있습니다. 그 "요리"는 컴포넌트가 React에 제공하여렌더링할 JSX입니다.

x명용 차 레시피: 물 x컵을 넣고, 차 x스푼과 향신료 0.5x스푼을 추가한 다음, 우유 0.5x컵을 넣어 끓입니다

일러스트:Rachel Lee Nabors

부수 효과: (의도하지 않은) 결과

React의 렌더링 과정은 항상 순수해야 합니다. 컴포넌트는 오직 자신의 JSX를반환해야 하며, 렌더링 전에 존재했던 객체나 변수를변경해서는 안 됩니다. 그렇게 하면 컴포넌트가 순수하지 않게 됩니다!

이 규칙을 어기는 컴포넌트 예시는 다음과 같습니다:

이 컴포넌트는 외부에 선언된guest변수를 읽고 쓰고 있습니다. 이는이 컴포넌트를 여러 번 호출하면 다른 JSX가 생성된다는 것을 의미합니다! 더욱이, 다른 컴포넌트가 guest를 읽으면, 렌더링된 시점에 따라 그들도 다른 JSX를 생성할 것입니다! 이는 예측할 수 없습니다.

공식 y= 2x로 돌아가보면, 이제x= 2라도 y= 4라고 믿을 수 없습니다. 우리의 테스트는 실패할 수 있고, 사용자는 당황할 것이며, 비행기는 하늘에서 떨어질 것입니다—이것이 어떻게 혼란스러운 버그로 이어지는지 알 수 있습니다!

이 컴포넌트는 guest를 prop으로 전달함으로써수정할 수 있습니다:

이제 컴포넌트는 순수합니다. 반환하는 JSX가 오직guestprop에만 의존하기 때문입니다.

일반적으로, 컴포넌트가 특정 순서로 렌더링될 것이라고 기대해서는 안 됩니다.y= 2xy= 5x전에 호출하든 후에 호출하든 상관없습니다: 두 공식은 서로 독립적으로 계산됩니다. 마찬가지로, 각 컴포넌트는 오직 "자기 자신만 생각"해야 하며, 렌더링 중에 다른 컴포넌트와 조율하거나 의존하려고 해서는 안 됩니다. 렌더링은 학교 시험과 같습니다: 각 컴포넌트는 스스로 JSX를 계산해야 합니다!

Deep Dive
StrictMode로 비순수 계산 감지하기

지역 변이: 컴포넌트의 작은 비밀

위 예제에서 문제는 컴포넌트가 렌더링 중에기존변수를 변경했다는 것입니다. 이것은 종종 조금 더 무섭게 들리도록"변이(mutation)"라고 불립니다. 순수 함수는 함수의 범위 밖에 있는 변수나 호출 전에 생성된 객체를 변이하지 않습니다—그렇게 하면 비순수해집니다!

그러나,렌더링 중에 방금생성한 변수와 객체를 변경하는 것은 완전히 괜찮습니다. 이 예제에서는 []배열을 생성하고, 이를cups변수에 할당한 다음, 그 안에push로 열두 개의 컵을 넣습니다:

만약 cups 변수나 [] 배열이 TeaGathering함수 외부에서 생성되었다면, 이것은 큰 문제가 될 것입니다! 배열에 항목을 푸시함으로써기존객체를 변경하게 될 것입니다.

그러나, 그것들을 같은 렌더링 중에, TeaGathering내부에서 생성했기 때문에 괜찮습니다.TeaGathering외부의 어떤 코드도 이것이 일어났다는 것을 알지 못할 것입니다. 이것을"지역 변이(local mutation)"라고 합니다—컴포넌트의 작은 비밀과 같습니다.

부수 효과를 일으킬 수있는

함수형 프로그래밍은 순수성에 크게 의존하지만, 어느 시점, 어딘가에서무언가가 변해야 합니다. 그것이 프로그래밍의 요점이죠! 이러한 변화—화면 업데이트, 애니메이션 시작, 데이터 변경—를부수 효과(side effects)라고 합니다. 그것들은 렌더링 중이 아닌,"부수적으로"일어나는 일들입니다.

React에서,부수 효과는 일반적으로이벤트 핸들러내부에 속합니다. 이벤트 핸들러는 예를 들어 버튼을 클릭할 때와 같은 작업을 수행할 때 React가 실행하는 함수입니다. 이벤트 핸들러가 컴포넌트내부에정의되어 있더라도, 그것들은 렌더링중에실행되지 않습니다!따라서 이벤트 핸들러는 순수할 필요가 없습니다.

다른 모든 옵션을 다 써버리고 부수 효과에 맞는 적절한 이벤트 핸들러를 찾을 수 없다면, 컴포넌트의 반환된 JSX에useEffect호출을 통해 부수 효과를 첨부할 수 있습니다. 이는 React에게 나중에, 렌더링 후, 부수 효과가 허용될 때 실행하라고 지시합니다.그러나, 이 접근법은 최후의 수단이어야 합니다.

가능하다면, 렌더링만으로 논리를 표현하려고 노력하세요. 이것이 얼마나 멀리 갈 수 있는지 놀라실 것입니다!

Deep Dive
React가 순수성에 신경 쓰는 이유는 무엇인가요?

요약

  • 컴포넌트는 순수해야 합니다. 즉:
    • 자기 일에만 신경 씁니다.렌더링 전에 존재했던 객체나 변수를 변경해서는 안 됩니다.
    • 동일한 입력, 동일한 출력.동일한 입력이 주어지면 컴포넌트는 항상 동일한 JSX를 반환해야 합니다.
  • 렌더링은 언제든지 발생할 수 있으므로, 컴포넌트는 서로의 렌더링 순서에 의존해서는 안 됩니다.
  • 컴포넌트가 렌더링에 사용하는 입력(프롭스, 상태, 컨텍스트 포함)을 변이(mutate)해서는 안 됩니다. 화면을 업데이트하려면 기존 객체를 변이하는 대신 상태를"설정"하세요.
  • 컴포넌트의 로직을 반환하는 JSX 안에 표현하도록 노력하세요. 무언가를 "변경"해야 할 때는 일반적으로 이벤트 핸들러에서 수행하고 싶을 것입니다. 최후의 수단으로useEffect를 사용할 수 있습니다.
  • 순수 함수를 작성하는 데는 약간의 연습이 필요하지만, 이는 React 패러다임의 힘을 발휘하게 합니다.

도전 과제를 시도해 보세요

Challenge 1 of 3:고장난 시계 수정하기 #

이 컴포넌트는 자정부터 아침 6시까지의 시간 동안 <h1>의 CSS 클래스를 "night"로 설정하고, 다른 시간에는 "day"로 설정하려고 합니다. 하지만 작동하지 않습니다. 이 컴포넌트를 수정할 수 있나요?

컴퓨터의 시간대를 일시적으로 변경하여 솔루션이 작동하는지 확인할 수 있습니다. 현재 시간이 자정부터 아침 6시 사이일 때 시계의 색상이 반전되어야 합니다!