편집 꺼짐
Next JS 치트 시트
2025.05.16 12:41:43
View란?
정의:
- PostgreSQL의 View는 하나 이상의 테이블을 조합한 가상의 읽기 전용 테이블이다.
- 복잡한 SELECT 쿼리를 미리 정의해서 재사용할 수 있음.
- Supabase에서는 이 View도
.from('view_name')
으로 조회 가능.
예시
CREATE VIEW post_summaries AS
SELECT
posts.id,
posts.title,
users.name AS author_name,
COUNT(comments.*) AS comment_count
FROM posts
JOIN users ON posts.author_id = users.id
LEFT JOIN comments ON comments.post_id = posts.id
GROUP BY posts.id, users.name;
→ Supabase에서 사용:
const { data } = await supabase
.from('post_summaries')
.select('*');
View 특징 요약
항목 | 설명 |
---|---|
읽기 전용 | 기본 View는 INSERT , UPDATE , DELETE 불가 |
쿼리 단순화 | 복잡한 JOIN, GROUP BY 등을 미리 정의 가능 |
권한 | View에도 RLS 정책 적용 가능 |
Supabase 사용법 | .from('뷰_이름').select(...) |
Supabase에서 View 등록 방법 (PostgreSQL View 생성)
A. SQL Editor에서 View 생성
- Supabase 프로젝트 접속
- 왼쪽 메뉴 → SQL Editor 클릭
- New Query → 다음과 같은 쿼리 입력
create or replace view public.post_summaries as
select
posts.id,
posts.title,
users.name as author_name,
count(comments.*) as comment_count
from posts
join users on posts.author_id = users.id
left join comments on comments.post_id = posts.id
group by posts.id, users.name;
- 상단의 Run 버튼 클릭 → 성공하면 뷰가 생성됨
B. 뷰 권한 부여 (읽기 허용)
grant select on public.post_summaries to anon, authenticated;
그래야 Supabase API로 접근할 수 있음
C. Supabase에서 사용
const { data, error } = await supabase
.from('post_summaries')
.select('*');
정리 요약
항목 | View | RPC(Function) |
---|---|---|
생성 | CREATE VIEW | CREATE FUNCTION |
SQL Editor | Supabase UI > SQL Editor | 동일 |
권한 부여 | GRANT SELECT ON view | GRANT EXECUTE ON FUNCTION ... |
호출 | .from('view') | .rpc('function_name', { params }) |
참고: materialized view가 필요한 경우?
- 조회 속도가 느리거나 정적인 요약 데이터를 빠르게 제공해야 한다면
materialized view
를 고려 - 하지만 Supabase에서 바로
refresh materialized view
는 사용자가 직접 트리거하거나 job으로 설정해야 함
RPC (Remote Procedure Call = SQL Function 호출)
정의:
- **PostgreSQL의 저장 함수(
CREATE FUNCTION
)**를 Supabase가 HTTP API처럼 실행할 수 있게 래핑한 것 - 복잡한 서버 로직(예: 트랜잭션, 커스텀 계산 등)을 캡슐화
예시
CREATE FUNCTION get_posts_by_tag(tag_input text)
RETURNS SETOF posts
LANGUAGE sql
AS $$
SELECT p.*
FROM posts p
JOIN post_tags pt ON pt.post_id = p.id
JOIN tags t ON t.id = pt.tag_id
WHERE t.name = tag_input;
$$;
→ Supabase에서 사용:
const { data } = await supabase
.rpc('get_posts_by_tag', { tag_input: 'nextjs' });
RPC 특징 요약
항목 | 설명 |
---|---|
완전 커스텀 쿼리 | SELECT뿐만 아니라 INSERT/UPDATE 등도 가능 |
매개변수 전달 | .rpc('함수이름', { 파라미터 }) |
리턴 타입 | SETOF , RECORD , BOOLEAN , INT 등 PostgreSQL에서 정의 |
권한 관리 | 함수에도 RLS 및 권한 설정 가능 (권한 없으면 실행 안 됨) |
Supabase JS 사용법 | .rpc('함수명', { 매개변수 }) |
View vs RPC 비교
항목 | View | RPC |
---|---|---|
목적 | 복잡한 SELECT 쿼리 정리 | 복잡한 로직/계산 실행 |
호출 방식 | .from('view') | .rpc('function', { params }) |
읽기/쓰기 | 읽기 전용 (기본) | 읽기/쓰기 모두 가능 |
RLS 적용 | 가능 | 가능 (explicit grant 필요) |
트랜잭션 | 불가 | 가능 (BEGIN ... COMMIT ) |
예시 | 가상의 게시글 요약 테이블 | 특정 태그에 해당하는 글 반환 |
Supabase에서 RPC 등록 방법 (PostgreSQL Function 생성)
A. SQL Editor에서 함수 생성
create or replace function public.get_posts_by_tag(tag_input text)
returns setof posts
language sql
as $$
select p.*
from posts p
join post_tags pt on pt.post_id = p.id
join tags t on t.id = pt.tag_id
where t.name = tag_input;
$$;
B. 함수 실행 권한 부여
grant execute on function public.get_posts_by_tag(text) to anon, authenticated;
Supabase 클라이언트에서
.rpc()
호출하려면 필수
C. Supabase에서 사용
const { data, error } = await supabase
.rpc('get_posts_by_tag', { tag_input: 'nextjs' });
Supabase에서 사용할 때 주의할 점
주의할 점 | 설명 |
---|---|
View는 읽기 전용 | 수정하려면 INSTEAD OF 트리거 혹은 materialized view 고려 |
RPC는 GRANT 필요 | GRANT EXECUTE ON FUNCTION your_func TO anon, authenticated 반드시 명시 |
View/RPC 모두 보안은 RLS | 뷰에서 참조하는 테이블의 RLS 정책을 따름 (주의!) |
- View는 조회 대상 테이블들의 RLS 정책을 따름
- RPC는 함수 안에서 사용하는 테이블의 RLS 정책을 따름
- 따라서 테스트할 때는
auth.uid()
를 쓰는 정책이 있다면 로그인된 JWT 필요