PostgreSQL 뜻과 특징: 포스트그레스큐엘은 어떤 데이터베이스인가

이 글의 핵심

PostgreSQL은 오픈소스 객체-관계형 데이터베이스 관리 시스템(ORDBMS)으로, 한국에서는 흔히 포스트그레스큐엘 또는 줄여서 포스트그레스라고 읽습니다. 이 글은 이름의 유래와 발음, MVCC·확장성 같은 핵심 특징, MySQL과의 차이를 짚고 Docker로 설치해 첫 쿼리를 실행하는 과정까지 초보자 눈높이에서 정리합니다.

PostgreSQL(포스트그레스큐엘, 줄여서 포스트그레스)은 오픈소스 객체-관계형 데이터베이스 관리 시스템(Object-Relational Database Management System, ORDBMS)입니다. 관계형 데이터베이스답게 테이블과 SQL로 데이터를 다루면서도, 사용자 정의 타입·함수·확장 모듈을 붙일 수 있는 객체지향적 확장성을 함께 갖춘 것이 이름의 “객체-관계형”이 가리키는 부분입니다. 이름은 “Post-Ingres”에서 왔으며, 1996년 표준 SQL 지원이 추가되면서 지금의 PostgreSQL이라는 이름으로 정착했습니다.

이 글은 PostgreSQL이 정확히 무엇이고 이름이 왜 이렇게 생겼는지부터, 실제로 무엇이 강점인지, 그리고 처음 설치해서 쿼리 한 줄을 실행해보기까지를 다룹니다. 이미 PostgreSQL을 운영 중이고 인덱스나 파티셔닝 같은 심화 주제가 필요하다면 PostgreSQL 고급 가이드로 넘어가는 것이 더 빠릅니다.

이름과 역사

Ingres에서 POSTGRES로

PostgreSQL의 뿌리는 1970년대 UC Berkeley에서 Michael Stonebraker 교수가 만든 관계형 데이터베이스 Ingres입니다. Stonebraker는 Ingres를 상용화한 뒤, 당시 관계형 모델의 한계(복합 데이터 타입을 다루기 어렵다는 점 등)를 넘어서기 위해 1986년 POSTGRES(“Post-Ingres”의 줄임)라는 후속 연구 프로젝트를 시작했습니다. 이 프로젝트가 객체지향적 개념—사용자 정의 타입, 상속, 규칙 시스템—을 관계형 데이터베이스에 결합한 것이 지금 PostgreSQL이 “객체-관계형”이라 불리는 이유입니다.

Postgres95에서 PostgreSQL로

1994년 두 명의 대학원생 Andrew Yu와 Jolly Chen이 POSTGRES에 SQL 질의 언어 지원을 추가해 Postgres95라는 이름으로 공개했습니다. 이후 커뮤니티가 이어받아 계속 표준 SQL 준수를 강화하면서, 1996년에 SQL 지원을 명확히 반영한 지금의 이름 PostgreSQL로 다시 바뀌었습니다. 발음이 길다 보니 실무에서는 Postgres(포스트그레스)로 줄여 부르는 경우가 훨씬 많고, 공식 CLI 도구 이름도 psql입니다.

라이선스와 거버넌스

PostgreSQL은 특정 회사가 소유한 제품이 아니라 PostgreSQL Global Development Group이라는 전 세계 개발자 커뮤니티가 유지·보수합니다. 라이선스는 MIT·BSD 계열과 유사하게 관대한 PostgreSQL License를 사용하며, 소스 공개 의무나 상업적 이용 제한 없이 자유롭게 쓸 수 있습니다. 이 점은 GPL 기반 소프트웨어와 라이선스를 섞어 써야 하는 기업 환경에서 실제로 채택 여부를 가르는 요인이 되곤 합니다.

핵심 특징

PostgreSQL이 오래도록 기술적 표준으로 언급되는 이유는 아래 특징들이 서로 맞물려 있기 때문입니다. 하나씩 “왜 이게 중요한지”를 함께 봅니다.

