대형 Drupal 7 포럼의 마이그레이션 전 평가

여러분 안녕하세요, 저는 인터넷에서 가장 큰 규모라고 생각되는 Drupal 기반 포럼 중 하나를 소유하고 관리하고 있으며, 현재 게시글 수가 200만 건에 육박하고 있습니다. Drupal 7은 명을 다하고 있고, Drupal 8/9는 콘텐츠 관리 시스템(CMS)보다는 웹 개발자를 위한 프레임워크로 변모하고 있습니다. 새로운 Drupal 버전들은 포럼의 기본 기능을 유지하기 위해 제가 필요로 하는 서드파티 모듈을 제공하지 않으며, PHP의 특성과 Drupal의 수많은 기이한 특성 덕분에 업그레이드는 완전히 다른 플랫폼으로 이관하는 것만큼이나 지옥 같은 과정이 될 것입니다. 그래서 저는 결국 다른 것으로 이관해야 합니다. 제 포럼 커뮤니티의 스타일에 있는 고유한 특성 때문에 Discourse여야 할 것이라고 확신합니다. 저는 유일한 관리자이며, 이것이 제 전일제 직업이 아닙니다. 그래서 수년간 저는 Drupal의 유연한 Rules와 Flag 프레임워크를 사용하여 스팸과 부적절한 게시물에 대한 커뮤니티 기반의 점진적인 모니터링 시스템을 구축해 왔습니다. 이 시스템은 사용자가 얼마나 신규인지에 따라, 그리고 얼마나 많은 사용자가 해당 게시물을 플래그했는지에 따라, 또한 플래그를 누른 사용자들의 신규도와 최근 플래그 활동도 고려하여 특정 임계값에 도달하면 게시물을 자동으로 삭제하거나 사용자 계정을 차단합니다. 다시 말해, 이는 Discourse가 구현한 것과 거의 정확히 일치합니다. Discourse가 커뮤니티 모니터링의 가치를 인식하고有这么 종합적이고 잘 계획된 시스템을 기본으로 구현해 준 것을 보니 정말 기쁩니다. Drupal 7은 경험 있는 개발자가 아닌 제가 이러한 종류의 사용자 정의 기능을 허용할 만큼 충분히 유연한 유일한 CMS였으며, 지금도 그렇습니다. 그래서 Discourse로 이관할 것으로 보입니다. 하지만 몇 가지 우려 사항이 있습니다.

  1. 커뮤니티 모니터링 시스템: 현재 포럼은 Discourse의 테스트용 설치 환경을 평가하고 있습니다. 전체 시스템이 얼마나 종합적이고 잘 계획되어 있는지 인상적입니다. 하지만 커뮤니티에서 몇 가지 특이점을 발견했습니다:
    • 자동으로 삭제된 게시물을 “무시된 콘텐츠 보기” 뒤에 숨기는 방식이 정말 마음에 들지 않습니다. 커뮤니티에 의해 삭제될 정도로 나쁜 게시물은 매우 공격적이거나 순수한 스팸일 텐데, 방문자나 사용자가 이를 볼 수 있는 옵션조차 원하지 않습니다. 스팸이거나 제목이 공격적인 토픽인 경우 특히 문제가 됩니다. 그리고 검색 엔진 크롤러가 숨겨진 스팸 콘텐츠까지 볼 수 있는 건가요? 사용자 개입 없이 자동으로 숨겨진 스팸 게시물이 공개된 곳에서 완전히 삭제되기까지의 시간을 설정할 수 있을까요? 또한 커뮤니티에 의해 부적절하다고 플래그된 토픽과 게시물에 대해서는 어떻게 되나요?
    • 게시물 삭제와/또는 사용자 침묵(silencing)으로 이어지는 임계값에 대해 *“참고: 위에서 언급한 모든 값은 기본 설정입니다. 관리자는 사이트 설정에서 이를 변경할 수 있습니다”*라는 내용을 여기에서 읽었습니다. 하지만 제 Discourse 테스트 인스턴스에서 이러한 세밀한 설정을 찾을 수 없습니다. 제가 찾을 수 있는 것은 "게시물 숨김 민감도"와 "신규 사용자 침묵 민감도"뿐인데, 이 민감도가 구체적으로 무엇을 의미하는지 이해하지 못하겠습니다.
    • 게시물 플래그 사유에서 "오프토픽(off-topic)"을 제거하고 싶습니다. 저희 포럼 커뮤니티는 그 점에서 매우 느긋하며, 오프토픽 게시물이 매우 흔하고 잘 수용되는 포럼 문화를 가지고 있습니다. 업데이트: 이것이 효과가 있을 것 같습니다.
  2. 개인 메시지 마이그레이션: 현재 포럼에는 Drupal 7의 privatemsg 모듈을 사용하여 약 100만 건에 가까운 개인 메시지 스레드가 있습니다. Drupal → Discourse 마이그레이션 스크립트는 이를 처리하지 않습니다. 이는Drupal 7 관리자가 기본적으로 사용하는 사실상 표준 개인 메시지 기능인 서드파티 모듈(전형적인 Drupal 스타일로)임에도 불구하고, 이는 중대한 누락으로 보입니다.
  3. 게시물 형식 변환: 안타깝게도 현재 포럼은 순수 HTML과 Textile 형식의 게시물을 혼합하여 사용하고 있습니다. 마이그레이션 스크립트가 순수 HTML은 처리할 수 있다는 것을 이해하고 있습니다(제가 틀렸다면 알려주세요) 하지만 Textile은 처리하지 못합니다. 가능하다면 Textile 게시물을 HTML 또는 Markdown으로 변환하고 싶습니다(어떤 것이 더 쉬운지 모르겠지만요). Pandoc을 마이그레이션 스크립트에 연결할 수 있다는 이야기를 들었지만, 그렇게 하면 마이그레이션 시간이 대폭 증가한다고 합니다. 기존 게시물의 형식을 변환하는 Drupal 모듈을 찾아보았지만, 대량의 게시물을 위한 배치 처리를 지원하지 않고, 또한 변환해야 할 "게시물"의 대부분을 차지하는 Drupal의 “댓글” 패러다임을 지원하지 않는 이것만 찾았습니다. 그래서 데이터베이스 덤프 파일에서 sed를 사용하여 여기에 설명된 것과 유사한 형태의 오프라인 찾기/치환을 하는 것을 고려해 보았습니다. 제안이나 해결책이 있다면 환영합니다. 저는 숙련된 Linux 사용자이며 regexp로 간헐적으로 작업해 왔지만, 여전히 능숙하지는 않습니다. 수정: 이것은 원시 데이터가 Discourse에 들어간 후 찾기/치환을 위한 흥미로운 옵션입니다.
  4. 광고: Discourse의 Ad Plugin이 제가 마지막으로 확인했을 때보다 많이 성숙해진 것을 보니 정말 기쁩니다. 내장 광고를 사용하면 클릭 시 대상 링크로 이동하는 이미지 배너를 특정 위치에 배치할 수 있고, 동일한 위치에 여러 광고가 할당되면 무작위로 선택된다는 것을 이해하고 있습니다. 맞나요? 하지만 모바일 환경에서는 어떻게 대처해야 할지 전혀 모르겠습니다. 현재 포럼에서는 상단에 가로 배너 하나와 왼쪽 사이드바에 세로 배너 세 개를 사용하고 있는데, 모두 Discourse의 반응형 인터페이스에서 모바일 사용자에게 실현 가능하지 않을 것입니다. 수정: 제 필요에 맞게 Ad Plugin을 수정해야 할 수도 있습니다. 유료 제안을 여기에 올렸습니다.
  5. 영구 링크(Permalinks): Drupal의 URL 체계에는 두 가지 주요 구성 요소가 있습니다: /node/XXXXXXX 와 해당 노드 내 특정 댓글에 대한 링크 /comment/YYYYYYY#comment-YYYYYYY (YYYYYYY는 두 곳에서 동일합니다). Drupal 7 → Discourse 마이그레이션 스크립트가 이러한 링크를 자동으로 유지하여 다른 스레드나 게시물에 대한 링크가 계속 작동하고 SEO를 유지할 수 있을까요? 검색 엔진을 위한 sitemap.xml 파일은 어떻게 되나요?
  6. 배치 처리: 마이그레이션 중에 배치로 실행될까요? 오류가 발생하면, 수정 후 계속 진행할까요, 아니면 처음부터 다시 시작해야 할까요?
  7. 구형 Apple 기기 사용자: 물론 구형 브라우저를 사용하는 위험성을 이해합니다. Windows와 구형 Android 기기의 경우 Discourse와 호환되는 최신 브라우저를 설치할 수 있는 방법이 거의 항상 있습니다. 하지만 2015년 Mac을 가지고 있다고 주장하는 사용자 한 명이 걱정됩니다. 이 기기는 업데이트를 전혀 받지 않으며, Discourse에서 비추천(deprecation) 알림을 표시하는 구형 Safari 버전 외에는 아무것도 설치할 수 없다고 합니다. Apple 기기에 대해 제가 아는 것은 잠금(lock-down)이 훨씬 더 강력하다는 사실뿐입니다. 다른 최신 브라우저를 설치하는 것이 정말로 그렇게 어려운 건가요?
  8. 이미지/업로드 저장소: 저와 제 사용자들은 Discourse에서 이미지를 업로드하는 간편함을 좋아하지만, 저장 공간과 비용에 대해 조금 걱정됩니다. 장기적으로 가장 좋은 옵션은 필요할 경우 VPS에 네트워크 저장 볼륨을 마운트하는 것일 것입니다. 처음에 Discourse를 기본 업로드 위치로 설정했다가 나중에 다른 볼륨으로 이동하면 문제가 생길까요?
  9. 백업:
    • 차등 백업이나, 더 좋게는 중복 제거(deduplicated) 백업 시스템이 있으면 좋겠습니다. 현재 Drupal 포럼에는 Amazon S3와 함께 Duplicity를 사용하고 있으며, 매우 긴 리비전 히스토리를 위해 비용이 믿기 어려울 정도로 낮습니다. S3 아카이브 생성 후 얼마 지나면 규칙이 이를 Glacier로 전환하게 할 수 있는지 바로 아시는 분이 있을까요?
    • Discourse 백업 인터페이스에서 Amazon S3의 아카이브를 삭제할 수 있나요? 조금 극단적일 수 있지만, 해커가 손상된 시스템에서 원격 백업을 삭제하는 것을 방지하기 위해 S3 버킷을 PUT, GET, LIST 권한만 있도록 설정했기 때문에 이 기능을 비활성화하고 싶습니다. 그런 다음 S3 라이프사이클 규칙이 작동하여 일정 시간이 지난 후 서버 측에서 오래된 아카이브를 삭제합니다.
  10. Stop Forum Spam 플러그인: Akismet은 사용하고 싶지 않지만, 스팸머 계정 생성을 방지하기 위해 StopForumSpam.com을 항상 좋은 결과로 사용해 왔습니다. 사용자 이름, IP 또는 이메일 주소가 거부되려면 데이터베이스에 몇 번의 히트가 있어야 하는지 임계값을 설정할 수 있는지 Discourse용 플러그인에 대해 아시는 분이 있을까요? 수정: 아니요, 설정할 수 없습니다. 여기에서 요청했습니다. 또한 안타깝게도 Drupal처럼 SFS 데이터베이스에 충분한 히트가 있는 경우 계정 생성을 실제로 방지하는 개입을 하지 않습니다.

