팬들(fanddle) 인턴쉽 회고록

Jay Yu·2022년 8월 31일
0

8월초부터 8월말까지 진행된 인턴쉽에 대한 회고록입니다.
인턴쉽을 진행했던 회사는 패니지먼트(fanagement)이고, 운영하는 서비스 어플리케이션의 이름은 팬들(fanddle)입니다.

react로 구현하여 배포한 서비스 소개페이지 화면

팬들 어플리케이션(이하 팬들)은 셀럽들에게 선물을 보내고 소통하고 싶어하는 fan들을 위해 중간에서 매개체 역할을 해주는 일종의 플랫폼이라고 할 수 있습니다.
셀럽에서 선물을 보내고 싶어하는 팬은 팬들에서 선물을 구매하고, 팬들은 그 선물을 셀럽에게 전달합니다. 그리고 선물을 받은 셀럽은 팬들을 통해서 선물을 보내준 팬에게 감사인사와 메시지를 전달할 수 있습니다.

What I did as a 👶🏻

첫날에는 개발자분들과 미팅을 가졌습니다. 제가 가지고 있는 기술 스택과 이해도를 확인하고, 어떤 업무를 맡게 될지 조정하는 시간이었습니다. 편안한 분위기에서 진행되었고, 저 또한 적극적으로 의견을 내어 사용하게 될 기술스택을 1차적으로 정립하는 시간을 가졌습니다.
미팅 결과 현재 react-native(이하 rn) 으로만 구현된 서비스를 web 으로도 소비자들에게 제공하기 위해 web application을 구축하는 프로젝트에 front-end를 혼자 맡아 진행하게 되었습니다.
사용한 기술스택은 다음과 같습니다.

  • React
  • typescript
  • react-query(서버 상태 관리)
  • recoil( 클라이언트 상태 관리 )
  • react-hook-form( form, input 로직 간소화 )
  • styled-components

부트캠프에 참여하기 직전 독학으로 react를 다루면서 여러가지 라이브러리를 접해볼 수 있었는데, 그 경험을 바탕으로 위와 같은 라이브러리들을 적용하게 되었습니다.
공부를 위해서 접했던 라이브러리들을 실제 실무에 적용해볼 수 있었던 것은 정말 짜릿한 경험이었습니다.

🔨 Trouble Shooting

저를 제외한 다른 팀원들은 다른 업무에 배정이 되고 저는 팬들의 백엔드 개발자이신 정환님이 만들어두신 swagger docs를 참고하여 혼자서 프론트엔드 개발을 진행하였습니다. 그렇다보니 막히는 부분이나 로직에 대해 고민이 되는 부분에 있어서 같이 의견을 나눌 팀원이 없었고, 혼자서 문제를 돌파해 나가려는 여러가지 시도를 하였습니다.

내가 겪는 문제는 지구상의 다른 프로그래머가 이미 겪은 문제이다.

나는 무적이고 구글은 신이다.

첫번째 Trouble...

이메일인증 회원가입을 구현하기 위해서 기획팀에서 제시한 상황은 다음과 같았습니다.

  1. 유저가 chrome 브라우저에서 회원가입 진행
  2. 인증 이메일 발송
  3. 유저가 firefox 등 다른 브라우저에서 이메일 인증 완료할 수도 있음
  4. 위와 같은 상황도 대응해서 회원가입 프로세스 구현
그리하여 redirect를 실질적으로 진행하는 backend 단에서 hash 처리된 데이터(유저 이메일, 토큰)을 hash 처리하여 보내주시기로 하였습니다. 허나 문제는 hash 처리된 데이터를 해독하는 과정이었습니다.
이 데이터를 프론트단에서 decode 해야만 회원가입을 정상적으로 진행할 수 있었는데, 자꾸만 읽을 수 없는 형식으로 해독이 되어서, 유저의 정보를 얻을 수 없었습니다.
결국 그 문제를 해결하지못한채 금요일을 맞이했고, 주말 동안 마음 편히 쉬지 못한 채 틈만 나면 관련 구글링을 하고 왜 되지 않는걸까 고민을 했습니다.
의심의 끝에 혹시 encode 하는 과정에서 뭔가 잘못하신 건 아닐까 하는 의심까지 했습니다.

정환님 죄송합니다..
하지만 결국 정환님의 조언과 구글링의 결과로 해결해냈고 오답노트는 다음과 같습니다

해결하기 전 코드는 다음과 같습니다.

 const email = CryptoJS.enc.Base64.stringify(cipher).split("|")[0];
 const emailToken = CryptoJS.enc.Base64.stringify(cipher).split("|")[1];

해결한 코드는 다음과 같습니다.

 const email = CryptoJS.enc.Utf8.stringify(cipher).split("|")[0];
 const emailToken = CryptoJS.enc.Utf8.stringify(cipher).split("|")[1];

Base64 형태로 encode를 해서 당연히 Base64 형태로 decode를 해야한다 라고 생각한 멍청한 제 자신이 너무 미웠습니다. 우리가 사용하고 읽을 수 있는 형태는 Utf8인데 Base64로 계속 데이터를 변환했기 때문에 사용할 수 없는 형식으로 데이터가 받아졌던 것이었습니다. 😭😭

두번째 Trouble ...

두번째 trouble은 첫번째 trouble에 비하면 아주 귀여운 수준이긴 하지만, 후에도 맞닥뜨릴 수 있는 문제라고 생각하기 때문에 다뤄보겠습니다.

