백엔드 데이터 인프라 4편. PostgreSQL의 표준 CLI psql에 첫 접속하고 메타 명령과 SQL 실행 흐름을 손에 익히는 학습 노트.
이 글은 백엔드 데이터 인프라 시리즈 70편 중 4편이에요. 3편 아키텍처 에서 "PG가 어떻게 생긴 시스템인지" 그림을 봤으니, 이번 4편은 그 그림 위에 psql로 손을 직접 올려 처음 만져 봐요.
psql이 뭐고 왜 중요한가
psql = PostgreSQL이 함께 배포하는 표준 CLI(명령줄 인터페이스) 클라이언트. GUI(그래픽 사용자 인터페이스) 도구(DBeaver·pg_admin)도 좋지만 — "운영 서버에 SSH(원격 셸 접속)로 들어가 빠르게 점검" 같은 시나리오는 무조건 psql.
면접·실무 둘 다 — "psql로 어떻게 X 하나요?" 가 자주 등장. SQL이 익숙해도 psql 메타 명령(\로 시작) 모르면 손이 느려요.
접속 — 방법별
2편 에서 설치한 방법에 따라.
Docker
docker exec -it postgres-dev psql -U postgres
-it = 대화형 터미널 연결, -U postgres = 슈퍼유저 접속.
Homebrew
psql -d postgres
# 또는 사용자명·DB 명시
psql -U postgres -d postgres
Linux apt
sudo -u postgres psql
외부 호스트
psql -h db.example.com -p 5432 -U appuser -d myappdb
# 비밀번호 프롬프트 → 입력
-h(host) -p(port) -U(user) -d(database) 4개가 표준 옵션.
첫 인사
psql (18.4)
Type "help" for help.
postgres=#
postgres=# 의 의미는 — postgres 가 현재 접속한 DB, = 가 명령 입력 대기 상태, # 가 슈퍼유저 표시(일반 사용자면 >).
메타 명령 — psql의 진짜 매력
\ 로 시작 = psql 자체의 단축 명령 (SQL이 아님). 가장 자주 쓰는 20개.
| 명령 | 의미 | 예 |
|---|---|---|
\? |
psql 도움말 전체 | 시작 시 한 번 |
\h SELECT |
SQL 문법 도움말 | \h CREATE TABLE |
\l |
DB 목록 | |
\c myappdb |
DB 접속 변경 | |
\dn |
스키마 목록 | |
\dt |
테이블 목록 (public) | |
\dt *.* |
모든 스키마 테이블 | |
\d users |
테이블 구조 | 컬럼·인덱스·제약 |
\d+ users |
더 자세히 | 통계·설명 포함 |
\du |
사용자(role) 목록 | |
\dp users |
권한 표시 | |
\df |
함수 목록 | |
\dv |
뷰 목록 | |
\timing |
쿼리 시간 토글 | 성능 검증 |
\x |
확장 표시 토글 | 컬럼 많은 행 보기 |
\e |
외부 에디터로 쿼리 작성 | $EDITOR |
\i file.sql |
파일 실행 | |
\o file.txt |
결과 파일 출력 | |
\copy |
CSV 등 import/export | |
\q |
종료 |
처음엔 \?·\l·\dt·\d 테이블·\q 5개만 외워도 OK.
첫 SQL — 한 줄씩
postgres=# SELECT 1 + 1 AS result;
result
--------
2
(1 row)
세미콜론(;) 으로 한 SQL 종료. 세미콜론 없으면 "여러 줄에 걸친 한 SQL" 로 계속 입력 대기.
postgres=# SELECT
postgres-# now(),
postgres-# current_user;
now | current_user
-------------------------------+--------------
2026-05-17 14:30:00.123456+09 | postgres
(1 row)
프롬프트가 =# → -# 로 바뀌면서 "아직 SQL 안 끝났음" 표시.
첫 테이블·CRUD 전 흐름
5편(pg-create-database) 부터 본격으로 다루지만 — 분위기 미리.
-- 새 DB 만들기
CREATE DATABASE myappdb;
-- 접속 변경
\c myappdb
-- 첫 테이블
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE,
created TIMESTAMPTZ DEFAULT NOW()
);
-- 데이터 입력
INSERT INTO users (name, email) VALUES
('Alice', 'alice@example.com'),
('Bob', 'bob@example.com');
-- 조회
SELECT * FROM users;
-- 변경
UPDATE users SET name = 'Alice Smith' WHERE name = 'Alice';
-- 삭제
DELETE FROM users WHERE name = 'Bob';
-- 테이블 구조 확인
\d users
이 흐름이 머릿속에 박혀 있으면 — 다음 편들이 "이 흐름의 각 단계 깊이" 로 자연스럽게 이어져요.
트랜잭션 미리 보기
BEGIN;
UPDATE users SET name = 'Test' WHERE id = 1;
SELECT * FROM users WHERE id = 1; -- 변경 보임
ROLLBACK; -- 취소
SELECT * FROM users WHERE id = 1; -- 원상 복귀
BEGIN·COMMIT·ROLLBACK 으로 명시적 트랜잭션. 17편 트랜잭션·6편 MVCC(다중 버전 동시성 제어)에서 깊이.
자주 쓰는 옵션
-c "SQL" — 한 줄 실행 후 종료
psql -U postgres -c "SELECT version();"
스크립트·CI에서 자주.
-f file.sql — 파일 실행
psql -U postgres -d myappdb -f migration.sql
마이그레이션·초기화 스크립트 실행.
--single-transaction
psql -U postgres -d myappdb --single-transaction -f migration.sql
파일 전체를 한 트랜잭션 으로 실행 — 하나 실패 시 전체 롤백. 안전.
-v var=value — 변수 전달
psql -v userid=42 -c "SELECT * FROM users WHERE id = :userid;"
.psqlrc — psql 설정 파일
홈 디렉토리 ~/.psqlrc 에 박으면 — psql 시동 시 자동 적용.
\set QUIET ON
\timing on
\set HISTSIZE 5000
\set PROMPT1 '%[%033[1m%]%M:%>%[%033[0m%] %~%R%# '
\pset null '[NULL]'
\set QUIET OFF
\timing on 은 모든 쿼리 시간을 자동 출력해 주고, \set HISTSIZE 5000 은 히스토리를 5000개로 늘리며, \pset null '[NULL]' 은 null을 [NULL] 로 보기 좋게 표시.
운영 환경 psql 첫 설정 = .psqlrc 박기.
외부 에디터 통합
postgres=# \e
\e 명령 = $EDITOR 환경 변수에 설정된 에디터(vim·nano 등) 가 열리고, 거기서 SQL 작성 → 저장 → psql이 실행. 긴 쿼리 작성 시 매우 편함.
GUI vs psql — 언제 무엇?
| 시나리오 | 권장 |
|---|---|
| 운영 서버 점검 (SSH) | psql 무조건 |
| 빠른 단순 쿼리 | psql |
| 데이터 탐색·시각화 | DBeaver·pg_admin |
| 테이블 구조 보기 | 둘 다 (취향) |
| CSV import/export | psql \copy 빠름 |
| 백업·복구 | psql + pg_dump |
GUI 도구는 "편의·시각화", psql은 "속도·신뢰성·운영". 둘 다 익숙해지는 게 표준.
함정 5가지
(1) 세미콜론 누락
postgres=# SELECT * FROM users
postgres-#
postgres-#
세미콜론 없으면 — 영원히 입력 대기. ; 박거나 \r (현재 입력 취소).
(2) \d 와 \dt 혼동
\dt 는 테이블 목록, \d 이름 은 그 이름의 객체 구조라 자주 헷갈림. \d 단독 = 모든 객체 목록 (테이블·뷰·시퀀스 등).
(3) 권한 부족
postgres=> CREATE TABLE foo (...);
ERROR: permission denied for schema public
슈퍼유저 아닌 사용자로 접속해 시스템 객체 만들려 할 때. 사용자 권한 확인 또는 슈퍼유저로.
(4) \copy vs COPY
COPY 는 SQL 명령으로 서버 측 파일을 보고, \copy 는 psql 메타 명령으로 클라이언트 측 파일을 본다. CSV(쉼표 구분 텍스트) import 시 "내 노트북 파일" 을 가져오려면 \copy 가 정답. COPY 는 서버 호스트의 파일을 봐서 일반 사용자는 못 쓸 때가 많음.
(5) 한글 깨짐
postgres=# SELECT * FROM users;
name
------
?????
서버·DB·클라이언트의 인코딩 불일치. 보통:
SHOW server_encoding; -- UTF8 이어야
SHOW client_encoding; -- UTF8 이어야
\encoding UTF8 로 클라이언트 변경. 운영 = 처음부터 UTF8로 DB 생성 (5편에서 다룸).
psql 접속 → \? 한 번 → \l · \dt · \d 테이블이름 · SELECT version() · SELECT 1+1 · \q. 이 6줄을 한 번 해 보는 게 시리즈 본격 진입의 첫 통과 의례.
한 줄 정리 — psql = PG 표준 CLI. 메타 명령(\)이 진짜 매력. \l·\dt·\d·\du·\timing·\e·\i·\q 가 자주 쓰는 8개. -c·-f·-h·-U·-d 가 명령행 표준 옵션. .psqlrc 가 설정 자동화.
시험 직전 한 번 더 — psql 입문자가 매번 헷갈리는 것
- psql = PG 표준 CLI 클라이언트
- 접속 =
psql -h host -p port -U user -d database - Docker =
docker exec -it postgres-dev psql -U postgres - macOS brew =
psql -d postgres - Linux apt =
sudo -u postgres psql - 프롬프트 =
dbname=#(슈퍼유저) 또는dbname=>(일반) - SQL 끝 = 세미콜론(
;) - 멀티라인 =
-#으로 프롬프트 바뀜 - 메타 명령 =
\로 시작 (psql 자체) \?= 도움말,\h SQL= SQL 문법\l= DB 목록,\c db= 접속 변경\dt= 테이블 목록,\d 이름= 객체 구조,\d+= 더 자세히\du= 사용자 목록\timing= 쿼리 시간 토글\x= 확장 표시 (컬럼 많은 행)\e= 외부 에디터,\i file.sql= 파일 실행\copy= 클라이언트 파일 import/export\q= 종료- 한 줄 실행 =
-c "SQL" - 파일 실행 =
-f file.sql(+--single-transaction) .psqlrc= 설정 자동화- 한글 깨짐 = encoding UTF8 확인
- 운영 서버 = psql 무조건, GUI는 개발 시각화
시리즈 다른 편 (앞뒤 글 모음)
이전 글:
- 1편 — PostgreSQL이란 + MySQL과의 비교
- 2편 — PostgreSQL 설치 (Docker·brew·apt 3가지)
- 3편 — PostgreSQL 아키텍처 (클라이언트·서버·DB·테이블)
다음 글: