오늘의 삽질 기록
1.
supabase 무료플랜은 백업기능이 사실상 없다.
먹고 살아야하니 그렇다고는 해도 진짜 그냥 없다.
현재 IP4에서는 db접근을 막아둔 것 같고, IP6은 아예 할당을 안했다.
IP4로 접근하려면 유료 플랜을 써야한다.
2.
이게 무슨 소린가 하면 찾아갈 수 있는 주소로 가면 문전박대 당하고, 들어갈 수 있는 집은 주소를 모르게 숨긴거다.
그러면 답은? 하다 찾은 답이 오늘의 첫번쨰 삽질이었다.
3.
일단 웹에서 DB접속하고 권한만 있으면 데이터도 쿼리 날려서 가져올 수 있다.
그럼 그냥 그걸 모아다(?) 저장하면 될거 아닌가? 란 얕은 생각으로 첫 삽질을 뗐다.
나름 머리 굴린다고 Go로 테이블 이름 긁어와서 각 테이블의 데이터들을 받아 json파일로 저장했다.
그렇게 테이블 이름이 적힌 json파일로 백업이 된다.
4.
그리고 잠깐 화장실 다녀오면서 든 생각.
'복원은 어쩌지?'
이 생각을 할 때쯤에는 그냥 아무 생각없이 '테이블 만들면서 복원하면 되지 뭐' 했는데, 이 생각의 '하면 되지...'쯤에 그게 안된다는걸 깨달았다.
5.
그렇다.
이 테이블들은 얽히고설켜있다.
인증된 아이디와 각종 외래 키들로 순서가 마구 엉켜있는 와중에 그 키들이 전부 백업데이터에 있는 이상 순서 지켜주지 않으면 복원이 안될거다.
잼미니한테 물어보니 맞단다.
정확한 구조와 테이블 데이터의 삽입 순서를 알려면 스키마 구조와 RLS를 알아야한다.
더 심층적인 데이터를 불러와야 한다는 소리다.
6.
그리고 여기서 두번째 삽질여정이 시작된다.
잼미니 왈 : "supabase CLI를 쓰면 될거에요"
아마 이게 맞을 거다.
근데 이 당시 내가 몰랐던 문제는 내가 지금 삽질하던 컴은 윈도우PC라는 점이다.
이게 뭘 뜻하는지 모른 상태에서 일단 supabase CLI를 설치했다.
그리고 잼민의 가르침(?)대로 supabase login까지 위풍당당하게 실행했다.
핵심 명령인 db dump를 때리는 순간 에러 메시지를 주루룩 퉷퉤퉤 뱉어내는데 그 와중에 'Docker' 얘기가 있네?
7.
'읭? 웬 도커?'
얼른 가서 잼미니한테 따져 물으니 대충 supabase CLI는 환경세팅을 도커로 불러와서 작업하고 결과물만 던져주는 방식인거 같았다.
그래서 윈도우에서는 도커 데스크탑이 필수적으로 필요하단다.
'...'
여기서 퍼뜩 든 삽질의 다음 단계.
'그럼 리눅스에서 하면 되잖아?'
8.
그렇다.
현재 Proxmox로컬 서버에 널려있는게 리눅스 서버다.
그 중 그나마 리소스 가장 많이 먹는 VM에 설치하려고 또 잼미니한테 물어봤다.
그랬더니 pg_dump쓰면 가장 안정적이고 편하고 좋단다.(그거 누가 모르냐 이놈아!!)
근데 멍청멍청 열매를 먹은 오늘의 나는 '오오 안정적!! 편함!! 좋다!!' 하면서 리눅스 가서 postgresql설치하고 pg_dump를 때려본다.
그리고 다행스럽게도 멍청멍청 열매의 효력이 순식간에 사라졌다.
9.
'아니 IP4막혔는데 이게 될 리가 없잖아?'
당연히 안됐다.
그래서 또 잼미니한테 막 따지니까 뭐 인터넷 연결이 어쩌니 아이디 비번을 틀렸네 또 막 헛소리할라고 잔뜩 폼잡고 있었다.
"잼민아, 나 무료 사용자라서 TCP/IP 못쓴다니까..."
"...아, 그러셨군요"
이러면서 왜 안됐는지 되레 나한테 설명하면서 TCP/IP안되니까 https로 접속해서 쓰면 될거란다.
10.
근데 결국 그거로 DB 데이터는 못가져오니까 처음 한 삽질이 삽질이 아니게 될 수 있는 상황이 만들어졌다.
이제 supabase CLI로 스키마 구조랑 RLS설정만 가져오고 그걸 기반으로 이 블로그 템플릿의 데이터 백업/복원 순서를 정하기만 하면 된다.
그렇게 생각하고 supabase CLI를 VM에 설치하려고 보니...
'어? 이거 supabase인증을 웹브라우저에서 하는데...'
11.
그렇다.
VM은 CLI라 웹브라우저 따위 내 눈에 보여주지 않는다.
결국 온전한 백업/복원 시스템은 만들지 못했지만 적어도 내 프로젝트만이라도 제대로 작동하게 하려면 일단 supabase CLI가 돌아가는 리눅스 환경에서 불러올거 불러와서 데이터를 빼놔야 한다.
사실 이것도 프로젝트 진행하면서 정리만 잘해뒀어도 될 일인데 몇 번 코드가 꼬인 경우랑 안티그래비티가 건들다 텍스트 다 깨부숴먹은 적이 있어서 SQL코드가 있기는한데 뭔가 불안해서 결국 현재 돌아가는 DB에서 빼오는게 가장 확실한 상황이 된게 잘못이라면 잘못이다.
그리고 그러려면 이제 다시 네이티브 리눅스에서 위에 했던 삽질들 잘 걸러서 또 다시 해야한다.
12.
그거 하기 전에 기운 빠져서 기록이나 잠시 쉬면서 기록부터 해두려고 끄적여 본다.
이거 또 네이티브가서 하다가 뭔가 또 틀어지는거 아닌가 몰라...