긴 글을 올려 죄송합니다. 모든 분의 통찰력에 미리 감사드리며, 이 훌륭한 제품을 만들어 주신 Discourse 프로젝트 전체에 많은 감사를 드립니다.

방금 이것을 발견했습니다:

정규식 기반 변환 집합을 적용하여 BBCode 태그를 Markdown으로 교체하는 등의 작업을 수행합니다.

마지막 업데이트가 2016년으로, 여전히 관련 있는 옵션인지 확실하지 않습니다.


이것은 여전히 관련이 있나요? Drupal importer 스크립트에서 다음과 같은 코드를 보고 있습니다:

 create_posts(results, total: total_count, offset: offset) do |row|
        topic_mapping = topic_lookup_from_imported_post_id("nid:#{row['nid']}")
 def create_permalinks
    puts '', 'creating permalinks...'

    Topic.listable_topics.find_each do |topic|
      begin
        tcf = topic.custom_fields
        if tcf && tcf['import_id']
          node_id = tcf['import_id'][/nid:(\d+)/, 1]
          slug = "/topic/#{node_id}"
          Permalink.create(url: slug, topic_id: topic.id)
        end

스크립트는 일반적으로 한 번에 1000개의 게시글을 가져옵니다.

처리된 내용을 추적하므로, 이후 실행 시 이미 처리된 데이터를 건너뛸 수 있습니다. 제가 작업한 스크립트에는 import_after 설정도 포함하여, 최근 데이터만 로드함으로써 이후 실행 속도를 더욱 높였습니다(소규모 데이터 하위 집합으로 테스트할 때도 유용합니다).

