앱센터 5번째 차시 - 인스타그램 디엠창 클론 코딩

유희원·2025년 11월 11일

앱센터

목록 보기
6/6
post-thumbnail

이번에는 인스타그램 디엠창 클론 코딩을 해보았습니다.
클론 코딩을 진행해보며 배운 점을 간단하게 리뷰해보려고 합니다!

1. 사이드바 제작

가장 먼저 사이드바 제작을 해주었습니다.

위 사진과 같이 components 폴더에 Sidebar라는 별도의 파일을 만든 후 사이드바를 두 가지 버전으로 만들어주었습니다.

사이드바 기본 버전
사이드바 컴팩트 버전

이렇게 두가지 버전으로 나누어 생각해서 제작을 해주었습니다.

import { useLocation } from "react-router-dom";
import Sidebar from "./Sidebar";
import SidebarCompact from "./SidebarCompact";
export default function SidebarComponents() {
  const location = useLocation();
  const isDm = location.pathname.startsWith("/dm");
  return isDm ? <SidebarCompact /> : <Sidebar />;
}

또한 index.tsx라는 중간 관리 컴포넌트 파일을 만들어서 dm 페이지에서는 자동으로 사이드바 컴팩트 버전이 보이도록 설정해주었습니다.

(근데 벨로그 작성하며 보니 dm 페이지에 대해서만 index.tsx 파일을 초기에 작성해두었더라고요..! 다른 페이지에 대해서도 page 파일에서 일일히 라우팅 처리하지 않고 index.tsx 파일을 이용했어도 좋았을 것 같아요..)

또한 처음에 제가 인스타그램 아이콘을 구현하기 위해 사용했던 방법은 라이브러리를 이용한 방법이었는데요..

import {
  Home,
  Search,
  Compass,
  PlaySquare,
  Send,
  Heart,
  Plus,
  Menu,
  Grid3X3,
} from "lucide-react";

아이콘이 기존 인스타그램과 너무 다르고 이질감이 들어서 결국 피그마에서 아이콘을 일일히 수정해가며 svg 파일로 불러와주었습니다!

아이콘 싱크로율을 최대한 맞추는 게 어려웠고, 파일로 불러오다보니 아이콘 사이의 간격과 크기를 일정하게 해주는 과정이 오래걸렸던 것 같습니다.

그리고 사이드바 두가지 버전의 통일성을 맞춰주는 과정도 복병이었습니다..둘이 아이콘 위치가 자꾸 너무 달라서 맞춰주느라 애를 좀 먹었던 것 같습니다.

2. 채팅창 구현

디엠 채팅창은
1. 디엠 채팅 목록
2. 디엠 상세 채팅창
위 두가지 영역으로 나누어서 제작해주었습니다.

// DmList.tsx (디엠 목록)

  • flex-1 overflow-y-auto : 디엠창과 분리되어 스크롤되도록
  • 목록을 클릭하면 onSelectDm(dm.id)을 통해 해당 디엠 상세창으로 이동할 수 있도록.
  • 프로필 이미지를 불러오고, 프로필을 누르면 <a> 태그를 통해 해당 링크로 이동되도록.

// DmDetail.tsx (디엠 상세창)

  • <a> 태그를 통해 새 탭으로 프로필 링크로 이동되도록.
  • prev(이전 메세지 객체)를 구해서 날짜 및 시간을 표시할지 여부인 showTime 계산.
  • 줄 전체를 group으로 감싸고, 말풍선 바로 옆에 hover 시 나타나는 아이콘 3개를 배치.
  • opacity-0 + group-hover:opacity-100으로 마우스 커서가 해당 줄에 올라갔을 때만 보이게 함. (처음에는 투명이다가 마우스가 올라가면 완전 불투명으로 보이게 한다는 소리)
  • 말풍선 옆에 101 x 34px 정도의 여백을 두어서 사용자가 창 크기를 줄일 때 메세지 줄바꿈 여부를 결정. (여백 이상의 창 크기를 유지한다면 줄 바꿈 x)
  • 유저가 Enter 키를 누르면 handleSendMessage() 함수가 실행돼서 메세지가 보내지도록.
  • 채팅창에서 입력이 비어 있으면 아이콘 3개, 입력이 있으면 Send 버튼이 뜨도록.

