[TangWay] - 팀 프로젝트

김찬영·2021년 1월 31일
1

Project Complete

목록 보기
3/4
post-thumbnail

TangWay Clone 🛫


TangWay

  • Clone website : T-way
  • Project Period : 2020.12.28 ~ 2021.01.08
  • Front-End : 임대호, 김찬영, 최용석
  • Back-End : 문승희, 최선우,
  • Demo Video
  • Github

Skill Stack

Front-End

  • HTML
  • ES6
  • JavaScript
  • React(CRA)
  • Sass
  • Redux
  • styled-component

Back-End

  • Python
  • Django
  • CORS Header
  • Bcrypt
  • PyJWT
  • MySQL
  • AqueryTool : 데이터베이스 모델링

협업 Tool

  • Git, Github
  • Slack : 비대면 소통
  • Trello : 일정관리 및 작업 현황 공유
  • Notion : 팀 내 개발 자료, 규칙, 안건 등 기록

구현한 기능 🔥

  • 회원가입 & 로그인
  • 카카오 소셜 로그인 기능 구현
  • 약관페이지 전체선택, 전체 해제, 개별 해제시 전체선택 해제되는 기능 구현
  • state를 props로 활용하여 예매 Bar 동적 레이아웃 구현
  • Redux를 통한 상태 관리
  • 협업 과정에서 나타날 수 있는 Git comflict 해결, Git squash, rebase 사용요령 습득
  • useEffect, setTimeout, keyframes로 로딩스피너 구현
  • Accordion Menu에서 탑승자 정보 입력시, 입력한 총합된 Data를 결제페이지로 최종적으로 전달

내가 담당한 기능

  • 탑승자 정보 입력란 페이지 담당
  • Accordion Menu를 컴포넌트 재사용으로 구현
  • 국적검색기능
  • 년도별에 맞는 월, 일 구현

1. 탑승자 정보

  • 탑승권 예매 페이지에서 탑승자 정보로 넘어오면, 사이트에서 자주 볼 수있는 Accordion Menu로 구현하여 탑승자가 정보를 편하게 입력 할 수 있도록 신경썼다.
  • 강경오라는 이름이 보이는데, 그부분은 로그인한 유저의 Data를 받아서 초기 설정을 해주었다.
  • 탐승권 예매의 오른쪽부분에 Breadcrumb기능을 추가하여 유저가 보다 직관적으로 step을 볼수 있게 하였다.

2. 지역검색

  • 국적검색버튼을 누르면 각 나라별로 선택할 수있는 모달창이 나온다.
  • 사용자가 편하게 찾을 수 있도록 검색기능도 추가하였다.

3. Seleted 생년월일에서 moment.js 사용하여 년도,월,일,월 자동적으로 세팅

  • 이번 프로젝트에서는 많은기능을 하기보단 하나의 기능을 좀더 깊게 들어가 완벽도를 높이고 싶었다. 그래서 문득, 생각한 부분이 날짜였다.
  • 윤날로 인해 4년마다 날이 다른 부분과 단순히 반복문을 사용했을때 월, 일수가 같다면 사용자입장에서 헷갈릴 수 있다는 판단이 들었다.
  • 그래서 년,월,일을 자동적으로 세팅했다.
  • 날짜를 공부하면서 생각보다 많은 것을 알 수있었다. 시차부분도 실무에서는 중요하게 다루고 있다는 점이다. 그부분에서 차후 더 공부해볼 예정이다.

휴대폰에 하이픈

  • 사용자가 입력할때 좀 더 편하게 작성하도록, 정규식을 이용해서 입력할때 하이픈을 넣었다.
  • 그리고 백엔드로 데이터를 보낼땐, 하이픈을 다시 소거하였다.

셀프 칭찬 👍

1. 분위기 살리고~ 살리고~

1차 프로젝트와 달리 2차프로젝트에서는 팀의 막내였다. 사실 막내라는 위치는 팀의 분위기에 많이 좌지우지 되는 거같다. 아무래도 남자만 6명이어서 그런지 다소 칙칙한 분위기는 지울 수 없었다. 그래서 조금이라도 팀의 분위기를 살리고 싶어서 형들에게 좋은?장난을 종종 걸었다. 우리 팀원들은 다들 밤을 새면서 새벽까지 프로젝트에 임했다. 그럴때 가끔씩 비타500을 들고갔었다. 그때마다 너무 감동했다고 하는 말을 들으면, 괜히 별거 아닌데도 기분이 좋았다.

2. 컴포넌트 재사용과의 혈투

1차프로젝트에서 다소 아쉬웠던부분이 바로 컴포넌트 재사용이다. 기능은 구현되었지만, 똑같은 기능을 하는 컴포넌트가 여러개 있어 난감했었다. 그리고 리팩토링 하려고 애를 썼지만 바로 2차프로젝트 투입하여 시간도 부족하고, 고민을 해봐도 쉽게 되진 않았다. 그런부분에서 아쉬움을 느껴 2차프로젝트에서는 꼭 컴포넌트를 재사용해보자! 라는 컨셉으로 다가갔다. 그래서 더더욱 진행속도가 느렸던거 같지만, 그러면서 많은 것들을 배울 수 있어 좋았다.

