supabase auth를 이용해 회원가입/로그인을 구현하면서 유저 정보(이메일, 이름, 프로필 사진, 전화번호)를 직접 auth에 접근하지 않고 userinfo 테이블을 생성해 관리했다.
(supabase에서도 유저 정보 테이블을 따로 생성해 관리하는 것을 추천한다.)
auth에 새로운 데이터가 insert된 후에 작동하는 trigger와 함수를 작성해 자동으로 새로운 유저가 가입하면 userinfo 테이블에 정보가 삽입되게 하였다.
처음에 작성한 트리거와 함수는 다음과 같다.
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에 insert가 발생하면 그 이후에 on_auth_user_created
라는 트리거가 활성화된다.
on_auth_user_created
는 handle_new_user()
라는 함수를 실행한다.
handle_new_user()
는 회원 가입 시 생성된 raw_user_meta_data
(auth.users 테이블에서 확인 가능)에 있는 id (auth.users에 자동 생성되는 primary key), email, username, avatar_url을 userInfo
테이블의 각 column에 맞게 넣어준다. (values 앞뒤로 순서 맞춰서 적어야 함)
이메일 회원가입 시 입력받은 이름을 raw_user_meta_data
에 name
이라는 키로 값을 저장해줬고, avatar_url
을 null
로 저장해줬으므로 회원가입 시 문제가 없었고,
const { data, error } = await supabase.auth.signUp({
email: id,
password: pw,
options: {
data: {
//options안 data 객체 안에 key:value형식으로 넣어주면
//raw_user_meta_data에 객체 형태로 저장된다.
name: name,
avatar_url: null,
}
}
});
구글과 카카오 소셜 로그인 시에도 raw_user_meta_data
에 해당 이름에 맞는 key가 존재하므로 문제가 없었다.
회원가입 시 전화번호를 입력받고 본인인증을 하면서 문제가 발생했다.
입력받은 전화번호를 아이디/비밀번호 찾기, 결제페이지에서 사용해야하므로 다른 정보와 동일하게 raw_user_meta_data
에 저장하고 handle_new_user()
를 수정해줬다.
(물론 userinfo 테이블에 phone column도 추가했다)
이렇게
const { data, error } = await supabase.auth.signUp({
email: id,
password: pw,
options: {
data: {
name: name,
avatar_url: null,
phone: phone,
}
}
});
--handle_new_user() 함수
begin
insert into public.userInfo(id, email, username, avatar_url, phone)
values (new.id, new.email, new.raw_user_meta_data->>'name', new.raw_user_meta_data->>'avatar_url');
return new;
end;
수정한 후 일반 회원가입 시 잘 작동하는 것을 확인하고, 문제가 없는 줄 알았으나,,
카카오 신규 로그인과 구글 신규 로그인 시 에러가 발생하는 것을 발견했다.
배포 이후 발견한 에러라 배포와 관련된 설정이 잘못되어 발생하는 오류인지 알고 이리저리 supabase나 kakao developers, google cloud console에서 url을 수정해보았지만 고쳐지지 않았다.
그러다가 trigger가 정상 작동하지 않으면 auth에 새로 등록이 안된다는 것이 생각났다.
(지난 프로젝트에서 trigger function 작성할 때 column이름에 오타가 있어서 회원가입이 정상 작동하지 않았었다.)
구글과 카카오로 로그인했을 때 raw_user_meta_data
에 전화번호 정보가 없어서 (정확히는 key가 'phone'인 값이 없다. 물론 가져올 수 있는 전화번호도 없다.) 에러가 발생하는 것이었다.
그래서 생각한 해결책은
1. 조건부로 trigger를 실행한다
2. function 내에서 분기처리한다.
였는데 일단 2번으로 해보기로 했다.
begin
if new.raw_app_meta_data->>'provider' = 'email' then
insert into public.userInfo(id, email, username, avatar_url, phone)
values (new.id, new.email, new.raw_user_meta_data->>'name', new.raw_user_meta_data->>'avatar_url', new.raw_user_meta_data->>'phone');
elsif new.raw_app_meta_data->>'provider' = 'kakao' then
insert into public.userInfo(id, email, username, avatar_url, phone)
values (new.id, new.email, new.raw_user_meta_data->>'name', new.raw_user_meta_data->>'avatar_url', 'kakao 유저');
elsif new.raw_app_meta_data->>'provider' = 'google' then
insert into public.userInfo(id, email, username, avatar_url, phone)
values (new.id, new.email, new.raw_user_meta_data->>'name', new.raw_user_meta_data->>'avatar_url', 'google 유저');
end if;
return new;
회원 가입 유형에 따라raw_app_meta_data
에 provider
값이 있다는 것을 이용해 조건문 처리를 하였다.
기본 이메일 회원가입시에는 기존과 동일하게 처리하고 카카오와 구글 로그인 시에는 phone
column에 각각 'kakao 유저', 'google 유저'라고 string을 넣어주었다. (phone은 text type으로 되어있다.)
elsif
라는 키워드는 생각도 못했다. elif
일거라고 생각했는데 ㄷㄷ
무튼 잘 해결해서 다행이다!@!