코드와이드-SPA

aydennote·2023년 9월 21일
0

Project

목록 보기
8/8

1. boder, outline, box-shadow

  1. 문제 :
  • 아이템 클릭 시 border가 추가되어 요소들이 움직이는 상황 발생.

해결 :

  • boder와 outline 에는 아래와 같은 차이가 있음.
  • border 같은 경우, 공간을 차지하며 radius 등으로 스타일링이 가능함.
  • outline 의 경우, 공간을 차지하지 않으며 스타일링 추가 불가능함.
  • 아래 블로그를 참고하여 해결.
  • 출처 : 블로그

  1. 문제 :
  • 위 문제와 동일한 문제가 발생
  • outline으로 요소들이 움직이는 현상은 해결을 했지만 outline으로 할 경우, 부모 요소 밖으로 선들이 잘리는 문제 발생.

해결 :

  • box-shadowinset을 활용하여 선들이 잘리는 문제와 요소가 움직이는 문제 해결.
  • inset은 내부 그림자 효과로 요소의 크기 변화 없이 테두리와 유사한 효과가 가능함.
    box-shadow: 'inset 0 0 0 1px #c3bcb7';

2. svg 이미지 색상 변경 최적화

문제 :

  • NavBar 각 Item 클릭 시 svg 이미지 색상 변경이 필요.
  • 클릭 전/후로 색상이 달라져 각 색상별로 이미지를 다운로드하면 각 아이템 별 이미지는 2개씩 필요하게 되며 전체로 보면 총 10개의 이미지를 로딩하는 불합리적인 부분이 있음.

해결 :

  • 하나의 svg 이미지 코드 자체를 하나의 컴포넌트로 만들어 컨트롤하여 해결.
// isSelected 라는 상태 변수에 클릭 여부를 저장
// isSelected 값에 따라 색상 변경
const NavCustomerSvg = ({ isSelected }) => {
  return (
    <svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
      <path
        fill-rule="evenodd"
        clip-rule="evenodd"
        d= ... // 생략
        fill={isSelected ? 'black' : '#353535'}
      />
    </svg>
  );
};

export default NavCustomerSvg;

3. React Query

React Query를 서버 전역 상태 관리 목적으로 도입했다. 처음에는 나와 동료 모두 해당 기술에 대한 지식이 부족하여 함께 공부하고 적용했다. 이러한 과정에서 초기에는 업무 효율이 떨어질 수 있었지만, 학습을 통해 코드의 통일성을 유지하고 상대적인 코드 이해도를 높일 수 있었다.

가독성과 재사용성을 고려하여 작성했고, 동료에게 해당 코드를 설명했다. 동료는 내 코드가 좋은 레퍼런스가 될 수 있을 것이라는 긍정적인 피드백을 주었고, 이를 통해 리액트 쿼리를 통한 전역 상태 관리에 대한 적극적인 도입이 팀 내에서 긍정적인 결과를 가져올 것으로 기대된다.

4. DOM 경고

React does not recognize the `fontColor` prop on a DOM element. 
If you intentionally want it to appear in the DOM as a custom attribute, 
spell it as lowercase `fontcolor` instead. 
If you accidentally passed it from a parent component,
remove it from the DOM element

문제 :

  • React prop 작성 중 위와 같은 에러가 발생함.

해결 :

  • React에서 fontColor 라는 속성을 찾지 못 했다고 발생하는 에러로 확인.
  • fontColor 는 컴포넌트에 전달하는 prop 중 하나로 onChnage 처럼 기본적으로 제공하는 DOM 속성 중 하나로 착각하여 발생한 에러로 추측됨.
  • 착각한 이유는 네이밍룰에 맞게 CamelCase로 작성했기 때문인 것 같음.

5. 예약 프로세스 재설계

예약 페이지 한 페이지에서 인원 메뉴 날짜 담당자 선택을 하도록 처음에 구현되어 있었다.
이렇게 되면 한 페이지에서 발생하는 상호작용(사용자 <-> 프론트 <-> 서버)이 많고 내용이 많아 모바일에서 사용할 때, 스크롤 액션 횟수가 증가되는 ux 저하 요인이라고 판단되어 한 페이지를 스텝별로 분리하여 구현하도록 디자인 설계를 다시 진행했다.

  • 예약하기 한 페이지에 많은 인터랙션이 집중되어 있어 프로젝트 설계에 대한 의문점 제시함.
  • 날짜, 시간, 매니저, 메뉴 등 많은 데이터들이 서로 연관되어 있고 사용자 클릭 시 데이터가 변동되기 때문에 한 페이지에 몰려있는 상황은 사용자 경험을 헤칠 우려가 있음.
  • 스텝별로 예약을 진행하는 것이 좋아보임.
  1. 날짜, 시간
  2. 코스 선택 또는 매니저 선택
  • 나의 의견이 합리적이다라는 판단으로 프로젝트 설계 변경.

