요즘 매일...은 아니지만 생각날 때마다 한번씩 포케맨틀을 하고 있다.
https://pokemantle.update.sh/
갓겜이니 해보시길
안타깝게도 내 포켓몬 지식은 4세대에 머물러있기 때문에 컨닝노트 보면서 하고 있다.
그런데 보니까 주제를 포켓몬에서 색상코드(hex)로 바꿔보면 어떨까 싶었다.
우선 해당 프로젝트의 주요 요소는 이와 같다
별 일 없으면 firebase
를 쓰겠지만 firebase의 firestore은 NoSQL이다보니 SQL에 익숙한 내가 쓰기에는 선뜻 손이 가진 않았다. 그러다가 supabase
를 알게 되었는데 꽤 괜찮아서 쓰게 되었다.
우선 제일 먼저 고려해야하는 것은 매일 정답이 달라진다 는 것이다.
처음에는 맨 처음 들어왔을 때, DB에서 해당 날짜를 조회하고 값이 있으면 반환, 아니면 새로운 데이터를 생성하고 반환하려고 했는데. 이러면 아무도 안 들어온 날이면 데이터가 생성되지 않는다는 단점이 있다.
그러면 스케쥴링으로 매일 0시에 새로운 데이터를 삽입하면 어떨까
supabase
에는 미리 함수를 등록할 수 있다.
함수를 등록하면 URL을 만들어주는데, postman이나 그런걸로 확인해보면 미리 지정해놓았던 Response를 내놓는다.
Deno.serve(async (req) => {
const { name } = await req.json()
const data = {
message: `Hello ${name}!`,
}
return new Response(JSON.stringify(data), { headers: { 'Content-Type': 'application/json' } })
})
다만, 이 기능을 사용하려면 Deno
를 사용해야하는데, 굳이 Deno 환경으로 만들어주지 않아도 도커만 실행시켜놓으면 등록 자체는 되니, 작업하는 동안 빨간줄만 참을 수 있으면 된다. 그리고 Vercel에 배포할 것이니 꼭 .gitignore
에 등록해주자.
# supabase/functions
# functions 디렉토리 내 전체 배포
supabase functions deploy
# functions 디렉토리 내 특정 파일 배포
supabase functions deploy 파일명
함수를 배포하려면 위와 같이 콘솔에 입력해주면 된다.
나는 랜덤으로 000000 ~ FFFFFF
사이의 값을 생성하여 DB에 등록하는 함수를 작성하여 배포했다.
이제 이걸 매일 0시에 함수를 실행시켜주면 된다. 보통 스케쥴링하면 Github Actions
를 생각할텐데 이번에는 supabase에서 스케쥴링을 지원하니 이를 이용해보자.
https://supabase.com/docs/guides/functions/schedule-functions
select
cron.schedule(
'invoke-function-every-0-hour',
'0 15 * * *', -- everyday at 0:00
$$
select
net.http_post(
url:='Edge Functions URL',
headers:='{"Content-Type": "application/json", "Authorization": "Bearer YOUR_ANON_KEY"}'::jsonb
) as request_id;
$$
);
SQL Editor로 가서 해당 쿼리문을 실행시켜주면 스케쥴링이 실행된다.
중요한 것은 우리가 만들어놓았던 Edge Functions의 URL이 여기에 쓰인다는 것이다.
그런데 0시 정각에 실행시킨다면서 왜 15시로 설정하신거죠?
아시다시피 * * * * *
은 cron이다. 그리고 cron은 UTC+0이다. 그러니 UTC+9인 한국에서 사용하려면 24 - 9
해주면 된다.
잘 실행된다.
https://supabase.com/docs/guides/database/functions?queryGroups=language&language=js
supabase에는 쿼리문을 함수로 만들어놓을 수 있다.
# get_daily_color
select 컬럼명 from "테이블명" order by created_at desc limit 1
최신 데이터를 가져오는 쿼리문을 작성해서 함수로 만들어놓았다.
const { data, error } = await supabase.rpc("get_daily_color");
그리고 Next.js에서 해당 함수를 사용할 수 있다.
이미 당일 정답을 맞추었다면 또 맞출 필요 없이 해당 결과를 localStorage
에 저장한다.
question_number
와 DB에서 받아온 최신 문제 번호를 비교해서 같지 않으면 try_list
를 초기화하고 question_number
를 최신 문제 번호로 변경try_list
를 업데이트question_number
와 try_list
를 last_record
에 반영결과물은 아래와 같다.
UI 베껴서 미안합니다 어흑흑