프로젝트 중 방화벽이 아직 뚫려 있지 않아서, Container가 설치된 VM에 있는 DB에 급하게 접속해야하는 경우가 생겼다.

그럴 때, 아래와 같은 명령어로 직접 postgresql가 설치된 docker container에 접속하여, psql 명령어를 통해 쿼리를 조회해 볼 수 있다.

 

Postgresql Container에 psql 명령어를 호출하기

명령어 형식: docker exec -it [컨테이너 이름 또는 ID] psql -U [사용자 이름] -d [데이터베이스 이름]

실행 예시:

Bash
 
docker exec -it myproject-db-1 psql -U myuser -d mydatabase
  • -it 옵션이 중요합니다!
    • -i (interactive): 키보드 입력을 컨테이너로 전달합니다. (SQL 쿼리를 입력할 수 있게 해줍니다)
    • -t (tty): 터미널 환경을 보기 좋게 만들어줍니다.
    • psql처럼 계속 명령을 주고받아야 하는 프로그램에 접속할 때는 반드시 -it 옵션을 함께 사용해야 합니다.
    • -it 옵션을 사용하지 않으면, 말그대로 container에서 해당 명령어만 수행할 뿐, container 바깥에 있는 terminal에서는 수행 결과를 확인하거나 interaction을 할 수가 없다.

Psql Quick Guide

psql에 익숙해지려면 아래 4개 명령어만 기억하고 시작해도 충분합니다.

  1. \l : 데이터베이스 목록 보기(list)
  2. \c [DB이름] : 다른 DB로 접속하기(connect)
  3. \dt : 테이블 목록 보기(database table)
  4. \d+ [테이블이름] : 테이블 상세 구조 완벽하게 파악하기
  5. \q : psql 종료

데이터베이스의 구조를 파악하기 위해 가장 많이 사용하는 메타 명령어들입니다.

명령어 설명 사용 예시
\l 또는 \list PostgreSQL 서버의 모든 데이터베이스 목록을 봅니다. \l
\c [db] 다른 데이터베이스로 접속을 전환합니다. \c other_database
\dt 현재 데이터베이스의 테이블 목록을 봅니다. \dt
\d [이름] 특정 테이블의 구조(컬럼, 타입 등) 또는 뷰, 시퀀스 정보를 봅니다. \d users
\dn 스키마(Schema) 목록을 봅니다. \dn
\df 함수(Function) 목록을 봅니다. \df
\dv 뷰(View) 목록을 봅니다. \dv
\du 사용자(Role) 목록을 봅니다. \du

✨ Pro Tip: 위 명령어 뒤에 +를 붙이면 훨씬 더 상세한 정보를 볼 수 있습니다.

  • \l+ : 데이터베이스의 크기, 테이블스페이스 등 추가 정보 표시
  • \dt+ : 테이블의 크기, 설명(Comment) 등 추가 정보 표시
  • \d+ [테이블] : 컬럼별 상세 정보, 제약 조건, 인덱스 등 모든 정보 표시 

실제 SQL을 실행하고 관리하는 방법입니다.

  • 기본 SQL 실행 일반적인 SQL 문을 작성하고, 반드시 문장 끝에 **세미콜론(;)**을 붙여야 실행됩니다.
    SELECT * FROM users WHERE id = 1;
    
  • 여러 줄로 쿼리 작성 세미콜론을 만나기 전까지는 엔터를 쳐도 쿼리가 실행되지 않으므로, 가독성 좋게 여러 줄로 작성할 수 있습니다.
    SELECT
        id,
        user_name
    FROM
        users
    WHERE
        created_at > '2025-01-01'
    ORDER BY
        created_at DESC;

Psql  Trouble shooting - "\dt" 명령어 시, 아무 목록도 뜨지 않는 문제 해결

가장 가능성이 높은 원인은 스키마(Schema) 문제입니다.

PostgreSQL에서 데이터베이스는 일종의 큰 폴더이고, 스키마는 그 안의 하위 폴더라고 생각하시면 쉽습니다. \dt 명령어는 기본적으로 현재 설정된 스키마 안에 있는 테이블만 보여줍니다.

원인 진단 및 해결 방법

1단계: 모든 스키마의 테이블 확인하기 (가장 확실한 방법)

먼저 테이블이 다른 스키마에 생성되었는지 확인해 보겠습니다. \dt 뒤에 *.* 를 붙여보세요.

\dt *.*

이 명령어는 "모든 스키마(첫 번째 *)에 있는 모든 테이블(두 번째 *)" 을 보여달라는 뜻입니다.

만약 이 명령어를 실행했을 때 아래와 같이 public 스키마에 테이블이 보인다면, 원인을 찾은 것입니다.

          List of relations
 Schema |   Name    | Type  |  Owner
--------+-----------+-------+----------
 public | my_table  | table | myuser
(1 row)

2단계: 현재 검색 경로(search_path) 확인

\dt가 왜 public 스키마를 자동으로 보여주지 않았는지 확인해 보겠습니다. 아래 명령어로 현재 세션의 search_path(스키마명)를 확인합니다.

SHOW search_path;

아마 결과가 아래와 같이 나올 것입니다.

   search_path
-----------------
 "$user", public
(1 row)
  • "$user": 현재 접속한 사용자와 이름이 같은 스키마를 먼저 찾습니다.
  • public: 그 다음으로 public 스키마를 찾습니다.

대부분의 경우, 사용자가 테이블을 만들면 기본적으로 public 스키마에 생성됩니다. 그런데 어떤 이유로 search_path에 public이 포함되어 있지 않거나, 다른 스키마가 우선순위로 되어 있으면 \dt만으로는 보이지 않게 됩니다.

 

해결책

위 진단을 통해 원인이 스키마 문제로 파악되었다면, 해결 방법은 여러 가지가 있습니다.

  • 방법 1 (임시 방편): 테이블을 조회할 때마다 스키마 이름을 명시합니다.
  • SQL
     
    SELECT * FROM public.my_table;
    
  • 방법 2 (현재 세션 변경): 현재 접속한 세션의 search_path에 public을 추가합니다. (접속을 끊으면 초기화됩니다)
  • SQL
     
    SET search_path TO public;
    
  • 방법 3 (영구 변경 - 추천): 접속하는 사용자의 기본 search_path를 변경합니다. 이렇게 하면 앞으로 해당 사용자로 접속할 때마다 자동으로 public 스키마를 보게 됩니다.예시: ALTER USER myuser SET search_path = public;
  • SQL
     
    ALTER USER [사용자_이름] SET search_path = public;
    
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기