[WANTED] ASSIGNMENT_2

jun gwon·2022년 11월 1일
0

원티드 프리온보딩

목록 보기
4/14
post-custom-banner

ASSIGNMENT_2

두번째 과제의 요구사항

두번째 과제의 요구사항은 대략적으로 이러하였습니다.

  1. GitAPI를 사용하여 정보를 가져온다
  2. List를 사용하여 목록을 보여준다
  3. 정보를 가져올때 Error,Loading에 대한 처리가 이뤄져야한다.
  4. List는 무한스크롤을 사용하여 계속하여 보여준다.
  5. List의 정보를 클릭시 상세페이지로 이동한다
  6. 상세 페이지의 정보는 마크다운 문법으로 되어있는데, 이것을 CSS로 가공 하여 보여준다.
  7. 모든 페이지는 반응형이어야 한다.
  • 과제 수행 시간 토요일 오후 3시~ 월요일 오전 9시 (약 1.5일)

시작하기에 앞서

초기 셋팅

초기 셋팅은 첫번째 과제물과 유사하게 진행하였습니다.
불필요한 파일이 제거된 CRA를 생성하고,
ESLint,Prettier,husky가 설정이 된 Repo를 main이 올린 뒤, 팀원들이 모두 클론하여 각자의 브런치를 만들고 진행하였습니다.

코딩 컨벤션

추가적으로 이번 과제물에서는 자체적으로 코딩 컨벤션을 정하고 진행해보자는 의견이 있어 컨벤션을 추가해보았습니다. 지정한 컨벤션은 아래와 같습니다.

  • 컴포넌트의 ID사용은 지양한다.
  • react의 state는 여러개 사용시 최소 집합을 찾아 사용한다.
  • 컴포넌트의 이벤트에서 불필요한 익명함수를 사용하지 않는다. (예시: 함수의 인자가 event 하나인 경우)
  • 코드를 설명하는 주석은 가급적 사용하지 않는다.
  • 상수는 영문 대문자 스네이크 표기법(Snake case)를 사용한다.(예시: SYMBOLIC_CONSTANTS)
  • 반환 값이 불린인 함수는 'is'로 시작한다
  • const와 let은 사용 시점에 선언 및 할당한다.
  • 함수는 사용 전에 선언해야 하며, 함수 선언문은 변수 선언문 다음에 오도록 한다.
  • 이벤트 핸들러는 'on'으로 시작한다.
  • 한 줄짜리 블록일 경우라도 {}를 생략하지 않으며 명확히 줄 바꿈 하여 사용한다.
    • 한 줄짜리 블록일 경우 {}를 생략할 수 있지만, 이는 코드 구조를 애매하게 만든다. 당장은 두 줄을 줄일 수 있겠지만 이후 오류 발생 확률이 높아 잠재된 위험 요소가 된다.
    • 단, map과 같은 화살표 함수의 암시적 반환은 허용한다.

여기에 더해

  • return문 바로 위는 한 칸 비워 놓는다
    라는 컨벤션도 있었지만, 프리티어와 충돌 되는 부분이 있어 도중에 제외 처리되었습니다.

BestPractice를 만들기 위해선?

문제점

과제물 제출 구현 시간이 어찌보면 매우 짧은 편이였습니다.
토요일 2시 30분쯤에 시작하여, 월요일 12시이전 제출, 자는 시간을 제외하면 결과적으로 일요일 자정까지는 완성이 되어야 하는, 하루 반나절정도의 시간이 주어졌습니다.

해결책

이런 상황에서 저희 팀은 우선적으로, 각자가 기능을 구현 한 후. git Repo의 Discusions을 제출 전날 자정 9시까지,
각자의 요구사항에 맞는 기능구현 방법을 적어두고, 어느분의 방법이 좋다고 생각하는지 각자가 comments를 달아 의견을 표시하기로 하였습니다.
이러한 방법을 통해 중요 로직만을 코드리뷰 할 수 있도록 하고, BestPractice의 선정을 조금 더 효율적이게 할 수 있도록 하엿습니다.
선정은 코드리뷰를 통해 누구의 코드가 가장 이상적인지를 투표를 통해 선정하였습니다.

아쉬운 점

사실 이방법은 엄연하게는 BestPractice를 뽑는 방법이라 생각치는 않습니다. 왜냐하면 어느분의 코드에서 A라는 부분이 좋았고, 다른분 코드에서는 B라는 코드가 좋았는데. 이 두 부분을 적절히 잘 조정하여 코드를 만들어내는것이 BestPractice에 가까운 방법이라고 생각하였습니다.

