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주차] 송유선 미션 제출합니다. #19

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

Conversation

s-uxun
Copy link

@s-uxun s-uxun commented Nov 2, 2024

3주차 미션: React-Messenger


🪄 결과물

🩵 구현 기능

  • 피그마 화면 구현

  • Theme.tsx, GlobalStyle.tsx, Keyframe.tsx, svgr 등으로 디자인 시스템 구축

  • (채팅방 상단의 프로필을 클릭하면 사용자를 변경하도록 했어야 했으나... 디자인에 단체 채팅방이 있던 관계로) user의 name을 클릭하면 해당 user로 변경되도록 함

  • 모바일 디자인 구현 (PC에서만 보이며 시간은 실제 시간과 같음)

  • 그 외 자동 스크롤, 커스텀 커서, 애니메이션, 내용에 따라 동적으로 길어지는 textarea 등 구현

  • mockData를 json 파일로 구성해서 user의 사진, 이름 등이 채팅방에 잘 연동되도록 하였으며 상대관리 라이브러리를 활용해 전역에서 관리할 수 있도록 함. => 채팅 데이터 로컬 저장

  • 친구 목록에서 다른 친구들의 이름을 클릭하면 해당 유저로 전환할 수 있으며, 그냥 더블클릭할 경우 해당 유저와의 채팅방으로 이동 (이전 대화 내역이 없을 경우 채팅방 생성)

  • 친구 목록에서 내 프로필의 이름을 클릭하면 프로필 편집 페이지 이동, 프로필 편집 버튼을 통해 이름, 전화번호, 생일 수정 가능. SNS 페이지 접근 가능.

  • 채팅 목록에서 현재 currentUser가 참여하고 있는 채팅방들만 렌더링. 각 채팅방에서 앞에 단톡방 인원 수 별 프로필 사진 레이아웃 다르게 함 -채팅 목록을 한 번 클릭하면 해당 채팅방으로 들어가지고, 두 번 더블클릭하면 고정상태가 토글됨

🩵 느낀 점

세오스에서 디자이너 분과 함께하는 첫 협업이라 더욱 즐거웠던 것 같다. 이번에 시간을 많이 들이면서 느낀 점도 많고 새롭게 배운 점도 많은데, 시간이 없어 따로 기록을 남기지 못해 너무 아쉽다. (추후 트러블 슈팅과 관련한 글을 적어볼 예정...) 또 주석을 열심히 남기려고 했는데 막바지로 갈 수록 시간이 없어 코드 쓰는 것에만 급급했는데.. 나중에 차근차근 달아보려고 한다. 이번에는 정말 결과물의 완성도에 신경을 많이 쓰려고 했는데, svgr이나 theme.tsx를 처음 써보니 확실히 편했다. 그리고 svg에 대해 공부를 하면서 몰랐던 사실들을 많이 알게되었고, 예전에는 색상별, 사이즈별로 다 export해서 저장한 뒤에 불러왔었는데 그럴 필요가 없다는 것도 깨닫게 되었다. 다만 tailwind.css를 써보고 싶었는데 시간이 부족해서 도전하지 못한 게 아쉬웠다. 다음에는 꼭 활용해 보는 걸로... 모바일 디자인을 구현하면서 모바일 뷰포트를 어떻게 설정해야 할 지도 많이 배운 것 같다! 더 열심히 공부해서 2차 과제까지 잘 마무리하고 싶다.


2차 과제도 잘하고 싶었는데 시험 기간 이슈로... 많이 시간을 못 써서 너무 아쉽다. 일단 최대한 채팅방의 기능들을 다 구현하고 싶었는데, 생일인 사람 필터링해서 보여주는 것과 프로필을 최근에 업데이트한 사람들을 필터링해서 보여주는 것을 완성하지 못해서 아쉬웠다. 특히 업데이트한 사람들 띄우는 거 구현하려고 일부러 프로필 편집 기능까지 넣었는데... 거기서 멈추게 되었다 ^ㅠ^.. 그래도 기본적으로 논리 오류 없이 현재유저 - 친구- 채팅 - 채팅목록이 잘 연결되도록 데이터를 짠 것 같아 다행이다. 다음 과제도 파이팅해야겠다.