form 태그와 input 태그를 다뤄보지 않은 프론트엔드 개발자가 있을까요 ?
저는 아가 프론트엔드 개발자이긴 하지만 없다고 단언할 수 있을 것 같습니다. 그만큼 필연적으로, 많은 컴포넌트에서 쓰이는 태그이고 이와 함께 적용해야하는 유효성 검사는 약간은 귀찮은 작업입니다. 각각의 input 태그의 value를 추적하기 위해 각각 mapping되는 state를 만들어주어야 하고, (물론 input 태그의 속성 중 하나인 name을 사용하여 객체 형태 로 많은 input 태그들의 상태를 하나로 묶을 수 있긴 합니다.) 관련된 state를 update 시키는 로직을 만들어주어야 합니다.
이는 상당히 귀찮은 작업이죠.
그렇기 때문에 react-hook-form을 사용하기로 결정했습니다.

human... 제대로 이해하고 라이브러리를 쓰고 있나요 ?


위의 이메일 Input 안에 자리한 X 버튼의 용도는 무엇일까요 ? 예상하시다시피 유저가 입력한 값을 초기화시키는 역할입니다. 이를 위해서 평소에는 다음과 같이 작성했었습니다.

const [emailValue, setEmailValue] = useState("");

<input type="text" value={emailValue} onChange={} />
<Xbutton onClick={()=>setEmailValue("")} />

물론 위와 같이 작성하는 것도 쉽고, 많은 코드량이 들지 않는 일이지만 react-hook-form은 여러가지 유용한 기능들을 제공해줍니다.

const {
    register,
    handleSubmit,
    setValue,
    watch,
    formState: { dirtyFields },
  } = useForm<FormData>();

객체 구조 분해 할당 문법을 사용하여 꺼낸 속성 중에 다루어볼 것은 setValue입니다. setValue는 이름에서부터 느낄 수 있듯이 input 태그의 값을 set해주는 역할을 합니다. 사용 방법은 다음과 같습니다.

setValue("email", "");

위와 같이 작성했을 때 input의 값이 초기화 되는것을 발견했습니다 !
이때까지만해도 react-hook-form은 신이고 나는 무적이다... 라고 생각했었습니다.
하지만 문제는 다른 곳에서 발생했습니다.

유저의 사용편의성을 위해서 input 태그에 값이 있다면 border-bottom의 색을 바꿔줘야했고 이를 위해서 제가 사용한 조건은 다음과 같았습니다.

const inputArr = Object.keys(dirtyFields);
const isEmailFilled = inputArr.includes("email");

/* styled-components로 작성한 input 태그 */
<EmailInput1
          filled={isEmailFilled}
          id="email"
          placeholder="이메일을 입력해주세요."
          type="text"
          {...register("email")}
        />
        
 /* styled-components 선언 부분 */
 
 const EmailInput1 = styled(EmailInput)<{ filled: boolean }>`
  border-color: ${(props) => (props.filled ? "#333333" : "#AAAAAA")};
`;

react-hook-form은 dirtyFields라는 기능을 제공해주는데, dirtyFields는 register함수로 등록한 input태그의 값이 존재하는지 존재하지 않는지에 대해 객체값으로 반환해줍니다.
즉 제가 의도한 대로 X 버튼을 눌러서 input 값이 초기화되었다면, dirtyFields가 제공하는 객체의 email 값은 false 여야했습니다.
그러나 X 버튼을 누르고 난 후 dirtyFields를 콘솔로 찍어봤을 때의 결과는 다음과 같았습니다.

{ email : true }

해달라는 대로 다 해줬잖아 ... 왜 안되는데 ?

문제는 제가 react-hook-form의 구동원리에 대해 제대로 이해하지 못했기 때문이었습니다.
공식문서에 나와있는 dirtyFields의 설명은 다음과 같았습니다.

An object with the user-modified fields. Make sure to provide all inputs' defaultValues via useForm, so the library can compare against the defaultValues.
그렇습니다 ... 저는 defaultValues를 제공해주지 않았기 때문에 제대로 작동하지 않았었던 것이었습니다.
그리하여 수정한 코드는 다음과 같았습니다.

const {
    register,
    handleSubmit,
    setValue,
    watch,
    formState: { dirtyFields },
  } = useForm<FormData>({
    defaultValues: {
      email: "",
      password1: "",
      password2: "",
      keepLoggedIn: false,
    },
  });

이렇게 defaultValues라는 옵션을 useForm 함수에 전달하고 나서야 모두가 행복해질 수 있는 결과를 만들 수 있었습니다.

성장 포인트

그래서 나는 성장했을까 ? 무엇을 얻었나 ?

이번 인턴쉽을 통해서 성장했다고 제가 생각한 포인트는 다음과 같습니다.

  1. 비개발 직군과의 대화하는 방법
  2. 실제 현업 백엔드 개발자와의 협업 경험
  3. trouble shooting 능력
  4. 긍정적 마인드셋
사실 4번 항목이 제가 이번에 인턴쉽을 하면서 가장 의미있는 것이라고 생각합니다. 그동안 스스로를 너무 돌멩이라고 비하하면서 부정적인 생각에 사로잡혀 있었었는데, 현업 개발자분들이 많이 칭찬해주시고, 좋게 봐주신 결과 최종적으로 내부적으로 회의를 거치셔서 함께 일해보자는 오퍼까지 받게 되었습니다.

아직은 아기 개발자이지만 앞으로도 발전을 거듭해서 꼭 멋진 시니어 개발자가 되어보겠습니다 !!

긍정적인 사람은 한계가 없다.

profile
니체의 마인드셋으로

0개의 댓글