코딩하는라민

[React] Supabase 이메일 회원가입 및 로그인 기능 구현 & 트리거 설정 본문

개발 공부/Supabase

[React] Supabase 이메일 회원가입 및 로그인 기능 구현 & 트리거 설정

코딩하는라민 2024. 6. 26. 16:07
728x90
반응형

[React] Supabase 이메일 회원가입 및 로그인 기능 구현 & 트리거 설정

 

 

Supabase 로 회원가입을 진행하면 회원가입을 한 유저의 정보는 기본적으로 Authentication 탭의 `Users` 테이블에 저장된다. Users 테이블에는 이메일과 패스워드, 사용자의 UUID 등이 저장되는데 우리는 이 외에도 회원 정보를 추가적으로 저장하고 관리해줘야 할 것이다. 예를 들면 이름, 닉네임, 프로필 이미지, 주소 등이 있을 것이다.

 

그러기 위해서는 별도로 테이블을 추가해줘야 한다. 또한, Users 테이블의 UUID 를 userinfo 테이블의 id 로 가져와야한다. 즉, 테이블과 테이블 사이에 `관계`를 만들어줘야 한다.

그래야 추가적인 유저 정보를 회원가입과 동시에 추가해줄 수 있기 때문이다.

 

 

회원가입 수단 지정하기

[ Authentication ] - [ Providers ] 탭으로 이동하면 다양한 로그인 수단 목록이 나온다.

Email 로 간단하게 진행할 수도 있고, Oauth 를 이용해 카카오톡, 페이스북, 구글 등으로 로그인하는 기능도 구현할 수 있다.

 

이메일로 회원가입하기

`Enable Email provider` 를 활성화해주면 회원가입, 로그인을 기본으로 이메일로 할 수 있도록 설정할 수 있다.

`Confirm email` 을 활성화하면 이메일 주소로 인증번호가 발송되며, 인증이 완료되어야 최종적으로 회원가입이 완료된다.

 

 

Authentication 탭 살펴보기

회원가입을 한 유저의 정보는 Authentication 탭에 저장된다.

그 중에서도 Users 라는 곳에 저장되는데, 이 Users 테이블에 저장되는 정보는 다음과 같다.

  • Email
  • Phone
  • Provider
  • Created
  • Last Sign In
  • User UID

 

 

이메일 회원가입을 하면 Email, Provider, Created, Last Sign In, User UID 에 해당 정보가 저장된다.

`Provider` 는 회원가입을 어떤 방식으로 진행했는지에 대한 정보이다.

Provider 가 eamil 이라면 Phone 에는 자동으로 저장되지 않으며, 별도로 업데이트해줘야 한다.

`User UUID` 는 사용자의 고유 식별자로 랜덤으로 생성된다.

 

 

userinfo 테이블 추가하기

Table Editor 이용한 방법

1. 테이블 이름 지정

우선, 테이블 이름을 입력해준다. Description 은 Optional 값이다.

 

* `RLS`는 데이터베이스 테이블의 특정 행에 대한 접근을 제어하는 기능이다. 쉽게 말해서 사용자가 자신의 데이터만 조회하거나 수정할 수 있도록 해주는 옵션이다. 이 옵션을 체크하면 별도의 SQL 문으로 policy 를 지정해줘야 사용자가 자신의 데이터를 조회하거나 수정 및 삭제할 수 있다.

 

 

2. 컬럼 추가

사용자 정보에 필요한 컬럼을 추가해준다.

id 컬럼의 타입은 uuid 로 설정해주고, 컬럼명 옆의 `🔗` 버튼을 클릭해준다.

 

 

 

3. 관계 설정

`🔗` 버튼은 테이블끼리 관계를 설정해줄 수 있는데, 우리는 Users 테이블의 uid 를 가져와야 하므로 `Select a schema` 의 auth 를 서택해주고, `select a table to reference to` 는 auth 의 users 테이블을 선택해준다.

 

public.userinfo 의 id 와 auth.users 의 id(uuid) 를 연결해준다. 화살표의 방향이 public.userinfo ➡️ auth.users 로 향해야한다. userinfo 테이블이 users 테이블을 참조하는 형태이다.

 

 

Action 은 해당 행이 지워질 경우에 관계된 행이 같이 지워질 수 있도록 Cascade 를 선택하고, 아래의 `save` 버튼을 눌러 저장해 준다.

 

 

관계 설정 완료

 

 

4. 테이블 생성 완료

최종적으로 `save` 버튼을 눌러주면 테이블이 생성된다.

처음에는 Authentication - users 테이블에서 임의로 유저를 추가해도 userinfo 테이블에 아래와 같이 자동으로 행이 추가되지 않는다. SQL 문을 통해 함수와 트리거를 추가해줘야 자동으로 userinfo 테이블에 정보가 추가된다.

 

 

 

SQL Editor 이용한 방법

 

SQL Editor 탭으로 이동해서 아래와 같이 SQL 문을 추가한 후 우측 하단의 `Run` 버튼을 눌러 SQL 문을 실행해준다.

create table userInfo(
  id uuid references auth.users on delete cascade not null primary key,
  email text,
  image_url text,
  username text,
  message text
)