💡Key Questions

1️⃣ 디자이너로부터 전달받은 피그마 링크, 피그마 캡처본, 디자이너와의 소통 tmi

🎨 피그마 링크

🗒️ QA 시트

앞서 말했다시피 피그마에 디자인 요소들이 잘 정리되어 있어서 작업하기 편했다. QA는 단순히 카톡으로 진행하는 것보다 노션을 활용하면 좋을 것 같아 공유 페이지를 하나 만들고, 일정표와 QA 시트를 넣었다. 일정표에 있는 일정 페이지에 피그마 디자인이랑 프론트 구현 결과를 넣어놓았고 (새벽에 좀 더 수정 필요...), 이후 디자이너 분께서 QA 시트에 카드를 남겨주시면 확인하는 대로 작업해서 상태를 완료로 변경할 예정이다. 아쉬운 점은 최대한 완벽하게 구현해서 전달드리려고 하다 보니 링크 전달이 다소 늦어졌다는 점이다. 또 피그마에 나와 있지 않은 것 중에서 내가 짐작해서 한 부분들도 있었는데, 다음에는 낯 가리지 말고(?) 적극적인 소통을 시도해보면 좋을 것 같다.

2️⃣ JSX, JS, TSX, TS 각각의 확장자 개념 사용이유와 차이점에 대해 설명해주세요.

JSX, JS, TSX, TS의 차이는 사용하는 언어와 문법에 있다. JS는 순수한 JavaScript 코드로 구성된 파일이고, TS는 여기에 타입 시스템을 추가한 TypeScript 코드로 이루어져 있다. JSX는 JavaScript 코드 안에서 JSX 문법을 사용한 것이며, TSX는 TypeScript와 JSX를 함께 사용하는 것이다. 즉, JS와 TS는 각각 JavaScript와 TypeScript를 나타내며, JSX와 TSX는 해당 언어에서 JSX 문법을 사용한 파일을 의미한다.

간혹 .jsx로 작성된 파일을 VSCode에서 .js로 변경해도 코드가 잘 작동하는 경우가 있는데, 이는 몇 가지 이유 때문일 수도 있다. 우선 첫째로, Babel이나 TypeScript 컴파일러 같은 트랜스파일러는 파일의 확장자보다는 파일 내용과 설정 파일에 따라 코드를 변환한다. 따라서 .js 확장자를 가진 파일이라도 내부에 JSX 문법이 포함되어 있고, 트랜스파일러 설정이 이를 처리하도록 되어 있다면 문제없이 컴파일된다. 그리고 둘째로, VSCode와 같은 현대적인 에디터는 파일 확장자뿐만 아니라 파일 내용에 따라 구문 강조와 자동 완성 기능을 제공한다. 설정을 통해 .js 파일에서도 JSX 문법을 지원하도록 구성할 수 있다. 이는 개발자가 편의에 따라 확장자를 변경하더라도 코딩 경험에 큰 차이가 없게 만든다. 마지막으로, Webpack 등의 모듈 번들러는 설정에 따라 다양한 확장자의 파일을 처리할 수 있다. 로더(loader) 설정에서 .js 확장자에 대해 JSX 처리를 포함하도록 하면 .jsx 확장자를 사용하지 않아도 된다.

3️⃣ TypeScript를 사용하는 이유에 대해서 설명해주세요.

TypeScript를 사용하는 이유는 코드의 안정성과 가독성을 높이기 위해서이다. 계속 타입을 규정하는 게 다소 귀찮을 수는 있지만(?) 그래도 이러한 정적 타입 검사를 통해 컴파일 단계에서 오류를 사전에 발견할 수 있어 런타임 에러를 줄일 수 있다. 그렇기 때문에 대규모 프로젝트에서 특히 중요하며, 팀원 간의 코드 이해도와 협업 효율을 향상시킬 수 있다. 처음에는 왜 이걸 써야하는지 이해가 잘 안 되었는데.. (실수 안 하면 되니까.. 란 생각...) 그런데 알아보면서 큰 프로젝트에서는 나 혼자 개발하는 게 아니고 다른 사람의 코드들도 봐야하니까 디버깅 측면에서도 어느 정도 엄격한 규칙이 필요하다는 걸 이해하게 되었다. 뿐만 아니라 TypeScript는 최신 ECMAScript 기능과 추가적인 객체 지향 프로그래밍 개념을 지원하여 더 구조적이고 확장성 있는 코드를 작성할 수 있게 해주며, 코드 자동 완성 및 리팩토링 도구와의 호환성도 좋아 개발 생산성을 높일 수 있다고 한다.

