์ง๊ธ ์์ฑํ๊ณ ์๋ dalmuri ํ๋ก์ ํธ ๋ด์ ๋๋ค ์ฃผ์ ๋ฅผ ๋์ง๋ฉด ๊ทธ๊ฒ์ ๋ํด ์์ ๋กญ๊ฒ ์ด์ผ๊ธฐํ๋ ๊ธฐ๋ฅ์ ๋ง๋ค๊ณ ์๋ค.

์ ๋ฌธ๊ตฌ์ ๋งค์ผ ๋ค๋ฅธ ๋ด์ฉ์ผ๋ก ๋ฐ๋๊ณ ์์ ๋กญ๊ฒ ์ด์ผ๊ธฐํ๋๊ฒ์ ๊ตฌ์ฑํ๋ค.
๋ผ์ฆ๋ฒ ๋ฆฌํ์ด๋ฅผ ์ธ๋ถ์์ ์ฐ๊ฒฐ ํ DB๋ฅผ ๊ตฌ์ถํ๊ณ ์ถ์๋๋ฐ, ์ข์ ์์คํ ์ ์ฐพ๋ ์์ค Supabase๋ผ๋๊ฑธ ์๊ฒ ๋์๋ค..
Supabase์ ๋ํ ์ค๋ช ์ ์ถํ์ ์์ฑํ๋ค...
์ด์ฐ๋ฌ๊ฑด Supabase๋ฅผ ํตํด open API๋ฅผ ๋ง๋ค๊ณ , ๊ทธ open API๋ฅผ ๋ด ํ๋ก์ ํธ์ ๋ถ๋ฌ ์ ์์ ฏ์ ๋ฌธ๊ตฌ๋ฅผ ๋์ฐ๋ ๋ฐฉ์์ผ๋ก ๋ง๋ค๊ธฐ๋ก ์๊ฐํ๋ค.
๋ค์ด๊ฐ๊ธฐ ์ ์!
๋จผ์ Supabase์ ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์๋ค๋ ๊ฐ์ ํ์ ์์ฑํ๋ค...
1. Supabase์์ TABLE ์์ฑ
ํ ์ด๋ธ์๋ ID, ๋ด์ฉ, ๊ทธ๋ฆฌ๊ณ insert time์ด ๋ค์ด๊ฐ ์๋ค. ๋๋คํ ์ฃผ์ ๊ฐ ํต์ฌ์ด๊ธฐ ๋๋ฌธ์ ๋ง์ ์ปฌ๋ผ์ ๋ฃ์ง ์์๋ค.

์ ๋ฐ์์ผ๋ก ๋ง๋ค์๋ค. ์์ฌ๋ ์ฐจ์ฐจ ๋ ์๊ฐํด๋ณผ ์์ .
์ฐธ๊ณ ๋ก ํ ์ด๋ธ์ ์์ฑํ ๋ ๋ฐ๋์ RLS์ ์ฑ ์ ์ ์ฉํ ์ ์๋๋ก ํ์๋ฅผ ํด์ผ ํ๋ค!
2. ๋ณด์ ์ ์ฑ ์ค์
Supabase์ ๊ฐ์ฅ ๋งค๋ ฅ์ ์ธ ์ฅ์ ์ผ๋ก, ๊ฐ ํ ์ด๋ธ ๋ณ๋ก ์ ์ฑ ์ ๋ง๋ค ์ ์๋ค๋ ๊ฒ์ด๋ค.
open API์ ํต์ฌ์ ์ฌ์ฉ์๊ฐ SELECT๋ฌธ๋ง ๊ฐ๋ฅํ๋๋ก ํด์ผ ํ๋ค.
API๋ฅผ ํธ์ถํ๋ ์ฌ์ฉ์๊ฐ INSERT, UPDATE, DELETE๋ฅผ ํ ์ ์์ผ๋ฉด ์ ๋ ์๋๊ธฐ ๋๋ฌธ....
๋ฐ๋ผ์ SELECT๋ง ํ ์ ์๋๋ก ๋ณ๋์ ์ค์ ์ ์ถ๊ฐํ๋ค.
1๏ธโฃ Policies ํด๋ฆญ > create Policy ํด๋ฆญ


2๏ธโฃ SELECT๋ง ์ฒดํฌ