MVCC — 읽기와 쓰기가 서로 막지 않는 구조

PostgreSQL은 다중 버전 동시성 제어(Multi-Version Concurrency Control, MVCC)를 사용합니다. 행을 수정(UPDATE)하거나 삭제(DELETE)해도 기존 데이터를 즉시 덮어쓰지 않고 새 버전을 만들어두는 방식으로, 한 트랜잭션이 데이터를 읽는 동안 다른 트랜잭션이 같은 행을 잠그지 않고 동시에 쓸 수 있습니다. 대신 이 방식은 “죽은 튜플”이 계속 쌓이기 때문에 VACUUM이라는 청소 과정이 필요하다는 트레이드오프를 동반합니다. 처음 PostgreSQL을 운영할 때 테이블 용량이 실제 데이터양보다 훨씬 커 보이는 현상(테이블 블로트)을 겪는 경우가 있는데, 대부분 autovacuum 설정이 워크로드에 비해 너무 느슨해서 생기는 문제입니다.

ACID 트랜잭션과 DDL

INSERT·UPDATE·DELETE 같은 데이터 조작뿐 아니라 CREATE TABLE, ALTER TABLE 같은 스키마 변경(DDL)까지 트랜잭션으로 묶을 수 있다는 점은 PostgreSQL의 실무적인 강점 중 하나입니다. 마이그레이션 스크립트를 실행하다 중간에 실패해도 ROLLBACK으로 스키마를 원상 복구할 수 있어, 배포 자동화 파이프라인에서 실패 처리가 훨씬 단순해집니다.

확장성 — 확장 모듈로 기능을 더할 수 있다

PostgreSQL은 CREATE EXTENSION 한 줄로 기능을 추가할 수 있는 확장 시스템을 제공합니다. 지리 정보 처리에 쓰이는 PostGIS, 벡터 유사도 검색에 쓰이는 pgvector, 시계열 데이터에 특화된 TimescaleDB 같은 확장이 대표적입니다. 별도의 데이터베이스 제품을 새로 도입하지 않고도 기존 PostgreSQL 인스턴스 위에서 이런 워크로드를 처리할 수 있다는 점이, 최근 RAG(검색 증강 생성) 애플리케이션에서 pgvector가 자주 선택되는 이유이기도 합니다.

풍부한 데이터 타입

배열, 범위 타입(int4range, tsrange 등), 그리고 특히 JSONB는 PostgreSQL을 반정형 데이터를 다루는 실무에서 자주 선택하게 만드는 요인입니다. JSONB는 JSON을 이진 형태로 저장해 파싱 비용 없이 인덱싱(GIN 인덱스)까지 지원하므로, “스키마가 자주 바뀌는 필드”를 관계형 테이블 안에서 함께 관리할 수 있습니다.

표준 SQL 준수와 윈도 함수, CTE

PostgreSQL은 ISO SQL 표준을 비교적 충실히 따르며, 윈도 함수(OVER, PARTITION BY)와 공통 테이블 표현식(CTE, WITH 구문)을 폭넓게 지원합니다. 순위 계산이나 이동 평균처럼 분석 쿼리에서 자주 나오는 패턴을 애플리케이션 코드로 끌어올리지 않고 SQL 한 번으로 처리할 수 있다는 뜻입니다.

flowchart LR
    A["요청/트랜잭션"] --> B{"MVCC 스냅샷"}
    B --> C["기존 데이터 읽기<br/>(잠기지 않음)"]
    B --> D["새 버전 행 생성"]
    D --> E["커밋"]
    D -.->|시간 경과| F["VACUUM이<br/>죽은 튜플 정리"]
    E --> G["ACID 보장"]
    G --> H["확장(PostGIS·pgvector 등)"]
    G --> I["JSONB·배열·범위 타입"]

MySQL·Oracle·SQLite와 어떻게 다른가