4️⃣ SSR과 CSR 특성 및 차이점에 대해서 설명해주세요.

  • SSR (Server-Side Rendering): SSR은 서버에서 HTML을 렌더링하여 완성된 페이지를 클라이언트에게 전달하는 방식이다. 이는 초기 로딩 속도가 빠르고, 검색 엔진 최적화에 유리하다. 서버에서 모든 처리를 완료하기 때문에 클라이언트는 단순히 렌더링된 HTML을 받아서 표시만 하면 된다. 그렇기 때문에 저사양 기기나 JavaScript를 비활성화한 브라우저에서도 콘텐츠를 제공할 수 있다. 그러나 서버 부하가 증가할 수 있고 사용자와의 실시간 상호작용이 많은 애플리케이션에서는 성능이 저하될 수 있다.

  • CSR (Client-Side Rendering): CSR은 클라이언트 측에서 JavaScript를 사용하여 페이지를 렌더링하는 방식이다. 서버는 기본적인 HTML 구조와 스크립트 파일만 제공하고, 실제 콘텐츠는 클라이언트에서 동적으로 생성된다. 그렇기 때문에 사용자 경험을 향상시키고 애플리케이션의 반응성을 높일 수 있다. SPA 개발에 주로 사용되며, 페이지 간 전환이 부드럽고 빠르다. 하지만 초기 로딩 시간이 길어질 수 있고 SEO에 불리하며 JavaScript를 지원하지 않는 환경에서는 제대로 동작하지 않을 수 있다는 단점이 있다.

  • 차이점: SSR과 CSR의 차이는 페이지 렌더링이 이루어지는 위치와 그에 따른 성능 및 사용자 경험에 있다. SSR은 서버에서 페이지를 렌더링하여 초기 로딩 속도와 SEO에 강하지만, 그만큼 서버 자원이 많이 소모된다. 반면 CSR은 클라이언트에서 렌더링하여 서버 부하는 줄지만, 초기 로딩 시간이 길고 SEO에 취약하다. 따라서 애플리케이션의 특성이나 사용자 대상, SEO 필요성 등을 고려하여 적합한 렌더링 방식을 선택해야 한다.

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

React Router의 동적 라우팅(Dynamic Routing)은 애플리케이션 내에서 URL 경로의 일부를 변수처럼 활용하여 다양한 콘텐츠나 페이지를 동적으로 렌더링하는 기법이다. 이는 URL 경로에 파라미터를 사용하여 여러 유사한 페이지를 하나의 라우트로 처리할 수 있게 해준다. 예를 들어, /users/:id와 같은 경로에서 :id는 동적으로 변하는 값으로, 특정 사용자 ID에 따라 다른 사용자 프로필 페이지를 렌더링할 수 있다.

동적 라우팅은 주로 데이터에 따라 페이지 내용이 달라져야 하는 상황에서 사용된다. 예를 들어, 블로그 애플리케이션에서 각 게시물의 상세 페이지를 구현할 때, 게시물 ID를 URL에 포함시켜 해당 게시물의 내용을 동적으로 불러올 수 있다. 이를 통해 수많은 게시물을 개별적으로 라우팅하지 않고도 효율적으로 관리할 수 있다. 또한, 전자상거래 사이트에서 상품 상세 페이지를 구현할 때도 동적 라우팅을 사용하여 상품 ID에 따라 페이지를 동적으로 생성할 수 있다.

React Router의 동적 라우팅을 사용하면 코드의 재사용성을 높이고 라우팅 구조를 간결하게 유지할 수 있다. URL 파라미터를 컴포넌트 내에서 접근하여 필요한 데이터를 불러오거나, 조건부 렌더링을 통해 다양한 상황에 대응할 수 있다. 이러한 동적 라우팅은 사용자 경험을 향상시키고, 개발자의 작업 효율을 높이는 데 큰 도움이 된다.

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