게시글이 영구 링크(permalink)에 포함되는지 확인하려면 더 자세히 살펴봐야 할 것 같습니다. 일반적으로는 포함되지 않지만, 그렇게 설정할 수는 있습니다.

모든 업로드 파일을 S3에 두는 것이 좋으므로, 백업에는 데이터베이스 덤프만 포함됩니다. 이를 최적화할 방법은 사실상 없습니다. Discourse가 특정 수의 백업을 유지하도록 설정하거나, 백업하지 않도록 설정할 수 있습니다(또는 백업 수를 큰 값으로 설정하고) S3의 규칙으로 처리하도록 두면 됩니다.

아, 정말 좋은 지적이네요. 다시 생각해보니, 업로드 파일이 S3로 직접(그리고 오직) 저장되든, Discourse 백업의 여러 tarball 안에 있든, S3 업로드 저장소에 대한 비용은 결국 청구되니까요.

그럼 Discourse 백업용 버킷에서 삭제 권한을 없애는 것은 어떻게 생각하시나요?

하지만 S3에 저장되어 있다면 단일 복사본만 존재합니다.

Discourse에 삭제 권한이 없다면 작동할 것 같지만, 확신은 하지 못하겠습니다.

맞습니다. 그리고 S3의 극도로 높은 데이터 중복성 수준을 고려할 때, 업로드를 저장하는 책임 있는 방식으로 일반적으로 받아들여지는 것이죠? 최근 S3 옵션을 직접 다뤄보진 않았지만, 삭제된 파일을 일정 기간 동안 복구할 수 있는 라이프사이클 규칙도 있다고 생각합니다. 여기서는 업로드가 Discourse의 잘못된 호출로 인해 삭제되는 상황을 가정하고 있습니다. 이는 (가능성이 낮고 대규모인) 코딩 버그든 사용자 실수든 마찬가지입니다. 아니면 해킹 사건을 상상하는 것이죠. 이는 버킷의 삭제 권한에 대한 제 원래의 우려로 돌아가는 것입니다.

