인생 첫 협업 프로젝트 회고

SurveyMate 프로젝트 회고 내용

2024로 넘어가는 겨울방학 동안 인생 첫 프로젝트를 진행했다. 한 학기 동안 배운 프론트 지식을 확실히 함도 있었고, PM과 디자이너까지 포함하는 프로젝트의 기회는 정말 귀하다고 생각되어 즐겁게 참여할 수 있었다.

 

UMC 5기 웹으로 참여하면서 기본적인 웹사이트를 만드는 데 필요한 언어들을 배웠기에 지식을 잘 써보자는 마음가짐으로 참여했다. 실제로 두 번의 지원 중 두 번째로 참여했던 프로젝트에 바로 참여할 수 있었다. 프로젝트에 참여하면서 중요하게 여긴 포인트는 세 가지이다. 웹앱 구현. 반응형. API. 결론적으로는 잘 배웠고 해낸 것 같다. 정말 감사하게도 프론트는 모두 첫 프로젝트였던 것에 반해 백 분들이 다들 경험이 있어 잘 이끌어주셨다. Swagger도 제대로 사용 못 해 당황한 프론트들을 많이 이끌어주셨다. 첫 프로젝트여서 그런가 많이 배웠다. 협업하는 법도, 연결하는 법도, 코드 짜는 법도. Git 쓰는 법도 제대로 배운 것 같다.

 

이 프로젝트는 PM 1명, 디자이너 1명, 프론트 4명과 백 3명으로 진행되었다.

 


 

 

1 .이메일 템플릿 제작

 

이번 프로젝트를 하면서 가장 노력한 점은 일단 시도해 보자는 마음가짐이었다. 혹여나 할 일이 하나 떨어지면 일단 해 보자는 마음으로 제가 할게요를 외쳤다. 이메일 템플릿이 그 첫 번째 도전이었다.

 

이 프로젝트의 회원가입은 학생 사용자와 일반 사용자를 구분하기 위해 학교용 계정을 구분하는 기능이 필요했다. 그러기 위해 단순 정규식 구분이 아닌 보안까지 신경 쓰기 위한 이메일을 통행 인증번호를 받는 형식으로 사용했다. 이메일로 딸랑 인증번호 6자를 보낼 수는 없으니 최소한의 형식을 갖춘 이메일 템플릿을 만들기로 했다. 평소에도 뉴스레터에 관심이 많은 터라 도움이 될 것 같아 내가 만든다고 해 봤다.

 

근데 놀랍게도 생각보다 정보가 없었다... 결론적으로는 html만을 사용해서 템플릿을 제작하고 백앤드에 넘겨야 했다. 

 

 

html 만을 사용해서 코드를 작성하는 것은 꽤 어려웠기 때문에 mjml 코드를 사용했다. mjml은 mjml 코드를 작성해 템플릿을 완성하면 자동으로 html 코드로 치환해 준다. 코드를 작성하기 위한 코드를 배워야 하는 것이므로 상당히 어이없고 귀찮아 보이지만... mjml은 다행히 사용법을 30분 이내로 마스터할 정도로 굉장히 쉬웠다. 아래의 라이브 코드에서 mjml로 원하는 템플릿을 만들고 html 코드로 변환해 그대로 가져다가 사용하면 된다. 

 

 

 

 

 

 

2. 처음으로 만든 반응형 페이지

 

반응형을 의식하고 페이지를 만든다는 것이 생각보다 힘든 일이었다. 그래도 애매하개 알고 있던 미디어 쿼리, 뷰포트 사용법에 대해 알아갈 수 있었다.

 

1) 상단바 기본 컴포넌트를 만들면서 애매했던 부분이 있었다. 공통 마진을 적용하기 위해 전역 스타일을 지정해 놨는데 상단바만큼은 기본 마진에서 제외되야 했기 때문이다. 이 부분을 해결하면서 보기만 했었던 calc 개념을 적극적으로 사용할 수 있었다. 

margin-left: calc(-50vw + 50%);

 

2) input type = file 의 어려움. 프로필 사진의 오른쪽 아래에 있는 보라색 버튼을 클릭하면 갤러리에서 사진을 선택할 수 있다. 문제는 input 태그의 타입을 지정하는 것만으로도 갤러리에 접근하는 것은 가능하지만 기본 라벨을 꾸미기 위해서는 input의 기본 css를 없앨 수 없기 때문에 아예 display: none으로 바꾼 후 label 태그를 추가해 input의 label을 따로 지정해야 한다. 

html에서는 for을 쓰면 된다고 한 것 같은데 리액트에서는 htmlFor을 써야한다고 해서... 뭔가 복잡했다.

+ accept 속성으로 파일 형식 지정이 UX에 더 좋다고 한다.

 

