본문 바로가기

회고/코드스테이츠 FE 부트캠프

[코드스테이츠 FE 부트캠프 40기] 메인 프로젝트 회고와 꿀팁 3탄

✨[코드스테이츠 FE 부트캠프 40기] 메인 프로젝트 회고와 꿀팁 1탄

⬆️아이디어 미믹, 기획, 디자인, api 문서 작성, 화면정의서 작성한 이야기가 궁금하다면

 

✨[코드스테이츠 FE 부트캠프 40기] 메인 프로젝트 회고와 꿀팁 2탄

⬆️기술 스택 선정과, 개발 밑작업에 대한 이야기가 궁금하다면

 


🏃🏻‍♀️공통 컴포넌트 개발 : 모달 컴포넌트

 

👍🏻 잘했던 점:
반응형과 전체 프로젝트에서 모든 경우의 활용을 생각해서 대응할 수 있도록 작성한점.
팀원들이 내가 제작한 컴포넌트를 어떻게 하면 더 잘 활용할 수 있을까 연구하고 문서로 남긴점


👎🏻 아쉬웠던 점: 
모달 컴포넌트를 프로젝트에 도입할때, 코드 구조를 단순하게 하려면 어떻게 해야할까라는 추가적인 고찰이 필요했다. 결국 외관적으론 대응을 잘했지만, 똑똑한 프로젝트 구조적으로 똑똑한 모달을 제작하진 못했던 것 같다.

 

컨테이너 컴포넌트를 제작한 후엔 모달 컴포넌트 제작에 들어갔다.

반투명 배경, 타이틀, 버튼을 넣을 수 있고,

사이즈를 max-width로 잡을 수 있도록 하여 다양한 상황에서

반응형 대응이 가능하도록 했다. 

 

이 컴포넌트도 마찬가지로 다양한 상황에 유용하게 쓸 수 있도록

위키에 약간의 설명을 남겼다.

 

최대한 직관적인 네이밍으로 어렵지 않게 사용할 수 있도록 했으나,

그래도 헷갈리는 경우에는 컴포넌트에 대한 설명을 볼 수 있도록 문서화 했고,

다행이도 팀원들이 다양한 케이스에 활용하며 나에게 기능에 대한 질문을 하는 사례는 없었다.

 

 

 


😂 아쉬움이 남는 모달 컴포넌트

 

개인적으로 모달 컴포넌트에 대한 부분이 가장 아쉬움이 많이 남는다.

 

기획했던 대로 진행한 결과물을 보자면,

 

다양한 상황에 들어가는 모달들

 

모달이 굉장히 많이 들어가는데,

일차원적으로 페이지에 한단계 덮어씌어지는 모달도 있지만,

상세 페이지처럼 모달 위에 한단계 모달이 덧씌워 지는 경우도 많았다.

 

상세 페이지도 모달 팝업인데, 그 위의 신고삭제 팝업도 모달 팝업이고,

또 팝업에서 팝업에서 팝업으로 넘어가는 경우도 많다 보니,

개발과정에서

스테이트 관리가 굉장히 복잡해졌다.

 

인스타그램을 베이스로 다른 프로젝트를 진행한 팀도 있었는데,

그 팀은 모달이 아닌 페이지로 넘어가도록 제작을 했더랬다.

 

그걸 보면서 아. 이런걸 미리 생각할 줄 아는게 내공이구나 싶었다.

 

👎🏻 
아쉬웠던 점들

1. 모달 컴포넌트의 중첩으로 상태관리가 복잡해진다.
2. 모달에서 모달로 넘어갈때 깔끔한 코드 구현이 어렵다.
3. 페이지 위에 덧대어 띄우다보니 주소값을 기본적으로 갖지 못한다.


🤔
어떻게 고치면 좋을까?

