-
Notifications
You must be signed in to change notification settings - Fork 10
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주차] 김류원 미션 제출합니다. #16
base: master
Are you sure you want to change the base?
Conversation
류원님 이번주차 과제도 고생 많으셨습니당!!! ⸜(ˊᗜˋ)⸝⭐ ⭐ 아, 그리고 친구 목록에 있는 친구들 저도 훔치고 싶어요... (˶• ﻌ •˶) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
안녕하세요 류원님:)
저번 주차에 이은 채팅방 구현 완료하시느라 수고많으셨습니다-!! 👊❤️🔥
src/App.tsx
Outdated
<div className=" md:max-w-[375px] mx-auto"> | ||
{" "} | ||
{chatRoomMatch ? null : <BottomNav></BottomNav>} | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 부분에서 null을 반환하는 대신 && 연산자를 사용하면 더 좋을 것 같아요!
<div className=" md:max-w-[375px] mx-auto"> | |
{" "} | |
{chatRoomMatch ? null : <BottomNav></BottomNav>} | |
</div> | |
<div className=" md:max-w-[375px] mx-auto"> | |
{!chatRoomMatch && <BottomNav />} | |
</div> |
const isHomeActive = location.pathname === "/"; | ||
const isChatActive = location.pathname === "/chat-list"; | ||
const isStoryActive = location.pathname === "/story"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아래에서 location.pathname === "path"
조건이 반복되는 코드를 간단히 하기 위해 여기선 이렇게 배열로 정의해두고,
const isHomeActive = location.pathname === "/"; | |
const isChatActive = location.pathname === "/chat-list"; | |
const isStoryActive = location.pathname === "/story"; | |
const navItems = [ | |
{ path: "/", label: "홈", icon: home }, | |
{ path: "/chat-list", label: "채팅", icon: chat }, | |
{ path: "/story", label: "스토리", icon: story }, | |
]; |
<button | ||
className={`flex flex-col items-center ${ | ||
location.pathname === "/" ? "text-blue-500" : "text-gray-500" | ||
}`} | ||
onClick={() => nav("/")} | ||
> | ||
<img | ||
src={home} | ||
style={{ filter: isHomeActive ? activeFilter : "none" }} | ||
className="w-6 h-6" | ||
alt="" | ||
/> | ||
<span className="text-xs mt-1">홈</span> | ||
</button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요 버튼 단위의 코드가 중복되고 있으니 위에서 정의한 배열을 map으로 돌려서 다음과 같이 쓰면 중복을 줄일 수 있겠습니당
조건부에서도 반복되는 location.pathname === ~~ 부분을 줄이기 위해 변수로 따로 뺐습니다! (suggestion은 아래쪽 68줄까지를 대신하는건데 아래쪽까지 드래그가 다 안되어서..! 여기까지로 잡았습니다 🥲 )
<button | |
className={`flex flex-col items-center ${ | |
location.pathname === "/" ? "text-blue-500" : "text-gray-500" | |
}`} | |
onClick={() => nav("/")} | |
> | |
<img | |
src={home} | |
style={{ filter: isHomeActive ? activeFilter : "none" }} | |
className="w-6 h-6" | |
alt="" | |
/> | |
<span className="text-xs mt-1">홈</span> | |
</button> | |
{navItems.map(({ path, label, icon }) => { | |
const isActive = location.pathname === path; | |
return ( | |
<button | |
key={path} | |
className={`flex flex-col items-center ${isActive ? "text-blue-500" : "text-gray-500"}`} | |
onClick={() => nav(path)} | |
> | |
<img | |
src={icon} | |
style={{ filter: isActive ? activeFilter : "none" }} | |
className="w-6 h-6" | |
alt={`${label} 아이콘`} | |
/> | |
<span className="text-xs mt-1">{label}</span> | |
</button> | |
); | |
})} |
const match = useMatch("/"); | ||
|
||
return ( | ||
<div className=" md:max-w-[375px] flex items-center justify-between py-[11px] px-[16px] bg-white border-b-[1px] fixed top-0 w-full md:max-w-[375px] h-[56px] mx-auto"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tailwind css에서 저도 계속 적응 안되던게 값 지정이었는데요 😅..
arbitary value로 [ ] 안에 넣어줘도 되지만 16px, 56px 등은 class로 적용 가능하니까 익숙해져보시는 것도 좋을 것 같아요!
); | ||
}; | ||
|
||
const DateTimeText = styled.div<{ isCurrentUser: boolean }>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
위에서는 테일윈드를 쓰셨는데 styled component와 혼용한 이유가 있으신가요?!
const getProfilePic = (sender: string): string => { | ||
return sender === "CEOS" ? "/Profile_image.svg" : "/Profile_image.svg"; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
조건부 앞뒤가 같은데 혹시 하나가 다른 경로여야 하는걸까요?-?
<DateTimeText isCurrentUser={message.sender === currentUser.name}> | ||
{formatDateTime(message.time)} | ||
</DateTimeText> | ||
)} | ||
<MessageContainer | ||
key={`${message.id}-${currentSender}`} | ||
isCurrentUser={message.sender === currentUser.name} | ||
> | ||
{message.sender !== currentUser.name && ( | ||
<img | ||
src={getProfilePic(message.sender)} | ||
alt="Profile" | ||
className="w-8 h-8 rounded-full mr-2" | ||
/> | ||
)} | ||
|
||
<MessageContent> | ||
{message.sender === currentUser.name ? ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
message.sender === currentUser.name
이 계속 반복되고 있어서 const isCurrentUser = message.sender === currentUser.name; 와 같이 변수로 따로 빼주어서 활용하면 가독성이 더 좋을 것 같습니다!
배포링크
💗key question💗
동적 라우팅이란 실행 중일 때 라우트를 정의하고 관리하는 방식임. URL의 특정 부분(파라미터)을 동적으로 받아와서 다른 컴포넌트를 렌더링함. 예를 들어, "/post/:postId" 형태의 URL에서 postId에 따라 각기 다른 페이지 내용 보여줌.
언제 사용?
상품 상세 페이지: URL ID에 따라 다른 상품 정보 표시
유저 프로필 페이지: 유저 ID에 따라 다른 프로필 보여줌
게시판: 게시물 ID로 특정 게시물 페이지로 이동할 때 사용함.
네트워크 느릴 때 UX/UI 개선 전략 및 최적화 방법
네트워크가 느리면 사용자가 불편해할 가능성 큼. 이를 줄이기 위해 몇 가지 디자인 전략과 최적화 방법 사용 가능.
Skeleton UI: 로딩 중에 뼈대 화면 보여줌. 기다림 시간 최소화됨.
Lazy Loading & Progressive Loading: 필요한 데이터부터 먼저 로드해 유저가 빨리 볼 수 있게 함.
로딩 인디케이터: 로딩 중임을 알림.
프리로딩(Preloading): 이후 필요할 가능성 큰 리소스 미리 로드하여 다음 페이지 빠르게 전환함.
기술적 최적화 방법
코드 스플리팅(Code Splitting): 필요한 코드만 불러와 초기 로딩 속도 개선
이미지 최적화, CDN 활용: 이미지 용량 줄이고 CDN 통해 빠르게 제공
React.lazy와 Suspense: 컴포넌트 지연 로딩으로 초기 번들 크기 줄임
데이터 캐싱: React Query나 SWR 써서 데이터를 캐싱, 불필요한 네트워크 요청 줄임.
useState와 useReducer로 지역 상태 관리 / Context API, 전역 상태 관리 라이브러리 차이
상태 관리는 주로 지역 상태와 전역 상태로 나뉨. 필요와 목적에 따라 사용 방식 다름.
useState: 간단한 상태 관리에 사용. 상태랑 상태 변경 함수 쌍 반환, 컴포넌트 내에서 직접 관리함.
useReducer: 복잡한 상태 로직에 유리함. 액션이 여러 개고 상태가 서로 얽혀 있으면 유용함.
Context API
Context API는 props drilling을 방지하기 위한 전역 상태 관리 방식임. 부모가 자식에 직접 데이터를 전달할 수 있어서 여러 단계 거치지 않고도 공유 가능.
주 용도: 인증 상태, 테마, 유저 설정 등 애플리케이션 전반에 필요한 데이터에 적합.
제약: 상태 많아지고 복잡해지면 Context API만으론 관리 어려워질 수 있음.
전역 상태 관리 라이브러리 (Redux, MobX, Recoil 등)
전역 상태 관리 라이브러리는 상태 체계적으로 관리할 때 사용함. 큰 규모, 복잡한 앱에서 데이터 흐름과 상태 변화 추적 쉽게 해줌.
Redux: 액션, 리듀서, 스토어 통해 상태 변화를 예측 가능하게 관리. 한 곳에서 관리해 애플리케이션 전체 상태 추적 쉬움.
Recoil: 최신 상태 관리 라이브러리, 비동기 상태 관리나 컴포넌트별 전역 상태 관리에 유리하게 설계됨.