Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[4주차] 안혜연 미션 제출합니다. #12

Open
wants to merge 46 commits into
base: main
Choose a base branch
from

Conversation

noeyeyh
Copy link

@noeyeyh noeyeyh commented May 3, 2024

미션

배포링크

피그마 링크

image

디자이너 분께 받은 QA

image
image

  • 입력창 폼 안에 양옆으로 10px 패딩 추가
  • 한줄짜리 채팅 버블 추가
  • 챗을 보내면 생성되는 ‘날짜 인디케이터’의 상하너비 수정
  • contact-info 페이지에서 상단 이름 축약

Key Questions

1. Routing이란?

Routing이란 사용자가 선택한 해당 경로로 페이지를 로드할 수 있게 해주는 과정을 일컫는 말입니다. React 자체에는 Routing 기능이 내장되어 있지 않습니다. 따라서 React 애플리케이션에서 Routing을 구현하기 위해 react-router와 같은 외부 라이브러리를 사용합니다. SPA는 구조상 단일 페이지이기 때문에 보여지는 페이지 모습은 달라져도 주소는 달라지지 않는 문제가 발생하여 react-router는 React에서 SPA를 구현할 때 널리 사용되는 Routing 라이브러리입니다.

이번 과제를 진행하며 react router에서 제공하는 여러 hook을 사용하였습니다. 가장 기본 경로를 채팅 목록 chats page로 지정하였고 이외에도 다른 페이지들은 각각의 URL에 맞는 컴포넌트를 정의하였습니다. URL 이동을 해야할 때에는 useNavigate을 사용해서 경로 이동을 하였습니다. useParams를 사용해서 URL에서 채팅방 ID를 추출하기도 하고 useLocation을 사용하여 이전 페이지로부터 전달받은 userId 정보를 컴포넌트 내에서 사용할 수 있게 하기도 하였습니다.

2. SPA란?

SPA는 Single Page Application의 약자로 하나의 페이지로 이루어진 웹 애플리케이션을 말합니다. 새로 페이지를 로드하지 않고 필요한 부분만 수정합니다. SPA는 클라이언트 사이드 렌더링(Client Side Rendering, CSR) 방식을 취하고 있습니다.
CSR이란 최초 로드 시 HTML, CSS, Javascript 등 필요한 파일들을 모두 받고 이후 사용자와의 상호 작용에 따라 리소스를 서버에서 제공한 후 클라이언트가 해석하고 렌더링하는 방식입니다. 이는 수정된 부분만 불러오기 때문에 빠른 페이지 로딩과 부드러운 페이지 전환이 장점입니다. 그리고 사용자 화면에 높은 반응성을 유지할 수 있도록 합니다. 하지만 검색 엔진 최적화에 제한이 있으며 필요한 정적 리소스를 서버로부터 최초 접근 시 받아와서 첫 페이지 로딩 속도가 느리다는 단점이 있습니다.

3. 상태관리란?

리액트의 가장 큰 특징은 부모 요소에서 자식 요소로 데이터를 전달한다는 것입니다. 컴포넌트 간에 상태를 공유하려면 이처럼 상위 컴포넌트에서 하위 컴포넌트로 porp을 넘겨 전달합니다. 이런 prop 전달 과정이 복잡해지면 계속해서 추적하고 관리하기 어렵기 때문에 전역 상태 관리를 합니다.

전역 상태 관리는 여러 방법이 있는데 그중에서도 Context API, Redux, React Query가 많이 쓰입니다.
제가 이번 과제에서 사용한 redux toolkit에 대해 간단히 설명을 해보면 . . .

리액트는 컴포넌트 자신이 개별적으로 상태관리를 하는데 redux를 쓰면 전용 장소 store에서 상태를 관리하고, 리액트 컴포넌트는 그걸 보여주기만 하는 용도로 쓰입니다. 리액트 컴포넌트가 store에 접근하고 싶으면 action을 발행해야합니다. 여기서 reducer는 이전 상태와 action을 합쳐서 새로운 상태를 state을 만드는 조작을 말합니다. redux 사용시 저장소 구성의 복잡성, 많은 패키지 필요성, 한 작업 시 필요한 수 많은 코드양 등의 문제점을 보완하여 redux toolkit은 redux를 더 사용하기 쉽게 만들었습니다. 여기서 createSlice는 action과 reducer를 전부 가진 함수로 기존에는 액션생성함수와 액션 타입을 선언해 사용했다면 createSlice는 액션을 선언하고 해당 액션이 dispatch되면 바로 해당 액션을 처리합니다.

