본문 바로가기

archive/Project

[MainProject] day-15 extra (5/20-5/21)

주말 연장근무

1. 자잘한 버그들 fix 및 게임등록 UI 수정,유효성 검사 부분 수정

2. 검색 페이지(UI, 기능) ➡️

3. 메세지 페이지(UI, 기능) ➡️

4. 지금까지의 작성한 코드의 지속적인 개선 ♻️

 

이제부터 일요일 자정, 아마도 월요일 오후 중까지는 지금까지 개발사항에서 문제가 생기는 부분을 지속적으로 개선해나가면서 검색과 메세지 기능을 완성하는 것에 집중할 것이다. 검색이라는 기능을 완성한다는 말은 감히 할 수 없을 것 같고 목표한 부분을 완성하는 것에 집중하겠다. 메인프로젝트가 끝나갈수록 나의 능력이 어디까지인지 윤곽이 잡히는 것 같아서 개인적으로 뿌듯한 마음이든다. 나는 확실히 느리다. 그래서 더 끈기를 가지고 덤벼들어야한다. 유연하지 못하다. 유연하게 사고할 수 있도록 전환점을 억지로 만들어야한다. 여전히 포기가 빠르다. 끝까지 붙들고 완성하려는 내 모습을 보면 포기가 빠르다는 말은 잘 안 와닿을 수 있겠으나 꼼꼼하게 한 가지 방법을 끝까지 시도해보지 않고 다른 방법으로 넘어가려다보니 여러 길을 돌아서 기능을 구현하는 경우가 아직도 많고 확실하게 이해하지 못하는 부분들이 생긴다. 물론 100%이해를 지금까지 추구해 본 적도 없고 앞으로도 추구하지 않을 것이지만 중요한 부분들은 적어도 남에게 설명할 수 있을 정도로 이해하고 싶다. 그래도 점점 성장해가고 있는 것 같다는 느낌을 많이 받는다. 그러니까 이번 주말에도 한 가지 방법이라도 더 시도해보고 구상을 하나라도 더 해보고 코드를 짜보는 유익한 시간이 되길.

 

토요일은 개인적인 사정 + 일일 냥이 돌봄활동으로 인해 작업을 많이 못해서 대부분 일요일 작업임을(TMI) 밝힙니다.

 

#1 버그 픽스 및 게임등록페이지 UI 1차 수정, 부가적인 기능 수정

 

1) 버그 픽스 내용

(1) Oauth 관련

메인프로젝트 초기에 Oauth를 만들어놓고 다른 작업들만 하다가 다시 Oauth 로그인이 안된다는 말을 들어서 청천벽력같은 기분이 들었다. 황급하게 수정하였는데 일단 프론트의 문제는 아니었고, 로그인기능은 문제없이 이전처럼 잘 되었으나 그 사이에 개발이 된 내용 중 로그인이 되면 유저정보를 받아오는 로직이 추가되어야해서 해당부분을 추가했는데 useEffect를 사용해서 data를 받아와야하는데 로컬에 토큰이 잘 저장이되었다가 홈 경로로 redirect되는 과정에서 토큰이 잘 있던 것을 날려먹어버리도록 코드가 작동해서 말썽인 상황이다.

 

뤼튼이가 비동기적인 코드 동작으로인해 useEffect가 진행되면서 동시에 다른 코드들이 동작해서 그렇다고 하는데 어떤 상황인지는 이해가 된다. 

 

※주의※ 굉장히 주관적이고 AI 답변을 비판적관점이 부족한 상태에서 적은 부분입니다.

뤼튼은 useEffect를 두 개 사용해서 첫 번째 useEffect는 렌더링되자마자 작동하도록 만들고, 두 번째 useEffect는 첫 번째 useEffect에서 accessToken이라는 상태가 변할 경우에 그것을 감지하여 작동되도록 만들라고 하였다. 그래서, 순서대로 작동하는 것인가라는 어리석은 질문에 의존성 배열을 잘 설정해서 동시에 실행될 수도 있는 코드들을 논리구조로 동기적으로 작동하도록 만들라는 의도였음을 파악했다.

 

