Skip to content

[4주차] 원채영 미션 제출합니다. #13

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

Open
wants to merge 58 commits into
base: master
Choose a base branch
from

Conversation

chaeyoungwon
Copy link

@chaeyoungwon chaeyoungwon commented Apr 24, 2025

배포 링크

🔗

과제를 진행하며

지난 과제를 리팩토링하면서, 당시에는 여러 화면을 구현하는 데 급급했다는 점을 느꼈습니다,,
이번에는 코드 리뷰를 바탕으로 전반적인 구조와 코드를 리팩토링하는 데 집중하였고,
추가할 새로운 UI는 많지 않았어서, 디테일한 기능들을 추가하고 다듬는 방향으로 과제를 진행하였습니다.
Zustand가 익숙하지 않은 상태에서 프론트만으로 상태를 관리하다 보니, 코드가 복잡하게 느껴져 아쉬움이 남았습니다 😭
(디자인이 금요일에 추가로 수정될 예정이라고 하셔서, 일정상 먼저 제출해두겠습니다ㅏ 😢)

3주차 & 4주차 구현 기능 정리

[3주차]

  • 온보딩, 홈, 채팅 리스트, 채팅방, 프로필 화면 등 주요 UI 및 라우팅 구현
  • sessionStorage를 활용한 온보딩 로직 구현
  • Zustand를 활용한 채팅 데이터 상태 관리
  • tailwindcss v3 기반 스타일링 적용
  • 텍스트 및 이미지 메시지 전송 기능 구현
  • localStorage를 활용해 새로고침 시 데이터 유지 처리
  • 친구 목록 기능 구현

[4주차]

  • 전반적인 코드 리팩토링 및 JSON 구조, 변수명, 파일명 정리
  • 온보딩 로직을 sessionStorage → timeout 방식으로 변경
  • 채팅방 진입 시 읽음 처리 및 새로고침 후 상태 유지 기능 구현
  • 채팅방 내 상대방 프로필 이미지 클릭 시 프로필 화면으로 이동 기능 구현
  • 상대 프로필 내 통화 버튼 클릭 시 통화 화면 UI 구현
  • 채팅 버튼 클릭 시 실제 채팅 내역으로 연결되도록 구현
  • 그룹 채팅의 경우 구성원 기반 렌더링 및 시점 전환 기능 구현
  • Zustand 코드 보완 (시점 전환 후 채팅방을 나갔을 때 사용자 정보가 꼬이는 문제 수정)
  • 설정 페이지에 로딩 UI 추가
  • vercel 설정 추가 (새로고침 시 라우팅 오류 해결)
  • useMobile, useStatusBar 훅 추가 → 모바일 환경에서 상태바 숨김 및 레이아웃 수정
  • 마지막 메시지가 이미지일 경우 대체 텍스트(“사진을 보냈습니다”)로 표시되도록 개선
  • 채팅 리스트가 store 기반으로 최신화되도록 구현 → 최근 메시지 순 정렬 적용
  • tailwindcss v4로 마이그레이션 및 전반적인 시스템 스타일 개편

Key Questions

1. React Router의 동적 라우팅(Dynamic Routing)이란 무엇이며, 언제 사용하나요?

동적 라우팅이란, URL의 경로에 따라 렌더링할 컴포넌트가 동적으로 결정되는 방식이다.
예를 들어, 특정 유저의 프로필 페이지를 /profile/:userId와 같은 형태로 설정하고,
useParams 훅을 통해 userId 값을 추출하여 해당 데이터를 기반으로 페이지를 렌더링할 때 주로 사용된다.
(ex) 유저 ID, 게시글 ID처럼 동적인 값에 따라 화면이 달라져야 할 때 주로 사용된다. (ex 상세 페이지)

2. 네트워크 속도가 느린 환경에서 사용자 경험을 개선하기 위해 사용할 수 있는 UI/UX 디자인 전략과 기술적 최적화 방법은 무엇인가요?

