-
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주차] 조유담 미션 제출합니다. #18
base: main
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.
Redux 전역 상태 관리 라이브러리의 설정도 깔끔하시고 React에서 제공하는 다양한 타입스크립트 타입도 잘 사용하시는 것 같아요!
전체적인 UI도 깔끔하게 잘 구현하신 것 같습니다.
다만, 사용자가 특정 웹 페이지에 링크를 타고 타고 자연스럽게 들어오는 것 이외에도 url path에 입력하여 들어오거나, 아니면 새로고침을 통해 동일한 url path에 대해 요청을 보내는 경우(기존의 상태는 사라질 수 있음)를 고려해보시면 더 멋진 코드가 될 것 같아요.
이번 과제도 너무 고생 많으셨습니다(그리고 뉴진스 민지 이미지도 좋았습니다).
public/images/Minji.png
Outdated
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.
민지 이미지 👍
<GlobalStyle /> | ||
<BrowserRouter> | ||
<Routes> | ||
<Route path="/" element={<Layout />}> |
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.
가장 공통적인 레이아웃을 Layout 컴포턴트로 구성하고 변경되는 내용들은 Outlet
컴포넌트로 구현한 로직 좋아요 :)
<GlobalStyle /> | ||
<BrowserRouter> | ||
<Routes> | ||
<Route path="/" element={<Layout />}> |
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.
다만, 현재 작성해주신 애플리케이션은 제가 인위적으로 url 주소를 /
로 설정하면 아직 크게 완성되지 않은 레이아웃만 보이는 것 같아요. 오히려 이럴 때에는 Navigate
컴포넌트를 이용하여 사용자를 유담님이 원하는 path로 리디렉션 시켜주면 좋을 것 같습니다.
<Route path="/" element={<Navigate replace to="/other" />} />
의 방식으로 할 수 있으니 공식 문서를 참고해 보시면 좋겠어요!
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.
해당 store 를 프로젝트 루트 디렉터리의 index.tsx 컴포넌트에서 import하여 Provider
컴포넌트의 store 속성으로 바로 사용하시는데, import 문에서 구체적인 파일명을 언급하지 않으면 index.js나 index.ts(여기에서는 tsx) 를 의미하는 것을 잘 알고 계신 것 같습니다
|
||
export default Layout; | ||
|
||
const LayoutContainer = styled.div<{ $backgroundColor: string }>` |
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.
기본적으로 html 요소의 속성을 우리가 지정해주기 위해서는 camelCase로 하면 react가 오류나 경고를 띄우는데, 이를 막아주는 $ 를 단어 앞에 붙여주는 컨벤션을 잘 알고 계신 것 같아요 👍
dispatch(toggleParticipants()); | ||
}; | ||
|
||
if (!partner) return null; |
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.
현재 유담님께서 배포하신 버전에서는 /chat/user2
경로로 들어갔다고 가정했을 때, 진입까지는 너무 깔끔하게 잘 되는 것 같습니다.
하지만 여기에서 새로고침을 하면 전역 상태로 관리해주고 있는 partner
가 초기화되어 null 값이 되고 이에 따라 chatRoom 컴포넌트는 null 을 리턴하고 있는 것으로 보입니다.
이는 useEffect() 훅을 통해 해결할 수 있을 것 같아요. 컴포넌트의 최상단에 useParams() 훅을 이용해 const {chatId} = useParams()
처럼 구조 분해로 받아주고 useEffect(() => { // dispatch를 활용하여 partner 상태를 컴포넌트가 마운트 될 시에 바꿔주기}. [])
이런 식으로요!
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.
맞아요! 상세 페이지(?)로 이동하는 경우에는 useParams가 유용하더라구요! 제가 알기로는 params는 string이라 형변환을 해줘야하는 번거로움이 있지만요..ㅎㅎ
|
||
const dispatch = useDispatch(); | ||
|
||
const handleChatRoomClick = (partnerId: string) => { |
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.
특정 사용자를 클릭했을 때, 해당 주소로 라우팅을 해주고, 상태를 변경해주시는 로직을 만들어주셨네요!
이것도 참 좋긴한데, 사용자가 화면 UI를 클릭하여 이동하는 케이스 말고 브라우저의 주소창에 입력을 하여 접근하는 경우도 고려하면 좋을 것 같습니다. 저 같은 경우는 자주 이용하는 웹 페이지는 즐겨찾기 폴더에 넣어두고 바로 이동하거든요(꼭 랜딩 페이지가 아니더라도 세부 페이지를 가는 경우를 의미합니다).
이런 경우에는 유담님께서 고려해주신 상황을 통한 것이 아니기 때문에 상태가 의도한 대로 변경되지 않을 수도 있을 것 같아요.
따라서 /chat/:chatId
경로로 이동하는 것을 렌더링하는 컴포넌트가 처음 마운트 될 때, 즉 useEffect(() => {}, [])
의 첫 인자로 전달되는 콜백함수 내에서 강제로 partner 상태를 전역적으로 변경하도록 강제하면 더 좋을 것 같아요
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.
저도 배워갑니다!
|
||
interface SearchBarProp { | ||
inputValue: string; | ||
setInputValue: Dispatch<SetStateAction<string>>; |
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.
유담님 덕분에 react에서 지원하는 타입스크립트인 Dispatch
, SetStateAction
를 잘 배워 갑니다!
이것들이 없다면 set상태() 함수들은 단지 void 를 return 한다는 시그니처를 가질 뿐, 어떤 매개변수 타입들이 들어올지 알 수 없는데 두 타입을 활용하면 꼼꼼하게 강제해줄 수 있겠네요! 😊
@@ -0,0 +1,22 @@ | |||
import { configureStore } from '@reduxjs/toolkit'; |
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.
기존의 redux 를 이용하면 createStore()
함수를 이용하여 여러 상태들을 합쳐주고 스스로 결정해야할 것들이 너무 많죠!
이보다는 RTK를 이용하여 슬라이스를 생성하고, 리듀서와 액션 생성 함수들을 만들어준 다음 필요한 컴포넌트에서 주도적으로 import 하여 사용하시는 모습은 flux 패턴을 잘 이해하고 계신 것 같아요👍
export const useAppDispatch = () => useDispatch<AppDispatch>(); | ||
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector; |
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.
저는 커스텀 훅을 만들면 프로젝트 루트 디렉터리에 hooks 라는 디렉터리를 하나 생성하고, 여기에서 만든 다음 필요할 때마다 사용하고 있어요.
이건 그냥 제 취향이라 그냥 그런게 있다... 정도만 인지해주셔도 충분할 것 같네요
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.
유담님 이번 과제도 정말 수고 많으셨습니다! 검색 기능과 같은 신경 써야할 기능들이 많아 보이는데 모두 구현하셨다는게 정말 대단해요..! 다음 과제도 화이팅 해봐요😁
// shift + enter로 줄 바꿈 기능 | ||
const handleKeyDownShiftEnter = (e: KeyboardEvent<HTMLTextAreaElement>) => { | ||
if (e.nativeEvent.isComposing) { | ||
// isComposing 이 true 이면 | ||
return; // 조합 중이므로 동작을 막는다. | ||
} |
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.
오 이부분도 따로 구현을 해주셨네요! 배워갑니당
dispatch(toggleParticipants()); | ||
}; | ||
|
||
if (!partner) return null; |
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.
맞아요! 상세 페이지(?)로 이동하는 경우에는 useParams가 유용하더라구요! 제가 알기로는 params는 string이라 형변환을 해줘야하는 번거로움이 있지만요..ㅎㅎ
|
||
const dispatch = useDispatch(); | ||
|
||
const handleChatRoomClick = (partnerId: string) => { |
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.
저도 배워갑니다!
<Link to="/contacts" className={isActivePath('/contacts') ? 'active' : 'inactive'}> | ||
<ProfileIcon alt="연락처 아이콘" /> | ||
<p>연락처</p> |
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.
이부분을 저는 useLocation을 사용했는데 useLocation과 useNavigate도 한번 확인해보지면 좋을거 같아요!
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.
채팅 검색 기능까지 구현하셨네요! 대단합니당...👍
@@ -0,0 +1,10 @@ | |||
declare module '*.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.
저도 svg를 못쓰고있었는데 이렇게 따로 파일로 빼면 되겠네요...! 배워갑니다
🐻 배포 링크
https://react-messenger-19th-beta.vercel.app/contacts
피그마 링크
https://www.figma.com/file/hrrLcfzraIMMgZMvESS7Kx/ceos_%ED%85%94%EB%A0%88%EA%B7%B8%EB%9E%A8-%EB%A6%AC%EB%94%94%EC%9E%90%EC%9D%B8-(Copy)?type=design&node-id=10%3A1457&mode=dev
👩💻 구현 기능
3주차에 답장하기 기능을 구현하겠다고 했으나, 전역 상태관리 없이 구현하기 어려울 거 같다고 판단하여 이번주차로 미루었습니다. 하지만 여전히 미완성이네요..^^ 주말에 틈틈히 해보겠습니다.-> 구현 완료🥳 후기
❓ Key Questions
1. Routing이란?
Routing은 사용자가 웹 애플리케이션의 다양한 부분을 방문할 수 있도록 URL을 특정 컴포넌트 뷰와 매핑하는 과정입니다. React와 Next.js에서의 라우팅은 조금 다른 방식으로 구현됩니다. 각각의 라이브러리 및 프레임워크가 제공하는 라우팅 솔루션에 대해 설명하겠습니다.
React 자체에는 내장된 라우팅 시스템이 없습니다. 대신, 주로 react-router-dom 라이브러리를 사용하여 라우팅을 구현합니다. 이 라이브러리는 선언적인 방법으로 라우트를 설정하고 관리할 수 있게 해줍니다.
Next.js는 파일 시스템을 기반으로 한 라우팅을 내장하고 있습니다. pages 디렉토리 내의 파일 구조를 기반으로 자동으로 라우트를 생성합니다.
2. SPA란?
SPA(Single Page Application)는 웹 애플리케이션 또는 웹사이트를 설계하는 접근 방식 중 하나로, 서버로부터 완전한 새로운 페이지를 불러오는 대신 사용자와의 상호작용에 필요한 데이터만 비동기적으로 불러와서 현재 페이지에 동적으로 렌더링하는 방식입니다. 이러한 접근 방식으로 인해 웹 애플리케이션의 사용자 경험이 데스크탑 애플리케이션과 유사한 매끄러운 경험을 제공할 수 있습니다.
SPA의 특징:
SPA의 장단점:
장점:
단점:
SPA는 사용자와의 인터랙션이 많은 대화형 애플리케이션에 적합한 구조로, 매끄러운 사용자 경험을 제공하고자 할 때 자주 선택됩니다.
3. 상태관리란?
상태 관리란 애플리케이션의 상태를 중앙에서 효율적으로 관리하는 프로세스를 말합니다. 이는 특히 복잡한 사용자 인터페이스를 가진 대규모 애플리케이션에서 중요한 역할을 합니다. 상태 관리를 통해 애플리케이션의 다양한 부분에서 데이터의 일관성을 유지하고, 데이터 흐름을 명확하게 관리하여 개발 및 유지보수의 복잡성을 줄일 수 있습니다.
상태 관리의 중요성
리덕스 툴킷(Redux Toolkit)
리덕스 툴킷은 Redux의 공식, 권장 도구 모음으로, Redux를 더 쉽게 사용할 수 있도록 설계되었습니다. 기존의 Redux가 갖는 복잡성과 보일러플레이트 코드를 줄이면서도, Redux의 핵심 개념인 상태의 예측 가능성과 중앙 집중식 관리는 유지합니다.
리덕스 툴킷의 주요 특징
createSlice()
: 이 함수는 액션 타입, 액션 생성자 및 리듀서를 한 번에 생성합니다. 이를 통해 리듀서와 액션을 쉽게 정의하고 관리할 수 있습니다.configureStore()
: 이 함수는 Redux 개발자 도구 확장 기능과 미들웨어를 자동으로 설정해주며, 여러 리듀서를 쉽게 결합하여 스토어를 구성할 수 있습니다.사용 후기
원래 리덕스부터 학습한 후 리덕스 툴킷을 적용해봤기 때문에 그 편리함을 더 느낄 수 있었는데요. 리덕스만 사용했을 때는 setState의 파라미터로 불변성을 유지하기 위해 새로운 객체를 생성하여 전달해야했던 것과 마찬가지로 항상 새로운 객체를 리턴해야하는 번거로움이 있었습니다. 하지만, 리덕스 툴킷을 사용하면 변경되어야하는 부분만 코드로 작성하면 됐기 때문에 편리했습니다.