1. 애초에 모달이 아닌 컴포넌트로 제작한다.
2. 인스타그램처럼 모달이지만 주소값에 따라 작동하도록 대처한다. 찾아보니 방법이 없는 것은 아니었지만,
이미 프로젝트가 많이 진행된 후반쯤에 문제를 인식한지라 프로젝트를 전체적으로 뜯어고칠 수가 없었다.
3. 모달에 컴포넌트에 대한 부분을 전역 상태로 관리한다.

 

이부분들은 개인적으로 이번 프로젝트에서 전체적인 구조를 뒤엎어야되는 부분이라

아쉽지만 리팩토링 하기엔 나의 범위를 넘어가는 부분이었다.

 

그래서 따로 시간을 빼서라도 관련해서 시도하고 블로깅을 남길 예정이다.

 


🚀 페이지 개발 :  회원가입 페이지, 로그인 페이지, 비번 찾기

 

👍🏻
잘했던 점:
-매끄럽지 않은 인터페이스에 대해 의견을 내고 변경했던 점.
-유효성 검사에 따른 버튼 비활성화나, 유저의 요청을 성공적으로 처리한 후 피드백등,
기획 디자인에서 놓치기 쉬운 접근성 부분들을 야무지게 챙긴것
-코드가 아주 읽기 쉽게 짜인것 같아 만족스러운 점

👎🏻
아쉬웠던 점: 
-애초에 기획회의부터 이메일 중복테스트만 따로 떼어서 하는 부분을 생각하지 못했다.
그때 생각했다면 가입 요청을 하기 전에
중복체크만 하는api도 따로 파고 실시간 중복체크나,"아이디 중복 확인"버튼을 활용할 수 있었을 텐데 싶다.
(지금은 회원가입 요청 자체가 통째로 거절당한 뒤 확인이 가능하다.)

 

일단 소셜 로그인 기능을 제외한,

회원가입 페이지와 로그인 페이지 제작은  어려운 부분은 아니었기에

최대한 깔끔하게 작성하는 것을 목표로 했다.

 

일단 완성된 페이지들은 아래와 같다.

 

 

왼쪽부터 회원가입, 로그인, 비밀번호찾기

 

회원 가입 페이지에선

서비스 특성상 꼭 받아야할 정보들을

더 매끄럽게 받을 수 있도록 구성했다.

 

유저타입을 받는 부분이 기획단계에선 모달창이었지만,

같은 회원 가입 단계에서 모달창으로 필수값을 받고, 그다음 단계로 넘어가는게

아무래도 매끄럽지 않은 것 같고 

개발 측면에서도 불필요하게 지저분해 질것 같았다.

 

이런 판단으로 팀원분들께 의견을 내어서, 

두 단계로 나누어, 같은 컴포넌트내에서 해결할 수 있도록 변경하였다.

 

바뀐 UI가 훨씬 매끄럽기도하고

step으로 나누니 컴포넌트가 아주 깔끔하게 분리되어서

바꾸길 참 잘했다 싶었다.

 

✨깔끔하게 switch문으로 처리되는 step✨

더보기
  <OuterContainer>
          <InnerContainer>
            <Conts>
              <Card>
                <Header>
                  {(() => {
                    switch (step) {
                      case 1:
                        return (
                          <>
                            <Step01Symbol></Step01Symbol>
                            <StepNum>step01</StepNum>
                            <StepDesc>종을 골라주세요</StepDesc>
                          </>
                        );
                      case 2:
                        return (
                          <>
                            <PrevStepBtn>
                              <ArrowIcon onClick={() => setStep(1)}></ArrowIcon>
                            </PrevStepBtn>
                            <Step02Symbol></Step02Symbol>
                            <StepNum>step02</StepNum>
                            <StepDesc>정보를 입력해주세요</StepDesc>
                          </>
                        );
                      case 3:
                        return (
                          <>
                            <Step03Symbol></Step03Symbol>
                            <StepNum>Success</StepNum>
                            <StepDesc>가입성공</StepDesc>
                          </>
                        );
                      default:
                        return null;
                    }
                  })()}
                </Header>
                {(() => {
                  switch (step) {
                    case 1:
                      return (
                        <>
                          <StepType userInfo={userInfo} setUserInfo={setUserInfo} />
                          <Button
                            className="signup-btn"
                            onClick={() => {
                              setStep(2);
                            }}
                            width="200px"
                            height="50px"
                            btnColor="yellow"
                            btnHoverColor="orange"
                            textColor="black"
                            fontSize="pc-regular"
                            disabled={userInfo.userType === ""}
                          >
                            다음
                          </Button>
                        </>
                      );
                    case 2:
                      return (
                        <form onChange={onFormChange} onSubmit={onSubmitClick}>
                          <StepForm userInfo={userInfo} setUserInfo={setUserInfo} setHasNoError={setHasNoError} />
                          <Button
                            className="signup-btn"
                            onClick={() => {}}
                            width="200px"
                            height="50px"
                            btnColor="yellow"
                            btnHoverColor="orange"
                            textColor="black"
                            fontSize="pc-regular"
                            disabled={!(hasNoError && hasNoEmptyRequired)}
                          >
                            완료
                          </Button>
                        </form>
                      );
                    case 3:
                      return (
                        <>
                          <StepSuccess />
                          <Button
                            className="signup-btn"
                            onClick={() => {
                              navigate("/login");
                            }}
                            width="200px"
                            height="50px"
                            btnColor="yellow"
                            btnHoverColor="orange"
                            textColor="black"
                            fontSize="pc-regular"
                          >
                            확인
                          </Button>
                        </>
                      );
                    default:
                      return null;
                  }
                })()}
                {alreadyExistError ? <Notice>이미 존재하는 회원입니다. 다시 확인해 주세요!</Notice> : ""}
              </Card>
              <Footer>
                계정이 있으신가요?
                <Link to="/login">로그인</Link>
              </Footer>
            </Conts>
          </InnerContainer>
        </OuterContainer>
      </SignupPage>

 

그리고 이 페이지에서 

불필요한 중복 요청이 가는 것을 방지하고,

한눈에 조건을 충족시키지 못했음을 보여주기 위해서

유효성 체크를 충족하지 못할 경우 실시간으로 버튼의 상태를 disabled로 바꾸었고,

opacity를 주어 한눈에 요청을 보낼 수 없는 상태임을 표현했는데,

 

이 부분 UI는

지난 프리프로젝트때 스택오버플로우의 글쓰기 단계에서있던 기능을

따온 것이었다.

 

사실 디자이너가 이부분까지 생각할 수 있지만, 

그렇지 않을 경우 프론트 단계에서 의견을 내거나 임의로 처리해야하는 부분이 될 수도 있는데

이전 프로젝트 경험을 녹여 만족스런 인터페이스를 만든 것 같아 만족스러웠다.

 

끝나고 많은 프로젝트를 보니,

유효성 검사에 대한 부분이 불친절하거나

유효성 검사를 통과하지 못해 요청을 못보내는 상태인데

UI적으로 표시가 되지 않아 도무지 된건지 만건지 모르는 팀들이 있었다.

 

또한 가입이나 로그인이 완료되었으면

완료되었다고 확실한 피드백을 넣어준것도,

기획단계에서 고려하지 못했지만, 잘 추가했다고 생각한 부분 중 하나였다.

 

이런점에서 여기 이 페이지에선 아쉬운점보단 만족스러움이 많이 남는다.

 

이후 어드밴스드로 기능을 더 추가할 기회가 있다면,

이메일 중복 검사를 요청 단계가 아니라 기입 단계에서 할 수 있도록 만들수 있음 좋겠다 싶다.

 


 

다음 편에선 api요청이 구석구석 엄청나게 필요해서 

제일 고생스러웠던 상세페이지에 대해서 말해보고자 한다.

 

 

으아!! 팝업 그만!!!!!!