PGAdapter를 사용하여 연결

이 문서에서는 PGAdapter를 사용하여 Spanner Omni에 연결하는 방법을 설명합니다. 보안 연결을 설정하도록 PGAdapter를 구성합니다. PGAdapter는 일반 텍스트, 전송 계층 보안 (TLS), 상호 TLS (mTLS) 보안 모드를 지원합니다. 이러한 모드는 다양한 수준의 암호화 및 인증을 제공하여 전송 중에 데이터를 보호합니다. 각 보안 모드에서는 데이터 무결성과 기밀성을 보장하기 위해 특정 클라이언트 구성이 필요합니다.

PGAdapter를 독립형 프로세스로 실행하거나 애플리케이션에 직접 통합할 수 있습니다. 대화형 관리 및 수동 쿼리 실행의 경우 psql과 같은 표준 PostgreSQL 도구를 사용하여 데이터베이스에 연결합니다. 자동화된 애플리케이션을 빌드하려면 다음과 같은 PostgreSQL 호환 드라이버를 사용하세요.

이러한 드라이버 중 일부를 사용하는 코드 샘플은 이 문서의 샘플 코드를 참고하세요.

보안 모드

Spanner Omni PGAdapter는 PGAdapter와 데이터베이스 간의 통신이 암호화되고 인증되는 방식을 정의하는 세 가지 보안 모드를 지원합니다. 이러한 모드를 사용하려면 다음 표에 설명된 대로 클라이언트 옵션을 구성하세요.

보안 모드 설명
일반 텍스트 통신이 암호화되지 않습니다.
TLS 통신은 전송 계층 보안 (TLS)을 사용하여 암호화됩니다. 이 모드에서는 Spanner Omni CA 인증서를 기본 Java 트러스트 저장소에 추가해야 합니다.
mTLS 통신은 상호 TLS (mTLS)를 사용하여 암호화됩니다. 이 모드에서는 클라이언트 인증서와 클라이언트 비공개 키를 모두 제공해야 합니다.

독립형 프로세스로 실행

수동 데이터베이스 상호작용이 필요한 경우 Java 이외의 애플리케이션과 표준 PostgreSQL 도구(예: psql)의 독립형 프로세스로 PGAdapter를 실행합니다. 이 접근 방식을 사용하면 프록시가 애플리케이션 수명 주기에서 분리되어 프록시를 독립적으로 관리하고 업데이트할 수 있습니다. PGAdapter를 독립형 프로세스로 시작하려면 선택한 보안 모드에 따라 다음 구성 방법을 사용하세요.

일반 텍스트 모드 사용

일반 텍스트 통신 모드에서 PGAdapter를 시작하려면 다음 명령어를 실행합니다.

java -jar pgadapter.jar \
     -d DATABASE_ID \
     -e ENDPOINT \
     -r "isExperimentalHost=true;usePlainText=true"

다음을 바꿉니다.

  • DATABASE_ID: Spanner Omni 데이터베이스의 ID입니다(예: test-db).

  • ENDPOINT: Spanner Omni 인스턴스의 엔드포인트입니다(예: localhost:15000).

TLS 모드 사용

Java 애플리케이션으로 TLS 모드에서 PGAdapter in-process를 시작하려면 먼저 Spanner Omni CA 인증서를 기본 Java 신뢰 저장소에 추가해야 합니다. 기존 CA 인증서를 Java 트러스트 저장소에 추가하려면 다음 명령어를 실행합니다.

sudo keytool -import -trustcacerts -file ~/.spanner/certs/ca.crt -alias spanner-ca -keystore $JAVA_HOME/lib/security/cacerts

TLS 모드에서 PGAdapter를 시작하려면 다음 명령어를 실행합니다.

java -Djavax.net.ssl.trustStore=$JAVA_HOME/lib/security/cacerts \
     -Djavax.net.ssl.trustStoreType=JKS \
     -jar pgadapter.jar \
     -d DATABASE_ID \
     -e ENDPOINT \
     -r "isExperimentalHost=true"

mTLS 모드 사용

mTLS 모드에서 PGAdapter를 시작하려면 클라이언트 키가 PKCS#8 형식인지 확인해야 합니다. 키 저장소의 기존 키를 PKCS#8 형식으로 변환하려면 다음 명령어를 실행합니다.