6. 아이템 삭제 사용자 경험

  • 웹앱 페이지인 상황에서 위와 같이 삭제 버튼이 상단 구석에 작게 있을 때, 사용자 경험을 고려하여 아래 두 가지 방식을 고려했음.
  1. 사용자가 'X' 버튼을 터치해서 삭제
  2. 삭제할 하나의 아이템 요소를 터치해서 삭제
  • 1로 구현했을 때, 페이지가 웹앱인 점과 기본적인 요소 사이즈를 고려했을 때 'x' 버튼이 작아 사용자가 한 번에 터치하기 힘들 수 있다라는 의견
  • 2로 구현했을 때, 반대로 사용자가 실수로 요소를 터치해 해당 요소가 삭제될 수도 있다라는 의견
  • 내 의견은 2 였고 결국 위와 같은 이유로 1방식으로 개발이 진행되었음.
  • 다시 생각해 보면 2 방식으로 구현했을 때, 사용자 실수로 요소가 사라지면 다시 추가하는 프로세스를 사용자가 진행해야되는 번거로움이 있는데 1번 방식으로 구현하게 되어 사용자가 'x'를 한 번에 터치 못 하더라도 사용자가 저 주변을 몇 번 터치하면 쉽게 될 것 같기도 함.
  • 하지만, 둘 다 사용자 경험으로 봤을 때 괜찮은 방법은 아닌 듯 하여 다음 프로젝트에서 참고할 수 있도록좀 더 고민하는 게 좋겠음.

7. 인앱 브라우저 구글 로그인

구글 간편 로그인을 카카오톡 인앱 브라우저를 통해 진행 중
google OAuth 403: disallowed_useragen 오류가 발생했다. PC, 다른 브라우저에서는 동작되지만 인앱 브라우저에서는 구글과 카카오톡 정책에 위반되어 동작되지 않는 오류이다. 인터넷에 검색해보니 꽤 많은 사람들이 겪은 오류이고 또 많은 사람들이 기본 브라우저 사용을 사용자에게 안내하는 방법으로 진행한 것으로 보인다. 리액트 네이트브에서는 userAgent 설정을 변경하는 방법으로 해결할 수 있는 것 같다.

8. 이미지 최적화

서버에 저장하는 이미지 용량이 커 서버에 정한 제한 용량을 벗어난 이슈가 있었다. 해당 문제로 API 호출이 거부되는 문제가 발생했는데 서버 용량에서 많이 차지는 부분인 이미지를 최적화하는 것으로 서버 용량을 줄이기로 했다. browser-image-compression 라이브러리를 사용해 서버로 올리는 이미지 사이즈를 약 14.4%를 줄였고 서버 부하가 줄었다.

9. 불필요한 API 호출

문제 :

  • 예약 가능 시간을 조회 할 때, 날짜 초기값이 매달 1일로 정해져있어 매장 또는 매니저 휴무가 1일이라면 예약 가능 시간 조회 API 호출시 오류 발생.

해결 :

  • 에러 발생 이후 프론트에서 매장, 매니저 휴무를 계산해 가능한 제일 빠른 날짜로 초기화하게 되는데 처음부터 휴무가 아닐 때만 API 호출하도록 로직을 개선해 불필요한 API 호출 감소.

10. 모노레포

도입 이유 :

  • useradmin으로 도메인을 분리하여 관심사 분리 필요성 향상.

도입 효과 :

  • 빌드, 배포 시간 단축. (12초에서 각 도메인 별 7초)
  • 도메인 별 코드 구조 파악 용이.(컴포넌트 관리 용이)
  • 기존 user <-> admin 간 토큰 관련 에러 해결.(로컬스토리지의 경우, 도메인 별 토큰을 관리할 수 있음.)

11. 컴포넌트 설계

atomic design pattern으로 컴포넌트를 설계하고 있는데, 현재까지 특정 페이지에서만 사용하는 부분을 컴포넌트화 시켜야 되는지 고민이있었다. 컴포넌트화 시키지 않으면 해당 페이지에 코드가 많아져 가독성과 유지보수성이 떨어지고 컴포넌트화 시키면 재사용되지 않을 부분을 컴포넌트화 시키는 의미가 있을까? 생각했다.

결국, 컴포넌트화 시키는 가장 큰 이유는 반복적인 코드를 컴포넌트화 시켜 코드 중복을 줄이는 것에 있지만, 가독성과 유지보수성을 위한 것도 있기 때문에 당장 재사용성이 낮은 코드를 컴포넌트로 분리하는 작업이 의미없는 작업은 아니며 추후 프로젝트 확장성을 고려했을 때 컴포넌트화 시키는 것이 좋을 것 같다. 라는 결론을 내렸다.

12. 예약 시간 버튼 사용자 경험 향상

우리 예약 시스템 중에 날짜와 시간 선택은 한 페이지에 이루어지며,
fullCalendar 달력 날짜를 클릭하면 아래 예약이 가능한 시간 버튼들이 줄지어 나오는 형태이다.

여기서 날짜를 클릭할 때마다 아래 시간들에 대한 데이터를 API로부터 받아오기 전까지 데이터가 없는 것으로 판단해 아무것도 안 보이다가 데이터가 받아 왔을 때, 시간 버튼들이 나오면서 사용자로 하여금 화면이 깜빡이는 듯한 느낌을 받게 되어있었다.