네, 버전 관리를 활성화하면 파일이 삭제된 것으로 표시되어도 실제로는 삭제되지 않도록 할 수 있습니다. 저장 공간에 대한 비용을 크게 신경 쓰지 않으신다면 그렇게 하셔도 됩니다. Discourse가 더 이상 사용되지 않는 파일을 삭제할 때, 최종 삭제 전에 잠시 동안 톰스톤(tombstone) 폴더로 이동시킵니다. 파일 관리는 Discourse에 맡기는 것을 권장합니다. 삭제 접근을 금지하면 시스템에 문제가 생기는지는 정확히 알 수 없습니다.

원하신다면 다른 권한(하지만 동일한 자격 증명)을 가진 별도의 버킷에 백업을 저장할 수 있습니다.

@pfaffman 또는 S3에 업로드를 저장하는 다른 분께 질문드립니다. 수많은 요인에 따라 달라지겠지만, 중대형 규모 포럼에서 S3에 업로드를 저장할 때 발생하는 대역폭 및 S3 요청 비용에 대한 경험적 정보라도 있으신가요? 정말 감사합니다!

간단한 업데이트입니다: 제가 하려는 것은 업로드를 로컬에 유지하는 것입니다. 당분간 로컬 저장소가 충분할 것이며, 필요 시 추가 저장소 볼륨으로 확장할 수 있는 옵션이 있습니다. 저는 CDN의 복잡성과 비용, 그리고 오브젝트 스토리지의 예측 불가능한 요금, 무엇보다 라이브 웹사이트 이미지 서빙에 따른 전송 비용을 감당하고 싶지 않습니다. 대신 업로드를 포함하여 Backblaze B2로 S3 자동 백업을 수행하고 s3 disable cleanup 옵션을 사용하겠습니다. Backblaze의 요금은 매우 저렴하여 중복된 업로드가 있더라도 몇 주간의 일일 백업을 유지하는 데 문제가 없을 것입니다. Backblaze B2에는 제가 필요로 하는 두 가지 매우 간단한 버킷 옵션이 있는 것으로 나타났습니다: 1) X일 후 파일을 삭제하는 자동 라이프사이클 규칙, 그리고 2) N일 동안 파일 삭제 또는 수정을 방지하는 기능(서버가 해킹당했을 경우 해커가 저장된 자격 증명을 사용하여 원격 백업을 삭제할 수 있는 작은 가능성을 방지하기 위함입니다). 이를 테스트해 보았는데 잘 작동하는 것 같습니다. Backblaze에 의해 삭제가 금지된 백업 아카이브를 Discourse GUI에서 삭제하려고 시도해 보았지만 아무 일도 일어나지 않았습니다.

저를 위해, 그리고 다른 사람들을 위해 명확히 하고 싶습니다: backup with uploads 옵션이 활성화되어 있을 때(기본값), 로컬 저장소의 업로드를 S3로 자동 백업하는 것이 가능한 것이 맞습니까?

네. 기본적으로 로컬 업로드 항목은 백업 파일에 포함됩니다.