도커 없이 워드프레스를 설치하는 기본 과정

2026-05-25

워드프레스 자체가 워낙 넓은 범주에서 데모로 사용된다. 호스팅 업체도 기본 설치가 완료된 상태로 상품을 제공한다. AI도 그냥 뚝딱뚝딱 설치해준다. 결정적으로 그냥 도커로 대충 설치해서 쓰는 경우가 거의 다수일테다. 이 문서도 조각 문서로 참 오래 가지고 있었다. 이제라도 메모장에서 해방시켜야 한다는 반의무감으로 옮긴다.

도커는 왜 안 쓰는가

왜 워드프레스를 도커로 설치하지 않느냐란 질문을 엄청 많이 받았고, 질타(?)도 받았다. 딱 나에게만 적용되는 이유는 크게 2가지다. 우선, 나는 도커가 익숙하지 않다. 개발 과정과 배포까지 연결되는 상황을 업무에서 겪을 일이 거의 없다보니, 도커를 쓰지 않아도 딱히 불편하지 않았다. 다음으로, 상대적으로 긴 시간 워드프레스 사이트를 운영하다보면 생기는 예외 상황과 빈틈을 처음부터 도커 컴포즈에 다 반영해서 구성하기가 너무 번거로웠다. 운영을 위해 별도 분리해야 하는 파트를 다 발골하다 보면, 도커로 구성하는 파일은 코어 파일 몇개밖에 안 남았다. 도커를 쓰는 철학과 목표와 이유가 있을텐데, 그것과 너무 상충된 결과가 아닌가. 그저 최초 설치의 간편함만 있을 뿐, 이후 모든 과정에서 생기는 이슈마다 워드프레스에만 집중하지 못하고 도커를 계속 설정해야 하니 번거롭단 생각만 남았다.

아무튼 워드프레스 설치 방법은 인터넷에 검색해도, AI한테 시켜도 넘쳐 흐른다. 이 글은 그저 내 만족을 위함이다. 불시에 내가 참고하기 위해 정리하는 것일 뿐이다.

LAMP

워드프레스를 쓰기 위해선 LAMP 환경을 먼저 선택하고 구성해야 한다. 뭐가 더 좋고 나쁘고는 사실 중요하지 않다. 그냥 본인에게 익숙한 것을 쓰는 게 좋다고 본다. 결국 운영은 각자 책임이지 않은가. AI가 다 해주니까 뭐든 괜찮다고 한다면, 운영도 AI에게 모조리 맡기면 된다. 난 모자른 토큰을 여기에 낭비하고 싶지 않으니, 내가 주도해서 선택할 뿐이다.

  • Ubuntu 24.04, Nginx, MariaDB, PHP 8.3

OS는 적당히 LTS 기준으로 손에 익은 스택을 골랐다. 이제 2026년 5월이니 곧 26.04.01 핫픽스 LTS가 나오면 갈아탈 생각도 조금은 해야할 것 같다. Nginx나 MariaDB는 설치하는 순간 기본 호출하는 최신 패키지를 쓴다. PHP는 버전별로 특성을 타는 것이 있지만, 워드프레스의 현재 최신 버전인 6.9나 7.0에서 특별한 장애가 나지 않는 8.3을 골랐다.

단일 인스턴스에 통합 설치하는 과정

단일 물리 서버나 가상 서버에 Nginx, PHP, MariaDB, 워드프레스까지 모두 한 곳에 모아서 설치해서 쓴다. 어차피 테스트용이나 개인용에서는 트래픽 같은 규모 걱정을 할 일이 없다고 본다. 그리고 한달에 UV 10만명~100만명까지도 단일 인스턴스만으로도 충분히 커버할 수 있는 서버 스펙이 널렸다. 단일 인스턴스로 쓰는 것이 운영상 가장 편한 방법이었다.

OS는 이미 있는 거고, 이제 순서대로 하나씩 설치 결과를 단계별로 확인할 수 있는 순서로 쭈욱 나열한다.

시스템 패키지 리스트 최신화 및 업그레이드

그리 큰 차이를 느껴보진 못했다. 그래도 습관처럼 설치 전엔 꼭 한 번씩 실행한다.

sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install -y software-properties-common apt-transport-https ca-certificates wget

PHP 설치

Ubuntu 24.04 LTS에서는 공식 리포지토리의 기본 PHP 버전이 8.3이므로, 별도의 외부 PPA 등록 없이 버전명을 생략하고 기본 패키지명으로 간결하게 즉시 설치할 수 있다.

우선 PHP 코어 및 워드프레스 전용 확장 모듈군 일괄 설치한다.

sudo apt-get install -y php-cli php-fpm php-bcmath php-bz2 php-common \
php-curl php-gd php-mbstring php-opcache php-readline \
php-soap php-xml php-zip php-redis php-mysql php-imagick php-intl