๋ค๋ฅธ๊ฑธ ์ ํํ๋ฉด ์ธ๋ถ ์ฌ์ฉ์๊ฐ INSERT, UPDATE, DELETE๋ ํ ์ ์๊ฒ ๋๋ฏ๋ก ๋ฌด์กฐ๊ฑด SELECT๋ง ํ์ฉํ๋ค.
3๏ธโฃ VIEW ์์ฑ
์ด์ฐจํผ ์ปจํ ์ธ ๋ฅผ ๋๋ค์ผ๋ก ๊ฐ์ ธ์ค๋ ๊ฒ์ด๋ฏ๋ก ์ฌ์ฉ์๋ id๋ inserttime๊ฐ์ ๋ถ๊ฐ์ ์ธ ์ปฌ๋ผ์ ํ์์๋ค.
๋ฐ๋ผ์ api ํธ์ถ ์ ์ปจํ ์ธ ๋ง ๊ฐ์ ธ์ฌ ์ ์๋๋ก, ์ฆ RANTO_CONTENT๋ง ๊ณต๊ฐํ ์ ์๋๋ก VIEW๋ฅผ ์์ฑํ๋ค.
(1) SQL ์๋ํฐ ์คํ

(2) VIEW๋ฅผ ์์ฑํ๋ ์ฟผ๋ฆฌ๋ฌธ ์์ฑ
-- ๋ทฐ๋ฅผ ํตํด ์ปจํ
์ธ ์ปฌ๋ผ(RANTO_CONTENT)๋ง ๊ณต๊ฐ
CREATE VIEW public."RANDOM_TOPIC_VIEW"
WITH (security_invoker = true)
AS
SELECT "RANTO_CONTENT" FROM public."RANDOM_TOPIC";
์ฃผ์์ !
PostegreSQL์ ๋์๋ฌธ์๋ฅผ ์๊ฒฉํ ๊ตฌ๋ถํ๋ค. ๋ํ ๋ณ๋์ ํ์๊ฐ ์๋ค๋ฉด ๋ฌด์กฐ๊ฑด ์๋ฌธ์๋ก ์ธ์ํ๋ค.
public.RANDOM_TOPIC์ด๋ผ๊ณ ์์ฑํ๋ฉด public.random_topic์ผ๋ก ์ธ์ํ๋๋ฐ, RANDOM_TOPIC = random_topic์ผ๋ก ์ธ์์ ํ์ง ๋ชปํด Error: Failed to run sql query: ์ ๊ฐ์ ์๋ฌ๊ฐ ๋ํ๋ฌ๋ค.
๋ฐ๋ผ์ ๋๋ฌธ์๋ก ํ ์ด๋ธ/์ปฌ๋ผ์ ์์ฑํ ๊ฒฝ์ฐ ๋ฐ๋์ ํฐ๋ฐ์ดํ "" ๋ฅผ ์์ ๊ฐ์ด ๋ถ์ผ ๊ฒ!
์ด๊ฑธ ๋ชฐ๋ผ์ ์ค๊ฐ์ ์ข ํค๋งธ๋คใ ใ ใ
๊ทธ๋ฆฌ๊ณ Supabase์ SQL์ ์ฃผ์์ ํ์ง ์์ผ๋ฉด ์คํฌ๋ฆฝํธ ์ ์ฒด๊ฐ ์คํ๋๊ธฐ ๋๋ฌธ์(; ๋จ์๋ก ๋์ด์ง์ง ์๋๋ผ...?) ๋ฐ๋์ ์คํํ ๊ตฌ๋ฌธ๋ง ๋จ๊ฒจ๋๊ณ ๋๋จธ์ง๋ ์ฃผ์ ์ฒ๋ฆฌ๋ฅผ ํ๋๋ก ํ๋ค.
์ฐธ๊ณ ๋ก security_invoker์ ์ค์ ํด์ผ ํ๋๋ฐ, ๊ทธ ์์ธ์ ๋ณด์ ๋๋ฌธ์ด๋ค..
โ SECURITY INVOKER vs SECURITY DEFINER
open API๋ ๋๊ตฌ๋ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ ์ ์๋ค.
- SECURITY INVOKER(ํธ์ถ์) : ์ค์ API ์์ฒญ์ ๋ณด๋ด๋ ์ฌ์ฉ์์ ๊ถํ์ ๊ธฐ์ค์ผ๋ก RLS๊ฐ ์ ์ฉ๋๋ฉฐ. ๊ณต๊ฐ์ฉ ๋ทฐ๋ผ๋ฉด public ์ญํ ์ ๋ง์ถ์ด ์์ ํ๊ฒ ๊ณต๊ฐํ ์ ์๋ค.
- SECURITY DEFINER(์ ์์) : ๋ทฐ ์์ ์์ ๊ถํ์ ๊ธฐ์ค์ผ๋ก ๋ฐ์ดํฐ๊ฐ ๋ฐํ๋๋ฉฐ, RLS ์ ์ฑ ์ด ๋ฌด์๋ ์ ์์ด ์ธ๋ถ์์ ์ ๊ทผํ๋ฉด ์๋๋ ๋ฐ์ดํฐ๊น์ง ๋ ธ์ถ๋ ์ ์๋ค.
๋๊ตฌ๋ฅผ ๊ธฐ์ค์ผ๋ก ์ ์ฑ ๊ถํ์ ์ ์ฉํ ์ง ์ค์ ํ๋ ๊ฒ์ธ๋ฐ, ์ฆ ๋ทฐ ์์ ์์ ๊ถํ์ด ์ฝ๊ธฐ/์ฐ๊ธฐ ๋ฑ์ ์ค์ํ ํธ์ง์ด ๊ฐ๋ฅํ๋ค๋ฉด ์ธ๋ถ ์ฌ์ฉ์๋ RLS ์ ์ฑ ์ด ๋ฌด์๋์ด ์ด์ํ๊ฒ ์ ๊ทผํ ์ ์๋ ์ํ์ด ์๊ธฐ๋๊ฑฐ๋ค.
๋ฐ๋ผ์ open API๋ก ์ฌ์ฉํ ์์ ์์ VIEW๋ฅผ ๋ง๋ค ๋ ๋ฐ๋์ 'INVOKER'๋ก ํ ๊ฒ!
4๏ธโฃ ํ๋ก์์ ธ ์์ฑ
์์์ ์์ฑํ๋ RANDOM_TOPIC_VIEW๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋๋ค์ผ๋ก ํ ํฝ์ ๊ฐ์ ธ์ค๋ ํ๋ก์์ ธ๋ฅผ ์์ฑํ๋ค.
CREATE FUNCTION get_random_topic()
RETURNS "RANDOM_TOPIC_VIEW"
as
$$
SELECT * FROM "RANDOM_TOPIC_VIEW" ORDER BY RANDOM() LIMIT 1;
$$
LANGUAGE sql STABLE;
- ํจ์ ์ด๋ฆ: get_random_topic
- ํจ์ ์ ๊ดํธ()๋ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ๋ ์์ญ์ธ๋ฐ, ์ง๊ธ์ ์์ผ๋ฏ๋ก ๋น์๋
- RETURNS "RANDOM_TOPIC_VIEW" : RANDOM_TOPIC_VIEW๋ผ๋ VIEW ์ ์ฒด ๊ตฌ์กฐ์ ๊ฐ์ ํ์์ผ๋ก ๋ฐํ. RANDOM_TOPIC_VIEW๋ RANTO_CONTENT ์ปฌ๋ผ๋ง ์์ผ๋ฏ๋ก ๊ทธ๊ฒ๋ง ๋ฐํํ ๊ฒ. PostegreSQL์์ TABLE์ด๋ VIEW ์ด๋ฆ์ ๋ฐํ ํ์ ์ผ๋ก ์ง์ ํ๋ฉด ๊ทธ ๊ตฌ์กฐ๋๋ก ๋ฐํ๋จ
- AS $$...$$ : ํจ์์ ์ค์ ์ฟผ๋ฆฌ๋ฌธ์ ๋ด๋ SQL ๋ธ๋ก
- SELECT * FROM "RANDOM_TOPIC_VIEW" : ํด๋น ๋ทฐ์์ ์ ์ฒด ์ปฌ๋ผ์ ์กฐํ(์ด์ฐจํผ CONTENT๋ง ์์ด์ ์๊ด ์์)
- ORDER BY RANDOM() : ๋๋ค์ผ๋ก ๋ฐฐ์ ํจ
- LIMIT 1: 1๊ฐ์ ํ๋ง ๊ฐ์ ธ์ด
- LANGUAGE sql : ์ด ํจ์๊ฐ SQL ๋ฌธ๋ฒ์ผ๋ก ์์ฑ๋จ
- STABLE : ๊ฐ์ ํธ๋์ญ์ ์์ ๊ฐ์ ์ ๋ ฅ์ ๋ํด ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ค๊ณ DB๊ฐ ํ๋จ
3. ํ๋ก ํธ ํ๋ก์ ํธ - supabase ์ค์
1๏ธโฃ ๋ด ํ๋ก ํธ ํ๋ก์ ํธ์ .env ํ์ผ ์ค์