3) 처음에 개념을 빠르게 건너뛰면서 공부를해서 flexbox나 position에 대한 개념이 추상적이었는데 이번에 제대로 공부했다. 기본 프로필 사진과 변경버튼의 위치를 고정한 상태로 반응형이 되게 위치하는 게 헷갈렸는데 wrapper 안에 두 컴포넌트를 position으로 고정한 이후에 위치를 조정함으로 해결했다.

 

 

3. 회원가입 

지금 보면 웃긴데 API 연결을 스스로 처음 해 봐서 신나서 캡처했다.. 여기서 공부한 건 1) Axios 문법 2) Axios에 담거나 받는 파일의 형식들 분류와 방법 3) 두 페이지에 걸친 API 연결 시 인자를 넘기는 방법 등 ; <navigate / >, <link /> 태그에 보내고 싶은 state을 담아서 보낼 수 있다는 게 신기했다.

 

 

4. 바텀시트 만들기

 

 

나름대로 어려웠던 하나만 클릭되는 버튼 만들기... 여기서 중요한 하나를 클릭할 시 이미 클릭돼있던 컴포넌트는 클릭이 해제되야 한다는 것. 

한참을 해매다가 selected 옵션을 통해 클릭한 것을 바로바로 selected로 지정하는 코드를 썼다. daybutton을 하나로 묶기 위해 아래처럼 코드를 묶어서 작성하고 변수에 의해 버튼이 생겨나게 했다! 

 {[1, 2, 3, 4, 5, 6, 7].map((day) => (
          <DayButton
            key={day}
            onClick={() => handleDayButtonClick(day)}
            selected={day === selectedDay}
          >
            <DayButtonText>{day}일</DayButtonText>
          </DayButton>
        ))}

 

 

 

 

바텀시트는 뒷면의 흑백처리되는 부분, 아래의 바텀시트, 그 안의 인자 모두 따로 컴포넌트로 만들었다. 

//설문등록 확인 바텀시트
function PointBottom({ point }) {
  return (
    <>
      <BackgroundBottomSheet>
        <BottomSheetWrapper>
          <BottomSheetInfo>
            <InputLabel>설문등록 확인</InputLabel>
            <ProcessExplain>
              {point}포인트를 사용하여 <br />
              설문을 등록하시겠습니까?
            </ProcessExplain>
            <img
              src={Warning}
              alt='warning'
            />
          </BottomSheetInfo>
          <BottomButtonWrapper>
            <CancelButton>
              <C.ButtonText>취소</C.ButtonText>
            </CancelButton>
            <ConfirmButton>
              <C.ButtonText>등록</C.ButtonText>
            </ConfirmButton>
          </BottomButtonWrapper>
        </BottomSheetWrapper>
      </BackgroundBottomSheet>
    </>
  );
}

//바텀시트 스타일 컴포넌트

const BackgroundBottomSheet = styled.div`
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background-color: rgba(0, 0, 0, 0.3);
  display: flex;
  align-items: flex-end;
  z-index: 1;
`;

const BottomSheetWrapper = styled.div`
  background-color: #ffffff;
  width: 100vw;
  margin-left: calc(-50vw + 50%);
  border: none;
  border-radius: 20px 20px 0px 0px;
  align-items: center;
`;

const BottomSheetInfo = styled.div`
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding: 5%;
  text-align: center;
`;

const BottomButtonWrapper = styled.div`
  display: flex;
  flex-wrap: wrap;
  justify-content: space-evenly;
  padding-bottom: 3vh;
`;

const CancelButton = styled.button`
  border-radius: 10px;
  border: 2px solid #cfc8ff;
  background: var(--white, #fff);
  box-shadow: 0px 2px 11px 0px rgba(0, 0, 0, 0.2);
  color: rgba(207, 200, 255, 1);
  width: 45vw;
  height: 5vh;
  justify-content: center;
  align-items: center;
  position: flex;
  cursor: pointer;
`;

const ConfirmButton = styled.button`
  border-radius: 10px;
  background: #6046ff;
  color: var(--white, #fff);
  width: 45vw;
  height: 5vh;
  justify-content: center;
  align-items: center;
  border: none;
  box-shadow: 0px 2px 11px 0px rgba(0, 0, 0, 0.2);
  cursor: pointer;
`;

 

 

자잘한 기능들을 해 보면서 상태 관리에 집중하면서 리액트를 더 배우고 싶다고 느꼈다. 작업사항은 더 있지만 첫 프로젝트에서 느낀 감상들을 늘어놓고 싶어서 회고를 적게 되었다. 인생 첫 프로젝트라 정말 느리게 조금씩 나아갔지만 많은 도움을 받고 많은 배움을 얻은 것 같다. 프로젝트와 함께 한 학기 내내 스터디를 진행한 UMC도 끝이 났다. 앞으로 첫 프로젝트를 양분 삼아 더 나아갈 수 있으면 좋겠다 

 

회고 끝 !