네트워크 속도가 느린 환경에서는 사용자에게 원활한 경험을 제공하기 위해 여러 가지 UI/UX 디자인 전략과 기술적 최적화 방법을 적용할 수 있다. 먼저, UI/UX 측면에서는 로딩 시간을 체감적으로 줄이기 위해 Skeleton Screen을 활용할 수 있다. Skeleton Screen은 콘텐츠가 로드되기 전에 페이지의 레이아웃이나 콘텐츠의 윤곽을 미리 보여줌으로써 실제 로딩 시간을 가리며, 사용자로 하여금 페이지가 빠르게 로드되고 있다는 인상을 줄 수 있다. 또한, 로딩 애니메이션이나 진행 바를 통해 현재 로딩 상태를 시각적으로 전달하여 사용자의 불편함을 최소화할 수 있다.

기술적인 최적화 방법으로는 리소스의 크기를 줄이는 것이 중요하다. 이미지 최적화를 위해 적절한 해상도의 이미지를 사용하고, 이미지 압축 기술이나 차세대 이미지 포맷(WebP, AVIF 등)을 활용하여 전송되는 데이터의 양을 줄일 수 있다. 코드 스플리팅(Code Splitting)을 통해 필요한 코드만을 로드하고, 지연 로딩(Lazy Loading)을 적용하여 사용자가 필요한 순간에만 리소스를 로드함으로써 초기 로딩 시간을 단축시킬 수 있다. 캐싱(Caching)을 활용하여 자주 사용되는 리소스를 브라우저나 서버에 저장하여 재사용함으로써 네트워크 요청을 줄일 수 있다.

또한, 콘텐츠 전송 네트워크(CDN)를 활용하여 지리적으로 가까운 서버에서 리소스를 제공함으로써 응답 시간을 줄일 수 있다. HTTP/2, HTTP/3와 같은 최신 프로토콜을 사용하여 다중 요청을 효율적으로 처리하고, 압축 기술(Gzip, Brotli)을 적용하여 전송되는 데이터의 크기를 줄일 수 있다. 서버 사이드 렌더링(SSR)이나 정적 사이트 생성(SSG)을 도입하여 초기 페이지 로딩 시 완성된 HTML을 제공함으로써 사용자에게 빠른 응답을 제공할 수 있다. 이러한 전략들을 종합적으로 적용하면 네트워크 속도가 느린 환경에서도 사용자 경험을 크게 개선할 수 있다.

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

React에서 상태 관리는 컴포넌트의 동적인 동작을 구현하는 핵심 요소이다. useState와 useReducer는 함수형 컴포넌트에서 지역 상태를 관리하기 위한 훅(Hook)으로 사용된다. useState는 간단한 상태 값을 관리할 때 주로 사용되며, 상태 값과 그 값을 업데이트하는 함수를 반환한다. 이는 단순한 카운터나 입력 값 등의 관리에 적합하다. 반면에 useReducer는 복잡한 상태 로직이나 다수의 하위 값을 포함하는 상태를 관리할 때 유용하다. 리듀서 함수는 현재 상태와 액션을 받아 새로운 상태를 반환하며, 상태 변경 로직을 한 곳에서 관리할 수 있어 코드의 가독성과 유지보수성을 높여준다.

Context API는 React에서 전역적으로 상태를 공유하기 위한 내장 기능이다. 이를 통해 컴포넌트 트리의 깊은 곳에 위치한 컴포넌트에도 필요한 데이터를 전달할 수 있으며, props drilling을 피할 수 있다. 그러나 Context API는 상태 변경이 빈번하게 일어나는 경우 성능 저하가 발생할 수 있으며, 모든 하위 컴포넌트가 리렌더링될 수 있다는 단점이 있다. 따라서 낮은 빈도의 상태 변경이나 테마, 사용자 정보와 같은 글로벌 상태를 관리하는 데 적합하다.

