skip to content
Q

[Spring๐ŸŒฑ] Supabase PostgreSQL Transaction Pooler ์—๋Ÿฌ ํ•ด๊ฒฐํ•˜๊ธฐ

/ 4 min read

Table of Contents

Supabase PostgreSQL Transaction Pooler ์—๋Ÿฌ ํ•ด๊ฒฐ

๋ฐฐ๊ฒฝ

Spring Boot ํ”„๋กœ์ ํŠธ๋ฅผ ๋ฐฐํฌํ•  ์ผ์ด ์žˆ์–ด์„œ DB ์„œ๋ฒ„๋ฅผ ์•Œ์•„๋ณด๋‹ค ์ตœ๊ทผ ๋งŽ์ด ์‚ฌ์šฉํ•œ Supabase๋ฅผ ์—ฐ๊ฒฐํ•˜๋ คํ–ˆ๋‹ค. PostgreSQL์„ ์ง€์›ํ•˜๊ธฐ์— ๋‚˜์ค‘์— migration์„ ํ• ๋•Œ์—๋„ ์ˆ˜์›”ํ•  ๊ฒƒ ๊ฐ™์•„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

์—ฐ๋™ ๋ฐฉ์‹์€ ์•„๋ž˜ ๋ธ”๋กœ๊ทธ ๊ธ€์„ ์ฐธ๊ณ ํ•˜๊ณ  Transaction Pooler ๋ชจ๋“œ๋กœ ์—ฐ๊ฒฐ์„ ์ง„ํ–‰ํ–ˆ๋‹ค. ์ฐธ๊ณ  ๋ธ”๋กœ๊ทธ

๋ฌธ์ œ ์ƒํ™ฉ

Spring Boot ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ Supabase PostgreSQL์„ Transaction Pooler ๋ชจ๋“œ๋กœ ์—ฐ๊ฒฐํ•˜๋˜ ์ค‘ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ์ง€์†์ ์œผ๋กœ ๋ฐœ์ƒํ–ˆ๋‹ค.

์‹ค์ œ ์—๋Ÿฌ ๋กœ๊ทธ

๋ฐฐํฌ๋œ AWS App Runner์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ๊ทธ

detailerror_severityevent_messagehintididentifiertimestamp
nullERRORprepared statement โ€œS_3โ€ already existsโ€ฆโ€ฆโ€ฆโ€ฆ

๋น„์Šทํ•˜๊ฒŒ "S_1" already exists, "S_2" already exists ๋“ฑ์˜ ์—๋Ÿฌ๋„ ํ•จ๊ป˜ ๋ฐœ์ƒํ–ˆ๋‹ค. S_x already exists ๋ฅ˜์˜ ์—๋Ÿฌ ๋ฐœ์ƒ!

์›์ธ ๋ถ„์„

Transaction Pooler vs Session Mode

Supabase๋Š” ๋‘ ๊ฐ€์ง€ ์—ฐ๊ฒฐ ๋ชจ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค:

  • Transaction Mode (ํฌํŠธ 6543): ์—ฐ๊ฒฐ์„ ์—ฌ๋Ÿฌ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ณต์œ ํ•˜์—ฌ ํšจ์œจ์ ์ธ ์ž์› ์‚ฌ์šฉ
  • Session Mode (ํฌํŠธ 5432): ๊ฐ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋…์ ์ ์ธ ์—ฐ๊ฒฐ์„ ์œ ์ง€

PostgreSQL JDBC Driver์˜ Prepared Statement ์บ์‹ฑ

PostgreSQL JDBC Driver๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ Server-side Prepared Statements๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค:

  1. prepareThreshold ๊ธฐ๋ณธ๊ฐ’์€ 5
  2. ๊ฐ™์€ ์ฟผ๋ฆฌ๊ฐ€ 5๋ฒˆ ์‹คํ–‰๋˜๋ฉด ์„œ๋ฒ„์—์„œ prepared statement๋ฅผ ์ƒ์„ฑ
  3. ์ด๋•Œ S_1, S_2, S_3 ๊ฐ™์€ ์ด๋ฆ„์œผ๋กœ statement๊ฐ€ ์ €์žฅ๋จ