하지만 각자의 코드 스타일과 구현방법이 다르며, 이 부분을 조정하여 리팩토링 하는데는 추가적인 시간이 들어갑니다. 또한 이러한 방식으로 같은 방식의 코드를 구현한다면 그것은 협업이 되고, 원티드 과제물의 기본적인 원칙인 개인 과제물과는 어울리지 않는다 생각하였습니다.

하지만 그럼에도, 좋은 점의 일부라도 가져와서 리팩토링을 적은 시간이나마 시간을 할당하여 하는것이 맞다 생각하였습니다.

진행

기본적인 진행방식은 아래와 같았습니다.

토의 진행 -> 진행 결과 Discusions을 공지 -> 기능구현 -> 토의 진행...
의 반복이였습니다.

이전 과제와는 달리 Discusions을 적극적으로 활용하였습니다.
Discusions을 토의 결과를 정리하는것과, 자신의 기능구현을 설명하는것.
이렇게 두가지 용도로 사용하였습니다.

토의 에는 는 구현 방법에 대한 논의, 코드 구조 및 기타 개발 정보공유 등이 이루어졌습니다.

토의 디스커션 예시

기능구현 설명 디스커션 예시

코딩구현

개인적인 구현 과정에서 막혔던 부분의 List는 아래와 같았습니다.

  1. Context를 사용하여 어떻게 구현할것인지
  2. 인피니티 스크롤의 구현방법은?
  3. useEffect가 두번 실행되는 이유는?
  4. 마크다운문법을 어떻게 css로 표현할까?
  5. 컴포넌트화는 어느정도로 어떻게 해야할까
  6. 반응형은 어느정도로 이루어져야되는걸까

1. Context를 사용하여 어떻게 구현할것인지

이부분은 loading과 error를 어떻게 같이 구현해야할지 고민을 좀 하다, 이전에 공부하였던 velopert 개발자님의 깃북을 참고하여 거의 대부분 따라하였습니다.

하지만, 기존 state값을 저장하는 부분은 적혀있지 않았기때문에, 약간의 코드를 변형하여 사용하였습니다.

// 리듀서 부분
if (list) {
	return {
            ...state,
            [key]: asyncState.listSuccess(state[key], action.payload),
          };
        }
// 사용되는 state
  listSuccess: (state, payload) => {
    return {
      loading: false,
      data: state.data ? state.data.concat(payload) : payload,
      error: null,
    };
  },

아쉬운 부분

  • 스프레드 연산자를 사용하였다면 조금 더 좋았을것 같습니다
  • 코드가 다른사람이 보기엔 좀 불편하지 않았을까 싶습니다.

2. 인피니티 스크롤의 구현방법은?

인피니티 스크롤의 구현방법 또한, 팀원이 공유해주신 방법을 따라 했습니다.
공유된 페이지에서는 useRef,useEffect,Interaction Observer를 사용한 구현이 적혀있었는데.

약간 미완성인채로 적혀있었습니다. useRef값을 useEffect에서 의존성 배열에 넣어줘야 하는데, 이것을 넣어주지 않아 초기에 값이 undefined가 표시되어 정상적인 실행이 되지 않았습니다.
때문에, useRef 대신 useState값을 useRef와 유사하게 사용하였습니다.

  useEffect(() => {
    const option = {
      threshold: 0,
    };
    const observer = new IntersectionObserver(onHandleObserver, option);

    if (target) {
      observer.observe(target);
    }

    return () => {
      observer && observer.disconnect();
    };
  }, [target, onHandleObserver]);

하지만 이 방법은 페이지가 리렌더링 될때마다 state 값 또한 재할당되고, 쓸데없이 리렌더링 되는 방법으로서 좋은 방법이 아니라고 생각합니다.
결과적으로, useRef의 값을 useEffect의 의존성 배열에 넣으면 해결되는 문제였습니다.

아쉬운 부분

  • useEffect의 의존성 배열을 미처 생각하지 못했습니다.

3.useEffect가 두번 실행되는 이유는?

List를 구현하며 느낀점은, 첫 렌더링시 useEffect 함수가 두번 실행된다는것입니다. 이 부분에 대해 왜 그런지 검색해보니 CRA로 생성된 리액트 프로젝트에서는
React.StrictMode가 기본적으로 적용이 되어있는데, 이것은 오류를 잘 찾아내기 위해 기본적으로 2번의 렌더링을 거치게 되고, 이로인해 useEffect가 두번 실행되었습니다.