3. 로직 구현

1. 채팅 상대별로 채팅창 내용이 분리되도록
2. 채팅 보낸 내용이 새로고침해도 날아가지 않도록
"새로고침 하지 않아도"
3. 채팅을 보내면 가장 최근에 보낸 메세지가 채팅 목록에 뜨도록
4. 가장 최근에 대화를 나눈 채팅창이 상단에 뜨도록
5. 가장 최근에 보낸 메세지를 보낸 시간 경과 값이 바뀌어 보이도록

사실 로직 구현 부분은 아직 부족한 점이 많아 지피티의 도움을 많이 받았는데요..! 코드에 대해서 최대한 정리를 해보자면 아래와 같습니다.

// DmList.tsx (디엠 목록)

  • 더미데이터를 넣어 디엠 목록이 뜨도록 함.
    (더미데이터 항목 중 message, time은 초기 값을 표시하기 위한 용도)
  • DmListProps를 통해 디엠 목록에서 클릭한 사용자 아이디 값을 위로 전달할 수 있도록 함.
  • 최신 메세지 가져오기 -> 로컬스토리지에서 가장 최신 메세지를 가져오되, 최근 메세지가 없거나 예외가 발생하면 더미 데이터 안의 내용들을 가져오도록 함.
  • 시간 포맷
    -> 60분 미만 : 분 단위,
    24시간 미만 : 시간 단위,
    7일 미만 : 일 단위,
    그 이상 : 주 단위
    로 표시될 수 있도록 설정.
  • DmDetail에서 로컬스토리지에 최근 메세지를 저장 -> 상태 공유를 위해 dm-updated라는 이벤트 함수를 만들어 신호를 줌 -> 강제 리렌더링.
  • 가장 최근 대화 순 정렬 : getLatestPreview를 통해 각 항목별 가장 최근 메세지를 가져온 후, time을 Date.parse()를 통해 숫자 타임스탬프로 바꿔서 비교하는 방식. (bTime - aTime 내림차순 정렬)

// DmDetail.tsx (디엠 상세창)

  • DmDetailProps를 통해 사용자 아이디를 가져옴.
  • 위 사용자 아이디에 해당하는 유저의 스레드 메세지를 Json 배열로 반환해서 불러옴.
  • 다른 사람의 아이디를 클릭해서 dmID가 달라지면 그 아이디에 해당하는 스레드 메세지를 보여주도록.
  • chatMessages가 바뀔 때마다, 즉 새로운 메세지가 추가될 때마다 자동으로 스크롤하여 맨 아래로 내리도록.
  • 스레드 메세지 배열을 로컬스토리지에 저장하고 dm-updated 신호를 통해 DmList에서 리렌더링하도록.
  • 메세지 전송 : 공백만 있는 입력은 무시, 새 메세지 객체 생성 -> 새로운 메세지를 기존 배열 뒤에 붙임 -> 로컬스토리지에 저장하고 신호 보냄 -> 입력창 비우기 순서. (+ enter 키로도 메세지가 전송되도록 설정)
  • 회색으로 날짜 및 시간이 뜨는 건
    1. 첫 메세지 2. 이전 메세지와 10분 이상 차이날 때 로 설정

4. 최종 수정 및 결과

메모장에 생각나는 것들 하나씩 정리해보고 수정해나가는 식으로 진행해보았습니다.

해보면서 느낀 점은.. 
생각보다 버튼 및 기능이 너무 많아서 놀랐고 아이콘들의 간격을 맞추거나 
한세트처럼 보이게(이질감이 들지 않게) 하는 것이 되게 까다로웠던 것 같다. 
아이콘을 하나하나 불러와서 하니 노가다가 힘들지만 뿌듯한 점도 있었다.
그리고 인스타그램 요소들 관리자 도구로 찍어가면서 폰트 설정하고 이러는 거 좀 재밌었음.
아이콘 배치나 띄우는 부분 처리하면서 flexbox에 대한 지식 한계도 
느껴서 좀 더 공부해야겠다고 느꼈고, 
항상 느끼는 거지만 로직 구현에 대한 부분 공부도 많이많이 필요할 것 같다..
(타입스크립트, 자바스크립트..)
profile
똑똑한 망치

0개의 댓글