성장과회고

11.20.2024(수) 제가 뭘 또 삽질했냐면요. Today I Learned 유데미x스나이퍼팩토리 프론트엔드 프로젝트 캠프

에밀오구 2024. 11. 21. 00:12

오늘은 저번시간에 북마크 기능이랑 페이지네이션 적용하지 못해서 이를  적용하고 오류를 분석하는 시간을 가졌습니다. 또 supabase 를 Next.js 에 적용하며 오랜만에 억까를 당해 기력이 쇠했던 날이기도 하네요. 하하 그래도 시간이 지나 경험이 쌓이면 과거의 억까들이 신의 장난이 아니라 지식부족이였다는 걸 깨닫겠지만요. 당 떨어지는 하루였습니다 ;ㅅ;   

 

-2. [ supabase ] supabase에  Next.js 개같이 털리기 

superbase 적용하는 시간이 너무 고생스러워서 꼭 정리해야 겠다 싶었어요.회원가입하고 새 프로젝트를 만들기를 눌러 프로젝트 이름, 비밀번호, 지역을 넣어서  프로젝트를 만듭니다. 여기서 프로젝트와 연결하는 과정이 개인적으로 어려웠는데요. 

로그인

 

new Project

 

 

왼쪽 home 버튼누르고 좀 기다리시면 connect 버튼이 나옵니다 누르시면

-2-1.    .env.local  파일 넣기 

상단 connect 버튼을 누르면 프로젝트와  연결할 수 있는 방법이 나옵니다.     프로젝트 최상단에 .env.local 파일을 만들어  App Framworks 탭에 나온 해당 코드를 넣습니다. 

 

-2-2. lib 폴더 내부 supabase.ts  

lib  폴더 내부에 supabase.ts 을 만들어 해당 코드를 넣습니다. 해당 코드를 복사후  변수명을  .env.local 에 있는 변수명과 맞췄어요. NEXT_ 뫄뫄 이런식으로요 변수 꼭 확인하시길 바랍니다.   as string 도 각각 넣고요

그리고 npm i  @supabase/supabase-js 를 터미널에 설치합니다.

 

 

 

-2-3. 테이블 세팅하기 

1.좌측 nav 에 Table Editor 버튼을 누르고 create a new Table 을 만들고 테이블에 이름만 넣고 저장합니다.

2. created_at 옆에 있는 + 버튼을 눌러 colum을 만듭니다. 저는 start_date 이라는 이름으로 날짜타입의 컬럼을 만들고 저장했습니다. 

이런식으로 총 4개의 column 을 만듭니다. 

column 이름 type 
start_date   timestamptz
end_date   timestamptz
title text
boards jsonb

 

 

 

컬럼 생성
4개 추가한 모습

 

-2-4. policy 추가 하기 

컬럼 위에 add RLS policy 버튼을 누르고  create policy  버튼을 누르고 

add Rls policy

 

 

create poilcy

 

policy 를 하나 생성해줍니다. 오른쪽 select 버튼을 누르고 이름 작성하고 policy command 가 select 인지 확인 그리고 하단 using 객체에 true 를 작성하고 저장을 합니다. 

 

 

또 하나 더 만들건데 이름을 비슷하게 지으려고 그전 policy 이름을 복사해 create policy 를 해줄게요  이번에는 select 버튼 눌러 이름, 하단 영역에 true 를 넣어 저장합니다. 이번에는 오른쪽 노랑색 insert 버튼은 안눌렀어여

 

이번엔 update 를 만들어줄게요. 해당 영역들 작성하고 저장합니다 . 이 것도 오른쪽  파랑색 update 버튼을 안눌렀고여

delete 도 같은 방식으로 만드러줍니다 

 

!주의할점 

해당 세 영역이 초록불이 떠야합니다. 프로젝트가 활성화될 때까지 시간이 좀 걸린다고 하더라고요.  

 

 

 

  const handleCreateTask = async () => {
    try {
      const { data, status } = await supabase
        .from('todos')
        .insert([
          {
            title: '',
            start_date: null,
            end_date: null,
            boards: [],
          },
        ])
        .select();

      if (status === 201 && data !== null) {
        toast({
          title: '새로운 TASK가 생성되었습니다.',
          description: '나만의 TODO-BOARD를 생성해보세요!',
        });
        router.push(`/board/${data[0].id}`);
      }
    } catch (error) {
      console.error(error);
      toast({
        variant: 'destructive',
        title: '에러가 발생했습니다.',
        description: '예상치 못한 에러가 발생했습니다. 문의해주세요!',
      });
    }
  };

 

