inflearn logo
강의

講義

知識共有

Reactマスタークラス:Part 1 - ミッションで悟るレンダリングの本質と設計

19. React Strict Mode — 開発段階で問題を早期に発見するための安全装置

Strict Mode 예시 질문!

47

dwc07109

投稿した質問数 1

0

image.png

안녕하세요, FE 개발자 준비중인 수강생입니다!

해당 강의 화면에서 Strict Mode에서 두번 실행시 값이 반복 변경되어있다고 작성되어있는데

해당 예시로는 객체 내부 값을 변경해서 2번을 실행해도 같은 값이 나올 것 같은데, Strict Mode에서 감지된다는 적절한 예시가 맞을까요?

제가 잘못 알고 있는 점이 있다면 말씀해주시면 감사하겠습니다:)

HTML/CSS javascript react 웹앱 frontend

回答 2

0

nhcodingstudio

안녕하세요 dwc07109님. 질문하신 부분은 중요한 포인트입니다.

강의 화면의 예시처럼

let formData = {};

function SignUpForm() {
  formData.name = "홍길동";

  console.log("폼 렌더링:", formData);

  return <p>{formData.name}</p>;
}

단순히 formData.name에 매번 동일한 "홍길동" 값을 할당하는 경우라면, Strict Mode에서 컴포넌트가 두 번 실행되더라도 최종 값은 계속 "홍길동"입니다. 그래서 이 코드는 “두 번 실행되면서 값이 반복적으로 변경되는 문제”를 직접 보여주는 예시로는 조금 약한 편입니다.

다만 이 예시에서 설명하려는 핵심은 React의 렌더링 과정이 순수해야 한다는 점입니다. 다시 말해, 컴포넌트가 렌더링되는 도중에 컴포넌트 외부에 있는 값이나 객체를 직접 변경하는 코드는 피하는 것이 좋습니다.

예를 들어 아래처럼 작성하면 Strict Mode가 왜 이런 코드를 드러내는지 훨씬 명확하게 확인할 수 있습니다.

const users = [];

function SignUpForm() {
  users.push("홍길동");

  console.log(users);

  return <p>회원가입</p>;
}

개발 환경에서 Strict Mode로 인해 렌더링 로직이 다시 실행되면 다음과 같이 값이 누적될 수 있습니다.

["홍길동"]
["홍길동", "홍길동"]

이 경우에는 같은 컴포넌트를 다시 실행했는데도 외부 배열의 상태가 달라졌습니다. 즉, 렌더링 과정 자체에서 사이드 이펙트가 발생하고 있는 것입니다.

여기서 한 가지 구분해두시면 좋습니다. Strict Mode가 “전역 변수를 사용했으니 잘못됐다”고 직접 감지해서 오류를 내는 것은 아닙니다. 개발 환경에서 일부 로직을 의도적으로 다시 실행해보면서, 순수하지 않은 렌더링 코드가 있다면 그 문제가 더 쉽게 드러나도록 도와주는 역할에 가깝습니다.

반대로 아래처럼 컴포넌트 내부에서 매번 새로운 객체를 생성하는 경우에는 괜찮습니다.

function SignUpForm() {
  const formData = {
    name: "홍길동",
  };

  return <p>{formData.name}</p>;
}

컴포넌트가 여러 번 실행되더라도 각 실행마다 새로운 객체가 만들어지기 때문에 외부 상태를 변경하지 않습니다.

실무에서는 “렌더링 중에는 계산만 하고, 외부 상태는 변경하지 않는다”는 기준을 잡아두시면 도움이 많이 됩니다. 서버 요청, 로컬 스토리지 저장, 전역 상태 변경, DOM 직접 조작처럼 외부에 영향을 주는 작업은 렌더링 과정에서 바로 수행하기보다 useEffect, 이벤트 핸들러, 상태 관리 로직 등 목적에 맞는 위치에서 처리하는 편이 안전합니다.

또 Strict Mode를 사용할 때 “왜 API가 두 번 호출되지?”, “왜 배열에 값이 두 번 들어가지?” 같은 상황을 만나면 Strict Mode 자체를 원인으로 보기보다, 먼저 기존 코드 안에 렌더링 중 발생하는 사이드 이펙트가 있는지 확인해보시는 게 좋습니다.

정리하면, 질문하신 것처럼 현재 "홍길동" 할당 예시는 Strict Mode의 문제를 보여주기에는 다소 약하고, push, ++, 누적 변경처럼 두 번째 실행에서 실제 결과가 달라지는 코드를 사용하는 편이 더 적절합니다.

좋은 질문 남겨주셔서 감사합니다.

0

communityai8509

안녕하세요, 인프런 AI 인턴입니다.

dwc07109님, 질문하신 내용이 맞습니다.

제시된 예시에서는 다음 코드가 렌더링될 때마다 실행됩니다.

let formData = {};

function SignUpForm() {
  formData.name = "홍길동";
  console.log("폼 렌더링:", formData);

  return <p>{formData.name}</p>;
}

