Just Do IT!

스파르타코딩클럽 내일배움캠프 16주차 회고 본문

스파르타코딩클럽 내일배움캠프/WIL

스파르타코딩클럽 내일배움캠프 16주차 회고

MOON달 2023. 2. 19. 21:21
728x90
최종 프로젝트 ~ing

지난 주에 이어 최종 프로젝트를 진행했는데, 사실상 기획 50% 개발 50%를 한 느낌이다. 확실히 우리가 이전에 했던 기획은 정말 틀만 잡아 놓은 것이었고, 지금은 진짜 협업을 한다는 기분이랄까...여튼 기획의 중요성을 절실히 느끼고 있다.

 

 

 

 

 

 

 

기획 회의

그라운드 룰로 오전 9시 30분에 한번, 오후 17시 30분에 한 번 총 두 번의 스크럼을 정했고 순조롭게 진행 중이다.

사실 오전에는 서로의 컨디션을 체크하고 오늘 할 일들을 이야기해보고, 또 오후에는 진행한 일들을 이야기 하는데 정해진 시간 외에도 자주 마이크를 키고 소통하고 있다.

 

솔직히 말하자면...내가 좀 말이 많은 편인것 같다 ㅋㅋㅋㅋㅋ 라이브러리 설치할 때도 자주 조원들에게 물어보고 뭐가 잘 안될 때도 조원들에게 공유하고...내가 거의 모든 걸 공유하다보니 자연스럽게 다른 조원분들도 자주 마이크를 켜주시는 것 같다. 회고를 틈타 감사의 말을 전하며....

 

여튼 우리끼리의 소통은 매우 잘 되고 있고, 디자이너님과의 소통은 선형님이 맡아서 하고 계신데 정말 수고가 많으시다. 사실 디자이너님의 관점을 접하는 것도 처음이고 '디자인'에 관해 생각해본 게 처음이라서 가끔은 이해가 안될 때도 있다. 뭔가 예뻐 보이는(?) 걸 제안해주시면서 기능이 되냐고 물어보시면 또 우리가 된다, 안된다 이야기 해야 하고... 실제로 회사를 가면 이런 식으로 소틍을 하는 걸까 하는 궁금증이 생긴다.

 

그래도 우리 조는 매일 디자이너님이 젭에 오셔서 기획 회의를 다같이 하기도 하고, 선형님과 이야기하고 그걸 우리가 전달받고 등등...소통이 잘 되고 있는 중이다.

 

그래도 이제는 기획 회의보다는 그냥 확정짓고 기능 구현을 더 해야 한다는 생각을 했었는데, 목요일이 되어서야 기획의 큰 틀을 확정지었다. 더 이상의 전체 회의는 웬만해선 하지 않는 걸로..!!

 

일단 글쓰기 큰 틀이 바뀌었다.

 

아직 기능 구현이 완료 된 건 아니지만, 글쓰기 페이지다.

 

이런 식으로 여행전/여행후 카테고리가 생기고, 그냥 코스만 잘 수 있기도 하고 리뷰를 남길 수 있기도 하다. 이렇게 큰 틀이 바뀌면서 메인 페이지도 많이 바뀌었는데, 그에 따라 디자이너님과 회의할 것들도 많아졌다.

 

그래서 그 결과로 저런 글쓰기 페이지가 나왔고, 시윤님이 열심히 구현해주고 있다. 

 

메인 페이지 와이어 프레임

피그마에서 캡처해왔는데, 우리 조 메인 메인페이지는 이런 식으로 구성될 예정이다. 저기 NOW PLANS, BEST REVIEWS를 어떤 글을 불러와야 할지 결정하는 게 이번주 내내 했던 회의 내용이었다. 이렇게 토론하고 열심히 서로를 설득한 끝에 만들어진 메인페이지...꼭 저대로 구현하고 싶다 ㅋㅋㅋㅋㅋ

 

그리고,

이번에 튜터님도 말씀해주셨지만, 유저 플로우에 대해 생각해본 적이 정말 처음이다. 유저가 우리 페이지에 들어와서 흥미로운지 아닌지, 스크롤을 어디까지 내리는지 등등 평소에 전혀 생각해본 적 없는데 이번에 처음으로 고민해봤다. 디자이너님이 유저 관점에서 잘 말씀해주셔서 한번도 생각 못해본 것들에 대해 생각해보는 계기가 되었다.

 

그래서 목요일에 조원들과 함께 워크 플로우를 작성했는데 생각보다 복잡했다(?)

기획 확정 전 워크 플로우

이것도 기획 확정 전에 작성한 거라서 아마 내일쯤 다시 수정해야 할 텐데....이렇게 전체적으로 만들어보면서 우리 웹페이지의 기능을 한 번 더 고민해보는 계기가 되었다. 그런데 이게 몇 시간이나 걸릴 줄은 전혀 예상 못했다 ㅋㅋㅋ

 

 

 

 

 

 

 

 

내가 맡은 기능

지난 주에 로그인/회원가입 기능을 전부 완료했다고 생각했는데 그건 나만의 착각일 뿐.