๋ฌธ์ œ์˜ ํ•ต์‹ฌ

Transaction Pooler ๋ชจ๋“œ์—์„œ๋Š” ์—ฌ๋Ÿฌ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ๊ณต์œ ํ•˜๋Š”๋ฐ, ๊ฐ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ฐ™์€ ์ด๋ฆ„์˜ prepared statement๋ฅผ ์ƒ์„ฑํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜๋ฉด์„œ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•œ๋‹ค.

Client A: CREATE PREPARED STATEMENT "S_1" ...
Client B: CREATE PREPARED STATEMENT "S_1" ... # ์ถฉ๋Œ!

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

์ง„๋ฆฌ์˜ ๋ฌธ stackoverflow์— ๋‹ต์ด ์žˆ์—ˆ๋‹คโ€ฆ ๊ฐ„๋‹จํ•œ ์ˆ˜์ •์œผ๋กœ ํ•ด๊ฒฐํ–ˆ์œผ๋ฉฐ ์•„๋ž˜์— ๊ธฐ์ˆ ํ•˜๊ฒ ๋‹ค!

1. prepareThreshold=0 ์„ค์ •

๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ํ•ด๊ฒฐ์ฑ…์€ server-side prepared statements๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

application.yml ์„ค์ •

spring:
datasource:
url: jdbc:postgresql://aws-0-us-west-1.pooler.supabase.com:6543/postgres?prepareThreshold=0
username: postgres.your-project-ref
password: your-password
driver-class-name: org.postgresql.Driver

2. ํฌํŠธ ๋ณ€๊ฒฝ ๊ณ ๋ ค

Transaction Pooler ๋ชจ๋“œ(6543)์—์„œ Session Mode(5432)๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ๋„ ํ•ด๊ฒฐ์ฑ…์ด ๋  ์ˆ˜ ์žˆ๋‹ค. supabase๊ณต์‹๋ฌธ์„œ

spring:
datasource:
url: jdbc:postgresql://aws-0-us-west-1.pooler.supabase.com:5432/postgres
username: postgres.your-project-ref
password: your-password

ํ•˜์ง€๋งŒ ์ด ๊ฒฝ์šฐ Connection Pool์˜ ์ด์ ์„ ์žƒ๊ฒŒ ๋œ๋‹ค.

์„ฑ๋Šฅ ๊ณ ๋ ค์‚ฌํ•ญ

prepareThreshold=0์˜ ์˜ํ–ฅ

  • ์žฅ์ : Transaction Pooler์™€์˜ ํ˜ธํ™˜์„ฑ ๋ณด์žฅ
  • ๋‹จ์ : Prepared Statement ์บ์‹ฑ ๋น„ํ™œ์„ฑํ™”๋กœ ์ธํ•œ ์•ฝ๊ฐ„์˜ ์„ฑ๋Šฅ ์ €ํ•˜

๊ฒฐ๋ก 

Supabase PostgreSQL Transaction Pooler์™€ Spring Boot๋ฅผ ์—ฐ๊ฒฐํ•  ๋•Œ๋Š” prepareThreshold=0 ์„ค์ •์ด ํ•„์š”ํ•˜๋‹ค. ์ด๋Š” PostgreSQL JDBC Driver์˜ server-side prepared statement ์บ์‹ฑ ๊ธฐ๋Šฅ๊ณผ Transaction Pooler์˜ ์—ฐ๊ฒฐ ๊ณต์œ  ๋ฐฉ์‹ ๊ฐ„์˜ ์ถฉ๋Œ์„ ํ•ด๊ฒฐํ•œ๋‹ค.

์„ฑ๋Šฅ์ƒ ์•ฝ๊ฐ„์˜ ์†์‹ค์ด ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ, ์•ˆ์ •์ ์ธ ์—ฐ๊ฒฐ์„ ์œ„ํ•ด์„œ๋Š” ํ•„์š”ํ•œ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋กœ ์ž˜ ๊ณ ๋ คํ•ด์„œ ์‚ฌ์šฉํ•˜์žโ€ฆ

์ฐธ๊ณ  ์ž๋ฃŒ