3. 주도적인 팀원관리

1차프로젝트 팀장님이 주도적으로 노션과 트렐로를 생성하여 팀원들의 규칙과 근무관리를 하셨다.
그런점을 보고 나 또한 언젠가 주도적으로 팀원들을 관리하고싶다는 생각을 많이 했었다.
그래서 용기를 내어 노션을 직접 생성하여 팀원들을 초대하고 관리하였다.

노션

아쉬운 점들 😓

1. 의사소통의 아쉬움

매일 오전 10시반에 팀 미팅이 있었다. 미팅의 주제는 현재 본인의 진행에 대한 특이사항 및 앞으로의 진행계획이 주를 이루었다. 처음 설계를 잘 잡아야 나중에 일을 하기가 편한 것을 1차프로젝트 때 서로가 많이 느껴서인지 1차프로젝트보다 회의가 더 열정적이었다. 하지만, 백엔드에 대해 기초적인 지식이 부족하다는 것을 많이 느꼈다. 의사소통하면서 프론트 입장과 백엔드 입장에 달랐다. 내가 백엔드를 조금이나마 안다면 좀더 의사소통이 잘되었을텐데 아쉬움이 느꼈다. 이래서 결국 프론트로 출발해도 백엔드 영역까지 입성하는 것같다.

2. 다른 역할을 맡은 기능들을 구현해보지 못한점!

1차 프로젝트에서도 같은 주제로 글을 작성했는데, 항상 이 부분은 어떤 프로젝트를 해도 아쉬움으로 남는 부분인거 같다. 애자일 스타일의 장점이자 단점은 보다 효율적으로 프로젝트를 단기간으로 구현 할 수 있지만, 세밀하고 디테일한 부분은 아쉬움으로 남는거같다. 특히, 내가 맡은 기능이 저번에도 했던 기능이라면 배우는 단계에서는 다른 기능을 하고싶다는 욕구를 참아야한다. 그래서 프로젝트가 끝난 뒤에 틈틈히 팀원들이 작성한 코드를 보면서 공부하고 있다.


기억에 꼭 저장하고싶은 코드!