index.js에 있는 <React.StrictMode> 태그를 제거 하였습니다.

4. 마크다운문법을 어떻게 css로 표현할까?

gitHub의 글은 대부분 마크다운으로 이루어집니다. 그래서 정보를 가져올때 컨텐츠 값이 마크다운일 경우가 많은데. 이것을 CSS로 변환을 어떻게 해야하는지에 대한 문제가 있었습니다.

찾아낸 해결법

  • marked 라는 Lib를 설치하여 마크다운 문법으로 이루어진 컨텐츠를 적용하여 html 언어로 변형합니다.
  • 이렇게 변형한 html을 react의 dangerouslySetInnerHTML의 기능을 이용하여 강제적으로 html에 innerHTML을 하게 합니다.
  • 여기서, 저는 tailwind를 사용하고 있었기 때문에 CSS가 정상적으로 표현되지 않았습니다. 때문에 추가적으로 '@tailwindcss/typography' Lib를 설치-이용하여 변형된 html을 자동으로 CSS를 꾸며주도록 하였습니다

최종적인 코드

  		마크다운 문법 변환
	  const markdown = marked(body);
  
  		// tailwind의 typo 기능을 구현하기 위하여  <article className="prose> 적용
        <article className="prose prose-stone sm:w-[578px] w-screen">
        {<div dangerouslySetInnerHTML={{ __html: markdown }}></div>}
      </article>
  

해당 로직을 통해 css처리화된 마크다운 컨텐츠

5. 컴포넌트화는 어느정도로 어떻게 해야할까

많은 분들의 과제물 결과를 보면, 컴포넌트를 작은 단위로 세분화 해서 만들었다고 느꼈습니다.

하지만 제 방식의 경우, 컴포넌트화는 정말 큰 레이아웃으로서 재활용되는 부분만 컴포넌트화를 진행하였습니다. 그 편이 개발 방식도 편하고, 컴포넌트를 너무 세분화 하면 보기 불편하지 않을까 하는 생각이였습니다.

사실 이부분은 아직도 애매모호한 부분이라고 생각되고 있습니다. 더욱 공부하고 노력해야 될 부분이라고 생각합니다.

그래도 이번 과제에서 적용된 부분은 일부있습니다.

  • 컴포넌트의 큰 부분에 대해서 styled-componet를 적용하여 조금 더 보기 편하고, 유지보수가 쉽도록 변경
  • 공통 Layout을 만들고, Outlet을 활용하여 라우터에 적용

아쉬운 부분

  • 컴포넌트화가 일부는 styled-componet를 적용시키지 않고, tailwind그대로 사용하는 등 통일화되지 않은점
  • 더 많은 부분에서 세분화가 가능했음에도 큰 레이아웃으로서만 컴포넌트화를 진행한 점

6. 반응형은 어느정도로 이루어져야되는걸까

tailwind CSS를 사용하는경우 큰 설정없이 반응형이 이루어진다고 생각하고 있었습니다. flex와 w-screen 등을 사용하면 자동적으로 반응형이 이루어지니까요.

하지만 약간의 착각이였습니다.
min-w 같은 옵션도 그냥 적당히 580px정도 주면 되겠지 하고 PC화면으로만 테스트 해봤는데, 모바일 환경에서는 깨져보이고, 실제 핸드폰으로 접속햇을경우는 더욱 안좋게 보이는 구나 라는 경험을 하였습니다.

때문에 반응형을 사용하는경우, 뷰 포트와 퍼센트 css를 사용할때 min-w 값과 기본 w값을 주는것에 대해서 신중하게 접근해야 한다는걸 알았습니다.

구현방법

  • 가능 하면 full 또는 screen값을 지정해주었습니다.
  • sm:w-[578px] 와 같이, sm(680px) 사이즈 이상일경우에만 px을 직접적으로 지정해주었습니다.

아쉬운 부분

  • Dark모드를 사용할 경우 모든 레이아웃에 다 같이 적용되어야 합니다. 일부만 적용되어 디자인이 매우 이상하게 되었습니다.
  • w 옵션과 h 옵션을 어느부분은 px단위로 주고, 어느부분은 full로 주어서 정확한 반응형이 이루어 지지 않았습니다.
  • pc같은 경우 스크롤 영역때문에 ui가 일부 먹혀들어가 좋지 않은 UX가 돼었습니다다. 이부분의 해결책을 찾지 못하고 제출하였습니다.

