(TIL 46일차) 코인원 프로젝트 2차 후기

빡기·2020년 3월 22일
1

TIL(Today I Learned)

목록 보기
42/43

프로젝트 소개

코인원 공식사이트

  • 거래액 전세계 47위 암호화폐 거래소, 국내 최초로 이더리움 클래식을 상장, 사이버배상책임 보험 계약을한 거래소 코인원 클론 프로젝트
  • 회원들의 매수 매도에 의한 정보를 통해 실시간 통신을 적용해 데이터를 계속 업데이트 해줘야 함, 그에 따른 실시간통신을 폴링방식(일정시간을 주기적으로 데이터를 받아오는 방식) 혹은 Socket 통신을 선택해야 했음
    => 결국 채팅(Websocket)을 제외한 나머지는 폴링 방식으로 하기로 함
  • 실시간 통신이라는 부담감이 있었고 백엔드는 매수, 매수도를 구현해야 하는데 큰 어려움이 있을거라고 예상 함
  • 처음에는 팀원이 6명이였지만 부득이한 사정으로 4명까지 줄어들었고 그에 따른 리스크는 나머지 팀원들이 감당해야 했기에 기능 구현하는데 큰 어려움이 있어 마지막까지 최선을 다했지만 많은 부분이 미흡 해 너무나도 아쉬운 프로젝트였다.

개발 인원

개발 인원은 프론트엔드 2명, 네이티브 1명, 백엔드 1명


프로젝트 데모 영상

적용 기술

  • Front-End : React, redux, hooks, react native,sass, highcharts, Websocket, Styled components
  • Back-End : Python, Django web framework, Beautifulsoup, Selenium, Bcrypt, My SQL
  • Common : email Link Authorization, AWS(EC2,RDS), RESTful API

프로젝트에서 내가 맡은 역할

  • 코인원은 페이지 수가 그렇게 많지 않은 편이지만 세부적인 기능들이 많다는 것을 알게 됐다.
  • 나는 로그인, 회원가입 페이지 및 코인들의 거래상황을 볼 수 있는 거래소 페이지를 맡게 됐다.
  • 또한, 채팅은 실시간을 구현하기 위해 Websocket을 적용해야 했다

담당역할

  • CRA 초기 셋팅설정(jsconfig.json, 폰트설정, reset.css, 디렉터리 구조 설정, sass 설정, Router 설정)
  • 로그인 및 회원가입 정규식 적용
  • Websocket(Express)를 이용한 실시간 채팅 구현
  • 매수,매도 및 거래에 관한 기본 기능 구현
  • 코인 별 데이터 가져오기

잘한점

  • 원래는 채팅도 백엔드 쪽에서 소켓을 구현해서 적용하려고 했지만 백엔드 쪽에서 적용하기 어려워 내가 프론트쪽에서 Express를 이용하여 짧은 시간 안에 실시간 채팅을 구현하여 성취감이 너무 컸다
  • hooks, redux, Styled components를 학습하면서 프로젝트를 같이 개발하는 과정에서 짧은 시간이였지만 빨리 배워 적용할 수 있어서 너무 행복했다
  • 회원가입 시 정규식이 5개 정도 사용 됐는데 정규식을 글로벌 파일로 따로 빼서 다 같이 사용할 수 있게 만든 점에서 별거 아니지만 나름 좋았다

아쉬운 점

  • 제일 아쉬운점은 프로젝트 시작하자마자 부득이하게 프론트엔드에서 1명이 나가고, 2주차에서는 백엔드분이 1명 나가셔서 나머지 팀원들이 짧은 시간안에 많은 부분을 도맡아 해야하기에 완성도가 많이 떨어졌던 것은 사실이였다.
  • 새로운 개념인 hooks, redux, Styled components를 적용하면서 개발했기에 그만큼 성장은 했지만 개발기간 안에서는 속도가 더뎠던 것은 사실이다.
  • 폴링 방식 및 그래프 데이터, 코인 데이터에 대한 여러 요청이 한 꺼번에 있어 사이트가 매우 느려진다는 단점이 발생

해결 및 개선 방법

  • 부득이한 사정으로 동료 개발자가 이탈 시 나름대로의 대책이 필요하다는 것을 느꼈다.
  • 이러한 상황 속에서도 기능 구현에 있어서 오류 같은 것들을 확실하게 되집고 넘어가는 것이 필요하다는 것을 느꼈다.
  • 백엔드 엔드포인트가 나오기전까지 기다리는 것보다 나름대로의 방법(mock data)를 사용해 속도에 제한받지 않고 개발할 수 있도록 해야겠다
  • 소켓 통신 및 코드 구조를 좀 더 공부 해 데이터가 변경 사항이 있을 때만 fetch 요청을 하여 서버 부하를 줄이고 느려지는 현상을 방지하도록 해야 겠다.

프로젝트 하면서 기록하고 싶은 코드

1. 회원가입 및 로그인 정규식

  • 사실 구글링하면 다 나오는 정규식이고 별거 아닌 것 처럼 보이지만 나름대로 정규식에 대해 공부할 필요성을 느끼게 된 계기이며, 나중에는 직접 정규식을 구현해 볼 생각이다.
  • 이 정규식을 글로벌 변수화 해서 사용하면 팀원들도 개발할 때 편리할 것이다.
 // 이메일 정규식
