Skip to content

Conversation

@Jy000n
Copy link

@Jy000n Jy000n commented Oct 25, 2025

결과화면

image image image image

느낀점 및 배운점

  • 채팅방Id 별로 각 사용자와 메시지가 렌더링될 수 있게끔 props를 각 컴포넌트에 전달하는 과정이 조금 까다로웠다.
  • 공통적으로 많이 적용되는 스타일들이 많았는데 컴포넌트화 하지 못한 것들이 꽤 있어서 코드가 쓸데없이 길어져서 아쉽다,,
  • @theme, @Utility 적용이 계속 안 되는데 왜인지 계속 검색하고 지피티에 물어봐도 이유를 찾지 못해서 일단 .클래스_이름{ 스타일_내용 } 형식으로 적용하려고 하고 있다

Review Questions

React Router의 동적 라우팅

동적 라우팅(Dynamic Routing)

  • 경로에 변수/파라미터를 포함하여, 해당 값에 따라 다른 컴포넌트를 렌더링하는 방식
  • 사용자 ID에 따라 페이지를 보여주거나, 제품 ID에 따라 상세 페이지를 보여주는 등, 미리 정해진 경로가 아닌 데이터에 따라 유연하게 경로 처리 시 사용

사용 시기

  • 리소스별 상세페이지 존재
    • ex) 카카오톡 채팅방 /chattingRoom/:id, 유저 프로필 /users/:userId
  • 라우트 기반 데이터 요청 필요 시
    • ex) useParams()로 URL의 파라미터를 받아 해당 ID를 기반으로 API 호출
  • 동적으로 생성되는 페이지

사용 예시

import { useParams } from 'react-router-dom';

fucnction UserProfile(){
    const { userId } = useParams();
    return <div>사용자 ID: {userId}</div>;
}

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

UI/UX 전략

  • 즉각적인 시각과 피드백 제공
    • Skeleton UI : 콘텐츠가 로딩되는 동안 실제 레이아웃과 유사한 회색의 가상 구조 보여줌
    • Progressive Loading (점진적 로딩) : 이미지와 같은 콘텐츠를 저해상도로 먼저 보여준 뒤, 네트워크 상태가 좋아지면 고해상도로 교체
    • Spinner / Loader : 로딩 중임을 명확히 표시
  • 사용자 행동 예측 및 대응
    • 명확한 상태메시지 : 네트워크 연결이 끊어졌거나 속도가 느릴 때, 그 이유를 사용자에게 명확히 알려줌 ('네트워크 연결이 불안정합니다", "데이터를 불러오는 데 시간이 오래 걸립니다")
    • Proactive Caching (선제적 캐싱) : 사용자가 다음에 방문할 가능성이 높은 페이지의 콘텐츠를 미리 캐시

기술적 최적화 방법

  • 프론트엔드 최적화
    • 이미지 최적화
      • 압축
      • 지연 로딩 : 화면에 보이지 않는 이미지는 로딩 미루어 초기 페이지 로딩 속도 향상
      • 반응형 이미지
    • 코드 최적화
      • 파일 압축/축소, 번들링
    • 캐싱
      • 브라우저 캐싱, 서비스 워커

React에서 useState와 useReducer를 활용한 지역 상태 관리와 Context API 및 전역 상태 관리 라이브러리의 차이점

구분 목적 사용 범위 특징
useState 간단한 로컬 상태 컴포넌트 내부 빠르고 직관적, 작은 단위의 상태에 적합
useReduce 복잡한 로컬 상태 로직 컴포넌트 내부 상태 변경 로직을 reducer로 관리 -> 예측 가능성 ↑
Context API 전역 상태 공유 앱 전체 여러 컴포넌트 간 props drilling 방지
전역 상태 라이브러리
(Redux, Zustand, Recoil)
대규모 앱 상태 관리 앱 전체 고급 기능(미들웨어, devtools, 비동기 상태 관리) 제공
  • 단순한 상태 (입력값, 토글) : useState
  • 상태 변경 로직이 복잡한 컴포넌트 : useReducer
  • 여러 컴포넌트에서 같은 상태 공유 : Context API
  • 규모가 크고 비동기 데이터 관리 많음 : 전역 상태 라이브러리

배포 링크 : react-messenger-22nd-pi.vercel.app

Copy link
Member

@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.

과제하느라 수고하셨습니다! 절대경로 설정이나, svgr사용면에서 프로젝트 세팅적으로 신경쓴게 보여서 재밌게 보았습니다. 페이지 개발 완성도라던가, 프로젝트 폴더 구조등 여러면에서 디테일하게 개발한 것 같아보인 과제였습니다 @>---
다만 절대경로를 이후에 설정하면서 그대로 상대경로로 남아있는 부분이라던가, svgr을 제대로 활용안된게 보여서 아쉬웠습니다ㅠ.... 수고하셨어요!~!

Copy link
Member

Choose a reason for hiding this comment

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

이렇게 두 개 링크 @theme 이라던가 @Utility 적용할 때 참고하라고 첨부해놨으니까 한 번 보고 다시 재적용해보시면 좋을 것 같아요!

tailwind.css theme variable 공식문서
tailwind.css v4 커스텀폰트 적용방법

"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-router-dom": "^7.9.4",
"styled-components": "^6.1.19",
Copy link
Member

Choose a reason for hiding this comment

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

tailwind.css랑 styled-components 패키지 둘 다 설치 되어있는데, 사용하는 패키지만 선택해서 삭제하면 좋을 것 같습니다!

"typescript": "~5.8.3",
"typescript-eslint": "^8.44.0",
"vite": "^7.1.7",
"vite-plugin-svgr": "^4.5.0"
Copy link
Member

Choose a reason for hiding this comment

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

svgr로 사용하기 위해서 설치한 것으로 보이는데, 현재 코드에서 봤을 때 img형식으로 에셋들을 import해온 것으로 보입니다😢

svgr로 사용했을 때 에셋의 색상 변화를 적용할 수 가 있어서 active, inactive에 따른 에셋 다운 필요없이 하나만 다운받으면 된다는 장점이 있으니, 다시 한 번 사용방법 공부해보시고, 재적용해보셨으면 합니다!

<ChatProvider>
<Router>
<div className="flex min-h-screen items-center justify-center">
<div className="border-[ #815840] flex h-[812px] w-[375px] flex-col rounded-[20px] border-[5px]">
Copy link
Member

Choose a reason for hiding this comment

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

여기 코드에 h-screen max-h-[812px]로 적용해야지 의도한 디자인을 표현할 수 있을 것 같아요. 현재 컴퓨터 화면이 812px보다 작은 경우 스크롤해야지만 볼 하단바가 보여요.
스크린샷 2025-10-26 오후 4 27 56

Comment on lines +1 to +4
import StatusBar from '../components/MenuBar/StatusBar';
import ChattingListHeader from '../components/MenuBar/ChattingListHeader';
import BookmarkChattingList from '../components/ChattingList/BookmarkChattingList';
import GeneralChattingList from '../components/ChattingList/GeneralChattingList';
Copy link
Member

Choose a reason for hiding this comment

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

절대경로가 적용되지 않은 import문도 있어서 이런 부분들 수정해줘야할 것 같아요

Copy link
Member

Choose a reason for hiding this comment

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

클래스나 컴포넌트 외에는 파일명이 소문자인게 좋아요. types/ 내 파일명들을 소문자로 유지해주는게 좋습니다.

Comment on lines +31 to +57
return (
<div
key={room.roomId}
className="flex cursor-pointer py-2.5"
onClick={() => navigate(`/chat/${room.roomId}`)}
>
<div className="mr-[12.44px] h-13.5">
<img src={ProfileIMGDefault} alt="친구프로필" className="h-13.5 w-13.5" />
</div>
<div className="flex w-67.5 flex-col justify-center gap-0.5">
<div className="flex items-center">
<div className="flex flex-1 items-center gap-1">
<div className="title4-sm">{room.name}</div>
<img src={FavoriteChatting} alt="즐겨찾기" className="relative top-[-1px] h-4 w-4" />
</div>
<div className="flex-end caption2-reg" style={{ color: 'var(--color-gray-6)' }}>
{lastMessage ? formatTimeAMPM(lastMessage.sentAt.toISOString()) : ''}
</div>
</div>
<div className="caption1-reg">{lastMessage?.content || ''}</div>
</div>
</div>
);
})}
</div>
)}
</div>
Copy link
Member

Choose a reason for hiding this comment

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

이부분이 FavoriteChatting icon의 여부 외에는 스타일이 동일한 것 같은데 이 영역을 컴포넌트화 하고 props로 isGeneral: boolean으로 받아와 즐겨찾기 아이콘을 배치하는 것이 재사용면에서 좋아보여요!

Comment on lines +33 to +37
<div
key={room.roomId}
className="flex cursor-pointer py-2.5"
onClick={() => navigate(`/chat/${room.roomId}`)}
>
Copy link
Member

Choose a reason for hiding this comment

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

지금 처럼 대화가 길어지는 경우에 한 없이 이 영역이 길어지게 되는데, 이 부분의 높이를 동일하게 처리하는것이 ui적으로 예쁘지 않을까 싶어요
스크린샷 2025-10-26 오후 5 04 46

Copy link
Member

Choose a reason for hiding this comment

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

스크린샷 2025-10-26 오후 5 02 20

채팅방 내부가 길어지면, 812px로 지정된 부분 넘어가서 저렇게 보이는 것 같아요! 이부분 수정해주면 좋을 듯해보입니다.

<div className="w-full cursor-pointer pb-1.25">
<div className="flex flex-row rounded-[4px] bg-[#815840] p-2.5">
<img src={ProflieIMGDefault} alt="유저프사" className="h-13.5 w-13.5" />
<span className="title4-sm ml-[15px] flex items-center text-white">사용자</span>
Copy link
Member

Choose a reason for hiding this comment

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

사용자명 천영현으로 따로 있는데 의도적으로 사용자라고 텍스트를 이용한 것인지 궁금합니다!

@@ -0,0 +1,36 @@
import type { Config } from 'tailwindcss';
Copy link

Choose a reason for hiding this comment

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

tailwindcss 4버전 부터는 이 파일을 사용하지 않는다고 들었어요. 아마 적용이 안됐던 게 이거 때문일 수도 있을 거 같아요.

@@ -0,0 +1,114 @@
@import 'tailwindcss';
@import '@/styles/font.css';

Copy link

Choose a reason for hiding this comment

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

@utillity@theme를 여기서 정의하면 된다던데...

<div className="border-[ #815840] flex h-[812px] w-[375px] flex-col rounded-[20px] border-[5px]">
<div className={`${hideLowerMenubar ? 'flex-1' : 'flex-1 overflow-y-auto'}`}>
<Routes>
<Route path="/" element={renderPage()} />
Copy link

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