팀프로젝트 - Dev-Note (프로젝트 기록노트)

개요

1. 진행 기간: 2024.08.28 ~ 2024.09.03

2. 인원: 5명

3. 개발환경

- React, Vite

- 전역상태관리: Context API

- 데이터베이스: Supabase

- Github, Figma, Slack, Notion 등 활용

 

4. Github 링크

프로젝트 소개

주제 선정 계기

단순 학습 용도가 아닌 실생활에서 활용할 수 있는 프로젝트를 만들어보고싶어 시작된 아이디어다!

내일배움캠프에서 빠르게 여러 프로젝트들을 진행하면서 발표를 듣지못한 다른 팀들의 프로젝트도 궁금하고, 내 프로젝트도 한 곳에 모여있으면 뿌듯할 것 같다는 생각이 들었는데 이 기회에 프로젝트들을 한눈에 모아볼 수 있는 기능을 만들어보기로 했다.

 

주요 담당 기능

1. Post fetch 및 Context Provider

2. Post 작성, 수정

- 썸네일 이미지, 제목, 기술 스택, 내용 등의 텍스트, 진행기간(날짜) 입력 + 유효성 검사

- 수정시 기존 Post 데이터와 비교해 달라진 부분만 update

3. ImageInput 컴포넌트

- 이미지 File 입력을 받아 미리보기와 파일명을 보여주고, 삭제할 수 있음

 

 

트러블슈팅

1. supabase storage 이미지 중복저장

- 문제: 정 기능에서 사용자가 어떤 입력을 수정하는지 고려하지 않고 모든 내용을 update하면서 storage에 이미지가 중복저장됨

- 해결: 수정 기능의 경우 작성 완료 버튼을 눌렀을 때 기존 값과 비교해 변경된 값만 객체에 넣어 update하는 방식으로 변경 → 썸네일을 수정하지 않은 경우 storage 업데이트로 url을 받아오는 과정을 거치지 않아 중복저장이 해결되고 큰 이미지의 post를 수정하는 경우 비교적 시간이 단축됨

if (prevColumns.title !== newColumns.title) updateColumns.title = newColumns.title;

if (prevColumns.tech_stack !== newColumns.tech_stack) updateColumns.tech_stack = newColumns.tech_stack.split(' ');

if (prevColumns.content !== newColumns.content) updateColumns.content = newColumns.content;

if (prevColumns.project_start_date !== newColumns.project_start_date)
  updateColumns.project_start_date = newColumns.project_start_date;

if (prevColumns.project_end_date !== newColumns.project_end_date)
  updateColumns.project_end_date = newColumns.project_end_date;

if (prevColumns.thumbnail !== newColumns.thumbnail)
  updateColumns.thumbnail_url = await getImageURL(newColumns.thumbnail, 'thumbnails');

const { error: tableError } = await supabase.from('DEV_POSTS').update(updateColumns).eq('post_id', id).select();

 

2. 사용자 권한에 따라 보일 기능 / 보이지 않는 기능 구분되는 페이지에서 세션만료로 user가 null이 됨

- 해결: user 정보(id 등)를 확인하기 전 user의 존재 여부를 먼저 확인하여 해결함

const isAuthor = user && post.author_id === user.id;

return (
 { isAuthor ? <작성자일 때만 보여야하는 요소/> : null }
)

 

3. 사용자 정보 관리

- 문제: 기본적으로 제공되는 유저 정보 외에 다른 내용(프로필 이미지 등)을 추가하고 싶은데, 테이블을 따로 생성하려니 비밀번호가 그대로 노출돼서 고민

- 해결: 새로운 사용자가 추가될 때(회원가입) 테이블과 연결하는 함수 사용하여 처리

begin
  insert into public.profile (id, email, name, nickname, avatar_url) 
  values (new.id, new.email, new.raw_user_meta_data->>'name', new.raw_user_meta_data->>'nickname', new.raw_user_meta_data->>'avatar_url');
  return new;
end;
create policy "public profiles are viewed by everyone." on profile
for select using(true);
create policy "Users can insert their own profile." on profile
for insert with check(auth.uid()=id);
create function public.handle_new_user()
returns trigger as $$
begin
  insert into public.profile (id, email, name, nickname, avatar_url)
  values (new.id, new.email, new.raw_user_meta_data->>'name', new.raw_user_meta_data->>'nickname', new.raw_user_meta_data->>'avatar_url');
  return new;
end;
$$ language plpgsql security definer;
create trigger on_auth_user_created
  after insert on auth.users
  for each row execute procedure public.handle_new_user();

 

 

소감

데일리 스크럼, PR 양식을 활용한 것이 좋았다!! 특히 PR 양식은 챌린지반 수업 후 도입을 제안했는데, 다른 팀원분들도 만족스럽게 사용하신 것 같아 좀 더 뿌듯했다..ㅎㅎ

도전과제를 많이 하지 못해 아쉽지만 그만큼 다음 프로젝트 때 더 욕심나는 부분이 생긴 것 같다. 범용적으로 사용할 수 있는 함수나 컴포넌트를 만들어보고싶었는데 이번에 이미지를 첨부하면 프리뷰를 보이게하는 기능이 두군데에 있어서 내가 만든 컴포넌트를 다른 곳에서 사용하는 케이스가 있었다. 다른 곳에서 사용할 수는 있지만 조금 사용하기 불편하다고 느껴졌는데, 여러 컴포넌트에서 공용으로 사용할 수 있는 util성 함수들이나 공용 컴포넌트들을 더 가독성있고 유지보수가 용이하게 만들어보고싶다!