openssl pkcs8 -topk8 -in ~/.spanner/certs/client.key -out ~/.spanner/certs/java-client.key -nocrypt

또는 Spanner Omni CLI를 사용하여 클라이언트 인증서와 키를 만들 때 --generate-pkcs8-key 매개변수를 제공하여 PKCS#8 형식으로 키를 생성합니다.

mTLS 모드에서 PGAdapter를 시작하려면 다음 명령어를 실행하세요.

java -Djavax.net.ssl.trustStore=$JAVA_HOME/lib/security/cacerts \
    -Djavax.net.ssl.trustStoreType=JKS \
    -jar pgadapter.jar \
    -d DATABASE_ID \
    -e ENDPOINT \
    -r "isExperimentalHost=true;clientCertificate=PATH_TO_CLIENT_CERT;clientKey=PATH_TO_CLIENT_KEY"

다음을 바꿉니다.

  • PATH_TO_CLIENT_CERT: 클라이언트 인증서 파일의 경로입니다.

  • PATH_TO_CLIENT_KEY: 클라이언트 키 파일의 경로

psql 비즈니스와 채팅

앞의 방법 중 하나를 사용하여 연결을 설정한 후 psql를 실행하여 데이터베이스를 관리하고 쿼리를 실행합니다. psql에 연결하려면 다음 명령어를 사용하세요.

psql -h PG_HOST -p PG_PORT -U USERNAME -d DATABASE_ID

다음을 바꿉니다.

  • PG_HOST: PGAdapter가 실행 중인 머신의 호스트 이름 또는 IP 주소입니다. 로컬에서 실행하는 경우 localhost를 사용합니다.

  • PG_PORT: PGAdapter가 실행 중인 포트 번호입니다. 맞춤 포트를 지정하지 않은 경우 PGAdapter는 기본적으로 포트 5432를 사용합니다.

  • USERNAME: PostgreSQL 사용자 이름입니다.

애플리케이션과 함께 인프로세스로 실행

애플리케이션에서 진행 중인 PGAdapter를 시작할 수도 있습니다. 보안을 설정하려면 OptionsMetadata 객체를 구성합니다.

일반 텍스트 모드 사용

암호화 오버헤드가 필요하지 않은 보안 환경에서 로컬 개발 또는 테스트와 같은 일반 텍스트 통신의 경우 다음 구성을 사용하세요.

OptionsMetadata.Builder builder =
    OptionsMetadata.newBuilder()
    .setEndpoint("ENDPOINT")
    .setUsePlainText();

ProxyServer server = new ProxyServer(builder.build());
server.startServer();
server.awaitRunning();

TLS 모드 사용

로컬 개발 또는 테스트와 같은 환경에서 사용할 일반 텍스트 통신의 경우 다음 구성을 사용하세요.

sudo keytool -import -trustcacerts -file /.spanner/certs/ca.crt -alias spanner-ca -keystore $JAVA_HOME/lib/security/cacerts

프로세스 내에서 TLS 연결을 설정하려면 다음 구성을 사용하세요.

OptionsMetadata.Builder builder =
    OptionsMetadata.newBuilder()
    .setEndpoint("ENDPOINT");

ProxyServer server = new ProxyServer(builder.build());
server.startServer();
server.awaitRunning();

mTLS 모드 사용

Java 애플리케이션에서 PGAdapter 인프로세스 모드를 시작하려면 클라이언트 키가 PKCS#8 형식이어야 합니다. 키 저장소의 기존 키를 PKCS#8 형식으로 변환하려면 다음 명령어를 실행합니다.

openssl pkcs8 -topk8 -in ~/.spanner/certs/client.key -out ~/.spanner/certs/java-client.key -nocrypt

또는 Spanner Omni CLI를 사용하여 클라이언트 인증서와 키를 만들 때 --generate-pkcs8-key 매개변수를 제공하여 PKCS#8 형식으로 키를 생성합니다.

프로세스 내에서 mTLS 연결을 설정하려면 다음 구성을 사용하세요.

OptionsMetadata.Builder builder =
    OptionsMetadata.newBuilder()
    .setEndpoint("ENDPOINT")
    .useClientCert("PATH_TO_CLIENT_CERT", "PATH_TO_CLIENT_KEY");

ProxyServer server = new ProxyServer(builder.build());
server.startServer();
server.awaitRunning();

샘플 코드

이 섹션에서는 다음 PostgreSQL 호환 드라이버를 사용하여 Spanner Omni 데이터베이스에 연결하는 샘플 코드를 제공합니다.

연결 문자열에서 다음 자리표시자를 바꿉니다.

  • PASSWORD: PostgreSQL 사용자 비밀번호

JDBC

PostgreSQL 데이터베이스에 연결하는 것처럼 PostgreSQL JDBC 드라이버를 사용하여 PGAdapter에 연결할 수 있습니다. Spanner Omni 데이터베이스의 테이블을 연결하고 쿼리하려면 다음 샘플 코드를 사용하세요.

String jdbcUrl =
    "jdbc:postgresql://PG_HOST:PG_PORT/DATABASE_ID";

try (Connection connection = DriverManager.getConnection(jdbcUrl)) {
  // Example: Query data
  try (Statement statement = connection.createStatement();
      ResultSet resultSet = statement.executeQuery("SELECT * FROM Singers")) {

    System.out.println("Query Results:");
    while (resultSet.next()) {
      long id = resultSet.getLong("id");
      String name = resultSet.getString("name");
      System.out.printf("ID: %d, Name: %s\n", id, name);
    }
  } catch (SQLException e) {
    throw new RuntimeException(e);
  }
}

Go(pgx)

PostgreSQL 데이터베이스에 연결하는 것처럼 pgx를 사용하여 PGAdapter에 연결할 수 있습니다. 다음 샘플 코드를 사용하세요.

// Database connection string
connString := "postgres://USERNAME:PASSWORD@PG_HOST:PG_PORT/DATABASE_ID?sslmode=disable"
ctx := context.Background()

// Connect to PGAdapter
conn, err := pgx.Connect(ctx, connString)
if err != nil {
  log.Fatalf("Connection error: %s", err.Error())
}
defer conn.Close(ctx)

// Query all rows from the Singers table
rows, err := conn.Query(ctx, "SELECT id, name FROM Singers")
if err != nil {
  log.Fatalf("Query error: %s", err.Error())
}
defer rows.Close()

// Iterate over the result set
fmt.Println("Singers Table Data:")
for rows.Next() {
  var id int
  var name string
  if err := rows.Scan(&id, &name); err != nil {
    log.Fatalf("Scan error: %s", err.Error())
  }
  fmt.Printf("ID: %d, Name: %s\n", id, name)
}

Python (psycopg2 또는 psycopg3)

PostgreSQL 데이터베이스에 연결하는 것처럼 psycopg2 또는 psycopg3을 사용하여 PGAdapter에 연결할 수 있습니다. Spanner Omni 데이터베이스의 테이블을 연결하고 쿼리하려면 다음 샘플 코드를 사용하세요.

# psycopg2
import psycopg2

connection = psycopg2.connect(database="DATABASE_ID",
                              host="PG_HOST",
                              port=PG_PORT)

cursor = connection.cursor()
cursor.execute('SELECT * FROM Singers')
for row in cursor:
  print(row)

cursor.close()
connection.close()


# psycopg3
import psycopg

with psycopg.connect("host=PG_HOST port=PG_PORT dbname=DATABASE_ID sslmode=disable") as conn:
  conn.autocommit = True
  with conn.cursor() as cur:
    cur.execute("SELECT * FROM Singers")
    for row in cur:
      print(row)

Node.js (node-postgres)

PostgreSQL 데이터베이스에 연결하는 것처럼 node-postgres를 사용하여 PGAdapter에 연결할 수 있습니다. Spanner Omni 데이터베이스의 테이블을 연결하고 쿼리하려면 다음 샘플 코드를 사용하세요.

const { Client } = require('pg');
const client = new Client({
  host: 'PG_HOST',
  port: PG_PORT,
  database: 'DATABASE_ID',
});
await client.connect();
const res = await client.query("SELECT * FROM Singers");
console.log(res.rows);
await client.end();