어디가지🍆 프로젝트를 진행하면서 처음으로 supabase를 사용해보았다.
supabase 공식 docs가 꽤나 친절하게 설명되어있는 편이지만 영어로 되어있고
구글링했을 때 한국어로 된 정보는 거의 없고 youtube이 대부분이었어서
정리를 해보려고 한다^^
supabase는 RDBMS이라는 것이 firebase와 가장 큰 차이점이다.
firebase는 'document-based data storage'를 기반으로 구축하지만 supabase는 'postgreSQL' 이라는 관계형 데이터베이스 시스템을 제공한다. 때문에 SQL 쿼리를 사용할 수 있다.
- SQL 쿼리 사용 가능
- 개발과정에서 가격 부담이 적음
( firebase는 CRUD에 대해 가격을 청구하고, supabase는 저장된 데이터 양에 따라 요금 청구 → 개발 과정에서 가격 부담이 적다)
이번 프로젝트에서는 이메일 로그인과 카카오 로그인을 구현했는데, Docs가 아주 친절하게 step by step으로 설명되어있어서 따라서 하면 어렵지 않았다. 특히 카카오 로그인에 대한 설명도 상세히 적혀있어서 꽤 감동이었다. (물론 자잘한 문제가 있긴 했지만,,)
supabase docs에서는 Authentication 자체의 meta_data를 활용하기 보다는 별개의 table을 만들어 관리하기를 추천하고 있다. (보안문제)
그래서 유저 정보를 갖는 table인 userinfo Auth에 새로운 정보가 생기면 userinfo 테이블에 자동으로 update되게 만드는 것이었다. (트리거를 만들어야되겠군..!!)
외국인 선생님의 youtube영상과 희미한 SQL 문법 기억을 이용해 함수와 트리거를 작성했다.
-- create a table for public profiles
-- userInfo라는 이름의 테이블을 생성
-- userInfo에서 관리하고 싶은 column들의 이름과 타입을 적어준다.
-- 생성은 꼭 SQL Editor에서 하지 않아도 된다. table Editor에서도 가능
create table userInfo(
id uuid references auth.users on delete cascade not null primary key,
email text,
avatar_url text,
username text
admin bool,
);
auth.users에 새로운 값 insert → auth.users에 새로 입력된 값으로 userinfo에 회원 정보 저장
create policy "public profiles are viewed by everyone." on userInfo
for select using(true);
create policy "Users can insert their own profile." on userInfo
for insert with check(auth.uid()=id);
-- 회원가입 시 auth 테이블에 새로 생기는 row의 id, email, raw_user_meta_data 칼럼에서 값을 가져와서 자동으로 userinfo 테이블에 업데이트 해줌
-- auth의 id == userinfo의 id
create function public.handle_new_user()
returns trigger as $$
begin
insert into public.userInfo(id, email, username, avatar_url)
values (new.id, new.email, new.raw_user_meta_data->>'name', 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();
auth 스키마의 users 테이블에서 값을 가져오는 것
(회원가입을 하면 users 테이블이 업데이트 된다.)
새로 회원 가입을 할 때 가져올 column의 값이 비어있으면 (가져올 수 있는 값이 없으면) 에러가 발생하므로 주의
위에서 작성한 트리거에 auth.users의 raw_user_meta_data_ column의 값을 가져왔으므로 회원가입 시에 raw_user_meta_data_ 값을 함께 등록하는 것이 매우 중요하다.
.
.
.
const { data, error } = await supabase.auth.signUp({
email: id,
password: pw,
options: {
data: {
user_name: name,
avatar_url: null
}
}
});
.
.
.
위의 코드에서 option의 data 부분이 raw_user_meta_data_ column에 저장되는 값이다.
회원가입을 진행하고나서 웹페이지 localstorage에 user 정보가 저장되는 것을 보아 정상적으로 회원가입이 진행되고 나면 자동으로 로그인 되는 듯 하다.
++ 기본설정이 이렇게↑ 되어있고 회원가입과 로그인을 분리하고 싶으면
Settings → Authentication → Auth Settings → User Signups 에서 Allow new users to sign up을 끄면 된다.
supabase auth 설정을 아무것도 건들이지 않은 상태에서 이메일 회원가입을 하게 되면 입력한 이메일 주소로 인증메일이 발송된다.
↓ waiting for verification,,
오 이런 기능이?! 하고 나서 회원가입과 로그인을 계속해서 테스트 하다보면
갑자기 회원가입도 로그인도 안되는 현상이 발생한다. 콘솔을 열어보면 429에러가 발생한 것을 볼 수 있는데 supabase에서 인증메일을 보내는 기본 횟수가 아주 적기 때문이다. (정확한 횟수는 모르겠다.)
const { data, error } = await supabase.auth.signInWithPassword({
email: id,
password: pw
});
로그인을 하면 localStorage에 동일한 이름의 key값으로 로그인 정보가 저장되는 것을 알 수 있다
const { error } = await supabase.auth.signOut();