pgAdmin에서 데이터 테이블 복사하는 완벽 가이드

PostgreSQL 데이터베이스 작업 중 테이블을 복사해야 하는 상황은 자주 발생합니다. 백업, 테스트, 데이터 마이그레이션 등 다양한 목적으로 테이블 복사가 필요한데요. 이 글에서는 pgAdmin을 활용한 여러 가지 테이블 복사 방법을 단계별로 알려드리겠습니다.


🎯 테이블 복사가 필요한 상황

  • 프로덕션 데이터를 테스트 환경으로 복사
  • 데이터 백업 및 복원
  • 테이블 구조만 복사하여 새 테이블 생성
  • 특정 데이터만 선택적으로 복사
  • 다른 데이터베이스로 테이블 이동


📋 방법 1: Backup/Restore 기능 활용 (GUI)

pgAdmin의 가장 직관적인 방법으로, 마우스 클릭만으로 테이블을 복사할 수 있습니다.

Backup 단계

1단계: 테이블 선택

  • pgAdmin 좌측 브라우저에서 복사할 테이블 찾기
  • 테이블에 우클릭
  • ‘Backup…’ 메뉴 선택

2단계: Backup 옵션 설정

General 탭:

  • Filename: 백업 파일 저장 경로 및 이름 지정 (예: users_backup.sql)
  • Format:
    • Plain – SQL 스크립트 형식 (텍스트, 편집 가능)
    • Custom – 압축된 커스텀 형식 (권장)
    • Tar – TAR 아카이브 형식
    • Directory – 디렉토리 형식

Data Options 탭:

  • Data: 체크 – 데이터 포함
  • Schemas: 체크 – 스키마 정보 포함
  • Blobs: 체크 – 대용량 객체 포함

3단계: Backup 실행

  • ‘Backup’ 버튼 클릭
  • 진행 상황 모니터링
  • 완료 메시지 확인

Restore 단계

1단계: 대상 데이터베이스 선택

  • 테이블을 복원할 데이터베이스 우클릭
  • ‘Restore…’ 메뉴 선택

2단계: Restore 옵션 설정

General 탭:

  • Filename: 백업 파일 선택
  • Format: 백업 시 선택한 형식과 동일하게 설정
  • Role name: 복원 수행 권한 사용자

Data Options 탭:

  • Only data: 데이터만 복원
  • Only schema: 구조만 복원
  • 둘 다 체크 안 함: 전체 복원

3단계: Restore 실행

  • ‘Restore’ 버튼 클릭
  • 완료 확인


💻 방법 2: SQL Query 사용 (추천)

SQL을 직접 작성하여 더 빠르고 유연하게 테이블을 복사할 수 있습니다.

구조와 데이터 모두 복사

-- 같은 데이터베이스 내에서 테이블 전체 복사
CREATE TABLE new_table AS
SELECT * FROM original_table;

-- 또는 더 명시적인 방법
CREATE TABLE new_table (LIKE original_table INCLUDING ALL);
INSERT INTO new_table SELECT * FROM original_table;

주의사항:

  • CREATE TABLE AS 방식은 인덱스, 제약조건, 기본값 등이 복사되지 않습니다
  • LIKE INCLUDING ALL 방식은 모든 속성을 복사합니다

테이블 구조만 복사

-- 데이터 없이 구조만 복사
CREATE TABLE new_table (LIKE original_table INCLUDING ALL);

-- 또는
CREATE TABLE new_table AS
SELECT * FROM original_table
WHERE 1=0;  -- 조건을 false로 만들어 데이터는 제외

특정 컬럼만 복사

-- 필요한 컬럼만 선택하여 복사
CREATE TABLE new_table AS
SELECT id, name, email, created_at
FROM original_table;

조건부 데이터 복사

-- 특정 조건의 데이터만 복사
CREATE TABLE active_users AS
SELECT * FROM users
WHERE status = 'active'
  AND created_at >= '2024-01-01';

인덱스와 제약조건 포함 복사

-- 1단계: 구조 복사 (모든 속성 포함)
CREATE TABLE new_table (
    LIKE original_table
    INCLUDING DEFAULTS
    INCLUDING CONSTRAINTS
    INCLUDING INDEXES
);

-- 2단계: 데이터 복사
INSERT INTO new_table
SELECT * FROM original_table;

-- 3단계: 시퀀스 재설정 (필요시)
SELECT setval('new_table_id_seq',
    (SELECT MAX(id) FROM new_table));

다른 스키마로 복사

-- 다른 스키마의 테이블로 복사
CREATE TABLE schema2.new_table AS
SELECT * FROM schema1.original_table;


🔧 방법 3: Query Tool 활용

pgAdmin의 Query Tool을 사용하면 복잡한 복사 작업도 쉽게 수행할 수 있습니다.

1단계: Query Tool 열기

  • 상단 메뉴에서 Tools > Query Tool 선택
  • 또는 단축키: Alt + Shift + Q

2단계: SQL 쿼리 작성

-- 예시: 최근 6개월 데이터만 복사
CREATE TABLE recent_orders AS
SELECT * FROM orders
WHERE order_date >= CURRENT_DATE - INTERVAL '6 months';

-- 테이블 정보 확인
SELECT COUNT(*) FROM recent_orders;

3단계: 쿼리 실행

  • 실행 버튼 클릭 (F5) 또는 재생 아이콘 클릭
  • 하단에서 실행 결과 확인


📊 방법 4: 대용량 테이블 복사

수백만 행 이상의 대용량 테이블을 복사할 때는 성능을 고려해야 합니다.

COPY 명령 사용