SUPABASE_URL์ ๋ด ํ๋ก์ ํธ ์์ด๋(https://๋ด ํ๋ก์ ํธ ์์ด๋.supabse.co)๋ฅผ ์์ฑํ๊ณ
SUPABASE_ANON_KEY์ Publishable key๋ฅผ ๋ณต๋ถ์ ํ๋๋ก ํ๋ค.
์ฐธ๊ณ ๋ก ANON = anonymous๋ ๋ป์ด๊ธฐ ๋๋ฌธ์ ๊ฐ ์ฌ์ดํธ๋ณ๋ก api key๊ฐ์ ๋ถ๋ฅธ ํธ์นญ์ด ๋ค๋ฅด๋ค. ์ค๋ช ์๋ supabase anon key๋ผ๊ณ ์ฐ์ฌ ์์ด์ ๋๋์ฒด ์ด๊ฒ ๋ญ ํค์ธ๊ณ ... ์ฐพ์๋ณด๋ ๊ทธ๋ฅ publishable key๋ฅผ ๊ฐ๋ค์ฐ๋ฉด ๋๋๊ฑฐ์๋คใ

General > Project ID์

API Keys > Publishable key ๋ฅผ ๊ฐ์ ธ์์ ๋ณต๋ถ์ ํ๋ฉด๋๋ค.
2๏ธโฃ npm install supabase๋ฅผ ์ค์น
๋ด ํ๋ก์ ํธ๋ node.js๋ฅผ ์ฌ์ฉํ๋๊น npm์ผ๋ก supabase๋ฅผ ์ค์นํ๋ค.
3๏ธโฃ ์ฝ๋ ์์ฑ
๋ค์๊ณผ ๊ฐ์ด ์ฝ๋๋ฅผ ์์ฑํด๋ณธ๋ค.
async function getRandomTopic () {
const { data, error } = await supabase.rpc('get_random_topic')
if(error) console.error(error)
if(data) {
console.log(data)
}
setTopic(data.RANTO_CONTENT)
}
์ ๋ ๊ฒ console.log๋ฅผ ํตํด data๋ฅผ ์ถ๋ ฅํ๋ฉด ์ ๋์จ๋ค!
4. ๋ฐฑ ํ๋ก์ ํธ - supabase ์ค์ , ์ฐ๊ฒฐ
๋ด ๋ฐฑ์ java+spring์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ spring ํ์์ ๋ฐ๋ฅธ๋ค.
1๏ธโฃ ์ธํ ๋ฆฌ์ ์ด์ ๋ด DB ์ฐ๊ฒฐ
์ด๊ฑฐ๋๋ฌธ์ ์ข ๋ง์ด ์ ๋จน์๋๋ฐ ๋ง์ ํ๋ฉด ์ฑ๊ณตํ ์ ์๋ค.

์ผ๋จ ์ด ํ๋ฉด์ด ๋ณด์ฌ์ผ ํ๋ค. ์ฐธ๊ณ ๋ก supabase๋ PostgreSQL์ ์ฌ์ฉํ๋ฏ๋ก ํด๋น SQL์ ์ ํํ๋ค.
2๏ธโฃ ๋ด supabase DB ์ ๋ณด ์ ๋ ฅ
์ ๋ณด ์ฐพ๋๊ฒ ์ ์ผ ์ ๋จน์๋ค. ์ง์ง๋กใ ใ ใ ใ
ํ๊ตญ์ด ์ค๋ช ์ ์์ด๋ฆฌ ์์๊น
(1) connect ํด๋ฆญ

(2) Method: Sesson pooler ํด๋ฆญ

Session pooler๋ก ํด๋ฆญํ๊ณ view parameters๋ฅผ ํด๋ฆญํ๋ฉด ์ธํ ๋ฆฌ์ ์ด properties์ ๋ฌด์จ ์ ๋ณด๋ฅผ ์ ๋ ฅํด์ผ ํ๋์ง ๋ฌ๋ค.
์ฐธ๊ณ ๋ก database๋ ๋ด๊ฐ ์์๋ก ์ ์ง ๋ง๊ณ postgres๋ฅผ ๋ฐ๋ผ ์ ๋๋ค. ๋ ๊ดํ ํ๋ก์ ํธ๋ช ์ผ๋ก ํ๋ค๊ฐ ์ ๋จน์๋ค..
๊ทธ๋ฆฌ๊ณ ๊ธฐ๋ณธ ํฌํธ๋ฒํธ๋ 5432์ด๋ค.
(3) ์ธํ ๋ฆฌ์ ์ด์ ๊ทธ๋๋ก ์์ฑ, ์ฐ๊ฒฐ



๊ธฐ์กด์ ๋ง๋ค์๋ ํ ์ด๋ธ์ด ์ ๋ณด์ธ๋ค. ์ค์!
๊ทธ ๋ค๋ก pom.xml์ ์์กด์ฑ ์ถ๊ฐ
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
์ฐธ๊ณ ๋ก dependencyManagement์ ์์ฑํ๋ฉด ์๋จ! ๊ฑฐ๊ธฐ์ ์์ฑํ๋ค๊ฐ ๊ดํ ์๊ฐ ๋ณด๋๋ค..
pom.xml์ ์์ฑํ์ผ๋ฉด applicaiton.properties์ ๊ฐ์ธ jdbc ์ฐ๊ฒฐ ์ ๋ณด ์์ฑ.
๊ทธ๋ฆฌ๊ณ ์ฝ๋ ์์ฑ, ํด๊ฒฐ!
3๏ธโฃ ์ฝ๋ ์์ฑ
MVCํจํด์ ์๊ฑฐํ์ฌ ์์ฑํ์๋ค. ์ฌ๊ธฐ์ controller, service๋ง ๊ณต๊ฐ
(1) controller
public class RandomTopicController {
public final RandomTopicService service;
@GetMapping("get-random-topic")
public RandomTopicResponseDTO getRandomTopic() {
return service.getRandomTopic();
} // getRandomTopic
}
(2) service
public class RandomTopicService {
private final JdbcTemplate jdbcTemplate;
public RandomTopicResponseDTO getRandomTopic () {
String sql = "SELECT * FROM get_random_topic()";
Map<String, Object> result = jdbcTemplate.queryForMap(sql);
String content = (String) result.get("RANTO_CONTENT");
RandomTopicResponseDTO res = new RandomTopicResponseDTO();
res.setRantoContent(content);
return res;
} // getRandomTopic
}
์์ ๊ฐ์ด ์์ฑํ๋ฉด ํธ์ถ ์ ์ ์์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์จ๊ฑธ ํ์ธํ ์ ์์๋ค.

5. Supabase Edge Function์ผ๋ก openAPI๋ฅผ ๋ง๋ค๊ธฐ
์ด์ localhost๊ฐ ์๋ ๋ชจ๋ ์ปดํจํฐ์์ api๋ฅผ ํธ์ถํ ์ ์๋๋ก ์์ ์ ํ๋ค.
๊ทธ๋ฌ๊ธฐ ์ํด์ ๋ scoop์ ๊น์์ผ ํ๋๋ฐ... ์๋๋ฉด ๋์ด์ supabase๊ฐ npm install -g supabase๋ฅผ ์ง์ํ์ง ์๊ธฐ ๋๋ฌธ์ด๋ค ใ ....
์ค์นํ๊ธฐ ๊ทธ ์ ์
C:\Dalmuri
โ
โโ src/ ← React ์์ค
โโ public/
โโ package.json
โโ supabase/ ← Supabase Edge Function ์ ์ฉ
โโ config.toml
โโ functions/
โโ get-random-topic/
โโ index.ts
โโ supabase.function.toml
์ด๋ฐ์์ผ๋ก ๋๋ ์ผ ํ๊ธฐ ๋๋ฌธ์ supabase๋ฅผ ์ํ ํด๋๋ฅผ ๋ฐ๋ก ํ๋ค.
(1) scoop ์ค์น
Invoke-RestMethod https://get.scoop.sh | Invoke-Expression
(2) Supabase Edge Function ์ค์น
scoop bucket add supabase https://github.com/supabase/scoop-bucket.git
scoop install supabase
(3) Supabase CLI์ ๋ก๊ทธ์ธ
supabase login
๋ผ๊ณ ์น๋ฉด ๋ค์ ํ๋ฉด์ด ๋์ค๋๋ฐ,

์ ๊ธฐ์ ๋์ค๋ ์ฝ๋๋ฅผ powershell์ฐฝ์ ๋ณต๋ถํ๋ค.
๊ทธ๋ฌ๋ฉด ๋ก๊ทธ์ธ์ด ๋๋ฉด์

์ด๋ด๊ฒ ๋ฌ๋ค. ์ง๊ธ ๐ถ๊ณ ์ํ๋ฉด์ ์ฝ๋ฉํ๊ณ ์๋๋ฐ ์ฅ๋ํ๋?
(4) ํค๊ฐ ๋ฑ๋ก
ํ๋ก ํธ๋ .env์ ํค๊ฐ์ ์ถ๊ฐํ๋ ๊ฒ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ฑ๋กํ๋ค.
supabase secrets set SUPABASE_URL=https://<URprojectID>.supabase.co
supabase secrets set SUPABASE_ANON_KEY=<your-anon-key>
๋ฅผ ๋ฑ๋กํ๋๋ฐ, ๋ง์ฝ

์ด๋ฐ ๋ฅ์ ์๋ฌ ๋ฌธ๊ตฌ๊ฐ ๋๋ฉด ์ด๋ฏธ SUPABASE_URL, SUPABASE_ANON_KEY ๊ฐ์ ์ด๋ฆ์ด Edge Functions์์ ์ด๋ฏธ ์์คํ ํ๊ฒฝ ๋ณ์๋ก ์ฌ์ฉ๋๊ณ ์์ผ๋ฏ๋ก ๋ฐ๋ก secrets๋ก ๋ฑ๋กํ ํ์ ์๋ค๋ ๋ป์ด๋ค.
(5) ์ฝ๋ ์์ฑ
import { serve } from "https://deno.land/std@0.168.0/http/server.ts"
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.36.0";
serve(async () => {
// ํ๊ฒฝ๋ณ์์์ supabase ์ ๋ณด ๊บผ๋ด๊ธฐ
const SUPABASE_URL = Deno.env.get("SUPABASE_URL")
const SUPABASE_ANON_KEY = Deno.env.get("SUPABASE_ANON_KEY")
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY)
try {
// ์ฌ๊ธด ๋ณธ์ธ ์ํฉ์ ๋ง๋ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ๋๋ค.
const { data, error } = await supabase.select ....
if (error) console.error(error)
if(data){
console.log(data)
}
if(!data || data.length === 0) {
return new Response(JSON.stringify({rantoContent:null}), {
status: 200,
headers: {
'content-type': 'application/json',
'Access-Control-Allow-Origin': '*', // ๊ณต๊ฐ ํ์ฉ
},
})
}
} catch (err) {
console.error(err)
return new Response(JSON.stringify({rantoContent:null}), {
status: 500,
headers: {
'content-type': 'application/json',
"Access-Control-Allow-Origin": "*",
},
})
}
})
์ฝ๋๋ฅผ ์ด๋ป๊ฒ ์์ฑํ ์ง๋ ๊ฐ๋ฐ์๋ง๋ค ๊ฐ๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์์๋ก์ ์ ๋ ๊ฒ ๋จ๊ฒจ๋๋ค.
(6) ๋ฐฐํฌํ๊ธฐ
๋ฐฐํฌ ๋ช ๋ น์ด๋ ์๋์ ๊ฐ๋ค.
supabase functions deploy ๋ฐฐํฌํ function ์ด๋ฆ --no-verify-jwt
์ --no-verify-jwt๋ฅผ ๋ง๋ถ์๋๋ฉด...supabase๋ ๊ธฐ๋ณธ์ ์ผ๋ก JWT ์ธ์ฆ์ ์๊ตฌํ๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทผ๋ฐ ์๋ฌด๋ ํธ์ถํ๋ ๊ณต๊ฐ api๋ก ๋ง๋ค๋ ค๋ฉด jwt์ธ์ฆ์ ๋๊ฑฐ๋, anon key๋ฅผ ์ฌ์ด์ ํธ์ถํด์ผ ํ๋ค.
- ์ธ์ฆ ์ผ์ง ์ํ
- Authorization ํค๋ ํ์
- Supabase ANON_KEY ๋๋ ๋ก๊ทธ์ธ ํ ํฐ ํ์
- ์ ๋ถ์ด๋ฉด 401 ์๋ฌ
- --no-verify-jwt ์ฌ์ฉ
- ์ธ์ฆ ์ฒดํฌ ๋
- ๋๊ตฌ๋ URL๋ง ์๋ฉด ํธ์ถ ๊ฐ๋ฅ
- ๋ธ๋ผ์ฐ์ ์์ ์ฝ๊ฒ fetch ๊ฐ๋ฅ
๊ทผ๋ฐ anon-key๋ฅผ ๋ถ์ด๊ณ ํธ์ถํ๋ฉด ๋์ค์ ๊ดํ ํค๊ฐ ๋ ธ์ถ๋ ๊น๋ด ๊ทธ๋ฅ jwt ์ธ์ฆ์ ์์ด ๋ถ๋ฅผ ์ ์๋๋ก ์ค์ ํ๋ค.
๋จ ๋ฐฐํฌํ ๋ ๋ง๋ค ๋ฐ๋์ no verify jwt๋ฅผ ๋ถ์ผ ๊ฒ!
6. ๊ฒฐ๊ณผ๋ฌผ!
๋๋ค์ผ๋ก ์ฃผ์ ํ๋๋ฅผ ๋์ง๋ ๊ณต๊ฐ API๋ก, ์ธ์ฆ์ด๋ ํค ์์ด ์ ๊ทผํ ์ ์๋ค.
Endpoint
https://llfsxgdcamgbxpwcsnwh.functions.supabase.co/get-random-topic
Request
| Method | URL | Headers | Body |
| GET | /get-random-topic | ์์ | ์์ |
Response
- 200 ok
[
{
"RANTO_CONTENT": "์ค๋ ์ ๋
๋ฉ๋ด ์ถ์ฒ!"
}
]
- 500 error : null / undefined ๋ฐํ
CORS ์ ์ฑ
- ๋ชจ๋ ๋๋ฉ์ธ์์ ์ ๊ทผ ๊ฐ๋ฅ (Access-Control-Allow-Origin: *)
- ํ๋ก ํธ์์ ๋ฐ๋ก fetch ํธ์ถ ๊ฐ๋ฅ
์์
async function fetchRandomTopic() {
const response = await fetch('https://llfsxgdcamgbxpwcsnwh.functions.supabase.co/get-random-topic');
const data = await response.json();
console.log(data[0].RANTO_CONTENT);
}
fetchRandomTopic();
์ด๊ฑฐ ๋ง๋๋๋ฐ ์์ด๋ฆฌ ํ๋๋...
๊ทธ๋ฆฌ๊ณ ๊ณ์ ํธ์ถํ์ง ๋ง๋ผ supabase ๋ฌด๋ก๋ฒ์ ์ด๋ผ ์๋ฒ ๋ถ์ ์ง๊น ๊ฑฑ์ ๋๋ค... ๋๋ ํ๋ฃจ์ ํ๋ฒ ํธ์ถํ๋๋ฐ
(๊ทธ๋ด๊ฑฐ๋ฉด ์ ์คํํจ?ใ
ใ
ใ
;)
7. ์ค๊ฐ์ค๊ฐ ์ค๋ฅ ์์ธ
1. RANDOM_TOPIC_VIEW๊ฐ ์๋๋ฐ DB์์ ์ธ์์ ๋ชปํ ๊ฒฝ์ฐ
๐ ํจ์์ ๋ฐํ ํ์ (Returns Type) ๋ถ์ผ์น. ํจ์ ๋ทฐ ๊ตฌ์กฐ์ ์ฌ๋ฌํ(SETOF)์ ๋ฐํํด์ผ ํ์ผ๋ ์ด๊ธฐ์ ๋จ์ผํ์ ๋ฐํํ๋๊ฒ์ฒ๋ผ ์์ฑ๋จ. VIEW๋ ์ฌ๋ฌ ํ์ ๋ฐํํ๋ ๋ด๊ฐ ๋จ์ผ ํ๋ง ๋ฐํํ๋ค๊ณ ์๋ชป ์ ์ธํ์
๋ฐ๋ผ์ ๊ธฐ์กด์ RETURNS_๋ทฐ_์ด๋ฆ์์ RETURNS SETOF ๋ทฐ_์ด๋ฆ์ผ๋ก ๋ณ๊ฒฝํจ
2. [XX000] FATAL: MaxClientsInSessionMode: max clients reached - in Session mode max clients are limited to pool_size
์ด ์๋ฌ๋ connection pool์ 30์ผ๋ก ๋๋ ธ๋๋ ํด๊ฒฐ์ ํ์ง๋ง.. connection pool์ ๋ํด ๊ณต๋ถํด์ผ๊ฒ ๋ค. ์ด๊ฑด ๋ค๋ฅธ ํฌ์คํธ์์!
3. scoop์ supabase๊ฐ ์๋ก ๋ง๋ ํ๋ก์ ํธ์์ ์ธ์์ด ๋์ง ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ ๋ฌธ์
์์คํ ํ๊ฒฝ๋ณ์ ํธ์ง > ํ๊ฒฝ ๋ณ์ > ์๋ก๋ง๋ค๊ธฐ > path ํด๋ฆญ > scoops\shims๊ฐ ์๋ ํ์ผ์ ์ถ๊ฐ
๊ทผ๋ฐ๋ ์ธ์ ์๋๋ฉด ๊ป๋ค ์ผ๋ผ. ๋ ๋ฌ๋คใ
[์ฐธ๊ณ ์๋ฃ]
https://rlawo32.tistory.com/entry/SUPABASE-SUPABASE-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0
[Supabase] Supabase ์ฌ์ฉํ๊ธฐ
1. Supabase๋?Supabase๋ BaaS(Backend as a Service)๋ก ์๋น์คํ ๋ฐฑ์๋์ด๋ค.ํ๋ก ํธ์๋๋จ์์ ๋ฐฑ์๋ ์๋น์ค๋ฅผ ์ ๊ณตํด ์ฃผ๋ ์๋น์ค ๋ชจ๋ธ์ด๋ค. ์ฆ, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ API๋ฅผ ๊ตฌ์ถํ๋ ๋ฐ ํ์ํ ๋ณต์กํ ์ค์ ๊ณผ
rlawo32.tistory.com
https://velog.io/@manner9945/supabase-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-6tyu3xcx
supabase ์ฌ์ฉํ๊ธฐ
๋ฐฑ์๋ ๊ธฐ๋ฅ๋ค์ ์ง์ํ๋ ํด๋ผ์ฐ๋ ์๋น์ค ํ๋ก ํธ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐฑ์๋ ์๋น์ค๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ชจ๋ธ PostgreSQL์ ๊ธฐ๋ฐ์ผ๋ก SQL ์ฟผ๋ฆฌ ๋ฐ ๋ค์ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์ ์ํํ ์
velog.io
https://velog.io/@itzel_02/IntelliJ-DB-%EC%97%B0%EB%8F%99
IntelliJ & DB ์ฐ๋
๋ฐ์ดํฐ ๋ฒ ์ด์ค์ ์ค์ ์์ ์์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ ํ์ผ์ ์์ฑ์์ ์ฌ์ง๊ณผ ๊ฐ์ด ์ฐ๊ฒฐ์ด Succeeded๋ ๊ฒ์ ๋ณผ ์ ์์
velog.io
https://like-grapejuice.tistory.com/214
PostgreSQL ํ๊ฒฝ์ค์ Intellij๋ก connectํ๊ธฐ + java code๋ก ์คํํ๊ธฐ
์ ์ค๋์ Intellij IDE๋ฅผ ์ด์ฉํด์ postgresql์ connect ํ๊ณ java code๋ก ์ฌ์ฉํ๋ ๋ฒ์ ๋ํด์ ์์๋ณด์. ์ฌ์ฉํ๋ ํ๊ฒฝ์ Window8, Intellij IDEA Ultimate 2020.3.3 Connect ์ผ๋จ java๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ๋น์ฐํ JDK๊ฐ ํ์
like-grapejuice.tistory.com
IT ๊ฐ๋ฐ์ ๋ธ๋ก๊ทธ - Java, Spring Boot, React ๋ฑ
๋ค์ํ ๊ฐ๋ฐ ์ง์๊ณผ ๋ ธํ์ฐ๋ฅผ ๊ณต์ ํ๋ ๋ธ๋ก๊ทธ | Java, Spring Boot, React, Next.js, NAS, ๋ฐ์ดํฐ๋ฒ ์ด์ค, ๋ฆฌ๋ ์ค
ai-one.tistory.com

'ToyProjects๐งธ > Dalmuriโญ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [Dalmuri] Java๋ก Google Cloud Nature Language API ํธ์ถํด์ ๊ฐ์ ๋ค์ด์ด๋ฆฌ ๋ง๋ค๊ธฐ (0) | 2025.10.16 |
|---|---|
| ํ๋ก์ ํธ Dalmuri ๊ธฐํ ๋ฐ ์ค๊ณ (0) | 2025.08.16 |