NextJS_Capstone-기록일지(2)

김형준·2025년 3월 29일

Capstone

목록 보기
2/2

1. Input 컴포넌트화 하기

다음과 같이 Input.tsx 컴포넌트를 만들면 됩니다. TypeScript로 props를 정의하여 재사용할 수 있도록 했어요.
그리고 외부 페이지에서 어떻게 사용할 수 있는지도 함께 예제를 보여줄게요.


Input.tsx (컴포넌트)

import React from "react";

interface InputProps {
  type: string;
  placeholder?: string;
  value: string;
  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
  className?: string;
}

const Input: React.FC<InputProps> = ({ type, placeholder, value, onChange, className }) => {
  return (
    <input
      type={type}
      placeholder={placeholder}
      value={value}
      onChange={onChange}
      className={`text-[#A3A7AF] bg-[#F1F3F6] w-full p-2 border rounded mb-2 px-5 focus:outline-none ${className}`}
    />
  );
};

export default Input;

App.tsx (사용 예시)

import React, { useState } from "react";
import Input from "./components/Input"; // 경로에 맞게 import

const App: React.FC = () => {
  const [userId, setUserId] = useState("");

  return (
    <div className="p-5">
      <Input
        type="text"
        placeholder="아이디"
        value={userId}
        onChange={(e) => setUserId(e.target.value)}
        className="border-none"
      />
      <p className="mt-2">입력한 아이디: {userId}</p>
    </div>
  );
};

export default App;

✅ 설명

  • Input.tsx에서 props를 받아서 재사용 가능한 컴포넌트를 만들었어요.
  • classNameprops로 받아서 필요한 경우 추가 스타일을 적용할 수 있도록 했어요.
  • App.tsx에서 useState로 상태를 관리하며, Input 컴포넌트를 사용해서 userId 값을 업데이트하도록 구현했어요.

2. 맨 처음 셋팅할 떄, 정중앙 정렬 배치하기

margin: auto를 사용하여 요소를 가운데 정렬하려면 몇 가지 조건이 필요합니다.

1. 블록 요소 가로 가운데 정렬

margin: auto는 블록 요소의 좌우 마진을 자동으로 설정하여 가운데 정렬합니다.

.container {
  width: 300px; /* 너비 지정 필수 */
  margin: auto;
}

필수 조건: width를 지정해야 함.

2. Flexbox를 활용한 세로/가로 가운데 정렬

display: flex를 사용하면 가로뿐만 아니라 세로 정렬도 가능함.

.parent {
  display: flex;
  justify-content: center; /* 가로 중앙 정렬 */
  align-items: center; /* 세로 중앙 정렬 */
  height: 100vh; /* 부모 요소 높이 지정 */
}

3. 인라인 요소 가운데 정렬 (text-align: center)

margin: auto는 블록 요소에서만 동작하므로, 인라인 요소는 text-align: center; 사용.

.parent {
  text-align: center;
}
.child {
  display: inline-block; /* 블록 성질 추가 */
}

3. ChangePwModal 문제

useEffect 추가로 문제 해결된 이유

이 문제의 핵심은 React의 상태 업데이트가 즉시 반영되지 않기 때문입니다.
React의 상태 업데이트(setState)는 비동기적으로 처리되므로, setPwInputOpen(false);가 호출된 직후에 pwInputOpen 값이 즉시 false로 변경되지 않습니다.


1. 원래 코드에서 발생한 문제

const handleCancel = () => {
  console.log("취소 버튼 클릭됨"); 
  setPwInputOpen(false); 
};
  • setPwInputOpen(false); 호출 → React가 리렌더링을 예약함
  • 하지만, 현재 실행 중인 함수(handleCancel) 내에서는 pwInputOpen 값이 변경되기 전의 상태를 사용
  • 즉, setPwInputOpen(false); 호출 직후에도 pwInputOpen 값은 아직 true
  • 따라서, ChangePwBox가 사라지지 않음

2. useEffect가 해결한 방식

useEffect(() => {
  console.log("pwInputOpen 상태 변경됨:", pwInputOpen);
}, [pwInputOpen]);
  • useEffectpwInputOpen 값이 변경될 때마다 실행됨
  • setPwInputOpen(false);가 호출된 후, React가 리렌더링을 진행하면서 이제야 pwInputOpen 값이 실제로 false로 반영됨
  • useEffect가 실행되면서 "pwInputOpen 상태 변경됨: false" 로그가 출력됨 → 리렌더링 확인 가능
  • 리렌더링이 완료되었으므로, ChangePwBox가 사라지고 "변경" 버튼이 다시 나타남

3. React의 상태 업데이트 흐름 정리

  1. setPwInputOpen(false); 실행 → 상태 업데이트 예약 (즉시 반영 아님)
  2. React가 컴포넌트를 다시 렌더링하면서 pwInputOpen 값을 false로 반영
  3. useEffect 실행 (pwInputOpen 값이 변경되었기 때문)
  4. 컴포넌트가 리렌더링됨 → 조건부 렌더링이 적용되어 ChangePwBox가 사라지고 "변경" 버튼이 보임

4. useEffect 없이 해결하는 방법

useEffect 없이도 올바르게 동작하게 하려면 리렌더링을 확실히 유도하는 방식으로 상태 업데이트를 관리해야 합니다.

방법 1: 상태 변경 후, 즉시 return

const handleCancel = () => {
  setPwInputOpen(false); 
};
  • 이 코드가 원래 의도한 대로 동작하려면 React의 리렌더링이 보장되어야 함
  • 하지만, React의 상태 업데이트는 비동기적으로 진행되므로, 때때로 예상보다 리렌더링이 늦어질 수 있음

방법 2: 상태 변경 후 setTimeout으로 강제 리렌더링 확인

const handleCancel = () => {
  setPwInputOpen(false); 
  setTimeout(() => {
    console.log("상태 변경 후 pwInputOpen 값:", pwInputOpen);
  }, 0);
};
  • setTimeout을 사용하면 React가 현재 이벤트 루프가 끝난 후 상태 업데이트를 반영하도록 유도할 수 있음
  • 다만, 이 방법은 일반적으로 추천되지 않음 (리액트의 최적화 방식과 충돌할 수 있음)

결론

🎯 useEffect가 해결책이 되었는가?

  • useEffect리렌더링 이후 상태가 변경되었을 때 실행되는 코드이므로, pwInputOpen 상태 변경이 반영된 이후 로직이 실행되었음
  • 즉, React의 비동기적인 상태 업데이트 타이밍을 보장하는 역할을 하였음

🔥 Best Practice

useEffect를 추가하는 것이 아니라, React 상태 관리 특성을 이해하고 로직을 설계하는 것이 중요
✅ React의 상태 변경이 비동기적으로 처리된다는 점을 기억하고, 조건부 렌더링을 제대로 구성하면 useEffect 없이도 해결 가능

profile
로으앞 근차근차

0개의 댓글