생각치 못한 버그들이 나오고 모달 관련해서도 새로운 기능을 추가하고 닉네임 변경만 추가했다가 프로필 설정 기능까지 추가하는 등...생각보다 짜잘하게 고칠 기능들이 너무 많았다. 

 

우선 첫 번째로, 모달 바깥을 누르면 모달 창이 꺼지는 것. 물론 모달창이 나오면 x 표시를 누르면 닫히긴 하지만, 다른 웹페이지들은 모달창 바깥을 누르면 자동으로 모달 창이 닫히니까 그걸 구현하고 싶어서 구글링을 통해서 구현했다. 처음에는 잘 안 먹혀서 잘못 생각했나 했는데, 다시 이것저것 코드 찾아보고 다른 사람들 코드를 보면서 이해하니까 성공했다.

 

그리고 나서 한 것은 유효성 검사 추가.

좀 오래전 같은데 프로그래머스에서 문제를 풀면서 정규 표현식이 나와서 튜터님한테 질문하러도 가보고 나름대로 공부해보고 블로그 글도 작성했었다. 예전에 뉴스 피드 프로젝트 할 때도 튜터님이 이메일 유효성 검사로 정규 표현식을 사용하셨었는데 그 때는 그냥 코드 복붙하고 넘어갔던 부분인데, 이번에는 직접 정규 표현식을 써보고자 이메일, 비밀번호 유효성 검사에 썼었다. 하나하나 하니까 복잡해졌지만...그래도 하기는 했으니까.

 

그런데 유효성 검사를 추가하고 직접 회원가입 하다보니까 버그가 생겼다. 비밀번호랑 비밀번호 재확인 input 창이 일치하지 안하도 회원가입이 된다는 것! 그래서 금요일에는 한참동안 그거 버그 고치려다가 결국 새로운 라이브러리로 회원가입/로그인 폼을 아예 리팩토링 해버렸다. 새롭게 배웠는데 나중에도 유용하게 써먹을것 같다.

 

react-hook-form 라이브러리 정리한 내용

https://daydream-sy.tistory.com/196

 

[TypeScript] react-hook-form 사용하기

react hook form이란? React 내에서 form, 양식을 만들 때 사용하는라 이브러리다. 복잡한 폼을 만들 때 간결하고 쉬운 코드 작성에 도움이 된다. 기존 폼에서 입력해야 하는 번거롱룬 작업을 줄여주며,

daydream-sy.tistory.com

 