UI/UX 디자인 전략:

  1. 스켈레톤 UI: 콘텐츠가 로딩되기 전에 레이아웃의 구조만 먼저 보여주는 방식으로, 체감 로딩 시간을 단축
  2. 로딩 애니메이션/ 메시지 제공: 로딩 스피너 및 텍스트 추가

기술적 최적화 방법:

  1. 이미지 압축: 파일 크기가 작으면서 품질 유지되는 포맷(webP, AVIF) 선택, lazy loading을 통해 화면이 보이는 시점에만 이미지 로드
  2. 브라우저 캐싱 사용: 사용자가 이전에 방문한 웹사이트에 내용을 저장함으로써, 재방문 시 로딩 시간 단축
  3. 코드 스플리팅: js 파일을 작은 파일들로 분할하는 기술로, import를 동적을 하여 런타임 시 필요한 모듈을 불러오게 함

3. React에서 useState와 useReducer를 활용한 지역 상태 관리와 Context API 및 전역 상태 관리 라이브러리의 차이점을 설명하세요.

지역 상태 관리

  1. useState:
  • 가장 기본적인 상태 관리 훅으로, 간단한 상태 값을 관리할 때 사용
  • 배열 구조 분해를 사용해 const [state, setState] = useState(initialValue) 형태로 사용하며, 상태와 상태 변경 함수를 반환
  1. useReducer: 복잡한 상태 로직이 필요한 경우 유용 (하나의 useState는 하나의 값만을 관리)
  • 상태 변경 로직을 외부의 reducer 함수로 분리함으로써 가독성과 유지보수성이 향상됨
  • const [state, dispatch] = useReducer(reducer, initialState); 형태로 사용함

전역 상태 관리

  1. Context API: 여러 컴포넌트 간 동일한 상태를 공유해야 할 때 사용함.
  • Provider를 통해 상태를 하위 트리로 전달하고, useContext 훅을 통해 해당 값을 사용함.
  • 상태 업데이트가 잦거나 트리 구조가 깊을 경우 불필요한 리렌더링이 발생할 수 있음.
  1. Recoil, Zustand 등 외부 상태 관리 라이브러리
  • 앱 전반의 상태 공유, 성능 최적화, 비동기 상태 처리 등에 적합함.
  • Zustand는 간단한 API와 구독 기반 구조를 제공하여 불필요한 렌더링을 방지할 수 있음.
  • Recoil은 atom 단위의 상태 관리와 비동기 흐름 처리를 지원하여 React 환경에 적합함.

차이점

지역 상태 관리는 해당 컴포넌트 내부에서만 상태가 유효하며, 마운트 또는 언마운트 시 상태가 초기화됨.
다른 컴포넌트와 상태를 공유하거나 유지하기 어려움.
전역 상태 관리는 여러 컴포넌트 간 상태를 공유하고, 전체 앱에서 일관된 상태 흐름을 제공할 수 있음.

/>

<div className="flex flex-col justify-center w-[254px]">
<span className="title-2 px-4 py-1 text-grey-900 h-[33px]">

Choose a reason for hiding this comment

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

