상현에 하루하루

삼표그룹 사이버감사실

( 업데이트: )

👋 들어가며

안녕하세요 퍼블리셔 한상현입니다.

.NET으로 만들어진 삼표그룹 사이버감사실의 홈페이지를 워드프레스로 작업하였습니다. was 퍼블리싱 워드프레스 구성 워드프레스 백엔드 커스텀

홈페이지를 구축하면서 얻은 경험들을 적어보려합니다 😁

퍼블리싱

main tailwindcss v3

tailwind의 v3가 업데이트가 되어 해당 라이브러리를 적극 사용했습니다.

tailwindcss는 작업 시간을 정말 많이 단축해주었습니다.

폼 ui (vue 3)

폼관련 ui를 어떤 것을 사용할까? 고민을 했습니다.

디자인과 기획대로 퍼블리싱한다면 textarea로 충분하지만, 이번에는 textarea가 아닌 makrdown 에디터를 넣으면 어떨까? 생각했고 vue3를 사용하여 tiptab markdown 에디터를 추가했습니다.

vue3를 처음 사용해봤지만 간단한 ui용 vue3 앱이었기 때문에 React를 사용해봤던 경험으로 비교적 쉽게 적용 할 수 있었습니다.

워드프레스 백엔드 커스텀

제보(report)의 커스텀 글 상태

워드프레스의 커스텀 타입의 글을 사용해서 게시판을 구축하였습니다. 기본적으로 워드프레스에서 제공하는

  • draft
  • published
  • private
  • pending

위과 같은 상태들이 아닌 커스텀한 상태값이 필요했습니다.

  • 대기중
  • 처리중
  • 답변완료

아카이브페이지에서 관리자권한의 사용자가 모든 포스트를 볼 수 있어야합니다. 그리고 개별 개시글은 작성자 또한 볼 수 있어야 합니다.

글 상태중에 private 상태는 작성자 & 관리자 이 외에 다른 사용자들에게는 보이지 않기 때문에 private 상태를 가지는 커스텀한 상태를 제작하면 되는 것입니다.

초기에 위 처럼 생각하고 개발을 진행하였지만 private랑 동일한 기능을 가진채로 확장하는 것은 wordpress에서 살펴볼 수 없었습니다.

그렇게 “custom private post type” 이 키워드들을 가지고 검색을 해봤고 결국 명확한 답을 찾지 못했습니다.

다시 처음부터 곰곰히 생각해보니 모든 포스트의 상태는 private이고 각각의 커스텀한 상태를 따로 가지는? 커스텀 메타!를 가지고 있으면 되는구나! 생각하고 다시금 모든 포스트에 글 상태와 다른 메타데이터를 추가해줘서 이 문제를 해결 할 수 있었습니다.

ACF의 기본값은 PHP로 포스트를 작성할때 등록되지 않는다

form data를 받아서 포스트를 등록할때 워드프레스의 wp_insert_post() 워드프레스 함수를 사용합니다. 이렇게 함수로 생성된 포스트는 ACF 필드에 기본값으로 등록되게 설정한 값은 등록이 되지 않는 것입니다. 해당 필드에는 null값이 들어가는 것을 확인하였습니다.

그렇다면 어떻게 해결 할 것인가?

백엔드에서 포스트를 등록하고 redirect하기 전에 해당 ACF 필드를 업데이트하면서 해당 문제를 해결했습니다.

update_field('status', 'waiting', $new_post);Code language: PHP (php)

워드프레스 댓글 수정은 워드프레스 관리자 대쉬보드로 이동?!

테스트를 위해서 댓글 부분을 활성화하고 등록된 댓글을 수정하려하면 워드프레스의 관리자 대쉬보드 ~/wp-admin으로 이동합니다. 이렇게하면 안 될 꺼같다 생각했고 어떻게해야 프론트에서도 워드프레스 댓글을 업데이트 할 수 있게 할까? 방법을 찾아봤고 프론트에서 댓글을 업데이트 할 수 있는 폼을 추가하였습니다.

댓글 업데이트 폼은 답변으로 이용 할 예정이라 권한을 설정하여 노출하였습니다.

그리고 해당 폼을 POST 데이터로 받아서 따로 처리하는 방법으로 워드프레스 함수로 등록하였습니다.

노출되는 댓글을 해당 제보글의 무조건 첫번째 댓글이고 해당 댓글을 가지고 답변글처럼 사용하여 답변 기능을 완료하였습니다.

Web Application Server

이 프로젝트의 서버 구성

  • NCP (ubuntu 18.04 LTS)
    • docker
      • wordpress (APM)
      • traefik (HTTP reverse-proxy & Load-Balancer)
      • redis
      • mariaDB

특정 ip만 허용하기

처음에 이 기능을 생각하면서 어떻게 구현할까 고민을 만이했습니다. traefik에서 미들웨어를 구성해서 ip 차단을 막는게 편하겠다 생각했습니다.

초기에는 해당 기능을 traefik에서 미들웨어를 구성함으로서 ip를 제한하는게 편할 것이라 생각했습니다.

하나의 PathPrefix를 통해 /wp-content/uploads의 요청을 특정 ip만 허용되게 설정했는데 /wp-content/uploads/**/*는 적용되지 않는 문제가 있었습니다.

Apache의 .htaccess처럼 하나의 폴더만 지정하면 하위 모든 폴더에 적용되는 방법을 찾아봤지만 찾지 못하였습니다.