// 이메일 정규식
export const check_email = /([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/;
// 대문자 정규식
export const upper_case = /[A-Z]/;
// 소문자 정규식
export const lower_case = /[a-z]/;
// 숫자 정규식
export const number_case = /\d/;

// 3자리
export const numberFormat = x => {
  x = x.replace(/^[0]|[^0-9,]/g, ""); // 입력값이 숫자 및 0으로 시작하는 것이 아니면 공백
  x = x.replace(/,/g, ""); // ,값 공백처리
  return x.replace(/\B(?=(\d{3})+(?!\d))/g, ","); // 정규식을 이용해서 3자리 마다 , 추가
};

export const removeComma = str => {
  return parseInt(str.replace(/,/g, ""));
};

2. useEffect 안에서 useState 사용 시 문제점

처음에 클래스형의 ComponentDidmount 처럼 useEffect를 사용하기 위해 두 번째 매개변수로 빈 배열을 주면 된다는 것을 알았지만 Eslint 자동 저장 때문에 배열안에 자동으로 변수를 기입하여 변수를 의존하게 만들었다.

const [msg, setMsg] = useState("");
const [arr, setArr] = useState([]);

useEffect(() => {
    socket.on("update message", obj => {
      setArr(res);
      // res값을 받아서 setRes로 변경하는 의도지만 아래 배열안에 자꾸 res가 자동으로 기입
    });
    bottom.current.scrollTo({ top: bottom.current.scrollHeight });
  }, [res]);

2가지 해결 방법

1. 이펙트가 자급자족 하도록 만들기

const [msg, setMsg] = useState("");
const [arr, setRes] = useState([]);

useEffect(() => {
    socket.on("update message", obj => {
      setArr(prev => [...prev, obj]);
      // res값을 받아서 setRes로 변경하는 의도지만 아래 배열안에 자꾸 res가 자동으로 기입
    });
    bottom.current.scrollTo({ top: bottom.current.scrollHeight });
  }, [res]);

  • 이전 상태를 기준으로 상태 값을 업데이트 하고 싶을 때는, setState 에 함수 형태의 업데이터를 사용하면 된다는 것을 알았다!!!
  • 의존성을 제거하지 않고도 실제로 문제를 해결!!!(편법이 아닌 올바른 방법)
  • 이펙트는 더 이상 랜더링 스코프에서 count 값을 읽어 들이지 않습니다.
  • res 는 우리가 setArr(res) 이라고 썼기 때문에 이펙트 안에서 필요한 의존성이었지만, 진짜로 우리는 res를 arr안에 불변성을 유지한 상태로 추가하고 돌려주는 것을 원한 것 뿐이다.
    => 한 마디로 res를 [] 안에 추가하여 의존성을 부여하고 싶지 않았을 뿐이다

    이러한 경우 함수 형태의 업데이터를 사용하면 된다 (최신 방법)prev => [...prev, obj]

2. Eslint 자동 저장 강제로 해제

제목없음 2
제목 없음

  • 위의 사진 처럼 강제로 자동 입력 되는 부분을 비워 놓으면 아이콘이 뜨는데 누르고 Disable을 적용 시켜주면 빈배열인 상태로 적용 할 수 있다.

3. redux 적용

  • 이번 프로젝트에서 처음으로 사용해본 redux 구조를 간단하게 설명하면서 상기 시켜보도록 하려고 합니다.
  • redux는 기본적으로 전역적으로 state를 관리하여 모든 컴포넌트에서 손쉽게 사용 및 변경할 수 있는 라이브러리 입니다.

1. redux 폴더 구조

스크린샷 2020-03-22 오후 11 55 11
  • src 폴더 아래 본인이 사용하려고 하는 Redux 폴더를 생성한다.
  • 액션 생성함수는 Actions 폴더안에 index.js 안에서 모두 선언하여 관리한다.
  • reducer는 reducer 폴더를 따로 생성하여 관리한다(나중에 rootReducer로 묶어줌)

2. 액션 생성함수 정의

스크린샷 2020-03-22 오후 11 55 32
  • 액션 생성함수는 store에 전역으로 관리되고 있는 state 값을 변경 시키기 위해 reducer가 필요한데 이 reducer의 액션 타입(state를 변경하는 타입)을 지정하고 해당 액션을 정의 해준다.

3. reducer 정의

스크린샷 2020-03-22 오후 11 55 45
  • reducer는 state 값을 변경하기 위해 사용 되는데 액션 타입에 따른 액션생성함수를 이용해 state 값을 변경 시킨다.

4. rootReducer로 recuder 묶기

스크린샷 2020-03-22 오후 11 55 37
  • 위에서 정의한 reducer들은 같은 폴더안에 rootReducer를 생성하여 모두 감싸 준다.

5. 프로젝트에 redux 적용하기

스크린샷 2020-03-22 오후 11 54 40
  • 위에서 감싸는 rootReducer를 포함한 createStorem, Provider를 사용하여 위와 같이 Provider로 프로젝트를 감싸주고 Provider에 변수로 선언한 리듀서를 적용 시켜주면 완성이다.

4. 컴포넌트 변수화

 const obj = {
      1: <StepOne goNext={this.goNext} />,
      2: <StepTwo goNext={this.goNext} />,
      3: <StepThree goNext={this.goNext} handleFetch={this.handleFetch} />,
      4: <Finish />
    };
  • 이렇게 하면 state, props로 컴포넌트를 렌더링 하는데 편리하다

마지막으로

  • 새로운 개념을 짧은 시간안에 배우면서 프로젝트도 진행 했기에 많이 버겁긴 했지만 그만큼 각성해서 열심히 배운기간 인거 같다.
  • 2차 프로젝트 보다 완성도가 떨어지지만 Websocket과 다양한 개념(hooks, redux, Styled components)를 배웠기에 값진 경험이였다.
profile
Front End. Dev

0개의 댓글