본문 바로가기

Racstagram_V2

20210808 리팩토링 Instagram 클론 프로젝트 by Redux-toolkit25 : Post Detail View로 이동시 해당 글의 scrollTop 위치로 이동 구현하기

리팩토링 Instagram 클론 프로젝트 by Redux-toolkit25



📄 프로젝트 설명


이 프로젝트는 기존에 React & firebase를 통해서 만든 인스타그램 클론 프로젝트 리팩토링 프로젝트 입니다. (해당 프로젝트는 프로젝트 카테고리에서 확인 가능합니다.)


상태 관리

해당 프로젝트에서는 redux-toolkit(Slice 모델)을 사용하여 상태관리를 구현하고 있습니다.


스타일

현재 SCSS를 채택하여 css 작업을 진행중에 있으며, 부분적으로 Material UI를 사용하고 있습니다.
대부분의 경우에는, Material UI와 React 호환성 문제로 대부분은 SCSS로 직접 구현하고 있습니다.




💻 화면 개요


체크는 현재 기능적으로 구현된 상황을 의미합니다.


  • 로딩 화면 또는 Component : 앱 실행 초기화 작업시 로딩 또는 다른 작업시 사용할 로딩 화면 및 Component
    • 스타일링 완료

  • 로그인 화면 : 기본 Email 로그인, Social 로그인, 로그인 에러
    • Email 로그인 : Email, Password input, 로그인 버튼
    • Social 로그인 : google로그인 버튼, github로그인 버튼
    • 로그인 에러 : Email로그인, google로그인, github 로그인 에러 발생시 사용자에게 출력

  • 회원가입 화면 : Email 로그인을 위한 계정을 만드는 화면, 회원가입 에러
    • Email 형식 가입 : Email, Password input, 회원가입 버튼
      • 가입시 사용자 Nickname 지정 input (추가 사항)

  • 피드 화면 : 사용 유저의 모든 게시글을 표시하는 화면
    • 게시글 박스 :
      • 타이틀 영역 : 최상단의 작성자 사진 + 이름, 게시글 수정 탭
        • 편집버튼 : 글 수정하기, 삭제하기 모달 -> 해당 버튼 누르면 삭제 또는 수정 페이지로 이동(아니면 모달이 수정하는 모달로 변경)
          • 삭제하기
          • 수정하기
      • 사진 영역 : 기존에는 1개만 가능했음 (욕심내면, 여러개 슬라이드 형식으로 가능하게 하고 싶음)
      • 내용 영역 : 게시글 내용

  • 글 작성 화면 : 글을 작성하는 화면
    • 이미지 리사이징

  • 현재 유저 프로필 화면 : 로그인한 현재 유저의 게시물과 대략적인 프로필를 표시하는 화면
    • 유저 프로필 수정하기 : 유저 프로필을 수정하는 화면 (userImage, userDisplayname, userIntro)
    • 작성 글 : 유저가 작성한 작성 글의 image 표 -> 클릭시 post detail
      • 작성 글 detail view : image 표에서 해당 이미지 클릭시 해당 글 detail view 화면
    • 로그아웃

  • 다른 유저 프로필 화면 : 다른 유저가 작성한 글의 유저 이름을 클릭하여 해당 유저의 프로필 화면 구현
    • 프로필 보기 : userImage, userDisplayname, userIntro
    • 작성 글 : 유저가 작성한 작성 글의 image 표 -> 클릭시 post detail
      • 작성 글 detail view : image 표에서 해당 이미지 클릭시 해당 글 detail view 화면

  • 네비게이션 바 : 앱로고 - 피드(Home)탭 - 글 작성탭 - 현재 유저 프로필(프로필 수정, 프로필 이동, 로그아웃) 탭
    • Navigation-profile 눌렀을 때 로그아웃, 프로필 수정, 프로필 이동 드롭 다운 필요



📅 TIL (Today I Learned, 오늘 깨달은 것들)


2021.08.08 사항


작업개요 및 고찰