create table 은 동일한 테이블 명으로 한번만 실행되며, 여러 번 실행할 경우 에러가 뜬다.

만약 create table 실행 후 테이블을 수정하고자 한다면 해당 테이블을 지우고 다시 실행하거나, `alter table` 혹은 `insert` , `update`, `delete` 를 통해 수정할 수 있다.

 

  • 테이블 수정
ALTER TABLE userinfo ADD COLUMN last_login TIMESTAMP; # 컬럼 추가
ALTER TABLE userinfo RENAME COLUMN username TO user_name; # 컬럼명 변경
ALTER TABLE userinfo ALTER COLUMN email TYPE TEXT; # 컬럼 타입 변경
ALTER TABLE userinfo DROP COLUMN message; # 컬럼 삭제
ALTER TABLE userinfo ADD CONSTRAINT chk_email CHECK (email LIKE '%@%'); # 제약조건 추가

 

  • 데이터 수정
INSERT INTO userinfo (uuid, username, email) VALUES ('123...', 'ramino', 'ramino@ex.com'); # 데이터 추가
UPDATE userinfo SET email = 'rarara123@example.com' WHERE username = 'ramino'; # 데이터 수정
DELETE FROM userinfo WHERE username = 'john_doe'; # 데이터 삭제

 

 

함수와 트리거 설정

add_new_user 함수 추가

`add_new_user` 함수는 `auth.users` 테이블에 새로운 행이 추가될 때 자동으로 `userinfo` 테이블에 해당 유저의 정보를 추가한다.

create function public.add_new_user()
returns trigger as $$
begin
insert into public.userInfo(id, email, username, image_url, message)
values (
  new.id, new.email,
  new.raw_user_meta_data->>'user_name',
  new.raw_user_meta_data->>'image_url',
  new.raw_user_meta_data->>'message'
);
return new;
end;

$$ language plpgsql security definer;

 

  • `RETURNS trigger AS $$` : 트리거와 함께 사용할 것이기 때문에 RETURNS trigger AS $$ 옵션을 추가해 반환 타입을 trigger 로 지정해준다.
  • `begin` : 이 함수는 begin 으로 시작해서 end 로 끝나야한다.
  • add_new_user 함수 안에는 insert 문으로 테이블의 데이터를 추가하는 sql 문이 들어있다.
    • `new.id`, `new.email` : 새로 삽입된 행의 id, email 값
    • users 의 기본 데이터인 id(uuid), email 외의 데이터는 메타 데이터로 들어간다.
    • `new.raw_user_meta_data->>` : raw_user_meta_data 컬럼에서 각각의 키값을 추출
  • `return new` : 트리거는 반드시 행을 반환해야한다.
  • `$$ LANGUAGE plpgsql SECURITY DEFINER` : 함수가 PL/pgSQL 언어로 작성되었으며, 함수를 실행하는 사용자가 아닌 함수를 정의한 사용자의 권한으로 실행됨을 의미한다.

Database 탭에서 함수를 조회할 수 있다. schema: public 에서 조회 가능하다.

 

 

on_auth_user_created 트리거 추가

users 테이블에 새로운 행이 추가되면 add_new_user() 함수를 실행하여 userInfo 테이블에 해당 유저의 정보를 자동으로 추가한다.

create trigger on_auth_user_created
  after insert on auth.users
  for each row execute procedure public.add_new_user();

 

 

Database 탭에서 트리거를 조회할 수 있다. 위의 트리거는 schema: auth 에서 조회 가능하다.

 

 

함수 혹은 트리거를 잘못 추가하여 삭제할 경우

함수 혹은 트리거를 잘못 추가하여 삭제하고 다시 생성할 경우 `drop function`, `drop trigger` 를 사용하여 제거할 수 있다.

동일한 함수명, 트리거명으로 생성하는 sql 문을 여러번 실행할 시 오류가 생길 수 있다. 함수, 트리거 수정이 복잡하다면 삭제하고 다시 생성해주는 것이 편하다.

drop trigger on_auth_user_created on auth.users;
DROP FUNCTION IF EXISTS public.add_new_user;

 

* 함수를 제거하려면 트리거 먼저 제거해야 한다.

 

 

리액트에서 회원가입 및 로그인 구현

회원가입

const { data, error } = await supabase.auth.signUp({
  email: email,
  password: password,
  options: {
    data: {
      user_name: name,
      image_url: imageUrl,
      message: message
    }
  }
})

eamil, password 외에 저장할 데이터는 options 객체의 data 객체에 넣어서 요청을 보낸다.

해당 정보는 users 테이블의 raw_user_meta_data 에 저장된다.

 

 

로그인

로그인은 이메일 로그인일 경우 eamil 과 password 만 넣어서 보내면 된다.

  const { data, error } = await supabase.auth.signInWithPassword({
    email: email,
    password: password
  })

 

 

실제로 회원가입을 진행해보면 Authentication - users 테이블에서 임의로 추가한 유저 정보가 userinfo 테이블에도 저장되는 것을 확인할 수 있다.

 

로그아웃

const { error } = await supabase.auth.signOut()

 


참고

 

 

728x90
반응형