-- 1단계: 테이블을 파일로 내보내기
COPY original_table TO '/tmp/data.csv'
WITH (FORMAT CSV, HEADER true);

-- 2단계: 새 테이블 생성
CREATE TABLE new_table (LIKE original_table INCLUDING ALL);

-- 3단계: 파일에서 데이터 가져오기
COPY new_table FROM '/tmp/data.csv'
WITH (FORMAT CSV, HEADER true);

배치 처리로 복사

-- 대용량 테이블을 배치로 나눠서 복사
DO $$
DECLARE
    batch_size INTEGER := 10000;
    offset_val INTEGER := 0;
    total_rows INTEGER;
BEGIN
    -- 새 테이블 생성
    CREATE TABLE IF NOT EXISTS new_table
        (LIKE original_table INCLUDING ALL);

    -- 전체 행 수 확인
    SELECT COUNT(*) INTO total_rows FROM original_table;

    -- 배치 단위로 복사
    WHILE offset_val < total_rows LOOP
        INSERT INTO new_table
        SELECT * FROM original_table
        ORDER BY id
        LIMIT batch_size OFFSET offset_val;

        offset_val := offset_val + batch_size;
        RAISE NOTICE '진행률: %/%', offset_val, total_rows;
    END LOOP;
END $$;

🔐 권한 및 소유권 복사

테이블을 복사한 후에는 권한 설정도 필요할 수 있습니다.

-- 소유권 변경
ALTER TABLE new_table OWNER TO new_owner;

-- 권한 부여
GRANT SELECT, INSERT, UPDATE, DELETE
ON new_table TO app_user;

-- 원본 테이블의 권한 확인
SELECT grantee, privilege_type
FROM information_schema.role_table_grants
WHERE table_name = 'original_table';

⚠️ 주의사항 및 모범 사례

복사 전 확인사항

디스크 공간 확인

-- 테이블 크기 확인
SELECT
    pg_size_pretty(pg_total_relation_size('original_table')) AS total_size,
    pg_size_pretty(pg_relation_size('original_table')) AS table_size,
    pg_size_pretty(pg_indexes_size('original_table')) AS indexes_size;

테이블 구조 확인

-- 테이블 정보 조회
\\d+ original_table

-- 또는 pgAdmin에서 테이블 우클릭 > Properties

복사 후 검증

-- 행 수 비교
SELECT
    (SELECT COUNT(*) FROM original_table) AS original_count,
    (SELECT COUNT(*) FROM new_table) AS new_count;

-- 데이터 무결성 검증
SELECT * FROM original_table
EXCEPT
SELECT * FROM new_table;

-- 비어있으면 정상 복사됨

성능 최적화 팁

인덱스 관리

-- 복사 전 인덱스 삭제 (대용량 데이터)
DROP INDEX IF EXISTS idx_original_column;

-- 데이터 복사
INSERT INTO new_table SELECT * FROM original_table;

-- 복사 후 인덱스 재생성
CREATE INDEX idx_new_column ON new_table(column_name);

-- VACUUM ANALYZE 실행
VACUUM ANALYZE new_table;

트랜잭션 활용

BEGIN;

CREATE TABLE new_table AS SELECT * FROM original_table;

-- 검증
SELECT COUNT(*) FROM new_table;

-- 문제없으면 커밋, 있으면 롤백
COMMIT;
-- ROLLBACK;

🛠️ 자동화 스크립트

정기적으로 테이블을 복사해야 한다면 스크립트를 작성하세요.

#!/bin/bash
# table_copy.sh

DB_NAME="your_database"
SOURCE_TABLE="original_table"
TARGET_TABLE="backup_$(date +%Y%m%d)_table"

psql -d $DB_NAME -c "
    CREATE TABLE $TARGET_TABLE AS
    SELECT * FROM $SOURCE_TABLE;

    CREATE INDEX ON $TARGET_TABLE(id);

    VACUUM ANALYZE $TARGET_TABLE;
"

echo "테이블 복사 완료: $TARGET_TABLE"

🔍 트러블슈팅

권한 오류

ERROR: permission denied for table original_table

해결방법:

-- 권한 확인
SELECT * FROM information_schema.table_privileges
WHERE table_name = 'original_table';

-- 관리자에게 권한 요청 또는
GRANT SELECT ON original_table TO current_user;

디스크 공간 부족

ERROR: could not extend file: No space left on device

해결방법:

  • 디스크 공간 확보
  • 불필요한 테이블 삭제
  • 배치 처리로 나눠서 복사

제약조건 충돌

ERROR: duplicate key value violates unique constraint

해결방법:

-- 시퀀스 초기화
SELECT setval('new_table_id_seq',
    COALESCE((SELECT MAX(id) FROM new_table), 1));

-- 또는 제약조건 임시 비활성화
ALTER TABLE new_table DISABLE TRIGGER ALL;
-- 데이터 복사
ALTER TABLE new_table ENABLE TRIGGER ALL;


📚 마무리

pgAdmin에서 테이블을 복사하는 방법은 상황에 따라 다양합니다. GUI를 선호한다면 Backup/Restore 기능을, 더 세밀한 제어가 필요하다면 SQL 쿼리를 활용하세요.

상황별 추천 방법:

  • 간단한 전체 복사: Backup/Restore
  • 조건부 복사: SQL Query
  • 대용량 테이블: COPY 명령 또는 배치 처리
  • 정기적 백업: 자동화 스크립트

실무에서는 복사 전후 검증을 철저히 하고, 프로덕션 환경에서는 항상 트랜잭션을 활용하여 안전하게 작업하시기 바랍니다.


pgAdmin 사용 중 궁금한 점이나 다른 팁이 있으시다면 댓글로 공유해주세요!

댓글 남기기