하지만 formData.name에 매번 동일한 값인 "홍길동"을 할당하므로, Strict Mode에서 컴포넌트 함수가 두 번 실행되어도 결과적으로 값 자체는 동일합니다.

즉, 이 예시만으로는 “Strict Mode에서 값이 반복해서 변경된다”는 설명이 충분히 드러나지 않습니다.

반복 실행의 문제를 보여주려면 다음처럼 값이 누적되거나 변경되는 예시가 더 적절합니다.

let formData = {
  names: [],
};

function SignUpForm() {
  formData.names.push("홍길동");

  console.log("폼 렌더링:", formData);

  return <p>{formData.names.join(", ")}</p>;
}

Strict Mode에서 개발 환경 기준으로 렌더링이 반복되면 다음과 같이 배열에 값이 중복해서 추가될 수 있습니다.

["홍길동", "홍길동"]

또는 다음과 같은 예시도 반복 실행의 문제를 잘 보여줍니다.

let renderCount = 0;

function SignUpForm() {
  renderCount += 1;

  console.log(renderCount);

  return <p>회원가입 폼</p>;
}

이 경우 컴포넌트가 렌더링될 때마다 전역 변수인 renderCount가 변경되므로, Strict Mode의 의도적인 추가 실행으로 인해 값이 예상보다 증가할 수 있습니다.

다만 Strict Mode가 전역 변수 변경을 직접 감지해서 오류를 발생시키는 것은 아닙니다.

Strict Mode는 개발 환경에서 컴포넌트의 렌더링 함수를 추가로 실행하여, 렌더링 중 발생하는 부수 효과를 개발자가 발견하기 쉽게 만들어 줍니다.

따라서 핵심 문제는 Strict Mode 자체가 아니라, 컴포넌트 렌더링 과정에서 전역 객체를 직접 변경하는 코드입니다.

이 코드는 Strict Mode가 없어도 다음과 같은 문제를 가질 수 있습니다.

  • 여러 SignUpForm 인스턴스가 같은 formData를 공유합니다.
  • 컴포넌트가 다시 렌더링될 때 전역 상태가 의도치 않게 변경될 수 있습니다.
  • 다른 컴포넌트의 렌더링 결과에 영향을 줄 수 있습니다.
  • 서버 환경에서는 사용자 간 데이터가 섞이는 문제가 발생할 수도 있습니다.

폼 입력값처럼 컴포넌트가 관리해야 하는 데이터는 전역 변수 대신 useState를 사용하는 것이 일반적입니다.

function SignUpForm() {
  const [formData, setFormData] = useState({
    name: "",
  });

  return (
    <input
      value={formData.name}
      onChange={(event) =>
        setFormData({
          ...formData,
          name: event.target.value,
        })
      }
    />
  );
}

정리하면, "홍길동"을 두 번 대입하는 원래 예시는 값이 누적되거나 달라지지 않기 때문에 Strict Mode의 문제를 설명하는 예시로는 다소 약합니다.

다만 렌더링 중 전역 변수를 직접 변경하는 방식 자체가 잘못된 패턴이며, 배열에 push하거나 카운터를 증가시키는 예시라면 Strict Mode의 반복 실행으로 인한 문제를 더 명확하게 확인할 수 있습니다.

참고 이미지:
https://cdn.inflearn.com/public/files/posts/10ec66e5-43ee-40a5-998e-f97ee6566349/c1f41a8a-a921-41f0-9ada-b738fe09a351.png

음성불량

0

11

1

1강 동영상 재생 오류

1

14

2

generateStaticParams() 응용 질문 드립니다.

0

13

1

Mac intel 에서 Homebrew 설치

0

19

0

🔥 [필수] 강의교안 & 소스코드 🔥 링크오류

0

21

2

Context7 버전 관련

0

16

1

깃 초기화?

0

18

1

13강 [로그인 단일 토큰] 에서 프로젝트 실행 시 에러

0

15

1

스테이징 파일들 커밋 시 오류 메시지

0

22

3

헤더에서 empty column이 삭제가 안되고, 헤더 레이아웃을 동영상처럼 선택하는 옵션이 안나오는데 어떻게 하나요?

0

14

1

Composition단계에서 `Layer`는 누가 만드는지

0

23

1

서브에이전트

0

31

2

서브에이전트의 유효성 질문

0

38

2

쉬림프 태스트 매니저 관련 질문

0

35

2

c:가 아니라 D:로 이동 할려면 어떻게 해야되나요?

0

40

2

ultrathink 관련 질문

0

47

2

수업이 안보여요

0

53

1

강의교안이 어디에 있는지 알 수 있을까요

0

59

2

node 실행 오류

0

49

2

저자 블로그에 있는 강의는 어떤 강의인가요?

1

51

1

해당 플러그인을 설치했는데 추가 지원 안될 수 있다고 다른 플러그인을 깔아보라는데 어떻게 해야하나여?

0

49

2

순수 함수 / 순수 컴포넌트

0

53

1

ReactScriptExample 관련 질문

0

55

1

state 객체로 묶기

0

81

1