따라서 traefik으로 ip 허용을 설정하는 것 대신 Apache로 특정 ip만 허용하게 하였습니다.

<Files ~ ".(xml|css|js|jpe?g|png|gif|pdf|docx|rtf|odf|zip|rar)$">
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/wp-content/uploads/2021/12/cropped-favicon.png$
RewriteCond %{REQUEST_URI} !^/wp-content/uploads/2021/12/cropped-favicon-150x150.png$
RewriteCond %{REQUEST_URI} !^/wp-content/uploads/2021/12/cropped-favicon-32x32.png$
RewriteCond %{REQUEST_URI} !^/wp-content/uploads/2021/12/cropped-favicon-192x192.png$
RewriteCond %{REQUEST_URI} !^/wp-content/uploads/2021/12/cropped-favicon-180x180.png$
RewriteCond %{REQUEST_URI} !^/wp-content/uploads/2021/12/cropped-favicon-270x270.png$
RewriteCond %{REQUEST_URI} !^/wp-content/uploads/2021/12/cropped-favicon-300x300.png$
# RewriteCond %{REMOTE_ADDR}  !ip #작성하기
# RewriteCond %{REMOTE_ADDR}  !^127.0.0 # 범위로 지정도 가능
RewriteRule (.*) https://%{HTTP_HOST}/404 [L]
</Files>Code language: PHP (php)

특정 ip 허용은 특이사항으로 남아 구현되지 않았다.

프로젝트 마지막 단계에서 클라이언트 요청으로 ip로 파일접근을 허용하는 로직이 사라져, ip를 가지고 /wp-content/uploads/**/*파일들을 허용하게끔 구성했던 기능을 변경해야 하므로 다른 해결책이 필요했습니다.

다른 해결 방안을 도입한다면 추가 비용이 발생하므로 내부적 논의를 거쳐 구현되지 않고 특이사항으로 남았습니다.

그렇다면 어떻게 데이터 보안을 설정 할 것인가?

결국 모든 인증은 워드프레스의 관리자 권한이있는 사용자로 제한된다. 그렇다면 인증은 워드프레스 로그인한 사용자로해야해서 apache .htaccess로 설정하면 안 될것같았습니다. 그래서 다시 traefik 미들웨어 구성으로 다시 작업하기 시작했습니다.

워드프레스 백업

Cafe24와 같은 편리한 솔루션을 사용하면 제한사항은 많지만 서비스가 다운되거나 오류가있어서 예전 상태로 되돌리거나 하는 이점이 있습니다.

  • 백업
  • 서버 타임머신
  • 다운되지 않을 신뢰성?

그렇다면 어떻게 이 3가지를 만족할 수 있을까? 고민을 했습니다

워드프레스의 DB만 백업한다고 사이트가 온전히 보전되지는 않습니다. uploads 파일에 업로드된 파일들도 따로 백업을 해야하는데 그렇게하면 관리자도 이해하기가 어렵습니다.

워드프레스 백업에는 DB백업 & 파일 백업 & 테마 파일 이렇게 3가지정도라고 생각합니다.

백업에서 DB와 파일은 따로따로 백업하지 않고 워드프레스를 하나의 이미지로 말아버리는 방식으로 All in one Migration 플러그인을 사용해서 백업하기로 결정하였습니다. 하나의 이미지 파일로 압축이 되면 해당 이미지 파일로 워드프레스를 완전히 해당 시점으로 되돌릴 수 있기 때문입니다.

  • All in one Migration (1주 간격)
  • SFTP 백업
  • Google Drive 백업

Google Drive로 메인 백업이라 생각하고 2중 백업으로 SFTP로 백업을 진행한다.

테마파일은 따로 백업하지 않고 Github의 소스코드로 관리합니다.

이렇게 워드프레스의 완전백업이 완료했습니다.

중간중간 NCP 인스턴스의 스냅샷을 남겨 더욱더 철저한 백업을 할 수 있다 가이드 하였습니다.

클라우드 네이티브 애플리케이션 프록시

인증 미들웨어 (forwardauth)

traefik의 ForwardAuth을 이용해서 워드프레스의 인증을 할 수 있는 커스텀한 페이지를 제작해서 해당 페이지로 인증을 위임하는 방법을 사용했습니다.

그래서 따로 인증을 구현하지 않아도 기존 워드프레스의 인증을 가지고 인증에 관한 부분을 해결할 수 있었습니다.

media uploads에 public assets? (redirectregex)

접근권한은 관리자 인증을 통해 완료하였지만 관리자가 아닌 모든 유저에게 보여줘야할 public한 파일들은 어떻게 해야할까?

traefik route 부분의 룰을 계속 살펴보았지만 exclude 관련된 룰은 찾지 못했다. 그래도 보여줘야하는 것들은 어떻게 해야할까? 고민하다가 홈페이지를 유지하면서 public한 파일들이 변경되지 않을 것같다는 판단이 들어서 public한 파일들은 /wp-content/uploads/public으로 파일들을 복사해서 만들어주고 redirect 미들웨어를 중간에 한번더 적용해서 public으로 이동하는 규칙을 추가했습니다.

👏 마무리하며

새롭게 접근했던 방식들이 다양해서 개인적으로도 많은 성장을 한 프로젝트라고 생각합니다. 워드프레스에서 그동안 프론트엔드에 포스팅기능을 플러그인에 의지했지만 직접 커스텀 제작을 해본 뿌듯한 프로젝트 였습니다.