1. Post Detail View로 이동시 해당 글의 scrollTop 위치로 이동하게 구현하기

  • 다른 유저 및 자신의 프로필에 있는 post Image table에서 특정 이미지 클릭시 해당 글위치로 이동 함
  • ProfilePostImages 컴포넌트에서 유저의 이미지 테이블을 보여주는데 해당 이미지를 클릭하는 경우 해당 이미지가 몇번째 글인지 postNum울 Posts라는 페이지로 전달하여 Posts 페이지에서 보여줄 해당글에 스크롤이 위치하도록 함
    • Posts 페이지는 자신 또는 특정 유저가 작성한 글만을 Home 페이지 (Feed) 처럼 글을 보여줌

  • Posts 페이지로 이동 시키는 함수
    • 현재 유저의 Profile 컴포넌트와 특정 유저의 User 컴포넌트의 경우에는 거의 비슷하여 Route는 다르지만 Profile 컴포넌트로 통합하여 사용하기 때문에, 각 함수를 구현할 때는 pathname을 조건으로 다른 라우트로 갈수 있게 해야함
      • 여기서 드는 생각은 현재 profile과 user pathname을 분리하여 놓았기 때문에 오히려 복잡한 로직 함수를 사용하게 되므로 pathname을 현재 유저도 userName을 현재 유저 이름으로 하여 /user/userName를 같이 사용하는게 좋을 듯 해 보인다.
    • Posts 페이지로 이동 시키는 함수는 선택한 글이 몇번째 글인지를 같이해서 보냄
    const goPosts = useCallback(
        (postNum) => {
            if (pathname === '/profile') {
                history.push({ pathname: '/profile/posts', state: { postNum } });
            } else if (pathname === `/user/${userName}`) {
                history.push({
                    pathname: `/user/${userName}/posts`,
                    state: { postNum },
                });
            } else {
                console.log('invalid location request');
            }
        },
        [hist

  • 선택한 이미지가 몇번째 글의 이미지인지 계산하기 (postNum)
    • 매개변수 postNum은 이미지 테이블 내에서 몇번째 row인지, row안에서 몇번째 인지를 계산해서 전달
    • ProfilePostImages 컴포넌트의 이미지 테이블은 1 row당 3개의 이미지가 들어가있음
    • 예를 들어, 5번째 이미지의 경우 row_index 1번 row의 index_in_row 1번에 해당하므로 3 * row_index + index_in_row 로 계산하여 전체 posts array에서 계산된 인덱스를 사용하여 해당 post를 가져올 수 있음
// 생략 ...
return (
  <div className="post_table">
    {devidePosts(posts).map((row, index) => (
      <div className="posts_row" key={index.toString()}>
        {[0, 1, 2].map((i) =>
          row[i] ? (
            <div
              className="post_image_container"
              onClick={() => {
                goPosts(3 * index + i);
              }}
              key={`postTable/${row[i].postId.toString()}`}
            >
              <img
                src={row[i].postImageUrl}
                alt={"postImageUrl"}
                className="post_image"
              />
            </div>
          ) : (
            <div className="none_image" key={i.toString()}></div>
          )
        )}
      </div>
    ))}
  </div>
);

  • 들어온 postNum을 사용하여 해당 글로 스크롤 움직이기
    • 글들을 감싸는 글(post)의 부모 요소 ref로 접근
    • 부모 요소 ref의 children 접근하여 해당 순서의 글을 인덱싱
    • 인덱싱한 요소의 offsetTop 값을 가져옴
    • offsetTop에서 navigatino height 만큼 뺀 값만큼 window.scrollTo() 함수로 이동
    • window.scrollBy() 함수 이용시, transition을 줄 수 있음
const scrollToPost = (postNum) => {
  if (!postNum) {
    return;
  }
  const targetRef = useRef();
  const top = targetRef.current.children[num].offsetTop;
  // window.scrollBy({
  //     top: top - 54,
  //     left: 0,
  //     behavior: 'smooth',
  // });
  window.scrollTo(0, top - 54);
};

다음에 필요한 사항

  • profile 정보 요청 시기 조정
    • 더 빠른 연산을 위해서, 화면이 render 되고 profile에 관련된 정보를 가져오지 말고 profile 보기위해 버튼을 눌렀을 때 부터 미리 profile 정보를 요청하게 하자

  • Post Detail View로 이동시 해당 글의 scrollX 위치로 이동하게 구현하기 (스타일링 이후에 scroll 위치 계산이 필요한 작업임)

  • validation 구현 필요함
    • input 같은 경우, display none 적용시 browser에서 제공하는 validation 말풍선이 뜨지 않기 때문에 따로 구현 필요함
    • required를 사용하지 말고, submit 함수 단에서 input값이 들어 왔는지 체크하여 validation error 구현 필요
    • post 관련한 input의 check 대략적인 (PostUpdateContainer, postFormContainer)
    • auth 관련한 input의 check 대략적인 조건 구현
    • 각 input 별로 데이터 형태에 따른 구체적인 조건 설정이 필요함
      • 이메일, 패스워드, 유저 네임, 글 내용의 형식(조건, 제한) 지정 필요

  • 글 작성 시간 (클라이언트 단에서 뿌리는 경우 로컬 시간 변경으로 조작 가능한지 테스트 필요함)

  • profileUpdateContainer과 postFormContainer 통합 시도

  • 효과적인 렌더링 제한을 위해서 container에 있는 함수들을 hook으로 만들어 구현하기



나중에 구현하고 싶은 기술


  • input 자동 체크(중복 검사 기능에 추가)
  • side 바에 유저 랜덤 추천 및 푸터 정보
  • 유저 이름 검색을 통한 프로필 보기 (이름 검색)
  • 무한 스크롤
  • 게시글 장소 태그로 장소 지도 보기 (지도 API)