🌿 Supabase 프로젝트 생성
🌿 TableEditor에서 테이블 생성
Column | Type | Detault Value | NOT NULL | Description |
id | uuid | o | PK | |
created_at | timestamp | now() | o | |
varchar | o | 중복체크 | ||
sns_type | varchar | x | Naver / Kakao / Google / Apple | |
nickname | varchar | o | ||
profile_img | varchar | x | ||
updated_at | timestamp | x | ||
sns_key | varchar | x |
id와 created_at은 기본적으로 생성되는 컬럼입니다. 회원 가입 시 필요한 항목들을 추가했다.
id의 경우 기존에 int8로 설정되어 있던 것을 uuid로 변경했다. 밑에서 다시 언급될 내용이지만, Supabase에서 제공하는 회원 가입 기능을 적용하기 위함이다.
이미 생성된 테이블에서 id 컬럼의 타입을 uuid로 변경 시, 오류가 발생한다면?
- 기존 id 컬럼을 제거 후 uuid 타입의 id 칼럼을 새로 추가해 주면 된다.
🌿 프로젝트에 Supabase 적용
Supabase 설치
npm i --save @supabase/supabase-js
.env 파일에 supabase url, supabase anon key 넣기
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
package.json에 generate-types 커맨드 추가하기
{
"scripts": {
# ...
"generate-types": "npx supabase gen types typescript --project-id [project_id] --schema public > types_db.ts"
}
}
이 명령어는 Supabase의 gen 커맨드를 사용해 Typescript로 실제 DB에 있는 테이블 타입을 생성하는 것이다.
- --project-id [project_id] : 사용자가 작업할 Supabase 프로젝트의 ID. [project_id]에는 Project URL의 앞부분을 입력하면 된다.
- --schema public : 사용하고자 하는 DB 스키마를 나타낸다.
- > types_db.ts : 생성된 타입을 types_db.ts 파일로 출력하겠다는 의미
터미널에서 Supabase 로그인 진행 & generate-types 실행
npx supabase login
# 브라우저가 열리면서 Supbase 로그인
npm run generate-types
# 정상로그인 후 처리가 되면 types_db.ts 파일이 새로 생성된다.
Supabase client 생성
- utils/supabase.ts 파일 생성
import { createClient } from "@supabase/supabase-js";
import { Database } from "../../types_db";
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL as string;
const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY as string;
export const supabase = createClient<Database>(supabaseUrl, supabaseKey);
Supabase의 경우 자체적으로 이메일 회원가입과 소셜 회원가입 기능을 제공하고 있다.
그래서 그 기능을 이용하여 이메일 회원가입, 로그인, 로그아웃을 구현했다.
User Management_supabase Docs.
Docs를 살펴보면 Auth의 meta_data를 활용하기보다는 public 스키마에 별도의 사용자 Table을 만들어 관리하라고 권장하고 있다.
auth.users 테이블을 참조해 데이터 무결성을 유지하고, 트리거를 생성해 신규 데이터가 생길 때마다 사용자 Table을 update 되게 만들어야 한다.
1. public 스키마에 테이블 생성 (member) 후 참조
이 과정이 위에서 테이블 생성 시, id 컬럼의 Type을 uuid로 변경한 이유이다.
auth.users의 id 컬럼을 참조하기 위해서는 데이터 형식이 일치해야 하기 때문이다.
- id 컬럼 옆에 📎 버튼을 누르고 auth.users을 참조한다.
- 참조에 대해 on delete cascade를 지정한다.
2. Auth Setting (Project Settings > Authentication)
- 회원가입 시 기본 세팅, 비밀번호 조건 등 설정 가능 (추가 기능은 Pro)
3. Auth Provider 설정(Authentication > Providers)
- 이메일 뿐만 아니라 소셜 로그인 기능 제공
- Email만 우선 enable 해주었다.
- 회원 가입 시, 이메일 인증을 필수로 할 경우 Confirm email 부분을 체크 상태(Default)로 두면 되지만 필요하지 않는 경우에는 체크를 해제해야 한다. 그렇지 않으면 사용자가 이메일을 인증하기 전까지 회원 가입이 완료되지 않는다.
4. auth.users와 public.member 연동
auth.users에 새로운 값 insert → auth.users에 새로 입력된 값으로 public.member에 회원 정보 저장
auth.users에 데이터가 추가되었을 때 동작할 Trigger와 public.member에 데이터를 저장할 Function을 추가한다.
Docs에 샘플 코드와 설명이 있어서 쿼리를 조금 수정해서 적용했다. 이 작업은 SQL Editor에서 가능하다.
- new : 회원가입 시 입력하는 데이터
- email, password 외의 정보들은 new.raw_user_meta_data에 저장된다.
그리고 이 데이터를 public.member 테이블에 추가한 컬럼들에 저장한다.
-- public.member insert function 추가
create function public.handle_new_member()
returns trigger
language plpgsql
security definer set search_path = ''
as $$
begin
insert into public.member (id, email, nickname, sns_type)
values (new.id, new.email, new.raw_user_meta_data ->> 'nickname', new.raw_user_meta_data ->> 'sns_type');
return new;
end;
$$;
-- auth.users insert trigger 추가
create trigger on_auth_user_created
after insert on auth.users
for each row execute procedure public.handle_new_member();
- Database > Schema Visualize에서 확인 가능
- Database > Functions에서 함수 수정/조회 가능
- Database > Triggers에서 트리거 조회 가능
🌿 회원가입
- option의 data 부분이 ras_user_meta_data_[column]에 저장되는 값
const { data, error: joinError } = await supabase.auth.signUp({
email,
password,
options: {
data: {
nickname: nickname,
sns_type: "",
},
},
});
FE 예외 처리 중 만난 오류..
타입에 맞지 않은 값이 할당 되어서 발생한 오류인데 TypeScript를 적용하다 보면 이런 단순 오류들이 자잘하게 반복되어서..
앞으로 더 신경을 잘 쓰자는 의미에서 추가로 기록해 본다.
[ 문제 ]
disabled에 boolean이 전달되어야 하는데, string | false가 할당되어 발생
[ 해결 ]
!! 연산자를 사용해 boolean을 반환하도록 수정
!! 연산자 : JS에서 특정 값의 boolean 변환을 위해 사용
- 첫 번째 ! : 값을 논리 NOT 연산자로 변환
- 두 번째 ! : 첫 번째로 반환된 값을 다시 반전. 원래 값의 진릿값을 다시 boolean 값으로 변환
<InputField
label="닉네임"
type="text"
value={nickname}
name="nickname"
placeholder="닉네임을 입력하세요"
onChange={handleChange}
buttonLabel="중복확인"
onButtonClick={handleDuplicateCheck}
disabled={!isDupl && !!duplMsg} // !!duplMsg로 boolean 변환
/>
- 닉네임이 중복이 아니고(사용 가능) dupMsg가 있을 경우, disabled 처리하기 위한 코드이다.
우선은 !!으로 처리하긴 했지만.. 나중에 다시 확인해보는 걸로.
🌿 로그인
const { data, error } = await supabase.auth.signInWithPassword({
email,
password,
});
🌿 로그아웃
const { error } = await supabase.auth.signOut();
'스터디 > 사이드 프로젝트' 카테고리의 다른 글
01. 포트폴리오 사이트 1차 완료 (2) | 2024.10.18 |
---|---|
00. 포트폴리오 사이트의 시작 (3) | 2024.10.15 |
02. Vercel로 배포하기 (0) | 2024.10.07 |
01. Zustand로 상태관리 하기 (1) | 2024.10.06 |
00. 사이드 프로젝트 세팅 (0) | 2024.10.05 |