내 해결 방법은 새로운 데이터를 받아오긴 전까지는(로딩 중일 때는) 이전 데이터를 보여주는 방식이다. 즉, 사용자는 데이터가 없을 때를 볼 수 없는 방식으로 해결했다.

 // 데이터가 로드되면 시간 옵션을 업데이트
  useEffect(() => {
    if (!isLoading && timeData) {
      setTimeOptions(timeData.data);
    }
  }, [timeData, isLoading]);

위 코드는 해결에 필요한 핵심 코드이다.
실제 timeOptions 상태 변수에는 가능한 시간의 배열 정보가 들어가며, timeData는 Query 데이터로 API로부터 받은 가능한 시간 배열의 정보이다. 그리고, 실제로는 timeOptions 변수에 있는 데이터를 기반으로 화면에 그려준다.
이전에는 timeData는 Query 데이터로 API로부터 받은 가능한 시간 배열의 정보를 그대로 화면에 그려주었다.
처음에는 리액트 쿼리 캐시, React.memo, useCallback를 이용해서 해결해보려고 했으나, 한 번 해당 날짜에 대한 시간이 받아와지면 깜빡임이 해결되었지만 새로운 날짜에 대해서는 여전히 깜빡이는 문제가 있었다.
개선 전
개선 후

13. 리팩토링 및 개선사항

13-1 컴포넌트 분리

기존에 체계가 없던 컴포넌트 디자인 패턴에서 atomic 디자인 패턴으로 컴포넌트 설계 진행.
변경 전 31,714 코드 라인에서 변경 후 27,683 코드 라인.(약 12.71% 코드 라인 감소)

13-2 스토리북 (개선 필요)

컴포넌트가 만들어져 있었음에도 있는 줄 모르고 사용하지 못 하는 경우도 있었고 해당 컴포넌트가 어느 디렉토리에 있는지 모르는 경우가 많아 스토리북을 통해 컴포넌트를 문서화시켜 컴포넌트 활용을 극대화하고 협업 효율 증대를 위해 사용이 필요할 것 같다.

13-3 알림창 (개선 필요)

프로젝트의 고도화를 위해 어떤 액션 이후 성공 실패 알림창이 출력되는 기능을 구현하려고 한다. 사실, alert로 구현한 부분이 있지만 디자인적으로 별로라는 느낌을 받기도 했으며, 액션 성공에 대한 안내 문구를 출력하지 않고 이전 페이지로 페이지가 이동되는 경우도 많아 알림창을 띄워주기 얘매한 부분이 있었다.

이러한 부분을 React-Toastify로 구현하면 괜찮을 것 같다.
만약, React-Toastify가 별로라면 직접 만드는 것도 괜찮을 것 같다. 아이디어는 React-Toastify와 비슷하게 하면 될 것 같다. 전역에 모달과 같은 컴포넌트를 선언하고 props 같은걸로 time과 text를 받아 time 있다면 해당 컴포넌트를 time 동안 띄워주고 사라지게 하면된다. 이때, 전역으로 선언했기 때문에 페이지 이동과 관계 없이 해당 안내 문구는 띄워지게 된다.

13-4 스켈레톤 디자인

스켈레톤 디자인 적용에 대해서는 프로젝트 중반부쯤에 내가 이야기를 했었다. 그러나, 코드량 증가와 이에따른 코드 가독성이 떨어질 수 있다는 부분에서 내가 이야기를 꺼냈지만 다시 주워 담았다. 이후 프로젝트 후반부 컴포넌트 분리 작업과 모노레포를 적용하면서 전체적인 가독성 향상과 코드량 감소로 인해 모노레포를 적용해도 크게 문제되지 않겠다라는 판단이 있었고, 실제 프로젝트 실행 환경은 해외이기 때문에 네트워크 속도를 생각하면 데이터를 받아 화면에 그려주는 동안 스켈레톤 디자인을 적용하는 것은 사용자 경험에 있어 크게 기여할 수 있는 부분이라 생각했기 때문에 번복에 번복에 번복을 하여 적용하게 되었다.

13-5 타입스크립트 (개선 필요)

최초 기획 단계에서 타입스크립트와 자바스크립트 기술 스택에 대한 논의가 있었을 때, 나에게 결정권이 주어졌었다. 타입스크립트 사용하고 싶었지만, 프로젝트 마감 기한과 타입스크립트에 대한 숙련도, 프로젝트 규모를 고려했을 때, 타입스크립트는 그다지 매력적이지 못한 선택지였다.
하지만, 글 작성 시점에서는 이미 프로젝트 기획이 많이 바뀌어 규모가 커졌고 그에 따른 마감 기한 까지 달라졌다. 이제 타입스크립트가 더 매력적인 선택지로 변했고 여기저기서 발생하는 에러들로 필요성을 많이 느끼고 있고 결국 에러를 해결하는 데 시간이 더 오래걸리는 문제들로 타입스크립트로 가지 않으면 안 될 정도이다.

profile
기록하는 개발자 Ayden 입니다.

0개의 댓글