PostgreSQL과 MySQL은 둘 다 널리 쓰이는 오픈소스 관계형 데이터베이스지만, PostgreSQL은 표준 SQL 준수와 확장 타입·DDL 트랜잭션 같은 기능 표현력에, MySQL은 단순한 구조와 폭넓은 호스팅 생태계에 강점이 있습니다. 스키마 설계·트랜잭션 격리·복제 방식까지 실무 기준으로 비교한 내용은 PostgreSQL vs MySQL 비교 글에서 더 자세히 다룹니다.

Oracle Database는 상용 라이선스 기반의 엔터프라이즈 DBMS로, 파티셔닝이나 고가용성 기능 상당수가 유료 옵션으로 분리되어 있습니다. PostgreSQL은 그런 기능 대부분을 오픈소스 상태로 기본 제공하거나 확장으로 붙일 수 있어, 라이선스 비용 없이 유사한 기능을 구성할 수 있는 경우가 많습니다.

SQLite는 서버 프로세스 없이 하나의 파일로 동작하는 임베디드 데이터베이스라는 점에서 PostgreSQL과 성격이 다릅니다. 모바일 앱이나 로컬 우선(local-first) 애플리케이션처럼 서버가 필요 없는 상황에는 SQLite가 적합하고, 여러 클라이언트가 동시에 접속하는 서버 환경에는 PostgreSQL이 적합합니다.

어디서 쓰이나

PostgreSQL은 Stack Overflow Developer Survey 같은 개발자 설문에서 여러 해 동안 “가장 좋아하는(most loved)” 또는 “가장 널리 쓰이는” 데이터베이스 상위권에 꾸준히 오르는 편이며, DB-Engines 순위에서도 상위 관계형 DBMS로 분류됩니다(정확한 순위는 시점마다 바뀌므로 최신 수치는 각 사이트에서 직접 확인하는 것을 권합니다). Supabase, Neon, Amazon RDS/Aurora, Google Cloud SQL 등 여러 매니지드 클라우드 서비스가 PostgreSQL을 기본 엔진으로 제공한다는 점도 채택이 늘어난 배경 중 하나입니다. 서버리스 환경에서 PostgreSQL을 어떻게 스토리지와 컴퓨트로 분리해 쓰는지는 Neon 서버리스 Postgres 가이드에서 다룹니다.

설치하고 첫 쿼리 실행하기

로컬 환경을 어지럽히지 않고 가장 빠르게 테스트해보는 방법은 Docker입니다.

# 최신 안정 버전 컨테이너 실행 (버전 번호는 필요에 따라 고정)
docker run --name pg-test \
  -e POSTGRES_PASSWORD=mysecret \
  -p 5432:5432 \
  -d postgres:17

# 컨테이너 안의 psql로 접속
docker exec -it pg-test psql -U postgres

Ubuntu/Debian 계열에서는 apt로 바로 설치할 수 있습니다.

sudo apt update
sudo apt install postgresql postgresql-contrib
sudo systemctl status postgresql

Windows에서는 공식 사이트에서 배포하는 EDB 설치 프로그램(Windows installer)을 내려받아 GUI 설치 마법사를 따라가면 됩니다. 설치 과정에서 postgres 슈퍼유저 비밀번호와 기본 포트(5432)를 지정하게 됩니다.

접속했다면 psql에서 아래 메타 명령으로 상태를 확인할 수 있습니다.

\l          -- 데이터베이스 목록
\c mydb     -- mydb 데이터베이스로 전환
\dt         -- 현재 데이터베이스의 테이블 목록
\d users    -- users 테이블의 구조(컬럼, 인덱스, 제약) 확인

첫 테이블을 만들고 데이터를 넣어 조회해봅니다.

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    email TEXT UNIQUE NOT NULL,
    created_at TIMESTAMPTZ DEFAULT now()
);

INSERT INTO users (name, email) VALUES ('홍길동', '[email protected]');

SELECT id, name, email FROM users WHERE name = '홍길동';