전역 상태 관리 라이브러리인 Redux, MobX, Zustand 등은 복잡한 애플리케이션에서 상태 관리의 일관성을 유지하고 복잡성을 줄이기 위해 사용된다. Redux는 단일 스토어 패턴과 불변성을 기반으로 상태를 관리하며, 미들웨어를 통해 비동기 작업이나 로깅, 에러 처리 등을 효율적으로 처리할 수 있다. MobX는 반응형 프로그래밍을 활용하여 상태 변경을 자동으로 추적하고 업데이트하며, 코드의 양을 줄이고 선언적으로 상태를 관리할 수 있다.

요약하자면, useState와 useReducer는 컴포넌트 수준의 지역 상태 관리를 위해 사용되며, 간단한 상태부터 복잡한 상태 로직까지 처리할 수 있다. Context API는 전역 상태를 공유해야 하지만 상태 변경 빈도가 낮은 경우에 적합하다. 반면에 전역 상태 관리 라이브러리는 대규모 애플리케이션에서 상태의 일관성, 유지보수성, 확장성을 높이기 위해 사용되며, 복잡한 상태 관리 요구 사항을 효율적으로 처리할 수 있다.

Copy link

@psst54 psst54 left a comment

Choose a reason for hiding this comment

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

2주짜리라 그런지 파일이 진짜 많네요 정말 고생하셨습니다👍👍👍👍

Copy link

Choose a reason for hiding this comment

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

헉 페이지가 정말 많았네용,,, 고생하셨어요!!😂

Copy link

Choose a reason for hiding this comment

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

띠용

color: string;
}[];

const isGroupChat = participants.length > 1;
Copy link

Choose a reason for hiding this comment

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

우왕 그룹챗까지 구현하셨네요👍👍👍

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 +1 to +10
import { useState } from "react";
import styled from "styled-components";
import { Pin } from "../../assets/icons";
import { useNavigate } from "react-router-dom";
import useChatroomStore from "../../stores/ChatroomStore";
import useChatStore from "../../stores/ChatStore";
import useUserStore from "../../stores/UserStore";
import { useTitle } from "../hooks/useTitle";
import ProfileGroup from "./ProfileGroup";
import { newDate } from "../hooks/useTime";
Copy link

Choose a reason for hiding this comment

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

유션님도 절대 경로를 사용해서 Import하시면 더 편하실거에요!

Copy link

Choose a reason for hiding this comment

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

희원 언니가 지수 언니의 코드에 리뷰 남긴 곳에 절대 경로 craco에 대한 걸 알려주셨는데 한 번 참고해 보세용 좋은 것 같습니다 👍🏻👍🏻

Copy link
Author

Choose a reason for hiding this comment

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

절대 경로..!! 담에 꼭 써보려구요.. import 때 자동완성되니까 별 생각이 없었는데... 절대 경로를 안 쓰니까 나중에 파일들 옮기거나 폴더 바꿀 때 너무 오류가 많이 나서 힘들었어요...

}
}

// 1클릭과 2클릭 구분 위해 timeout 사용 (이거 없으면 더블 클릭해도 그냥 채팅방 들어가짐)
Copy link

Choose a reason for hiding this comment

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

앗 제가 알기로는 doubleclick 이벤트가 있는 것 같은데 이 이벤트가 올바르게 작동하지 않았나요?

Copy link
Author

Choose a reason for hiding this comment

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

저도 첨에는 이걸 썼는데..!!! 모바일에서는 적용이 안 되더라구요...😂 그래서 timeout 쓰는 걸로 로직을 바꿨습니당


