본문 바로가기

엘리스 sw 엔지니어 트랙 2기

엘리스 2차 프로젝트 회고

반응형

프로젝트가 끝나고 일주일이 지났다. 3주 동안 정말 열심히 했던 프로젝트였다. 2차 프로젝트는 리액트로 처음 개발하는 나에게 아주 의미있는 프로젝트였다. 리액트를 배운지 2달도 채 안 된 상태에서 시작한거라 처음에는 막연한 두려움이 있었지만 금방 적응했다. 1차 프로젝트를 바닐라 자바스크립트로 진행했어서 그런지 개발하면서 리액트의 편리함을 느낄 수 있었다. 

 

내가 회고글을 적는 이유는 1차 프로젝트 회고글에서 언급했듯이 내가 했던 것들을 기록하기 위함이기도 하지만, 엘리스 sw 엔지니어 트랙을 고민하는 사람들에게 정보를 주기 위함이기도 하다. 또한 미래의 엘리스 레이서분들이 프로젝트를 진행하면서 혹시나 이 글을 보게 된다면 참고해도 좋을 것 같다.

 

여행가다

 

GitLab이 비공개로 설정되어 있어서 나중에 Github로 이전하면 링크를 달도록 하겠다. 여행가다는 일별 여행 루트를 짜고, 이를 그대로 다른 사람에게 공유할 수 있는 여행 플래너 커뮤니티 서비스다 . 나는 plan 페이지 이외의 모든 것을 했다. 내 역할들을 구체적으로 나열해보면 아래와 같다.  

  • 메인, 공유 게시판, 로그인, 프로필 페이지 구현
  • plan 페이지 계획 공유 기능 담당
  • svg 및 라이브러리 컴포넌트화 작업
  • 모달창 관리
  • UI/UX 디자인

plan 페이지에 핵심 기능이 다 들어가있어서 plan 페이지를 1.3 명이 작업했고, 내가 나머지를 했다고 보면 된다. 1.3명이라고 적은 이유는 팀원 한분이 개인 사정으로 중간에 나갔기 때문이다. plan 페이지에서 내가 관여한 부분은 공유하기 기능 뿐이다. 

 

프로젝트 진행 방식

기간:  3주
주제:  자유주제
사용 언어:  React
팀당 인원:  5명(Front 3 + Back 2) or 6명(Front 4 + Back 2) 

 

기본적인 정보는 이정도다. 주제는 엘리스에서 추천해주는 주제가 있었다. 엘리스의 추천 주제는 펜션 예약 웹 서비스 프로젝트와 웹 빌더 서비스 프로젝트였다. 그런데 실제로 추천 주제로 한 팀은 절반도 안됐다. 

 

스켈레톤 코드는 주어지지 않는다. 따라서 처음부터 끝까지 팀원과 상의해서 진행해야 한다. 스케줄상 처음 3일은 아예 기획으로 잡혀있어서 그동안은 오피스아워가 없다. 1차 프로젝트와 마찬가지로 포지션별로 현업 코치님이 한 분씩 매칭되고, 격일로 오피스아워가 진행된다. 매주 토요일마다 코드 리뷰가 진행되는 점도 동일하다. 

 

인원은 5명 또는 6명이다. 그런데 중간에 나가는 사람이 간혹 있어서 인원이 줄수도 있다. 우리팀은 원래 5명이었는데 중간에 한명이 나가서 4명이 됐다. 근데 4명도 괜찮았다. 

 

1차 프로젝트는 엘리스가 밥상까지 차려줬다면, 2차 프로젝트는 처음부터 끝까지 팀끼리 해결해야 한다. 

 

느낀점 및 고민들

1. 재사용 가능한 컴포넌트

리액트가 강력한 이유 중 하나는 '컴포넌트의 재사용성'이라고 생각한다. 나는 재사용할 수 있는 것들은 컴포넌트화 시켜서 개발 속도를 향상시키고자 했다. 내가 가장 먼저 작업했던 부분은 '아이콘'이다. components 하위 폴더에 icons라는 폴더를 생성해서 서비스 전반에 사용되는 모든 아이콘을 모았다. 아래는 두 종류의 좋아요 하트 아이콘을 사용하는 예시다. 

 

import { LikeIcon, UnlikeIcon } from 'components/icons';

...
<LikeIcon />
<UnlikeIcon />
...

 