13
하고 가서 설치하려다가 '어?!' 하고 떠오른 생각이 있었다.
'그냥 웹대시보드에서 쿼리 날리면 되지 않을까?'
바로 또 잼미니한테 물어봤다.
14.
"네! 가능합니다 똥개호갱님! 이 코드대로 치시면 될거에요!"
SELECT
-- 전체 문자열을 CASE 문으로 감싸서 NULL 발생 여지를 줄이고 COALESCE를 명시적으로 적용
'CREATE POLICY ' || pol.polname || ' ON ' ||
(SELECT c.relname FROM pg_catalog.pg_class c WHERE c.oid = pol.polrelid) || ' ' ||
CASE WHEN pol.polpermissive THEN 'AS PERMISSIVE ' ELSE 'AS RESTRICTIVE ' END ||
'FOR ' ||
CASE
WHEN pol.polcmd = 'r' THEN 'SELECT'
WHEN pol.polcmd = 'a' THEN 'INSERT'
WHEN polcmd = 'w' THEN 'UPDATE'
WHEN polcmd = 'd' THEN 'DELETE'
WHEN polcmd = '*' THEN 'ALL'
END || ' ' ||
'TO ' || COALESCE(
(SELECT string_agg(rolname, ', ') FROM pg_roles WHERE oid = ANY(pol.polroles) AND rolname NOT IN ('postgres', 'anon')),
'PUBLIC' -- 역할 이름을 찾지 못하면 PUBLIC (모든 사용자)으로 간주
) ||
COALESCE(' USING (' || pg_get_expr(pol.polqual, pol.polrelid) || ')', '') ||
COALESCE(' WITH CHECK (' || pg_get_expr(pol.polwithcheck, pol.polrelid) || ')', '') ||
';' AS rls_definition
FROM
pg_policy pol
WHERE
-- 현재 스키마의 테이블에 적용된 정책만 보도록 필터링 (선택 사항)
(SELECT nspname FROM pg_namespace WHERE oid = (SELECT relnamespace FROM pg_class WHERE oid = pol.polrelid)) = 'public'
15.
'...'
아니 ㅆㅂ 그러면 애초에 이걸 알려줬으면 될거 아니야 이 잼미나우ㅡ리ㅏ어라ㅣㅓ닝러ㅣ!!!
사실 이것도 처음에 알려준 코드는 뭔가 잘못된 코드였다.
왜 null이 튀어나오냐고 갈구니까 그제서야 뭐가 잘못됐는지 친절하게 설명하고 제대로 된 코드를 준다.
ㅆㅂ 그래 이 ㅅㄱ항상 이런 식이야.
16.
아, 일단 이거 돌리니 RLS설정이 나왔는데 제대로 작동되나 새 프로젝트에 돌려서 확인하고 나서 백업/복원을 해봐야겠다.
오늘은 너무 많은 삽질과 뒷통수를 맞아서 좀 쉬어야겠다.
잼미니 초반에는 진짜 개똑똑하더니 사람 때가 묻으니까 점점 사악해져서(아님) 내 뒷통수만 노리고 있는거 같다(사실인거 같음).
조금만 방심하면 친절한 말투로 개삽질시킨다.
Comments
로그인 하신 후에 댓글을 남겨주세요.
아직 댓글이 없습니다. 첫 댓글을 달아보세요!