배포 링크

(작업 기한 1.5일)
http://wanted-pre-onboarding-june.s3-website.ap-northeast-2.amazonaws.com/

Git Repo

https://github.com/jun-05/wanted_assignment_02

BestPractice 선정 결과

Discusions을 통하여 의견을 나누고, 최종적으로 선정된 분의 과제물을 최종 과제물로 제출하였습니다. 이분의 코드에서 좋다고 생각하였던 부분은 아래와 같습니다.

  1. 폴더구조가 관심사에 맞게 잘 분리되어있다.
  2. gitMsg와 Msg의 설명이 깔끔히 잘 되어있었다.
  3. 코딩 구현 자체도 깔끔히 잘 하셨다
  4. 요구사항을 모두 충족하셨고, 반응형도 깨짐 없이 잘 되어있었다.
  5. 컨텍스트에서 스프레드 연산자를 사용하셨는데, 이부분을 저는 생각 못했던점
  6. 마찬가지로 무한스크롤을 useEffect가 아니라 함수로 만들어서 사용하신부분도 배울만한 점이였습니다.

사실 저는 막히는 부분은 검색하여 대부분 약간만 변형하여 구현하였는데, 이런식으로 변형하여 코딩을 구현하는점은 많이 배워야 한다고 생각했습니다.

선정 결과 링크(비공개)

진행 중 아쉬웠던 점

코딩 부분

  • 스스로 검색에 의존한 코딩개발을 하였던것 같다고 느껴 아쉬웠습니다.
  • 컴포넌트화를 어느정도 할지, 그리고 어느부분은 styled-componet가 진행되고, 어느 부분은 tailwind가 날것 그대로 있고, 전체적인 마무리가 아쉬웠습니다.
  • .env 파일을 .gitignore에 추가하는것을 깜빡했습니다.
  • context에서 state를 관리할때. concat대신 스프레드 연산자를 사용하는것을 생각하지 못한게 아쉬웠습니다.
  • 생각해보면 당연한 버그인데, 한참 고민했던점(무한 스크롤 부분)
  • 미처 수정하지 못했던 버그들.. (글자가 길어지면 레이아웃이 살짝 아래로 내려감, pc화면에서 width를 최소로 하면 스크롤 영역때문에 레이아웃이 살짝 짤림 등..)

팀 진행 부분

  • 아직 BestPractice를 뽑는 방식의 최적점을 찾지 못한게 아쉬웠습니다.
  • 첫 토의때는 기록보다는 구두 소통을 진행하였습니다. 때문에 기록을 제대로 남기지 못한 점이 아쉬웠습니다.
    • 때문에 토의가 진행될수록 기록을 남길 수 있도록 노력하였습니다.
  • Discusions에 기능구현에 대한 설명을 통일되지 않은 양식으로 하다보니 비교 및 보는게 불편했던것 같습니다.
  • 과제물에 제출할 readMe를 매 과제마다 작성해야 하는 점 등이 불편할것 같다 생각했습니다.
    • 때문에 Discusions을과 readMe에 대한 대략적인 템플릿을 만들어 둬야 한다 생각하였습니다.

과제물 진행 중 좋았던 점

개인 과제 기준입니다.

  • 짧은시간 몰입하여 프로덕션을 개발하는 경험을 하였습니다.
  • 진행 할 수록 진행을 어떤식으로 해야 발전할수있는지에 대한 경험을 하였습니다.
  • 코드의 품질이 조금씩 발전되고 있다는 경험을 하였습니다.
  • git commit과 코딩 컨벤션이 추가 되어, 코딩에 규칙이 생긴점이 좋았습니다.
  • 이전 과제물과 달리 tailwind-styled-componet를 사용하여 컴포넌트를 조금 더 보기 쉽게 정리하였던 점이 좋았습니다.
  • gitMsg를 어떻게 활용해야 할지 알게 되었습니다.
  • tailwind의 typograpy 기능과 marked라는 라이브러리를 새롭게 익히고 사용해본 경험을 통해, 다음에 마크다운 언어를 어떻게 다뤄야 할지 배우게 되었습니다.
  • 동료 학습을 통해, 내가 맞다고 생각한 부분이 틀릴수도 있다는것을 알게 되었습니다.
  • CI/CD를 통해 배포 자동화를 경험해 보았습니다.
post-custom-banner

0개의 댓글