패스트캠퍼스 데브캠프

파이널 프로젝트 - 회원가입(1) 약관 동의

vitamin3000 2025. 4. 3. 21:59

 

이번 포스트에서는 구현한 회원가입에 내용에 대해 기술하고자 한다

 

1. 회원가입 페이지는 약관 동의 컴포넌트, 전화번호 인증 컴포넌트,  회원정보 입력 컴포넌트로 구분한다.

이때, 현재 진행하고있는 페이지에 대한 구분을 위해 아래 사진과 같이 구현하였다.

 

 

코드는 다음과 같이 작성하여 현재 컴포넌트 단계에 대한 값을 저장하고,

const [currentStep, setCurrentStep] = useState(0);

 

아래와 같이 그에따라 step에 알맞는 컴포넌트를 출력하게 하였다. 

const renderComponent = () => {
    if (currentStep === 0) {
      return (
        <AgreeComponent
        // ... 
        } else if (currentStep === 1) {
      return (
        <PhoneComponent
        // ...
   
    } else if (currentStep === 2) {
      return (
        <InfoComponent
        //...
 }

 

 

추가적으로 이전 또는 다음 버튼을 누르면 항목별로 이동해야 한다.

 

다음(Next) 버튼은 다음과 같이 정의하였다.

  const goToNext = async () => {
    if (currentStep === 0 && requiredAgreementsChecked) {
      setCurrentStep(1);
      setIsPhoned(true);
    } else if (currentStep === 1 && isCheckPhone) {
      setCurrentStep(2);
      setIsLocked(true);
    } else if (currentStep === 2 && isCheckInfo) {
      // ...
    }
  };

 

원본 코드에는 api 호출 관련 코드도 존재하지만, 우선 컴포넌트 step 이동에 대해서만 살펴보자.

 

currentStep이 0인 즉, 약관 동의 컴포넌트가 출력되고 있을 때, requeiredArgreemtnsChecked가 true가 되어야 이동할 수 있게 되어있다.

requeiredArgreemtnsChecked는 다음과 같이 정의되어 있다.

 

const [requiredAgreementsChecked, setRequiredAgreementsChecked] = useState(false);

 

requriedAgreementsChecked는 부모 컴포넌트에서 자식 컴포넌트인 AgreeComponent로 "내려"주고 있다.

  const handleRequiredAgreementChange = (isValid: boolean) => {
    setRequiredAgreementsChecked(isValid);
  };
  
const renderComponent = () => {
if (currentStep === 0) {
  return (
    <AgreeComponent
      setIsChecked={setIsChecked}
      onRequiredAgreementChange={handleRequiredAgreementChange}
      savedAgreements={agreements}
      onAgreementsChange={handleAgreementsChange}
    />
  );

 

자식 컴포넌트인 AgreeComponent에서는 다음과 같이 state를 정의하고 있다.

이것들은 약관 동의 페이지에서 각 항목별에 대한 것이다.

  const [agreements, setAgreements] = useState(
    savedAgreements || {
      privacy: false,
      terms: false,
      marketing: false,
      youtube: false,
    }
  );

 

우리가 다음 컴포넌트인 전화번호 인증 컴포넌트로 넘어갈 수 있을 때는, 

약관 동의 중 필수 항목인

1. 개인정보처리 동의

2. 이용약관 동의

두 항목이 check되었을 때이다.

따라서. useEffect를 사용하여 

  useEffect(() => {
    function checkRequiredAgreements() {
      return agreements.privacy && agreements.terms;
    }

    onRequiredAgreementChange(checkRequiredAgreements());
  }, [agreements, onRequiredAgreementChange]);

 

두 항목이 true가 될 때 props로 내려받는 onRequiredAgreementChange를 통해 부모 컴포넌트의 

requiredAgreementsChecked 값을 true로 변경해 다음 컴포넌트로 이동할 수 있도록 하였다.

 

이를 구현한 코드는 아래와 같다.

      return (
        <S.NextButtonContainer
          $inGroup={false}
          onClick={goToNext}
          disabled={!requiredAgreementsChecked}
          $isActive={requiredAgreementsChecked}
        >
          <p>다음</p>
        </S.NextButtonContainer>
      );

 

styledComponents를 사용하고 있어서, $로 styled-props임을 나타내어 실제 DOM으로 랜더링되지 않게 하였다.

여기서 $를 사용하지 않으면, 실제 DOM에 랜더링되므로 관련 오류가 출력되므로 주의하자