해당 의도가 반영되도록 코드를 수정하여 테스트해보자.

일단, 해결이 되었고... 보다 근본적인 문제가 있었는데 내가 login에서 axios 응답을 가지고 하는 과정을 별 생각없이 가져다써서 사실 계속 바꾸던 부분이 첫번째 useEffect안에서 null인지 검사하고 그에 따라 다른 코드가 작동되도록 짜는 부분이었는데, 이 부분의 논리는 문제가 없다고 생각했지만 자꾸 멀쩡히 존재하던 access토큰이 사라지는 일을 겪다보니 살짝 자신이 없었는데 논리에는 문제가 없는 것이 맞았고, 사실 진짜 문제는 header에 access 토큰이 담겨오지않는데 해당 응답에서 accessToken을 뽑아서 다시 로컬에 덧씌워버렸으니 멀쩡히 있던 토큰이 날아가고 undefined씨가 그 자리를 대신 차지하는 것이었다. 따라서, 해당로직을 아예 없애고 accessToken은 한 번 받으면 그냥 유지하도록 현재 구현해서 작동이 된다. 코드 변화는 다음과 같다.

 

수정 전

import Loading from '../common/Loading';
import { useNavigate } from 'react-router-dom';

const GoogleLogIn = () => {
  const navigator = useNavigate();

  const url = new URL(window.location.href);
  const accessToken = url.searchParams.get('token');
  if (accessToken) {
    localStorage.setItem('access_token', accessToken);
    navigator('/');
  } else {
    alert('로그인에 실패하였습니다.');
    console.log('Access token이 없습니다.');
    navigator('/signup');
  }

  return (
    <>
      <Loading />
    </>
  );
};

export default GoogleLogIn;

 

수정 후

import { useEffect, useState } from 'react';
import Loading from '../common/Loading';
import { useNavigate } from 'react-router-dom';
import axios from 'axios';

import { useDispatch } from 'react-redux';
import { setUser } from '../../slice/userSlice';

const GoogleLogIn = () => {
  const navigator = useNavigate();

  const dispatch = useDispatch();

  const [accessToken, setAccessToken] = useState('');

  useEffect(() => {
    const url = new URL(window.location.href);
    if (!localStorage.getItem('accessToken')) {
      const param = url.searchParams.get('token');
      if (param) setAccessToken(param);
    } else setAccessToken(localStorage.getItem('accessToken')!);
  }, []);

  useEffect(() => {
    if (!accessToken) {
      const actoken = localStorage.getItem('access_token');
      if (actoken) setAccessToken(actoken);
    }
    if (accessToken) {
      localStorage.setItem('access_token', `Bearer ${accessToken}`);
      const headers = {
        Authorization: `Bearer ${accessToken}`
      };
      try {
        axios(`${process.env.REACT_APP_API_URL}/api/members/profile`, {
          headers
        }).then((response) => {
          const userdata = response.data;
          dispatch(setUser({ ...userdata }));
          localStorage.setItem('user', JSON.stringify(userdata));
          alert('you successfully logged in!');
          navigator('/');
        });
      } catch (error) {
        console.log(error);
        alert('you failed to login!');
        navigator('/error');
      }
    }
  }, [accessToken]);

  return (
    <>
      <Loading />
    </>
  );
};

export default GoogleLogIn;

한 줌의 코드였던 것이 다소 복잡하게 바뀌었고 if문으로 조건을 나눈것도 정말 많아서 가독성이 떨어지는 단점이 있다. 다만, 지금 너무 잘 작동이 된다. 여기서 refresh 토큰을 사용하려면 조금 더 복잡해지는데 api를 하나 새로 만들든지 profile 부분에서 쓰지도 않는 토큰들이 오고가는 것을 구현해야한다. 쓰지도 않는 이라고 표현한 것은 관심사분리 측면에서 profile api는 프로필정보만 보내면 되는데 구글로그인도 이 api를 공유하게되면서 괜히 토큰도 보내야하게 되기 때문에 부적절하다고 생각되어서이다. 그래서 해당 부분은 백엔드와 상의해보고 더 수정할 것이고 일단 회원가입/로그인이 잘 될 수 있도록 다시 바꿔놓아서 맘이 편해졌다.

 

(2) Loading 중 버그: google login을 손보는 과정에서 발견한 것인데 Loading 컴포넌트가 화면에 나올 때, 왜 전체화면이 안가려지도록 바뀌었는지 궁금하다. CSS에 손을대서 그런 것일까? 이건 만든 팀원에게 다시 물어봐서 수정을 하도록 해야겠다.

 

(3)

 

 

#2 검색기능

1) UI 1차 구상 및 구현

팀원들의 어떤 컴포넌트들을 가져와서 재사용을 잘 할지 살펴보았다. 먼저 유저부분은 마이페이지 유저 정보 카드? 를 가져다가 쓰면 될 것이고, 게임 검색결과도 게임채널 등을 참고하여 대표사진 썸네일을 이용하여 상대방과 붙으면 된다.  그리고 게시글 역시 마찬가지다. 팀원들이 잘 만들어놓아서 대부분의 코드를 이해만 하면 재사용이 가능할 것 같다고 생각이들었다.

 

Search
 ┣ SearchContents.tsx
 ┣ SearchGame.tsx
 ┗ SearchUser.tsx

이런 구조로 만들고, SearchGame부터 하나씩 만들어서 일단은 검색결과에 세 가지를 다 보여주도록 하고, 추후에 각각 검색힌트 선택에 따라 보이고 안보이고 나눠서 렌더링하는 로직을 짜면 될 것 같다.

 

 

 

(1) SearchGame

재사용을하면 뚝딱 만들 것 같았는데 상황에 따라 보여주는 화면이 복잡하게 구성되어서 처음에 코드를 잘 짜야할 것 같았다. 그래서 또 다시 나름 자신있는 figma을 꺼냈는데.. ㅋㅋㅋㅋ

 

Figma까지 가지않고 우리에게 꽤 많은 참고가되는 reference 사이트인 gamejolt를 참고하였다.

 지금 이 화면과 동일하게 위에는 All, user, game, contents 이렇게 구분해놓고 탭을 선택하거나 미리보기에서 View All을 누를 경우 탭을 이동하도록 하는 방식을 사용하고 싶다. 그렇다면 구조를 어떻게 짜야할까?

 

처음에 Search 페이지에 진입하면 아무런 힌트도 입력하지 않았다는 가정하에 SearchUser, Search Game, SearchContents가 차례로 미리보기가 다 보여야한다. (Search Contents는 혼자만 아래로 계속 내려도 나오도록 무한 스크롤을 적용할까 고민중이다.)

따라서 탭 전환 기능은 가장 상단인 Search Page에 있어야하고 각각의 탭인 Search User,Game,Contents는 자신이 선택된지 알 수 있도록 상태값을 넘겨받아 표시되는 내용이 다르도록 해야한다.(미리보기 5개만 보여줄 지, 1페이지 전부를 보여줄지)

 

삼항연산자가 두 번 들어가서 중복 서술을 피하고자 다음과 같이 구분해 보았다.

선택된 탭 인덱스가 0이다(all tap 선택) : 2이다(game tap 선택)
그리고 보여줄 검색결과가 1개 이상이다 : 아니다

선택된 탭을 기준으로 먼저 구분하려고했는데 생각해보니 그것보다도 보여줄 검색결과가 1개 이상있는지 없는지를 삼항연산자를 바깥에서 적용하면 더 구분하기 쉽다. 어찌됐든 보여줄 검색결과가 없는 경우에는 '검색결과가 없다'고 보여주는 것이 먼저다. 

 

검색결과 > 0 ? (선택된 탭 0 ? 미리보기 : 전체) : 검색결과 없음

 

이렇게 정리해 볼 수 있겠다.

 

attrs 관련 부정확한 내용

이 와중에 attrs를 적용해보고 싶어서 뤼튼한테 공식문서를 학습했는데 아직 쓰는게 어려워서 방법을 알려달라고 여러번 꼬리질문을 했는데 대답을 잘 해주었다. 다만, 여기서는 prop을 활용해서 속성을 바꿔주는 것이 아니라서 attrs 는 안쓰기로 결론내렸다.

 

이런 주석을 썼다가 지웟다.

// prop을 내려받아서 속성에 설정해줄거면 attrs 쓰는게 좋은데 그냥 추가하고 싶으면 아래처럼 하는게 좋은 것 같다.

 

 

 

(2) SearchContents

(3) SearchUser

 

아직 UI적으로 크게 손댄 것이 없다. 렌더링 로직만 동일하게 적용해놓은 상태. Contents부분은 다른 팀원이 안만들어도 게시글 컴포넌트 가져올 수 있는데 해당부분은 월요일 오전에 완성하고 User만 기다리는 것으로 해야겠다.

 

2)  기능 구현

 

기능 구현이 정말 계속해서 발목을 잡았는데,

월요일 작업내용을 포스팅하러 가야하기 때문에 일요일 밤에 계속 고통받던 내용을 정리하자면
(1) Promise.all 문제

(2) 경로이동하면서 useSearchParams 값이 제대로 전달안되는 문제

(3) 검색어 입력안하면 user 검색은 400error(Bad Request)가 떠버리는 문제

로 요약할 수 있는데 이 역경들을 헤치고 기능을 완성하는 모습은 다음 포스팅에서 확인할 수 있다.(과연..두둥⌛️)

 

3) 자잘한 수정사항들

 

 

힌트 조금 틀어지는거 no wrap 적용하기

 

#4 지금까지의 코드 developement

1) 

(1) Ouath useEffect 줄이기(현재까지는 실패중)

뤼튼에게도 다시 물어보고 이렇게 저렇게 생각해보고 있으나 줄기차게 실패중이다.

 

 

#5 기타 detail한 고민

1) 자동배포이슈

2) 게임팔로우 클릭 시 다른 유저에게 팔로우 수가 업데이트 되는 로직

post 요청 > back에서 response 

3) 개별게임채널에 추가기능

게임 이미지에 hover 했을 때, 게임설명 overlay되는 기능,

게임 이미지를 클릭했을 때 다운로드링크로 이동하는 기능 

 

#6 팀원 코드 살피고 의견 나누기(코드리뷰)

 

아무리 바빠도 팀원들이 풀리퀘 날리고 질문하는 내용들에 대해 살펴보면서 해야한다.

이렇게 풀리퀘 코드도 확인했다고 표시해주고.. ㅋㅋㅋㅋ

풀리퀘에 적어준 내용을 잘 읽은 뒤 리뷰로 의견공유도 해준다.

그리고나서 현재 작업한 부분 중에 Oauth 작동되는지 확인하고 싶다고해서 그 부분만 풀리퀘를 날려준다..

날렸는데 컨플릭이 나는 부분들은 또 미리 수정해두고

다시 검색,메세지 페이지를 만들러 간다 ~!!

'archive > Project' 카테고리의 다른 글

[MainProject] day-16 (5/22)  (1) 2023.05.22
[MainProject] day-14,15 (5/18-5/19)  (0) 2023.05.19
[MainProject] day-13 (5/17)  (2) 2023.05.17
[MainProject] day12 (5/16)  (1) 2023.05.17
[MainProject] day 10 extra (5/13-5/14)  (1) 2023.05.15