스포트라이트 (SPOT-LIGHT) 프로젝트 회고

창우·2024년 9월 9일
1

TeamProject

목록 보기
2/2
post-thumbnail

개요

스포트라이트 (Spotlight)

  • 6개월간 진행했던 풀스택 데브코스의 최종 프로젝트인 스포트라이트가 드디어 끝이났다
  • 프로젝트를 진행하면서 주어진 한 달이라는 시간이 정말 쏜살같이 지나간 느낌이다
  • 과정의 마무리를 부끄럽지 않게 하고 싶은 욕심이 가득 담겨있었던 프로젝트이다

프로젝트 소개

최애의 이야기가 있는 곳! 스포트라이트

영화에 나온 그 장소, 애니메이션에서 등장한 그 배경, 내 최애가 다녔던 그 맛집! 혹시 어딘지 궁금하진 않으셨나요?

스포트라이트는 셀렉션을 통해 여러분의 특별한 장소를 공유할 수 있는 지도 중심의 커뮤니티 웹 서비스입니다.

사용자는 자신이 아끼는 스팟들을 하나의 셀렉션으로 묶어 다른 사람들과 공유 할 수 있습니다.

스포트라이트와 함께 일상 속의 최애 장소를 기록하고, 공유하며, 새로운 경험을 해보세요!

담당 기능

  • UI, UX 디자인
  • 메인 페이지 기능 구현 ( 인기 셀렉션, 해시태그 맞춤 셀렉션 )
  • 검색 페이지 기능 구현 ( 카테고리 필터링, 해시태그 검색, 자동완성, 해시태그 추천 )
  • 마이 페이지 기능 구현 ( 프로필 변경, 셀렉션 상태 설정, 삭제, 관심태그 설정 )

검색 페이지

  • 스포트라이트의 검색 페이지에서는 카테고리, 해시태그, 지역, 정렬에 따른 다양한 필터 기능을 제공하기에 특히 설계에 많은 시간을 할애해야 했다.
  • 유틸리티 함수를 만들어 쿼리스트링을 활용해 모든 필터데이터들을 처리하도록 하였고, 검색 페이지 쿼리문에 필터 데이터 여부에 따라 조건부 조회를 하여 받도록 하였다.

세션 태그 저장과 태그 기록 동기화 문제

  • 사용자가 검색한 태그 기록을 세션에 저장하여 페이지를 이탈 한 후 다시 접근하더라도 셀렉션을 필터하도록 구상하였다.
  • 초기에는 태그를 추가/삭제 할 때 마다 세션 데이터에 접근하여 수정하도록 했다.
  • 하지만 해당 방식은, 태그들이동일한 세션 아이디에서 배열형태로 처리하고 있기에 기존 세션태그를 받아서 처리 하게되면 이전 데이터의 중복이 생기게 되어 하나의 태그만을 추가/삭제하더라도 모든 태그 배열을 재할당 해야하는 문제가 있었다.
  useEffect(() => {
    if (tagInputRef.current) tagInputRef.current?.focus();
    const addtagList = []; // 검색 태그 기록을 받을 임시 배열
    const HeaderSearchTag = searchParams.get(QUERY_STRING_NAME.tags);
    if (HeaderSearchTag) addtagList.push(HeaderSearchTag);
    // 만약 헤더의 검색 바를 통해 검색하는 경우, 해당 태그 추가
    const storedTags = sessionStorage.getItem(QUERY_STRING_NAME.tags);
    if (storedTags) {
      const parseStoredTags = JSON.parse(storedTags);
      parseStoredTags.forEach((tag: string) => {
      addtagList.push(tag);
      });
    }
    // 초기값으로 세션에 있는 데이터들을 전부 받아와 데이터 동기화

    if (addtagList.length > 0) {
      addtagList.forEach((tag: string) => {
      addQueryString(QUERY_STRING_NAME.tags, tag);
    });
    setTagList(addtagList);
  }
  }, []);
// 검색 기록에 해당하는 태그들을 쿼리스트링에 적용함으로 필터, 

  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    // 태그 필터 시 동작
    e.preventDefault();
      const addTag = tagValue.replace(/\s+/g, "");
      if(searchValidator(addTag, tagList)){ // 생성 유효성 검사
        const updatedTagList = [...tagList, addTag];
        setTagList(updatedTagList);
        sessionStorage.setItem(
          QUERY_STRING_NAME.tags,
          JSON.stringify(updatedTagList)
        );
        // 검색 기록 태그리스트에 데이터 추가, 이후 세션에 저장
        addQueryString(QUERY_STRING_NAME.tags, addTag);
        // 쿼리스트링에 태그 추가
        setVisibleAutoCompletion(false);
      } else {
        setTagValue("");
        setVisibleAutoCompletion(false);

      }
  };

