🤔 배경

저는 이전까지 프로젝트 경험이 거의 없었고 개발 지식도 부족한 상태에서 이번 멤버쉽 과정에서 프로젝트를 시작하게 되었습니다. 물론 이전 과정들에서 배운 내용들도 많았지만, 직접 프로젝트를 진행해보니 부족한 점이 굉장히 많았고 이후 여러 문제들을 만나게 되었습니다. 그 중에서 상태 관리에 대한 어려움이 가장 막막했던 것 같습니다. 예를 들면, 채널 생성 페이지를 구현하던 중, 문제가 생겼습니다. 사용자가 다른 페이지로 이동해 작업을 마친 후 다시 돌아왔을 때, 이전 데이터를 그대로 유지해야 했던 것입니다.

아래는 현재 구현된 화면입니다! 화면과 같이 그리기 페이지로 이동한 후 다시 돌아왔을 때, 유저의 정보가 남아 있어야 했습니다.

선따라-길따라-DDara-Chrome-2024-12-01-21-51-42-online-video-cutter.com.gif

😅 처음 선택: 로컬 스토리지

당시 데이터 유지라는 개념에 대해 아는 것이 없었기 때문에, 가장 먼저 떠오른 방법은 로컬 스토리지를 사용하는 것이었습니다. 로컬 스토리지는 브라우저에 데이터를 저장하기 때문에 새로고침이나 페이지 이동에도 데이터를 유지할 수 있다는 점에서 직관적이고 간단해 보였습니다.

그래서 로컬 스토리지의 setItemgetItem을 사용해 데이터를 저장하고 가져오는 방식으로 구현했습니다. 잘 작동하는 것 처럼 보였지만 추후 피드백을 통해 고치게 되었습니다

🙆🏻‍♂️ 피드백과 새로운 깨달음

데일리 스크럼 시간에 어제 한 일에 대해 발표하는 시간이 있었습니다. 그 과정에서 저는 위의 문제를 공유하게 되었고, 팀원들의 피드백을 받으면서 로컬 스토리지 대신 props나 전역 상태 관리가 더 적합하다는 점을 깨달았습니다. 이를 통해 유저 데이터를 로컬 스토리지에 저장할 때 발생할 수 있는 문제점들과, 전역 상태로 관리할 경우의 장점들에 대해 더 명확히 알게 되었습니다.

  1. 비효율 적인 데이터 동기화: 로컬 스토리지에 저장하면, 사용자가 페이지를 이동할 때 마다 데이터를 읽고 쓰는 작업을 반복해야 하여 성능의 문제가 생길 수 있었습니다.
  2. 보안 : 로컬 스토리지는 브라우저에 노출된 저장소 이므로, 유저의 데이터를 쉽게 조작하거나 삭제 할 수 있어 데이터 무결성을 해칠 수 있었습니다.
  3. 설계 : 아직 구현하지 못한 다른 페이지들에서도 해당 데이터가 사용될 수 있음을 깨닫게 되었고, 이를 고려할 때 전역 상태 관리가 필요하다고 판단했습니다.

이러한 이유들로 인해 데이터를 전역으로 관리해주기로 결정하였습니다!

👍🏻 전역 상태 관리 도입

이러한 과정들을 통해, 전역 상태 관리를 사용하는 것이 프로젝트에 더 적합하다고 판단했습니다. 팀원들과 상의하여 전역 상태 라이브러리를 사용하는데 쓰일 러닝 커브 대신, 멤버십 과정에서 배우고 많이 사용해 보았던 Context를 활용하기로 결정하였고 코드에 적용할 수 있었습니다.

import React, { createContext, ReactNode, useMemo, useState } from 'react';

export interface IUser {
  id: string;
  name: string;
  index: number;
  start_location: {
    title: string;
    lat: number;
    lng: number;
  };
  end_location: {
    title: string;
    lat: number;
    lng: number;
  };
  path: { lat: number; lng: number }[]; // 경로가 여러 개일 수 있도록 수정
  marker_style: {
    color: string; // color는 일반적인 문자열로 수정
  };
}

interface IUserContextProps {
  children: ReactNode;
}

interface IUserOptionContext {
  users: IUser[];
  setUsers: React.Dispatch<React.SetStateAction<IUser[]>>; // setUsers 함수 타입 수정
  resetUsers: () => void;
}
const defaultUserContext: IUserOptionContext = {
  users: [],
  setUsers: () => {},
  resetUsers: () => {},
};

export const UserContext = createContext<IUserOptionContext>(defaultUserContext); // 기본값을 null로 설정

export const UserProvider = (props: IUserContextProps) => {
  const [users, setUsers] = useState<IUser[]>([]);

  const resetUsers = () => {
    setUsers([]);
  };

  const contextValue = useMemo(() => ({ users, setUsers, resetUsers }), [users, setUsers]);

  return <UserContext.Provider value={contextValue}>{props.children}</UserContext.Provider>;
};

Context를 적용하면서 처음에는 복잡하게 느껴졌지만, 팀원들과 협업하면서 점차 그 장점들을 체감할 수 있었습니다. 특히, 데이터의 흐름을 명확하게 정의하고, 페이지 간 상태 전이를 간단하게 관리할 수 있는 점이 매우 유용했습니다. 또한, 이를 통해 상태 관리의 중요성효율적인 설계의 필요성을 더욱 깊이 이해할 수 있었습니다. 이 후, 다른 페이지들도 전역 상태를 활용하여 일관된 방식으로 데이터를 관리할 수 있었고, 이를 통해 상태 관리의 일관성이 높아져 프로젝트가 더욱 체계적으로 진행되었습니다. 이러한 경험은 향후 다른 프로젝트나 팀 협업에서도 중요한 경험이 될 것 같습니다.

😊 결론

이러한 경험은 단순한 기술적 문제 해결뿐만 아니라, 전반적인 개발 지식과 팀 협업의 중요성을 깨닫게 해준 값진 경험이었습니다. 이전까지는 문제를 어떻게 해결해야 할지 스스로 판단하여 때로는 아쉬운 결정을 내리기도 했습니다. 하지만 데일리 스크럼을 비롯한 팀원들과의 소통을 통해, 부족한 지식이나 경험을 서로 채워가며 더 나은 방향으로 나아갈 수 있었습니다. 팀원들의 빠른 피드백 덕분에 문제 해결이 더 효율적이고 정확하게 이루어졌고, 이 과정에서 중요한 것은 혼자서 모든 것을 해결하려 하기보다는 팀의 힘을 빌려 함께 성장해 나가는 것임을 깨달았습니다.