https://supabase.com/

 

Supabase | The Open Source Firebase Alternative

Build production-grade applications with a Postgres database, Authentication, instant APIs, Realtime, Functions, Storage and Vector embeddings. Start for free.

supabase.com

 

 

-1. e.preventDefault();의 무서운 맛 보기

페이지네이션 구현중 다른 페이지네이션 버튼을 누르면 api 호출까지 잘하다가 새로고침되어 처음 초기값 1페이지로 호출되는 문제가 있었습니다.  결국 원인은  e.preventDefault(); 를 넣지 않아서 생기는 문제였습니다.  e.preventDefault(); 가 이렇게 무서운 놈이였다니 . 내일  e.preventDefault();의 기능이 html 표준에서 기본으로 제공하는 이벤트 기능을 막는다고 만 알고 있었는 데 정확히 무엇인지 살펴봐야겠습니다.

 

 

 

0. [ pagination ] 현재 페이지(page)를 기준으로 10개의 페이지 번호 리스트를 생성하기 

다른 분의 코드를 보던중 페이지네이션 코드에서 유용한 코드가 보여 정리했습니다. 

 const pageList = Array.from({ length: 10 }, (_, index) => {
    return Math.floor((page - 1) / 10) * 10 + index + 1;
  });

1. [ React ] 상태에 따른 파생 데이터 관리 

bookmark 된 카드 목록중 인덱스가 앞선 카드를 삭제하면 뒤에 있던 카드의 isMarked 가 true 가 되어 똑같은 카드가 중복 북마크되는 이슈가 있었습니다.  원인은 기존 상태인 bookmarks 의 파생 데이터 인 isMarked 또한 상태로 관리하고 있었기 때문이였어요. (아흙)   상태를 변경하면 이에 파생되는 데이터까지 재렌더링되기때문에 주의가 필요합니다. 

 

 React 의 useState에서 주의해야할 점 

 - state 변경함수를 일괄적으로 처리하거나 다른 상태 없데이트가 방해를 받아 매번 올바르게 업데이트 되지 않을 수 있다. 

 state 변경함수의 preCounter 인자를 받아 사용할 것 . ex> setCounter((prev)=> prev +1 )

- 상태는 불변으로 취급되어야 한다. 객체와 배열과 같은 구조는 상태를  새 객체로 직접 변경해야함 .

- 상태에 파생될 수 있는 데이터는 상태로 관리하지 않는다.  

//오류 코드
const [bookmarks, setBookmarks] = useAtom<BookmarkType>(bookmarksAtom); //[{},{}]

  const initMarked = bookmarks.findIndex((item) => item.id === data.id) > -1; //true, true

  const [isMarked, setisMarked] = useState(initMarked);
  
  
  //..
    const removeBookmark = (imageData: ImageDataType) => {
    const newBookmarks = bookmarks.filter((book) => book.id !== imageData.id);
    setBookmarks(newBookmarks);
    setisMarked(false);
    localStorage.setItem('bookmark', JSON.stringify(newBookmarks));

    toast({
      variant: 'destructive',
      title: '로컬스토리지에 해당 데이터가 삭제되었습니다.',
    });
  };

 

//해결 코드   
  const [bookmarks, setBookmarks] = useAtom<BookmarkType>(bookmarksAtom);
  const isMarked = bookmarks.findIndex((item) => item.id === data.id) > -1;

 

3.  [ React ] button tag 중첩 문제 

HTML 구조 상 <button> 태그가 또 다른 <button> 태그의 하위 요소로 포함되면  HTML 명세를 위반하는 거라 React의 유효성 검사에서 감지된다고 합니다. 중첩하지 맙시다 (넹) 

 

 

——————————————————————————

본 후기는 본 후기는 [유데미x스나이퍼팩토리] 프론트엔드 프로젝트 캠프 과정(B-log) 리뷰로 작성 되었습니다.