다음과 같이 세션에 저장한 태그리스트와 검색 기록 태그리스트를 분리함으로 해결하였다.
검색 기록 태그리스트를 세션 값을 초기값으로 하는 useState로 처리하고, 해당 데이터만을 세션에 담는 식으로 구상을 하니 태그 중복과 불필요한 재할당 문제를 해결 할 수 있었다.

메인 페이지

  • 메인페이지는 섹션별로 추천하는 셀렉션 (인기, 사용자 태그 맞춤, 서비스 추천 ) 리스트를 제공한다.
  • 북마크와 같은 즉각적인 상호작용이 없는 셀렉션들의 경우, 서버사이드 렌더를 활용할 수 있을 것 같아 적용해 보았다.

서버사이드 렌더링 데이터 빌드 중 누락, 불일치 오류

  • 빌드를 하는 과정에서 데이터가 누락이 되거나 렌더링시 결과가 불일치하는 문제가 생겼다.
  • 동적으로 데이터를 받아오는 서버 컴포넌트를 적절하게 처리하지 않았을 때 발생하는 문제였다.
  • 또한, useSearchParams Hook을 통해 받아오는 데이터들이 정상적으로 렌더링이 되어지지 않았다.
export const dynamic = "force-dynamic";

export default async function Home() {
  try {
    const popularSelections = await fetchHandler("api/selections/popular");
    return (
      <Suspense fallback={<PageLoading />}>
      // 내부 컴포넌트에서 UseSearchParams를 통해 데이터를 처리함으로,
      // Suspense를 통해 해당 데이터가 삽입되기까지 fallBack 제공
        <main className="...(style)">
          <BannerSection />
          <DisplaySection />
          <PopularSection selections={popularSelections} />
          <RecommendationSection />
        </main>
      </Suspense>
    );
  } catch (error) {
    console.error(error)
    return <PageError/>
  }
  • 빌드 과정 이후에도 Fetch를 통해 데이터를 받는 컴포넌트를 force-dynamic을 통해 동적 컴포넌트임을 명시하였다.
  • 또한 useSearchParams에 데이터가 들어오기 전 빌드가 되어 HTML이 생성되는 오류를 방지하기 위해 Next에서 제공하는 Suspense 컴포넌트를 활용하여 데이터를 기다리도록 하였다.
  • 두 방법을 통해 빌드 과정에서 생기는 오류를 해결할 수 있었다.
  • 확실히 서버사이드렌더에 대한 이해와 Next에 대한 경험이 부족하다고 느낄 수 있었던 이슈들이었다.

4L 회고

Liked 👍

1. 구체적인 기획

  • 스포트라이트 프로젝트는 특히 기획 단계에서 많은 시간을 할애했다.
  • 해당 기간 동안 WBS, 기능명세, API 명세등을 활용하여 최대한 팀원들이 기능에 대해 명확히 이해하도록 노력했다.
  • 그로인해 기획 기간이 길어지고, 개발시간이 부족하지 않을까에 대한 불안도 있었지만, 기획에 시간을 소모한만큼 개발단계에서의 부가적인 회의가 줄어들었다.
  • 결과적으로 더 빠르고 수월하게 프로젝트를 진행할 수 있었다.

2. 명확한 업무 분담

  • 다섯명 모두 풀 스택으로 개발을 진행했기에 업무를 분담할 때 기능을 기준으로 나누었다.
  • 이러한 업무 분담은 프론트-백 엔드 간 소통간 발생하는 시간비용을 최소화 할 수 있었다.
  • 개발기간이 여유롭지 않은 현재와 같은 상황에서 정말 효율적인 작업 방식이었다.

3. 풀 사이클 경험

  • 풀 사이클을 직접 경험했던 것이 프로젝트를 진행하면서 가장 좋았던 부분이다.
  • 프론트엔드 직군을 희망하지만, 백엔드 기능도 도맡아 구현하다보니 전체적인 개발 프로세스를 확실하게 익힐 수 있었다.
  • 이러한 경험은 앞으로 백엔드 파트와의 API 명세구현, 데이터 모델 생성과 같은 설계 단계에 소통에서 정말 유의미한 도움이 될 것이라고 생각한다.

Learned ✏️

1. 새로운 기술 스택(Next, tailwindCSS) 학습

  • 이전부터 Next를 학습해보고 싶었는데, 운이 좋게도 이번 프로젝트의 프레임워크로 Next.js를 활용할 기회를 얻게 되었다.
  • 본격적으로 개발을 진행하면서 대략적인 Next.js의 생태, appRouter 방식의 라우팅 동작에 대해 경험할 수 있었다.
  • 서버사이드 렌더를 직접 프로젝트에 적용시킴으로 그 장점을 체감할 수 있었다.

2. 백엔드 로직에 대한 이해

  • 프론트 엔드 개발을 희망하여 해당 기술스택을 위주로 학습했기에 백 엔드 이해 능력이 다소 부족했다.
  • 하지만 이번 프로젝트를 진행하면서 백엔드 로직 외에도 모델 매핑, 유효성 검사 등 기본적인 레이어를 이해할 수 있었다.
  • 특히 쿼리문 작성을 어려워했었는데 Knex 라이브러리의 도움을 받아 빌더를 통해 작업하다보니 수월하게 진행할 수 있었다.
  • 아직은 정말 미숙하지만 나름대로 백엔드 성능 최적화에 욕심도 생겼다.

Lacked 😂

1. 현업보다는 분업 느낌

  • 기능을 나누고, 이를 풀스택으로 개발하다보니 협업을 하는 것이 아닌 분업을 하는 느낌이 들었다.
  • 서로가 철저하게 업무를 분리하여 담당하다보니 각 기능마다 팀원 각각의 코드 스타일이 반영이 되었다.
  • 프로젝트 진행 기간이 짧아 어쩔 수 없는 상황이지만, 그래도 조금 더 구체적인 컨벤션을 지정하고 작업을 했으면 하는 아쉬움도 들었다.

2. 부족한 코드 리딩 실력

  • 코드 리뷰 세션을 가지면서 내 코드 리딩 능력이 부족하다는걸 몸소 느꼈다.
  • 팀원의 코드를 보고 의문을 가지고 접근해야하는데 그 과정이 뭔가 자연스럽지 않았다.
  • 리딩 능력의 부족으로 팀원에게 다방면의 코딩 방법을 제공하기에도, 팀원의 코드를 통해 내가 성장하기에도 어려움이 있었다.
  • 다음 프로젝트가 진행되기 까지, 반드시 향상시키고 싶은 부분이다.

LongedFor ✨

1. 담당 업무에 대한 책임감

  • 팀 프로젝트인만큼, 팀원에게 누를 끼치지 않으려면 적어도 내가 담당한 기능만큼은 최선을 다해야겠다는 다짐을 했다.
  • 그런 코드치고는 애석하게도 첫 QA 세션 단계에서 수많은 이슈들을 가져왔지만(😂) 최대한 일정을 쪼개가며 코드를 리팩토링 했다.
  • 트러블 슈팅, 기능 구현, 발표 준비까지 일정이 굉장히 빠듯했지만 성공적으로 마무리하고 좋은 평가를 받으니 내 자신이 대견했다.

2. 개발에 대한 흥미

  • 돌이켜보니 스포트라이트 프로젝트는 잠깐의 휴가를 제외하고는 주말을 구분하지 않고 매일 일정 시간 이상의 작업을 했다.
  • 한 달 남짓한 기간이라 바쁠수밖에 없었지만 그 시간동안은 단순한 작업조차 정말 지루하지 않게 느껴졌다
  • 아마도 내가 흥미를 가지고 있는, 매력적인 주제의 서비스라고 생각이 들었기 때문에 개발이 즐거웠던 것 같다.
  • 개발자로의 취업에 있어,도메인에 대한 흥미 역시 정말 중요한 선택요소라는걸 새삼 깨닫게 되었다.

마치며

  • 처음 팀이 구성되었을 때, 초기 기획안이 엎어지는등 여러 우여곡절이 많아 프로젝트를 성공적으로 마칠 수 있는지에 대한 걱정이 많았다.
  • 그렇지만 팀원 모두 열심히 해주었기에 만족스러운 결과물이 나온 것 같다. 다들 정말 고생하셨습니다!
  • 힘들기도 정말 많이 힘들었지만, 그만큼 재미있었고 많은 성장을 할 수 있었던 프로젝트 였다.

(참고) 발표자료

SPOTLIGT_PRESENTATION

profile
물을 줘야지😂

0개의 댓글

관련 채용 정보