<form className=" rounded px-8 pt-6 pb-8 w-full">
          <div className="text-red-600 font-bold m-2">{error}</div>
          <label className="block text-black font-2xl font-bold mb-3">
            이메일
          </label>
          <input
            className="shadow appearance-none border rounded w-full py-2 px-1 text-black"
            {...register("email", {
              required: "이메일을 올바르게 입력해주세요.",
              pattern: {
                value:
                  /^(([^<>()\[\].,;:\s@"]+(\.[^<>()\[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i,
                message: "이메일 형식에 맞게 입력해주세요,",
              },
            })}
            name="email"
            type="email"
            id="email"
            value={email}
            onChange={(event) => setEmail(event.target.value)}
            placeholder="이메일"
            onKeyUp={(e) => {
              if (e.key === "Enter") {
                loginBtn(e);
              }
            }}
          />
          <div className="text-red-600 font-sm mb-6">
            {errors?.email?.message}
          </div>
          <label className="block text-black font-2xl font-bold mb-3">
            비밀번호
          </label>
          <input
            className="shadow appearance-none border rounded w-full py-2 px-1 text-black"
            {...register("password", {
              required: "비밀번호를 입력해주세요",
              minLength: {
                value: 8,
                message:
                  "비밀번호는 영문 대소문자, 숫자를 혼합하여 8~15자로 입력해주세요.",
              },
              pattern: {
                value: /^[A-Za-z0-9]{8,15}$/,
                message:
                  "비밀번호는 영문 대소문자, 숫자를 혼합하여 8~15자로 입력해주세요.",
              },
            })}
            name="password"
            type="password"
            id="password"
            value={password}
            onChange={(event) => setPassword(event.target.value)}
            placeholder="비밀번호"
            onKeyUp={(e) => {
              if (e.key === "Enter") {
                loginBtn(e);
              }
            }}
          />
          <div className="text-red-600 font-sm mb-6">
            {errors?.password?.message}
          </div>
          <div className="flex items-center justify-center">
            <button
              className="m-1 text-white bg-purple-300 active:bg-purple-700 font-bold uppercase text-sm px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mb-1"
              type="submit"
              disabled={isLogin}
              onClick={(e) => loginBtn(e)}
            >
              로그인
            </button>
          </div>
        </form>

이게 라이브러리를 이용해서 리팩토링한 로그인 부분이다. 처음에는 좀 낯설었는데 공식 문서 좀 보고, 다른 사람들이 적용한 블로그 글들을 찾아보니까 다행히 금요일 안으로 구현할 수 있었다.

 

여기서도 예전에 적용했던 유효성 검사 추가. 이메일 부분이 좀 긴가 싶은데 그래도 뭐...아, 그리고 원래 없었던 enter 키 누르면 똑같이 적용되는 것도 추가했다. 이렇게 해서 유효성 검사 버그를 잡아서 다행이다.

 

그리고 마지막으로 했던 건, 프로필 수정 부분.

이것도 내가 중점으로 맡았던 부분은 아니지만, 뉴스피드 프로젝트하면서 바닐라 js로 SPA 프로젝트 할 때 했었는데, 이번에 프로필 수정을 직접 구현해봤다.

 

원래는 닉네임만 추가하려고 했었는데 하다보니 프로필 사진까지 넣어서 구현했다. 이것도 나중에 추가한 게 있는데, 처음에는 localstorage에 저장하고 그 이미지를 firebase에 올린 다음에 firebase에서 url을 불러오는 식으로 구현했었다.

그런데 내가 몰랐던 점이 있었다. 바로 localstorage에 저장하면 이미지 용량에 제한이 있었던 것...! 선형님이 알려주셨는데 전혀 몰랐던 사실....하나 더 배웠다.

 

아무튼 그래서 이거에 대해서 좀 고민하다가 선형님이 그냥 firebase에서 바로 불러오자고 의견을 내주셔서 해결 완료.

 

  const profileEdit = async () => {
    const imgRef = ref(storage, `${authService.currentUser?.uid}${Date.now()}`);

    const imgDataUrl = img;
    let downloadUrl;
    if (imgDataUrl) {
      const response = await uploadString(imgRef, imgDataUrl, "data_url");
      downloadUrl = await getDownloadURL(response.ref);
    }
    updateProfile(authService.currentUser as any, {
      displayName: nickname,
      photoURL: downloadUrl ? downloadUrl : null,
    })
      .then(() => {
        alert("프로필 수정을 완료했습니다");
        setModal(false);
        navigate("/user/:id");
      })
      .catch((error) => {
        console.log("error: ", error);
      });
  };

 

저기서 imgDataUrl이 원래 localstorage에서 저장한 img를 불러오는 것이었는데 바로 firebase storage에 저장된 이미지를 불러오게 바꿨다. 그러고 나서 이미지 용량이 큰 걸로 프로필 설정을 했더니 조금 느려지는 것 말고는 정상적으로 잘 수정이 되었다.

 

여기까지가 이번주에 내가 구현한 기능들이다. 이거 외에도 주말에 더 한 것들이 있지만 그건 성공하면 내일 TIL에 쓸 예정이다. 뭐...못해도 TIL에 작성하겠지만...ㅋㅋㅋ 주말에 한 건 아직 완성은 아니라서...

아무튼, 기획 회의하면서 시간을 많이 보내서 그런지 따져보면 그리 많은 시간은 아니었어서 다음주에는 더 열심히 기능 구현할 예정이다. 3주가 긴 줄 알았는데 전혀 나만의 착각일 뿐, 생각보다 너무 짧았다.

 

 

 

 

 

 

 

 

 

이번주 마무리

시간이 왜 이렇게 빨리 가는 건지, 1주차가 지났다 싶었는데 벌써 2주차가 지나고 다음주면 중간 발표날이 다가오고 있다.

이럴수가...3주는 역시 너무 짧았다. 목요일까지 발표 자료 제출이지만 우리 조끼리는 수요일까지 전부 완성하기로 했는데, 그 계획대로 잘 진행되었으면 좋겠다. 튜터님이 UI보다는 일단은 기능 구현 먼저 하고 난뒤에 UI 생각하라고 하셨는데 아마 우리 조도 그렇게 되지 않을까 싶다. 디자이너님이 열심히 디자인 해주고 계시니까...최종 발표 전에는 꼭 그대로 만들어내야겠지만.

 

여튼 이번주도 기획 회의가 길어지고 또 워크 플로우 작성한다고 오전 시간을 다 써버려서, 다음주에는 최대한 회의를 짧게 하고 각자 기능 개발에 더 집중해야겠다. 지난 주 WIL에도 기능 구현을 빨리 해야한다고 했었는데...ㅋㅋㅋ 이번주 회고도 똑같이 끝난다.

 

그래도 좋은 건, 최종 프로젝트를 아주 즐겁게 하고 있다는 점이다. 내 개인적 몸 컨디션(!) 과는 별개로 조원들과 너무 재밌게 프로젝트를 하고 있고, 소통의 어려움 없이 진행 중이다. 뭔가 내가 너무 긍정적인가 싶긴 한데 좋은게 좋은 거지 뭐. 나만 재밌을 수 있지만(?) 그래도 난 즐겁게 하고 있다. 우리 조 조원분들도 그랬으면 좋겠다.

뭔가 다음주에 중간 발표가 끝나면 약간 한 고비를 넘긴 듯한 기분이 들것 같은데, MVP 기능을 잘 마무리해서 마지막 프로젝트에서 유종의 미를 거둘 수 있었으면 좋겠다.