만약, 다른 버전을 설치해야 하거나 OS 버전 차이로 인해 기본 버전이 다를땐, 수동 지정해서 설치해야 한다.

sudo add-apt-repository ppa:ondrej/php -y && sudo apt-get update
sudo apt-get install -y php8.3-cli php8.3-fpm php8.3-mysql php8.3-gd... 외 기타 나머지

PHP는 설치 후에 바로 뭔가 웹 페이지로 확인하긴 힘들고, php -vsudo systemctl status php8.3-fpm 등으로 설치 결과를 본다.

Nginx 설치

Nginx를 설치한 이후부터는, 웹 페이지로 접속 화면을 하나씩 볼 수 있다.

sudo apt-get install -y nginx
sudo systemctl enable nginx
sudo systemctl start nginx

Nginx 설치가 끝나면, IP주소를 웹 브라우저에 입력하자. 바로 기본 화면을 볼 수 있다.

워드프레스 코어 파일 다운로드

코어 파일 다운로드에 앞서, 대략 파일을 어느 디렉터리에 둘 것인지 정해야 한다. /var/www/html 같은 디렉터리도 있고, 그냥 사용자의 홈 디렉터리 하위를 쓰기도 한다. 나는 별도의 독립 디렉터리에 쓰는 것을 가정하고 /a36/wordpress 디렉터리를 쓰기로 했다.

# 1. 작업 공간용 폴더 생성 및 소유권 설정
sudo mkdir -p /a36/wordpress
sudo chown -R $USER:$USER /a36

# 2. 다운로드와 동시에 임시 저장 낭비 없이 목적지에 즉시 다이렉트로 압축 해제
wget https://wordpress.org/latest.tar.gz
tar -zxf latest.tar.gz -C /a36/wordpress --strip-components=1
rm -f latest.tar.gz

# 3. 플러그인 업로드 및 임시 저장을 위한 필수 서브 디렉터리 사전에 일괄 생성
cd /a36/wordpress/
mkdir -p wp-content/upgrade wp-content/uploads wp-content/temp

# 4. 동적 작업과 보안을 위해 wp-content 및 그 하위 전체 소유권만 www-data로 지정
sudo chown -R www-data:www-data /a36/wordpress/wp-content

다운로드한 압축 파일의 내부 디렉터리 구조를 모르는 상태이므로, 다이렉트 압축 해제보다는 그냥 그 자리에서 압축 해제하고 내부 디렉터리 구조 확인 후에 코어 파일만 복사해서 넣는 방법도 있다.

Nginx 가상 호스트 설정 및 PHP FPM 소켓 연동

이제부터는 각 설정 변경마다 왠만해선 웹 페이지로 확인할 수 있다. Nginx 설정 파일을 수정하자.

# 설정 파일 편집기 실행
sudo vi /etc/nginx/sites-available/default
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        # 작업 공간 매핑 (/a36/wordpress 표준 경로 설정)
        root /a36/wordpress;
        index index.php index.html index.htm;
        server_name _;

        location / {
            # 워드프레스 고유주소(Permalink) 구조를 지원하기 위한 핵심 지시어
            try_files $uri $uri/ /index.php?$args;
        }

        location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
        }

Nginx 설정에서 블럭 괄호 여닫기는 꼭 잘 챙겨야 한다.

# 연동 설정 문법 진단 및 Nginx 리로드 반영
sudo nginx -t
sudo systemctl reload nginx.service

이제 여기서 웹 페이지 접속해보면, 뭔가 뜨긴한다. DB 설치를 아직 안 했으니 에러 페이지가 뜨는 것은 당연하다.

DB 연결이 안 돼서 뜨는 에러 페이지다.

만약 PHP 동작 확인을 하고 싶다면, 임시 php 파일을 만들어서 확인하면 된다.

echo "<?php phpinfo(); ?>" | sudo tee /a36/wordpress/php.php

브라우저에서 http://서버_IP/php.php 주소에 접속하면, PHP 정보 테이블을 볼 수 있다. 확인을 마치면 보안을 위해 이 파일은 지우는 것이 좋다.

MariaDB 설치 및 설정

sudo apt-get install -y mariadb-server
sudo systemctl enable mariadb
sudo systemctl start mariadb

# 루트 권한 확인 및 대화형 보안 설정 수행
sudo mariadb-secure-installation
# 루트 패스워드 신규 지정 (예: 'elqlfnxm')

이 때 입력하는 루트 패스워드는 말 그대로 MariaDB의 전체 루트 패스워드다. 최상위 계정의 비밀번호이므로, 잘 보호하고 보관해야 한다.

MariaDB를 설치했으니, 이제 이 안에 워드프레스가 쓸 DB를 만들고, 그 DB를 호출할 계정을 생성해야 한다. 워드프레스 전용으로 생성한 계정과 비번을 워드프레스 설정 파일에서 쓸 예정이므로, DB 루트 계정과 혼동하지 말자. 워드프레스에서 DB 루트 계정을 호출해서 쓰는 건 보안상 매우 좋지 않은 방법이므로 지양하자.

# MariaDB 루트 실행
sudo mariadb

# DB 생성
CREATE DATABASE a36_wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

# 워드프레스 전용 계정 분리 생성
CREATE USER 'a36_root'@'localhost' IDENTIFIED BY 'dktkadbr';
    
# 로컬 접속 대상 권한 전체 할당 및 캐시 반영
GRANT ALL PRIVILEGES ON a36_wordpress.* TO 'a36_root'@'localhost';
FLUSH PRIVILEGES;

# 생성한 계정 확인
use mysql;
select user, host from user;

그리고 간단한 설정값을 추가한다.

# 데이터 무결성 유지를 위한 전역 캐릭터셋 설정
sudo vi /etc/mysql/conf.d/mariadb.cnf
[client]
default-character-set = utf8mb4

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
character_set_server = utf8mb4
collation_server = utf8mb4_unicode_ci

설정 파일 반영을 위해 MariaDB를 재시작한다.

sudo systemctl restart mariadb

단일 인스턴스에서 로컬 호스트로 DB에 접근하도록 하는 중이니, 외부 연결 차단은 해제할 이유가 없으므로 기본 값인 로컬 루프백 상태 그대로 둔다.

wp-config.php에서 DB 연결

워드프레스 설정 파일에는 DB 연결을 위한 계정과 연결 정보를 넣어야 한다. 완전히 설치한 적 없는 최초 설치 상태에서는 wp-config.php 파일이 없으므로, 샘플 파일을 복사해서 써야 한다.

cp -p /a36/wordpress/wp-config-sample.php /a36/wordpress/wp-config.php
vi /a36/wordpress/wp-config.php
// ** 데이터베이스 연결 정보 ** //
define('DB_NAME', 'a36_wordpress');
define('DB_USER', 'a36_root');
define('DB_PASSWORD', 'dktkadbr');
define('DB_HOST', 'localhost');
define('DB_CHARSET', 'utf8mb4');
define('DB_COLLATE', '');

Salt 값으로 인증키를 넣는 것은, 설정 파일 안에 있는 키 생성 URL을 눌러서 복사해서 쓰면 된다.

추가로 업로드 성능과 FTP 우회를 위한 설정도 추가한다.

define('WP_TEMP_DIR', dirname(__FILE__) . '/wp-content/temp');
define('FS_METHOD', 'direct');

여기까지 완료하면, 웹 브라우저에서 최초 화면을 볼 수 있다.

언제봐도 반가운 화면이다.

아직 Nginx와 PHP 세부 환경 설정 이외에도, SSL 설정 등등 무수히 많은 설정이 남아 있다. 그래도 여기까지면 사실상 그냥 쓰는 데에는 전혀 문제 없다.

DB를 따로 설치한다면?

워드프레스의 모든 기능이 DB를 호출하진 않는다. 아니, DB를 호출하지 않도록 레디스나 캐시 플러그인 등을 쓰면 DB가 소모하는 리소스 자원을 확실히 아낄 수 있다. 하지만, 검색 기능이나 관리자 페이지 설정 등등을 바꾸는 부분에선 DB 호출을 막을 수 없다. 그러다가 DB가 리소스를 많이 소모하게 되면, 서버가 다운되는 현상이 나온다. 반대 현상도 있다. 너무 많은 트래픽이 몰려서 PHP가 리소스를 과다 소모하면, DB가 써야하는 리소스가 부족할 때가 있다.

이럴 때, 가용성을 위해 웹과 DB를 분리해서 설치해서 쓰는 방법을 쓴다. 특히, AWS, Azure, GCP, 오라클 클라우드 등 대부분 클라우드 회사에서 DB 자체를 하나의 상품으로 제공한다. 이런 DB에 워드프레스를 바로 붙여서 쓸 수도 있다. 단순히 별도 인스턴스를 올려서 DB만 깔아두고 쓰는 방법도 있다. DB를 분리해서 관리한 다는 개념 만으로 다양한 선택지가 생긴다.

별도 인스턴스에 DB만 깔아두고 연결해서 쓸 때 바뀌는 몇몇 설정을 보자. 먼저, MariaDB는 기본적으로 외부 연결이 차단돼 있으므로, 이것부터 해제해야 한다. 당연히 DB쪽에서 해야하는 설정이다.

sudo vi /etc/mysql/mariadb.conf.d/50-server.cnf
# 기존 bind-address = 127.0.0.1 항목을 0.0.0.0으로 확장
bind-address = 0.0.0.0
또는
bind-address = 웹 서버 IP
# 설정 반영 재시작
sudo systemctl restart mariadb

앞서 생성한 워드프레스용 DB 계정은 정확하게 로컬 호스트에서만 접근하도록 생성했다. 원격 접속을 해야하므로, 원격 접속용 DB 계정을 생성해야 한다.

CREATE USER 'a36_root_re'@'웹 서버 IP' IDENTIFIED BY 'dktkadbrflahxm';
GRANT ALL PRIVILEGES ON a36_wp.* TO 'a36_root_re'@'웹 서버 IP';
FLUSH PRIVILEGES;

정확히 웹 서버 IP에서 접근하는 경우만 허용하는 것이 보안상 안전하므로, 웹 서버 IP로만 범위를 제한하는 것이 좋다.

원격 접속용 계정 생성이 끝났다면, 이 DB 정보와 계정 정보를 wp-config.php에 반영하면 된다.

공통 성능 최적화 및 보안 설정

PHP의 기본 설정값은 현재 내가 쓰는 서버 자원 상태를 반영하지 못한다. 훨씬 넉넉한 서버를 쓰는데, 기본값은 타이트하게 잡혀있다면, 서버 리소스가 남아돌아서 의미없이 놀게 된다. 반대로 서버 자체가 엄청 타이트한데, 기본값이 그걸 소화 못할 수준이라면, 이건 서버를 바꿔야 한다. 워드프레스를 안정적으로 쓰기 위한 최소값은 PHP 기본 설정값이 아닐까 한다.

설정을 하나하나 찾아보면서 정한 값이긴 하지만, 더 늘려도 된다. 난 그저 내 기본값을 보관할 용도로 설정 값을 옮겨본다.

/etc/php/8.3/fpm/php.ini

; 최대 용량 한도 증강
post_max_size = 64M
upload_max_filesize = 64M
max_file_uploads = 50

; 메모리 가용 및 연산 가용 한계 증설
memory_limit = 256M
max_execution_time = 120
max_input_time = 60
max_input_vars = 1000

; HTTP 세션 취약성 방어
session.cookie_httponly = 1
session.cookie_secure = 1

; OPcache 하드웨어 가속 최적화
opcache.enable = 1
opcache.enable_cli = 1
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 12000
opcache.max_wasted_percentage = 10
opcache.validate_timestamps = 1
opcache.revalidate_freq = 60

; PHP JIT(Just-In-Time) 연산 가속 활성화
opcache.jit_buffer_size = 100M
opcache.jit = tracing

/etc/nginx/nginx.conf

http {
    # Nginx 기준 미디어 전송 허용 한도 변경
    client_max_body_size 100M;
    tcp_nodelay on;
}

Nginx 세부 버전 및 헤더를 지워서 정보를 감추는 것도 필요하다. 헤더 정보를 지우는 Nginx 플러그인을 추가 설치하고 설정값을 추가한다.

sudo apt-get install nginx-extras -y
http {
    # Nginx 시그니처 끄기
    server_tokens off;
    
    # 추가 불필요 서버 서명 소거
    more_clear_headers "Server";
    more_clear_headers "X-Powered-By";
}

PHP와 Nginx 설정값을 바꾸면 리스타트하라

Nginx는 reload하는 방법도 있다. 하지만, 초기인 만큼 깔끔하게 리스타트 하는 것도 좋다고 본다.

sudo systemctl restart php8.3-fpm
sudo systemctl restart nginx

디렉터리 권한 정비 체계

보안 누수를 차단하기 위해 디렉터리는 755, 파일은 644 구조를 기본으로 사용하며, 핵심 설정 정보인 wp-config.php600 권한으로 강하게 제한한다.

# 기본 소유권 설정 (일반 권한 사용자 소유화)
cd /a36/wordpress/
sudo find . -type f -exec chmod 644 {} +
sudo find . -type d -exec chmod 755 {} +

# 환경 설정 정보 극비 제한
sudo chmod 600 wp-config.php

# 웹서버에서 동적 연산(미디어, 플러그인, 테마)이 수행되는 wp-content 디렉터리 및 하위 전체를 웹서버 권한 소유로 정의
sudo chown -R www-data:www-data wp-content/

웹 서비스 운영을 위한 최소 레벨은 아직 여럿 남았다

대략 이정도면 완전 기본의 기본 설정이 끝난 상태다. 하지만, 각자 사정이 다르고, 보안이나 편의 등을 위한 남은 설정은 한참 더 남아있다. 특히 SSL도 설정해서 https를 쓰도록 해야하니, Nginx에서 잡아야 하는 설정은 한참 더 남았다..

그래도 일단 여기까지면 Hello, World?까지 온거라 생각한다.

이후는 여기에 붙일 내용이 아니라, 각기 다시 별도로 따로 보는 것이 좋을 것 같아서, 문서 조각 정리는 여기서 마친다.