혹시 h-[33px] 이랑 px-4 이렇게 구분해서 사용하는 기준이 있으신가요?
4px 단위이신 것도 어떤 거는 gap-[60px] 쓰고 어떤거는 gap-1 이렇게 쓰시던데, 가능하시다면 알려주시면 너무 감사할 것 같습니다!
저는 고민하다가 모르겠어서 그냥 다 [#px] 로 통일해서 쓰고 있어서..

Copy link
Author

@chaeyoungwon chaeyoungwon Apr 28, 2025

Choose a reason for hiding this comment

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

저는 4px 단위라면 px-4와 같은 형태로 사용하고, 지원하지 않는 애매한 길이의 경우에는 직접 px 값으로 지정해주었습니다.
이렇게 클래스로 작성하면 무엇보다 빠르기도 하고, 가독성이 좋아 지원되는 값이라면 클래스 형식으로 작성하는 방식을 선호하고 있습니다.

4px 단위인데 px로 직접 지정이 되어있는 경우는 지난 과제에서 v3->v4로 넘어가면서 변경이 안된 부분이라고 할 수 있습니다 😓
기존 v3에서는 gap-12, gap-14, gap-16, gap-20처럼 중간값이 빠져있는 상태로 제공되었고, gap-15와 같은 값은 직접 설정해주어야 사용이 가능했습니다.
하지만 이번에 v4로 변경되면서 gap-15와 같은 형식으로 직접 작성할 수 있게 되었고, gap-[60px] 같은 코드는 이제 gap-15로 바꿔도 괜찮을 것 같습니다!

이제 v4가 나와서 필요하지는 않지만, 혹시 궁금하실 수도 있으니 관련 자료를 첨부하겠습니다 !!
tailwind v3 문서

Choose a reason for hiding this comment

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

아하 감사합니다! 저는 처음에 코드 봤을 때 width랑 height만 px 지정하고 나머지는 tailwind 스타일 적용해서 사용하나 생각했는데 v3에서는 지정된 값만 사용할 수 있어서 그렇게 하신 거군요

Copy link

@lemoncurdyogurt lemoncurdyogurt left a comment

Choose a reason for hiding this comment

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

정말 코드가 깔끔해서 배울점이 많았습니다!! 신경 쓴 디테일들이 많이 엿보였던 이번 과제였던 것 같아요!!! 수고하셨습니다

Comment on lines +12 to +31
const menus = [
{
name: '홈',
path: '/home',
iconOn: HomeOn,
iconOff: HomeOff,
},
{
name: '채팅',
path: '/chat',
iconOn: ChatOn,
iconOff: ChatOff,
},
{
name: '설정',
path: '/setting',
iconOn: MoreOn,
iconOff: MoreOff,
},
];

Choose a reason for hiding this comment

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

svg?react를 사용하면 svg파일을 컴포넌트로 변환해서 isActive상태를 통해 색상의 변화를 줄 수가 있어요. 그래서 파일을 하나만 받으면 된답니다

<span className="body-1 text-grey-900">{title}</span>
{count !== undefined && <span className="body-1 text-grey-400">{count}</span>}
</div>
<img src={UpArrow} alt="toggle" className={`w-[24px] h-[24px] ${!isOpen ? 'rotate-180' : ''}`} />

Choose a reason for hiding this comment

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

Arrow방향마다 이미를 다운받았는데 rotate를 시킬 수 있는 방법이 있었군요..!

Comment on lines +78 to +82
// 메시지 수신 시 자동 스크롤
const bottomRef = useRef<HTMLDivElement>(null);
useEffect(() => {
bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [messages]);

Choose a reason for hiding this comment

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

메세지스크롤이 smooth덕에 자동으로 내려가져서 좋은거 사용자 입장에서좋은거 같아요!

Choose a reason for hiding this comment

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

뭔가 따로 안보내도, 자동으로 스크롤이 흘러내려가는데 의도한걸까요..?

Comment on lines +44 to +47
const getLastMessageContent = (msg?: Message['messages'][0]) => {
if (!msg) return '';
return msg.messageType === 'image' ? '사진을 보냈습니다.' : (msg.content ?? '');
};

Choose a reason for hiding this comment

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

사진 보냈을 때의 경우에 따라 사진보냈습니다 만든거에서 디테일이 엿보이는거 같아요

Comment on lines +37 to +41
.sort((a, b) => {
const aTime = new Date(a.messages.at(-1)?.createdAt ?? 0).getTime();
const bTime = new Date(b.messages.at(-1)?.createdAt ?? 0).getTime();
return bTime - aTime;
});

Choose a reason for hiding this comment

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

보낸 시간에 따라서 채팅방 순서 바뀌니까 좋네요!!

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