링크 및 참고자료

Copy link

@songess songess left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이번주 과제 고생하셨습니다!
리덕스를 사용해 상태관리를 깔끔하게 해주셔서 보기 편했습니다. 리팩토링 할 때에는localStorage에 저장하는 것도 시도해보시면 좋을 거 같아요!

Comment on lines +13 to +18
const Container = styled.div<{ $bgColor: string }>`
width: 23.4375rem;
height: 50.75rem;
background: ${({ $bgColor }) => $bgColor};
position: relative;
`;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이번 과제는 375x812 고정이였기 때문에 상관없지만, 반응형을 고려해서 height는 100%를 사용해도 좋았을 거 같아요! 맥북같은 경우는 기본이 812보다 작기 때문에 화면에서 잘리는 현상이 발생해서요!

Comment on lines +40 to +50
<AppContainer>
<StatusBar />
<Routes>
<Route path="/" element={<ChatsPage />} />
<Route path="/chatroom/:chatRoomId" element={<ChattingPage />} />
<Route path="/contact-info" element={<ContactInfoPage />} />
<Route path="/status" element={<StatusPage />} />
<Route path="/edit-contact" element={<EditContactPage />} />
</Routes>
<HomeIndicator />
</AppContainer>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

공통되는 Container를 선언하고 그 안에서 라우팅하는 방식 좋아요! 이를 위해서 리액트 라우터는 중첩라우팅을 제공하고 있고, 를 하나의 으로 지정하고 그 안에서 을 사용해 라우팅하는 방식을 사용해도 좋을 거 같아요! 참고문서걸어놓을게요!

그리고 사용자가 예상치못한 URL을 타고 들어올 수 있기 때문에, 이를 대비한 페이지가 있었다면 더 좋았을 거 같아요!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

optional(?), &&과 동적스타일링을 사용해서 확장성있는 NavBar가 된거 같아요!

<TextContainer
style={{ borderBottom: '0.0625rem solid rgba(60, 60, 67, 0.29)' }}
>
<EditText style={{ fontWeight: '600', marginTop: '0.91rem' }}>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

디자이너님이 보낸 시안을 따라 만들다보면 중복되는 스타일을 적용해야 하는데, 이럴때 theme을 사용해 미리 스타일을 정의해놓으면 훨씬 편하게 사용할 수 있어요!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

비슷한 결의 코드가 반복된다고 생각되는데, 이를 배열화 해서 작성하면 더 가독성있게 만들 수 있지 않을까 싶어요.
예를들어

const arr = [
  {
    name: 'Timothée',
    lastName: 'Chalamet',
  },
  {
    name: 'United Kingdom',
  },
  {
    name: 'Instagram',
  },
  {
    name: '+44 1234 567890',
  },
]

이런식으로 뽑아주고, map을 사용해 각 인덱스에서 key값을 왼쪽, value값을 오른쪽에 할당하는 방식을 사용할 수 있을 거 같아요!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

깔끔하게 짜진 코드에요! 기능별로 컴포넌트화 시켜도 좋을 거 같습니다.

Comment on lines +5 to +7
import add from '../../assets/img/status-add.svg';
import camera from '../../assets/img/status-camera.svg';
import edit from '../../assets/img/status-edit.svg';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

상대경로를 이용하고 있는데, baseUrlpath를 활용해서 절대경로를 사용해도 좋았을 거 같아요! 현재 저희는 cra를 사용하고 있기에 커스터마이징을 위해 craco,react-app-alias를 사용해야 하긴 하지만 한번 쯤 해보는 것도 좋은 거 같아요! 참고자료 첨부할게요!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

파트너가 없을 때를 위한 페이지 좋아요! 없을 때

태그가 가운데 배치된다면 더 좋을 거 같아요!

Copy link

@Shunamo Shunamo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

혜연님! 이번 과제도 고생 많으셨어요 ㅎㅎ
채팅방에서 사용자 토글시 다른 화면에서도 바뀐 user 정보가 그대로 적용되는 점이
정말 신기하구 멋있었어요!!
그리고 함수를 따로 컴포넌트로 활용하셔서 코드 읽기 정말 편했어요!
컴포넌트를 재사용하면서 조건부 스타일링을 되게 능숙하게 하시는 것 같아요!
좋은 코드 멋진 화면 보고 많이 배워가요 :) 💯 👍 💯

}, [location]);

return <Container $bgColor={bgColor}>{children}</Container>;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 각 파일에 배경색을 prop으로 전달해서 동적으로 바꿨었는데,
경로에 따라서 배경색을 설정해놓는 방법도 편하고 좋은 것 같아요!

width: auto;
height: auto;
position: absolute;
`;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

absolute 포지션도 좋지만 나중에 화면 비율에 맞춰서도 조정 될 수 있게
아이콘들을 justify-content: space-evenly 로 상대적인 값으로 조정하는 방법도 좋을 것 같아요!


dispatch(changeUser(nextUserId));
}
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nowUser을 전역으로 관리해서,
사용자를 토글한 상태가 어플리케이션 전체에 반영되는게 되게 멋있고 신기한 것 같아요!!!
채팅방 내에서 사용자를 토글한 채로 마이페이지랑 채팅리스트에도 그대로 반영이 되어있는데,
Redux에서의 전역 상태 관리를 훌륭하게 활용하신 것 같아요!!

저는 채팅방 내에서만 바뀌게 구현했는데 너무 어려웠고 시간도 오래 걸렸는데
전역으로 관리하고 그에 맞게 프로필이나 채팅 목록을 업데이트 하는게
퍼포먼스적으로도 좋고 이번 과제에서 요구하는 바에 더 잘 맞아 떨어지는 것 같습니다 👍 👍 👍

<TextContainer>
<EditText
style={{ fontWeight: '400', marginTop: '0.88rem', color: '#FF3B30' }}
>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

컴포넌트 재사용하고 스타일 따로 적용해준 부분 좋아요 👍

}
}, [chatList]); // chatList가 변경될 때마다 useEffect를 다시 실행

let lastDate = '';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

날짜처럼 변동 가능한 값을은 useState를 사용해서 컴포넌트로 관리를 하고
useEffect내에서 관리하는 것이 더 좋을 것 같아요!

const [lastDate, setLastDate] = useState('');

useEffect(() => {
  const newDate = FormatDateToDMY(chatList[chatList.length - 1]?.time);
  if (newDate !== lastDate) {
    setLastDate(newDate);
  }
}, [chatList]);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 함수들을 컴포넌트화 해서 사용하는 방법은 시도해 본 적이 없는데 되게 좋은 것 같아요!
이번 과제를 하면서 중복 선언했던 함수들이 많아서 매번 복붙하는 것도 번거로웠고 코드 가독성이 떨어지는 것 같아서 고치고 싶었는데 이렇게 따로 분리를 해놓으니 사용하기도 리팩토링 할 때도 편할 것 같아요!! 👍 👍

<SubTextBox>
<EditText>United Kingdom</EditText>
<RightArrowImg src={RightArrow} alt="오른쪽 화살표 이미지" />
</SubTextBox>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사용자를 변경하는 로직이 잘 구현되어 있어서 여기도 선택된 user 정보에 맞춰서 text들이 바뀌었다면 더 멋있었을 것 같아요!!

width: 2.25rem;
height: 2.25rem;
justify-content: center;
align-items: center;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flex 속성은 이미지에는 적용하지 않아도 될 것 같아요!! :)


const ChattingPageContainer = styled.div`
width: 23.4375rem;
height: 40.25rem;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

물론 이번 과제에 화면 크기가 고정으로 주어졌긴 하지만,
모바일에서 확인했을 때 꽉 찬 화면을 위해서 컨테이너의 min-width를 고정 값으로 설정하고,
뷰포트 viewport의 너비에 맞춰 조정하는 방식이 더 좋을 것 같아요!!

{children}
{title && <TitleText>{title}</TitleText>}{' '}
<RightContainer>
{rightImgSrc && <IconImg src={rightImgSrc} alt="" />}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alt 값이 비어있어요..!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants