Skip to content
VDS · 데이터베이스

데이터베이스의 사용자와 권한

MySQL과 PostgreSQL에서 각 애플리케이션용 사용자를 따로 만들고, 최소 권한만 부여하고, 불필요한 권한이 없는지 확인하는 방법을 다뤄요.

업데이트 2026년 8월 23일

root 또는 postgres로 실행되는 애플리케이션은 첫 번째 취약점이 발생하는 순간 머신의 모든 데이터베이스를 공격자에게 넘겨줘요. 자신의 스키마에만 권한을 가진 전용 사용자는 피해를 한 프로젝트로 제한해요.

MySQL과 MariaDB

여기서 사용자는 "이름과 호스트" 쌍이며, 이것이 혼란의 주요 원인이에요:

CREATE USER 'shop'@'localhost' IDENTIFIED BY 'long-random-password';
GRANT SELECT, INSERT, UPDATE, DELETE ON shop.* TO 'shop'@'localhost';
FLUSH PRIVILEGES;

'shop'@'localhost'와 'shop'@'%'는 서로 다른 비밀번호를 가진 서로 다른 사용자예요. 필요하지 않다면 호스트 %로 레코드를 만들지 마세요: 모든 주소에서 로그인할 수 있게 해줘요.

구조에 대한 권한은 마이그레이션 중에만 필요해요:

GRANT CREATE, ALTER, DROP, INDEX, REFERENCES ON shop.* TO 'shop_migrate'@'localhost';

애플리케이션 역할과 마이그레이션 역할을 분리하는 것이 좋은 관행이에요: 그러면 일반 쿼리는 물리적으로 테이블을 삭제할 수 없어요.

확인:

SELECT user, host FROM mysql.user;
SHOW GRANTS FOR 'shop'@'localhost';

비밀번호 변경과 삭제:

ALTER USER 'shop'@'localhost' IDENTIFIED BY 'new-password';
DROP USER 'shop'@'localhost';

PostgreSQL

역할과 데이터베이스 및 스키마에 대한 권한:

CREATE ROLE shop WITH LOGIN PASSWORD 'long-random-password';
CREATE DATABASE shop OWNER shop;
REVOKE ALL ON DATABASE shop FROM PUBLIC;

읽기 전용 역할(보고서, 분석, 모니터링 제어판)의 경우:

CREATE ROLE reader WITH LOGIN PASSWORD '...';
GRANT CONNECT ON DATABASE shop TO reader;
GRANT USAGE ON SCHEMA public TO reader;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO reader;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT ON TABLES TO reader;

마지막 줄은 필수예요: 이것이 없으면 역할은 권한이 부여된 후에 생성된 테이블을 보지 못하고, 한 달 뒤에는 보고서가 새 데이터에서 깨질 거예요.

확인:

\du
\l
\dp

반드시 잠가야 할 것

  • 어떤 애플리케이션 역할도 슈퍼유저가 아니에요.
  • 각 프로젝트에는 자체 데이터베이스와 자체 사용자가 있어요.
  • 비밀번호는 길고 무작위이며, 프로젝트마다 달라요.
  • 외부 로그인은 필요한 주소에만 허용돼요 — 원격 접속.
  • MySQL에는 익명 사용자와 테스트 데이터베이스가 없어요: mariadb-secure-installation이 이걸 해줘요.

흔한 실수

증상원인
올바른 비밀번호인데 Access denied다른 호스트 규칙이 일치했어요, 예를 들어 ''@'localhost'
권한을 부여했는데 SELECT가 작동하지 않아요PostgreSQL에 USAGE ON SCHEMA가 없어요
역할에 새 테이블이 보이지 않아요DEFAULT PRIVILEGES가 설정되지 않았어요
실패한 마이그레이션 중에 애플리케이션이 모든 것을 삭제했어요애플리케이션 역할에 DROP 권한이 있었어요
명령 기록에 비밀번호가 보여요파일에서 비밀번호를 설정하고 ~/.mysql_history를 지우세요

데이터베이스 비밀번호는 코드가 아니라 600 권한을 가진 서비스 환경 파일에 저장하세요. 유출되면 전체 프로젝트를 다시 구축하는 게 아니라 한 줄을 바꾸고 재시작하면 돼요.