1. 바람직한 State 관리를 통한 Accordion 구현


  useEffect(() => {
    fetch("http://localhost:3000/config/passengerUserInfo.json")
      .then((res) => res.json())
      .then((res) => {
        const newData = res.useInfo.map((passenger) => {
          if (passenger.data_of_birth === "") {
            return {
              ...passenger,
              data_of_birth: passenger.data_of_birth + CURRENT_DATE,
            };
          }
          return passenger;
        });
        setPassengerInputList(newData || []);
      });
  }, []);

  const goToPayment = (e) => {
    dispatch(passengerUserInfo(passengerInputList));
    /* 함수 => 재사용가능 */
    const type = e.target.name;
    setType(type);
  };

  const handleChangePassengerInfo = (index, data) => {
    const newList = [...passengerInputList];
    newList[index] = data;
    setPassengerInputList(newList);
  };
  const goToBooking = (e) => {
    const type = e.target.name;
    setType(type);
  };

  return (
    <PassengerInfoInput>
      <div className="passengerTitle">
        <h2>탑승자 정보</h2>
        <p>신분증에 기재된 이름, 생년월일을 작성하세요.</p>
      </div>
      {passengerInputList &&
        passengerInputList.map((passenger, index) => (
          <PassengerInfoAccordion
            key={index}
            data={passenger}
            onChange={(data) => handleChangePassengerInfo(index, data)}
            active={active}
            title={passenger.title}
            setActive={setActive}
          />
        ))}

      <PassengerInfoButton>
        <Button name="first" onClick={goToBooking}>
          이전 단계
        </Button>
        <Button color={100} name="third" onClick={goToPayment}>
          다음 단계
        </Button>
      </PassengerInfoButton>
      {/* Get & Post   */}
      <PassengerInfoWarning />
    </PassengerInfoInput>
  • 최상위 컴포넌트에서 state를 관리하여, state의 흐름을 보다 직관적으로 이해 할 수 있으며, server에서 data를 받아올때, 이를 자식컴포넌트에서 반복작업을 하지않을 수있다.

  • PassengerInfo 컴포넌트 안에 있는 함수와 state는 자식에게 까지 props로 연결하여 data를 받는 형식이다. 특히, 탑승자 정보를 입력하는 모든 data를 handleChangePssengerInfo 함수의 인자로 주어, state를 변경한다.

2. 컴포넌트 재사용을 통한 Accrodion menu 구현

--PassengerInfoAccordion.js--
const clickHandler = () => {
    setActive(title);

    if (active === title) {
      setActive("");
    }
  };
<AccordionHeading title active={active} onClick={clickHandler}>
<Accordion>
      {active === title ? (
        <AccordionContent>
          <AccordionPassengerInfoWrap data={data} onChange={onChange} />
        </AccordionContent>
      ) : (
        <AccordionContent />
      )}
    </Accordion>
  • 최상위 컴포넌트에서 백엔드에서 받은 passenger.title과 active state를 props로 PassengerInfoAccordion 컴포넌트로 전달
  • PassengerInfoAccordion 컴포넌트는 title만 다르며, 안의 기능과 내용은 동일하므로 Passenger data를 받아온 것을 mapping하여 data에 갯수만큼 컴포넌트 추가
  • title과 active를 비교하여 active와 title이 동일하다면 AccordionPassengerInfoWrap컴포넌트를 실행 (AccordionPassengerInfoWrap은 Accordion의 Body역할)
  • 클릭시, active에 title을 추가하여 비교함
  • 만약 이미 같은 것이 있다면 값을 비워줌
  • 예를들어, active의 초기값이 빈값이라면, 클릭시 state에 title이 추가된다. 그리고 클릭한 title의 값이 state로 추가되어, active와 title이 같은 것만 보여지게 되는것이다.

3. moment.js로 날짜 변환하기

  • useEffect로 초기값설정
  • const BASE_YEAR = 1950
  • const THIS_YEAR = new Date().getFullYear()
  • 1950 ~ 현재 년도까지 push
  • endMonth 는 moment의 내장 함수를 통해 일수를구하여 push
  • 각각을 state로 관리
  • 이를 각각 mapping하여 UI로 나타냄
  • value로 초기값 설정 (처음 랜더링할때 최신날짜로 업데이트됨)
  • select에서 onChange 이벤트를 동작하면 처음 백엔드에서 받은 data에 data_of_birth값 설정
  • 이로써, 최종적으로 백엔드로 보냄
  • 여기서 눈여겨 볼건, 스프레드를 사용하여 객체를 인자로 넘겨주었다는 점이다.
  • 이러한 이유는 크게 2가지가 있다.

의도하지 않은 특정 객체가 변경되면 참조하고 있던 객체에서도 변경이 일어난다. 이 상태를 유지할 경우 side-effect가 발생할 확률과 프로그램의 복잡도가 높아진다.
변경이 일어난 객체의 프로퍼티만 비교함으로써 React에서 최적화가 가능하다.

4. git rebase 사용

rebase를 사용하기전에는 해당 브랜치에서 작업을 하고 push를 하기전 local master에서 remote master를 pull 작업하여 업데이트 시켜주고, 다시 해당 브랜치로 이동 후, push해주었다.

위의 사진은 부끄럽지만 아무것도 모르는 시절.. 생각없이 push가 저장하는 기능밖에 없는 줄알았던 그 시절이다.. 확실히 위의사진과 같이 git flow가 많이질수록 관리하기가 어려워진다.

자세한 사항은 따로 정리해놓았다.

rebase

Tang-Way 프로젝트 후기

쉼없이 달려온 나에게

사실 개인적인 생각이지만, 나는 친화력이 없는 편은아니다. 딱히 낯을 가리지도 않는 성격이라, 누군가에게 말을걸때, 다가갈 때, 그리 어렵지 않게 다가가는 편이다. 하지만 아무리 그런나라도 에어비앤비는 쉽지 않았다. 알게된지 얼마되지않은 남자 여럿이 2주동안 같이 생활한다는 것은 솔직히 그리 달갑지는 않았다. 전에 회사생활을 해봤을때, 단체생활은 쉽지 않다는 것을 느꼈기 때문일 수도 있다. 단체생활을 한다는 것은 개개인의 성격이 다 다르므로 그 차이를 이해하고 서로를 배려하는 마음이 생겨야 잘 지낼 수 있다고 생각한다. 하지만, 그런 이상적인 상황은 살다보면 그리 쉽지 않다는 것을 알 수있다. 그래서 처음에는 너무 친해지려고 애쓰지 않기로 했다. 그리고 내 할일을 묵묵하게 할 필요가 있다고 생각했다. 이건 학교의 MT가 아니라 협업이라는 점. 그 차이를 분명히 할 필요가 있었다. 새벽까지 서로 고민하며, 안간힘을 썼던 우리 팀원들에게 진심으로 감사의 마음을 전한다. 그리고 무엇보다 쉼없이 달린 나에게, 집에서 선릉역까지 왕복3시간이상, 누구에게 뒤쳐질까봐, 어제의 나보다 뒤쳐질까봐, 첫차타고 새벽부터 키보드를 잡고 밤늦게 가는 것을 반복하자 컨디션이 급격하게 안좋아졌던 나한테도 고생했다고 토닥여주고싶다.

profile
Front-end Developer

2개의 댓글

comment-user-thumbnail
2021년 2월 1일

그동안 노력한 것들 이상으로 좋은 결실 맺기를!
앞으로 더 큰 성장 이루실 찬영님을 진심으로 응원합니다 너무 수고많으셨어요!👏🏻👏🏻

1개의 답글