우리 팀은 스타일링을 styled-components로 했기 때문에 아이콘에 추가적인 스타일을 적용하려면 'styled(Icon)'꼴로 상속만 시켜주면 됐다. 컴포넌트화 시키는 과정이 시간이 걸리는 작업이긴 하지만 한번 해놓고 나면 이후가 편하다. 

 

 

메인 페이지, 플랜 페이지, 장소 추가 모달에 사용되는 slick-slider도 컴포넌트화 시켰다. 사실 원래 컴포넌트화 시킬 생각은 없었는데 구현하다 보니 코드 중복이 많이져서 컴포넌트화 시키기로 결정했다. 그리고 라이브러리를 적용시키려면 사용법을 따로 익혀야 하는데 굳이 팀원분이 또 사용법을 익혀야하나 싶기도 했다. 무엇보다 팀원분이 핵심 기능 구현에 고통을 호소하셔서 내가 그냥 사용하기 쉽게 만들어서 줘야지.. 라고 생각했다. 아래는 컴포넌트화 시킨 slick-slider의 사용 예시다.

 

<SlickSlider
width={1200}
slidesToShow={5}
slidesToScroll={2}
arrowPadding={50}
arrowSize={25}
boxShadow>
	{요소 삽입}                    
</SlickSlider>

 

 

이렇게 컴포넌트화 시킨 것들은 노션에 사용법을 상세히 기록해놨다. 아직 컴포넌트화 시키지 않은 것들이 몇개 있는데 이는 리팩토링 할 때 진행할 생각이다. 

 

 

라이브러리는 개발 속도를 높여 주지만 커스터마이징 하기에는 제한이 많다는 것을 느꼈다. 스타일에 변화를 주고 싶거나 기능을 추가할 수 있으면 좋겠지만.. 마음처럼 안 될 때가 많다. 그래서 큰 기업일수록 라이브러리를 사용하지 않고 하나하나 직접 구현하겠구나.. 라는 생각을 했다. 그리고 라이브러리 내부 로직과 나의 로직이 꼬이면 트러블 슈팅이 힘들어질 수 있다. 그래서 개인적으로 라이브러리 사용을 최대한 지양하는게 좋다고 생각한다. 

 

2. 모달창 구현에 대한 고민 (feat. 확인창)

나는 모달창 또한 컴포넌트화 시켜서 재사용하기 쉽도록 했다. 모달창은 다른 컴포넌트와 다르게 전역으로 관리했다. modalIsOpen이라는 전역 상태값을 가지고 있어서 modalIsOpen이 true가 되면 모달창이 열리고, false가 되면 모달창이 닫히는 구조다. 내가 모달창을 전역으로 관리한 이유는 기획 과정에서 '모달창은 하나만 뜬다'를 규칙으로 정했기 때문이다. 우리 팀은 모달 위에 또 모달이 뜨는 구조는 사용자 경험이 좋지 않기 때문에, 이런 경우에는 다른 페이지로 이동시키는게 좋다고 생각했다. 

 

모달창은 리팩토링만 세 번 했다. 결론적으로 커스텀 훅으로 코드를 간결하게 만들 수 있었다. 모달창을 생성하고 불러오기까지 세 단계를 거쳐야 한다. 아래 예시는 EmailAuth라는 모달을 생성하고 이를 불러오는 과정이다. 

 

 

1) 모달 생성

import Modal from 'components/Modal';
import EmailAuthForm from 'components/EmailAuthModal/EmailAuthForm';

const EmailAuthModal: FC = () => {

    return (
        <Modal
        width={400}
        height={400}
        >
            <EmailAuthForm />
        </Modal>
    )
}

 

Modal 컴포넌트로 새로운 모달을 생성한다. 위 코드에서 EmailAuthForm은 모달창 내부 요소다. 

 

 

2) 모달 등록

import EmailAuthModal from "components/EmailAuthModal";
import { useSelector } from 'react-redux';

const ModalSelector = (state) => state.modal

// 이름: <컴포넌트> 형태로 모달 등록
const modalComponents = {
    "EmailAuthModal" : <EmailAuthModal/>,
}

const PickModal = () => {
    const { modalIsOpen, modalName } = useSelector(ModalSelector);
    return (
        <div>
            {modalIsOpen && modalComponents[modalName]}
        </div>
    )
}

 

모달 컴포넌트 이름으로 모달을 등록한다. modalIsOpen 조건부 렌더링으로 이름에 맞는 모달 컴포넌트가 렌더링 되는 구조다. 

 

 

 

3) 모달 불러오기

import useModal from 'hooks/useModal';

const LoginForm = () => {
    const registerClickHandler = useModal('EmailAuthModal');
    
    ... 
    return (
    	<Register 
        onClick={registerClickHandler}>
        	회원가입
        </Register>
    )
}

 

useModal 커스텀 훅의 인자로 모달 이름을 적어주면 이벤트 콜백 함수를 반환한다. 이를 클릭 이벤트 콜백 함수로 등록하면 된다. 

 

 

 

모달창은 만족스럽게 리팩토링 했는데, 문제는 확인창이다. 지금의 확인창은 약간 '돌아간다..?' 느낌이다. 확인창과 일반 모달창의 차이점은 '확인 버튼'에 있다.

 

문제의 확인창

 

확인 버튼을 누르면 서버에 추가적인 요청을 해야 하는 상황이 대부분이었기 때문에 사용자가 확인 버튼을 눌렀는지 안눌렀는지에 대한 상태값이 필요했다. 문제는 모달창을 전역으로 관리하고 있어서 확인에 대한 상태값(confirmState)도 전역으로 관리해야 했다. 지금 임시로 해결한 방법은 확인창을 불러오는 컴포넌트에 store로부터 confirmState를 불러와서 useEffect로 confirmState가 true일때 서버에 요청을 보내도록 했다. 이를 어떻게 하면 깔끔하게 리팩토링 할 수 있을까 고민해봤는데.. 뭔가 createAsyncThunk를 사용하면 되지 않을까 싶다. 아직 createAsyncThunk 사용법을 잘 몰라서 우선 사용법을 익히고 리팩토링 할 수 있으면 해야겠다!

3. 동작 원리에 대한 궁금증

이번에 개발을 하면서 느낀건데 구현 자체는 어찌어찌 되기는 한다. 굳이 이해를 하지 않아도 돌아가게는 만들 수 있다. 문제는 '제대로 이해하고 있는가'라고 생각한다. 내가 구현한 것들, 내가 해결한 오류들, 내가 사용하고 있는 툴 등을 제대로 이해하고 있는지 묻는다면 나는 No다. 평소에 왜?라는 질문을 많이 해서 찾아보고 싶은게 많았는데 3주 안에 결과물을 내야했기에 잠시 미뤄둔 부분도 있다. 지금은 시간이 많으니깐 이론적인 부분에 시간 투자를 많이 해야겠다. 내가 프로젝트를 하면서 꼭 공부해야겠다고 생각한 부분은 아래와 같다. 

 

  • 로그인을 구현하면서 끊임없이 나를 괴롭혔던 CORS
  • 폰트 깜빡임의 원인이었던 FOUT, FOUC
  • FOUT, FOUC와 관련된 브라우저 렌더링 과정
  • 디렉토리 구조를 고민하면서 관심이 생긴 디자인 패턴
  • 리액트 훅에 대한 깊은 이해 (useCallback, useMemo 등의 사용 시점)
  • 개발환경 세팅과 관련된 webpack과 babel
  • CSR, SSR 어떻게 다른지(상세하게)
  • 빌드와 배포
  • 타입스크립트
  • 백엔드 지식

백엔드 지식이 많이 추상적인데 백엔드 공부를 소홀히 하지 말자는 의미에서 일부러 그렇게 적었다. 공부할게 많지만 이것은 개발자의 숙명.. 좀 뜬금없지만 개발자가 꾸준히 공부하지 않으면 도태된다는 점에서 아주 매력적인 직업이라고 생각한다. 노력만이 살 길이다!

 

흥미로웠던 이슈

위에 다 적어놨다. 가장 흥미로웠던 이슈는 FOUT, FOUC로 인한 폰트 깜빡임 이슈였다. 문제를 해결하기는 했지만 아직 완벽하게 이해를 못해서 따로 포스팅할 생각이다. 

 

아쉬운 점

처음에 너무 급하게 진행했던게 약간 아쉽다. 기획이 탄탄하지 않은 상태에서 시작해서 중간에 한번 갈아 엎었다. 만약에 기획에 힘을 실었더라면 더 많은 것을 구현할 수 있지 않았을까? 1차때 그렇게 강조했는데 똑같은 실수를 반복하다니.. 기획은 너무 중요하다! 

 

리팩토링은 틈틈이 진행할 생각이다. 테스트 코드도 짜보고 싶고, next.js로 마이그레이션도 해보고 싶다. 또한 응급용으로 적었던 any 타입도 빨리 바꿔야 한다. 로그인 로직도 바꿀 필요가 있다. 지금도 계속 진행형이다!

 

 

반응형