export function MobileTop() {
const currentTime = useTime()
.replace(/오전|오후/g, "")
Copy link

Choose a reason for hiding this comment

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

오 정규식,,, 짱신기해용👍👍


useEffect(() => {
const userAgent = navigator.userAgent;
const isMobileDevice = /android|iphone|ipad|windows phone/i.test(userAgent);
Copy link

Choose a reason for hiding this comment

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

오 이렇게 하면 유저가 사용중인 기기가 뭔지 알 수 있나요?!

Copy link
Author

Choose a reason for hiding this comment

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

모바일 기기인지 감지할 수 있어요!! 짱~~

Copy link

Choose a reason for hiding this comment

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

😯😯짱 세심하네요...!!!

@@ -0,0 +1,70 @@
import { create } from "zustand";
Copy link

Choose a reason for hiding this comment

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

오 zustand 쓰시는구나 zustand 좋아요?? 저도 써보고싶은데 진입장벽 괜찮나여

Copy link

Choose a reason for hiding this comment

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

@psst54 이번 과제에 zustand 쓴 사람만 지금까지 확인된 바... 3명이어서 뭔가... 저도 써보고 싶네욥... ㅎㅎㅎ

Copy link
Author

Choose a reason for hiding this comment

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

주스탠드 조아요 try~~

};

// 프사 색상 랜덤으로 부여하는 부분
const profileColors = ["#FCC", "#D193F6", "#FF7F7F"];
Copy link

Choose a reason for hiding this comment

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

헉 디테일 좋아요🤭

<GlobalStyle />
<ThemeProvider theme={Theme}>
<Router>
<Routes>
Copy link

Choose a reason for hiding this comment

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

우오아 페이지가 진짜 많네용 수고 많으셨습니다 😍

function App() {
// 뷰포트 높이 계산
Copy link

Choose a reason for hiding this comment

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

오오!!! 모바일 환경에서 정확하게 높이를 측정할 수 있게 하셨네용... 주소창이나 탐색바 등 UI 요소가 동적으로 변할 때 엄청 유용할 것 같아요!!
저는 이런 것까지 고려하진 못해서 모바일로 들어갔을 때 부자연스러운 면이 있는데... 배워갑니다 👍🏻👍🏻
근데 이 함수는 컴포넌트가 처음 렌더링 될 때 한 번 높이를 계산하며 실행되고 그 뒤로는 안 될 것 같은데... 그래서 화면을 처음 키고 바로 뭔가 모바일에서 화면을 가로로 변경한다든가 하는 높이의 변화가 측정되지 않을 것 같아용 window.addEventListener("resize", setScreenSize); 이런 식으로 화면의 높이가 resize될 때의 이벤트 리스너를 추가해 보시는 건 어떨까용??

Copy link
Author

Choose a reason for hiding this comment

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

아하..!! 뭔가 전 사용자의 기기 높이를 다시 계산할 일이 없을 것 같다고 생각하긴 했어요..! 그리고 기기를 돌렸을 때 그 가로 너비만큼을 세로 길이로 재설정하면 채팅방 높이가 너무 짧아져서... 내용들을 확인하기가 힘틀테니까..?! 그럴 바엔 차라리 스크롤이 생겨서 밑으로 내리더라도 높이를 유지하는 게 더 낫다고 판단했습니다. 그렇지만 민재님께서 이런 부분까지 세심하게 봐주서서 넘 감동했어요,,,🥹 만약 가로 방향의 반응형도 꼭 고려해야하는 서비스를 만들게 된다면 잊지 안혹 적어주신 내용들을 적용해볼게요!

"typescript": "^4.9.5",
"web-vitals": "^2.1.4"
"web-vitals": "^2.1.4",
Copy link

Choose a reason for hiding this comment

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

이건 웹 애플리케이션의 성능을 측정하는 지표... 를 나타내기 위한 라이브러리라고 방금!! 찾아봤는데 이건 어떤 이유에서 사용하신 걸까용?!!! 어떻게 활용하신 건지 궁금합니다... 🔎🔎

Copy link
Author

Choose a reason for hiding this comment

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

오잉 제가 추가한 거 아니에요 ㅋㅋㅋ 실수로 삭제했었다가 추가되었나..?

Copy link

Choose a reason for hiding this comment

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

이거 아마 기본적으로 create react app으로 프로젝트 만들면 들어갈거에요!

Copy link

Choose a reason for hiding this comment

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

미미재님께도 있답니다...✨

Copy link

Choose a reason for hiding this comment

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

아니이런바보가튼.. 이렇게 무지를 들켜버렷다..

@@ -0,0 +1,16 @@
import * as React from "react";
import type { SVGProps } from "react";
const SvgAddFriend = (props: SVGProps<SVGSVGElement>) => (
Copy link

Choose a reason for hiding this comment

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

오!! 저도 svg 파일을 컴포넌트화 해서 사용했는데 SVGProps 이 타입은 몰랐어서 따로 interface 정의해서 color을 props로 전달했었는데 이런 유용한 방법이... 이걸 쓰면 {...props} 이 안에 다양한 속성들을 그냥 전달할 수 있는 것 같네용 완전 좋다... 🔥🔥

Copy link
Author

Choose a reason for hiding this comment

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

svgr을 꼭 사용해보시는 걸 추천합니다..🤍


export default ChatInfo;

const Container = styled.div<{ isFixed: boolean }>`
Copy link

Choose a reason for hiding this comment

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

이렇게 styled-component를 한 파일에 함께 써 놓으면 관련된 코드(스타일과 컴포넌트)가 가까이 있어 코드 흐름을 이해하기 쉬워질 것 같습니다 👍🏻👍🏻
저는 항상 코드가 길든 작든 분리!!분리... 하는 걸 좋아해서 스타일 컴포넌트를 항상 분리했었는데 파일을 이곳 저곳 왔다 갔다 하며 확인하려니 힘들더라고요 언제나 장단점이 항상 공존하는 것 같아용...

너무 코드가 길어져서 가독성이 약간 떨어지는 것 같을 때, 혹시나 비슷한 스타일을 여러 곳에서 재사용해야 하는 경우에는 스타일을 별도의 파일로 분리해서 사용하는 방법도 고려해 보시면 좋을 것 같아용 🔥

};

// 엔터키로 전송할 수 있도록 처리 (Shift + Enter로 줄바꿈)
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
Copy link

Choose a reason for hiding this comment

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

우와 성준 회장님께서 보내주신대로 이미 한글이 두 번 입력되는 걸 미리 방지하셨네요 정말 세세하십니다 👍🏻👍🏻🫢

if (!value.trim() || !currentUserId || !roomId) return; // 입력값이나 현재 유저 id나 채팅방 id가 없으면 전송 X

const newChat = {
id: Date.now(),
Copy link

Choose a reason for hiding this comment

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

Date.now()는 현재 시간을 밀리초 단위로 반환하는데, 이는 동일한 시점에 여러 메시지가 전송될 경우, 그 메시지들의 ID가 중복될 가능성이 있습니다!!
특히, 빠르게 여러 메시지를 전송하는 상황에서는 같은 ID가 생성될 수 있으니 고유성이 보장되는 UIUD 같은 표준을 사용해 보시는 것은 어떨까용??

저는 id를 다 숫자로 하드코딩해서 이런 부분까지는 생각 못했는데 유선 님의 코드를 보니 저도 리팩토링할 때 id를 UIUD로 생성하는 방향으로 바꿔봐야 할 것 같습니다 ㅎㅎ

Copy link
Author

Choose a reason for hiding this comment

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

오 좋은 것 같아요~~ 다음엔 UIUD도 고려해볼게요!!!


const Container = styled.div``;

const FHeader = styled.div`
Copy link

Choose a reason for hiding this comment

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

이건 저도 똑같아서 할 말이 없습니다...... 🥹🥹 저는 급하다보니 시멘틱 태그까지 미처 생각하지 못하고 냅다 div나 span을 박아버리는 습관이 있는데 리팩할 때 고쳐보려고용... 유선 님께서도 리팩 때 수정해 보시는 게 어떠실까용...

그리고 const Container = styled.div``; -> 이건 부모 컴포넌트가 상위에 있어야 한다는 것 때문에 이렇게 설정해 두신 걸까용?? 저는 이럴 때 그냥 <></>을 사용하긴 합니당 스타일이 필요 없는데도 불구하고 불필요한 div가 추가되는 것보다는 그냥 <></>이렇게 해두는 게 나을 것 같아서용...!!!

이런 의도가 아니셨다면 그냥 참고만 해주시면 감사할 것 같습니답 하하 🫨

Copy link
Author

Choose a reason for hiding this comment

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

ㅋㅋㅋㅋ 이거 까먹고 있었어요...😂 큰.. 의미는 없었구요. 원래 나중에 전체 스타일이나 레이아웃을 조정할 일이 생길 걸 대비해서 늘 먼저 저렇게 작성해 놓고 시작하는 편입니다... 다음엔 작업 끝내기 전에 다시 한 번 확인하고 안 쓰는 것들은 정리해야겠네요!

Copy link
Member

@ddhelop ddhelop left a comment

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.

4 participants