SERIAL은 자동 증가하는 정수 기본키를 만드는 편의 타입이고, TIMESTAMPTZ는 타임존 정보를 함께 저장하는 시각 타입입니다. 여러 지역 사용자를 다루는 서비스라면 처음부터 TIMESTAMP가 아니라 TIMESTAMPTZ를 쓰는 편이 나중에 타임존 버그를 줄이는 데 도움이 됩니다.

초보자가 자주 겪는 오류

PostgreSQL을 처음 설치하고 접속을 시도할 때 거의 모두가 한 번쯤 마주치는 메시지들이 있습니다. 미리 알아두면 당황하지 않고 넘어갈 수 있습니다.

psql: error: connection to server ... failed: FATAL: Peer authentication failed for user "postgres"

Linux 패키지로 설치한 PostgreSQL은 기본적으로 OS 사용자 이름과 데이터베이스 사용자 이름이 일치할 때만 접속을 허용하는 peer 인증을 씁니다. 로그인 리눅스 사용자가 postgres가 아니라면 sudo -u postgres psql처럼 OS 사용자를 맞춰 접속하거나, pg_hba.conf에서 인증 방식을 peer에서 md5(또는 scram-sha-256)로 바꿔야 합니다. 처음 이 오류를 보면 “비밀번호가 틀렸나” 하고 계속 비밀번호를 바꿔보게 되는데, 사실은 인증 방식 자체가 비밀번호를 아예 확인하지 않는 방식이라 생기는 문제라서 원인을 알고 나면 오히려 간단합니다.

FATAL: role "myuser" does not exist

PostgreSQL에서 로그인 계정은 역할(role)로 관리됩니다. OS 계정과 달리 데이터베이스 역할은 CREATE ROLE myuser LOGIN PASSWORD '...'로 명시적으로 만들어야 하며, 시스템 계정이 있다고 자동으로 생기지 않습니다.

FATAL: password authentication failed for user "postgres"

비밀번호 자체가 틀렸거나, pg_hba.conf의 인증 방식이 scram-sha-256인데 클라이언트가 이전 방식(md5)의 해시를 들고 있는 경우에 발생합니다. Docker 이미지처럼 환경변수로 최초 비밀번호를 설정하는 경우, 컨테이너를 재생성해도 기존 볼륨이 남아있으면 비밀번호가 갱신되지 않는다는 점도 흔히 놓치는 부분입니다.

포트 5432 충돌

로컬에 이미 PostgreSQL이 설치돼 있는데 Docker 컨테이너를 같은 포트로 또 띄우면 bind: address already in use 류의 오류가 납니다. 둘 중 하나를 종료하거나, -p 5433:5432처럼 호스트 쪽 포트를 바꿔 매핑하면 됩니다.

대소문자 섞인 식별자

테이블이나 컬럼 이름을 큰따옴표 없이 CREATE TABLE Users (...)처럼 만들면 PostgreSQL은 내부적으로 이를 소문자로 접어 users로 저장합니다. 이후 SELECT * FROM "Users"처럼 큰따옴표로 대소문자를 강제하면 relation "Users" does not exist 오류가 납니다. 실무에서는 처음부터 식별자를 전부 소문자와 밑줄(snake_case)로 통일해 이 문제 자체를 피하는 것이 가장 속 편합니다.

다음 단계

기본기를 익혔다면 아래 글들이 실무로 넘어가는 다음 단계가 됩니다.

마치며

PostgreSQL이라는 이름은 낯설어 보여도, 그 안에는 “Ingres를 잇는다”는 연구 계보와 “표준 SQL을 지원한다”는 실용적 결정이 함께 녹아 있습니다. 이름의 유래를 알고 나면 왜 이 데이터베이스가 관계형 모델의 엄격함과 확장 가능한 유연함을 동시에 추구하는지도 조금 더 자연스럽게 이해됩니다. 처음 설치·접속 단계에서 겪는 오류 대부분은 인증 방식과 권한 모델을 이해하지 못해서 생기는 것이므로, 이 글에서 다룬 오류 메시지들만 기억해둬도 초반 진입 장벽은 크게 낮아질 것입니다.