제 phpBB 마이그레이션 여정 (postgresql)

phpBB3에서 discourse로 마이그레이션하는 과정에서 발견한 내용들을 공유합니다.

해결 방안은 다음과 같습니다:

  • postgres 소스 DB
  • 이모지
  • 임포터 조정 (인용구 버그 수정, bbcode 지원 개선 (youtube 포함), 첨부파일 댓글)
  • 소프트 삭제된 게시물이 일반 게시물로 가져오기

저는 아주 까다로운 편이라, 따라 하시면 꽤 좋은 결과를 얻으실 수 있을 것입니다.


phpbb에서 discourse로 이동을 고려하고 있습니다 (설치된 버전 히스토리: 3.2.1 - 3.2.8).
문제는 DB에 postgresql을 사용한다는 점입니다. 조언이 있을까요? 아직 시도해 보지는 않았지만, OP(최초 게시자)의 내용 기준으로 아직 지원되지 않는 것으로 추정됩니다.

새로운 임포트 스크립트가 출시된 적이 있나요? 그 내용이 약 1년 전의 것이었기 때문입니다.

대량 가져오기 스크립트가 도움이 될 것입니다… discourse/script/bulk_import/phpbb_postgresql.rb at 52d4de7b45eb1b7c7997da2ba8bff83a3c22a3a5 · discourse/discourse · GitHub

고맙습니다, @gerhard

제 이해가 맞나요?

  • script/import_scripts/phpbb3와 script/bulk_import는 완전히 별개의 가져오기(importer) 도구입니다.
  • 대량 가져오기 도구는 덜 정교하며(비록 더 빠르긴 하지만), 예를 들어 첨부파일을 가져오지 못합니다.

만약 그렇다면, 대량 가져오기 도구를 사용하는 것에는 단점이 있는 것 같습니다…

그렇다면 다른 해결책이 없나요? PostgreSQL에서 MySQL로 DB 마이그레이션을 하는 것을 고려해 보는 것이 좋을까요?

네, 단점이 있습니다. Ruby로 작업하는 데 익숙하시다면, discourse/script/import_scripts/phpbb3/database at main · discourse/discourse · GitHub 에 있는 파일들을 수정하여 mysql2 대신 pg 제마를 사용하도록 변경하는 것을 권장합니다.

그럴 수도 있겠죠? 얼마나 쉬운 작업인지, 실제로 작동할지는 전혀 모르겠습니다. 한번 시도해 보셔도 될 것 같습니다…

아쉽군. 그래도 한번 시도해볼게. 뭔가 나오면 다시 연락할게.

그 가져오기(importer)가 비권장 처리될 예정인 것인가요? ‘새로운’ 가져오기(importer)의 상태는 어떻게 되나요? 이 작업에 얼마나 많은 노력을 기울일지 결정하려 합니다. 업스트림(upstream)에 가치가 있을까요?

저는 PostgreSQL에서 MySQL로 전환하는 문제를 직접 다루어 본 적은 없지만, phpBB에서 Discourse로 마이그레이션하는 관점에서만 말씀드리면, 마이그레이션을 완료하기 위해 무엇이든 하라는 것이 제 의견입니다.

저는 phpBB 포럼 두 개를 Discourse로 마이그레이션해 보았는데, 어떤 변화에서도 흔히 볼 수 있는 소수의 사용자 불만이 있었음에도 불구하고, Discourse의 이점은 충분히 가치가 있습니다! Discourse는 유지보수와 관리가 훨씬 쉬운 것은 물론, 내장된 사용자 참여 기능, 이미지 처리, 사용자 커스터마이징, 가독성 등이 phpBB에 비해 압도적으로 앞서 있어 비교 자체가 어렵습니다. 또한 Discourse에서는 훨씬 더 나은 지원을 받을 수 있습니다.

저는 전문가가 아니지만, 간단한 검색을 해 보니 스키마 덤프를 수행한 후 스키마 선언의 데이터 유형을 MySQL에서 사용하는 유형으로 변경하고, 수정된 스키마를 사용하여 MySQL 데이터베이스에 테이블을 생성한 뒤, 테이블별 CSV 내보내기 및 가져오기를 수행함으로써 PostgreSQL에서 MySQL로 마이그레이션할 수 있을 것 같습니다.

MySQL 데이터베이스를 확보한 후에는 정적인 phpBB 마이그레이션 스크립트를 사용하여 모든 첨부 파일을 가져올 수 있습니다.

노력할 가치가 있습니다!

데이터베이스 문자 인코딩(charset)과 정렬 규칙(collation)을 주의 깊게 다루지 않으면 재앙으로 이어질 수 있습니다.

몇 년 전에 이 작업을 시작했지만, 아직 미완성 상태이고 최신 버전이 아닙니다. 그래도 도움이 될 수 있을지도 모릅니다.

그 일이 쉽다고 말하려는 의도는 아니었습니다. 다만, 수동으로라도 수행할 가치가 있으며, 실제로도 가능하다는 뜻입니다. 또한 이를 위해 자동화 도구나 수동 작업을 활용할 수 있는 자원이 많이 존재하는 것 같습니다. :grinning:

ruby를 싫어하는 데다 기존 importers는 곧 bulk importer로 대체될 예정이지만(아직 내 용도에는 부족함이 있어서), postgres → mysql 마이그레이션 전략으로 진행하기로 했습니다.

mysql workbench의 마이그레이션 마법사를 통해 어느 정도 진전을 보고 있습니다. 성공하면 간단한 가이드를 작성해 보겠지만, 지금까지는 유망해 보입니다.

지금까지 이 문제에 막혀 있습니다:

https://bugs.mysql.com/bug.php?id=89048

결론적으로, MySQL Workbench가 유니코드 가져오기를 실패합니다. 내일 MariaDB로 시도해보고, 가져오기 전에 기본 데이터베이스 인코딩을 설정할 수 있는지 확인해 보겠습니다.

MySQL Workbench가 제대로 작동했다면 좋았을 텐데, 옵션을 살펴보니 관련 오류 보고서가 많이 보여서 추천하지 않았습니다.

스키마 덤프와 CSV 내보내기/가져오기 방법을 전에 한 번 언급했고, 이번에는 훨씬 더 쉽게 사용할 수 있도록 약간 수정해서 한 번 더 언급한 뒤 더 이상 이 주제에 대해 이야기하지 않겠습니다.

GUI를 사용하려는 경우:

  1. 현재 사용 중인 phpBB3 버전과 동일한 버전의 phpBB3가 MySQL/MariaDB에서 실행 중인 정상적인 사본의 모든 테이블에 대한 구조 전용(structure-only) 내보내기를 확보하세요. MySQL/MariaDB를 실행하는 대부분의 웹 호스팅 업체에서 사용할 수 있는 phpMyAdmin을 사용하면 이를 만드는 데 고작 2분이면 충분합니다. (대안으로, 누군가가 구조 전용 내보내기를 대신해 주지 않을 경우 phpBB3 설치 스크립트에서 필요한 CREATE TABLE 문장을 가져올 수 있거나, 저렴한 웹 호스팅 계정으로 MySQL/MariaDB 환경에 해당 버전의 phpBB3를 깨끗하게 설치한 후 생성된 테이블의 데이터를 삭제하여 빈 MySQL/MariaDB 데이터베이스를 만드는 방법도 있습니다.)
  2. MySQL/MariaDB와 phpMyAdmin이 있는 웹 호스팅에 접근하여 데이터베이스를 생성하고, phpMyAdmin을 사용하여 1단계에서 만든 구조 전용 내보내기 파일에서 구조를 가져오세요.
  3. postgresql 데이터베이스에서 각 테이블에 대해 CSV 내보내기를 생성하고, 새로 만든 MySQL/MariaDB 데이터베이스에서 phpMyAdmin을 사용하여 해당 테이블에 CSV를 가져오세요.

이렇게 하면 문자 집합(charset)과 인코딩 관련 문제를 방지할 수 있고, postgre에서 스키마 덤프를 수동으로 변환하려 할 때 필요한 모든 대응 데이터 타입과 필드 크기를 파악할 필요도 없습니다.

구조 전용 SQL 문장을 제공할 수는 있지만, 제가 아직 가지고 있는 DB는 phpBB3 3.3.8 버전의 것이므로, v. 3.2.x를 사용 중이라면 오히려 더 많은 문제를 야기할 수 있습니다.

하하. 네, 제가 현재까지 도달한 수준으로 작동시키기조차 꽤 눈에 띄지 않는 트릭들이 필요했어요. 여전히 작동할 수 있다고 생각하지만, 새로운 방향을 탐색할 수 있게 해주셔서 감사합니다.

음, 다행이네요. PostgreSQL 임포트를 위한 제 해결책입니다.

이것은 PostgreSQL 덤프를 가져와서 임포터(Importer)를 연결할 수 있는 작동하는 MariaDB 서버로 만들어 줍니다. Docker Compose가 필요합니다.

phpBB 3.2에서는 작동합니다. 3.3에 대해서는 잘 모르겠습니다. 3.3 지원이 간절하다면, phpBB 3.3의 pg_dumpall 덤프를 제공해 주시면 수정해 볼 수 있습니다.

phpbb_smilies.zip (87.2 KB)

(기본 이모지와 비교하기)

참고로 제 이모지 해결책은 다음과 같습니다.

두 가지 옵션을 제안합니다:

  1. 네이티브
    • 원래 phpBB 이모지를 유지하지 않으려면, 이미 Discourse에 존재하는 네이티브 이모지로 매핑할 수 있습니다.

:grin: :smile: :wink: :slightly_frowning_face: :astonished: :exploding_head: :confounded: :sunglasses: :joy: :rage:
:stuck_out_tongue: :person_facepalming: :sob: :imp: :smiling_imp: :roll_eyes: :exclamation: :question: :bulb: :arrow_forward:
:neutral_face: :smiley_cat: :nerd_face: :nerd_face:

  1. 가져오기(Imported)
    • 원래 phpBB 이모지를 유지하되 단축코드(shortcode)로 계속 사용 가능하게 하려면:
      • 가져오기(importer)를 실행하기 전에 Discourse 대시보드의 이모지 섹션(admin/customize/emojis)으로 이동하세요.
      • 원한다면 먼저 phpbb 또는 다른 이름의 이모지 그룹을 생성하세요.
      • new_files에 있는 이모지 파일(5개씩)을 브라우저로 드래그하여 커스텀 이모지로 가져오세요.

두 옵션에 대한 설정이 포함된 import.yml 파일이 zip 파일에 포함되어 있습니다.

또한 zip 파일에는 결정이나 직접 매핑을 돕기 위한 스프레드시트가 포함되어 있습니다:

phpbb_smilies
├── phpbb_smilies.xlsx # 결정을 돕기 위한 마스터 참조 자료
├── import.yml # 두 옵션이 포함된 설정 파일
├── orig_phpbb_smilies.csv # 원래 phpbb 데이터
├── orig_files # 원래 phpbb 이모지 파일
│   ├── icon_arrow.gif
│   └── ...
└── new_files # 스프레드시트의 `new_shortcode` 열과 일치하도록 이름이 변경된 이모지 파일
    ├── phpbb_arrow.gif
    └── ...

누군가 인용 속성(attribution)이 제대로 작동하게 만든 적이 있나요?

phpbb에서 가져온 인용이 포함된 원본 게시글의 예시입니다 (사용자 이름과 콘텐츠는 변경했으며, ID 등은 동일합니다)

[quote=someuser post_id=46649 time=1677556325 user_id=48]
foo
[/quote]

bar

discourse에서 이 게시글이 어떻게 보이는지 확인해 보세요:

discourse로 마이그레이션된 게시글의 원본(raw)은 다음과 같습니다:

[quote=", post:37, topic:1893"]
foo
[/quote]

bar

마이그레이션된 postid와 topicid는 정확하지만 사용자 이름이 누락되었습니다. 이로 인해 인용 블록이 비인터랙티브(noninteractive) 상태가 됩니다. 사용자 이름이 빈 문자열일 경우, 인용 블록이 확장되지 않으며 원본 게시글로 이동하기 위해 클릭할 수도 없습니다.

importer를 개선하지 않고 더 나은 경험을 기대할 수 있을까요? 즉, 제가 뭔가 잘못하고 있는 건가요?

지난 한 달 동안 수행한 phpbb3 가져오기에서 해당 항목들이 정상적으로 작동했다는 사실에 꽤 확신을 갖고 있습니다.

아직 마지막 문제를 해결하지 못했지만, 다른 질문이 하나 있습니다.

수입(import)이 끝나고 앱 컨테이너를 시작하면, 아직 남아 있는 phpbb 서버에 엄청난 트래픽이 몰리는 것을 확인했습니다. sidekiq의 후처리(post processing) 단계에서 일어나는 일이라고 생각합니다.

phpbb는 여전히 www.example.com에 있고, discourse는 dc.example.com에 있습니다.

실제로 무슨 일이 일어나고 있는지 이해하려고 합니다. 이 테스트 마이그레이션 중에 어떤 설정이 적절한지, 그리고 최종 마이그레이션 시에는 어떤 설정이 의미 있는지도 알고 싶습니다. 또한 sidekiq 후처리를 위해 phpbb를 실행해 두어야 하는지도 궁금합니다. 후처리 단계에서 정확히 무슨 일이 일어나는지 전혀 모르기 때문에 물어봅니다.

현재 settings.yml에서 관련이 있을 수 있는 설정 몇 가지입니다:

import:
  # 여러 phpBB 포럼을 단일 Discourse 포럼으로 가져올 경우 이 값을 설정합니다.
  site_name:
  site_prefix:
    # 게시물 내부의 내부 링크를 다시 작성하는 데 필요합니다.
    original: example.com    # http(s):// 없이
    new: https://dc.example.com       # http:// 또는 https:// 포함

확인해 봐야 할 다른 사항이 있다면 알려 주세요.

또한 www 서브도메인에 대해서도 명확하지 않은 부분이 있습니다. 현재 phpbb를 위해 nginx에서 www로 리다이렉트하고 있습니다. 따라서 위 예시에서 original: example.com으로 설정하는 것과 original: www.example.com으로 설정하는 것 중 차이가 있을까요? 최종 마이그레이션 시 new 설정에 대해서도 같은 질문을 하고 싶습니다. 제 사용자들은 실제로 discourse에 www.example.com으로 접속하게 될 텐데, 어떤 것이 모범 사례인지 잘 모르겠습니다.

인용구 파싱에 실제로 문제가 있는 것 같습니다.

방금 설치한 phpBB 3.2.8 (mariadb에 설치됨)를 가져와서 테스트해 보았더니

인용 출처가 깨져 있습니다 – 가져온 인용구에서 사용자 이름 필드가 비어 있지만, 나머지는 정상입니다.

가져온 게시글의 discourse 스크린샷:

discourse로 가져온 게시글:

[quote=", post:4, topic:12"]
[quote=", post:3, topic:12"]
[quote=", post:2, topic:12"]
msg 1
[/quote]

second
[/quote]

third
[/quote]

fourth

원본 phpbb 게시글:

MariaDB [phpbb]> select post_text from phpbb_posts where post_id=5;
...
| <r><QUOTE author="admin" post_id="4" time="1678400691" user_id="2"><s>[quote=admin post_id=4 time=1678400691 user_id=2]</s>
<QUOTE author="admin" post_id="3" time="1678400685" user_id="2"><s>[quote=admin post_id=3 time=1678400685 user_id=2]</s>
<QUOTE author="admin" post_id="2" time="1678400675" user_id="2"><s>[quote=admin post_id=2 time=1678400675 user_id=2]</s>msg 1<e>[/quote]</e></QUOTE>

second
<e>[/quote]</e></QUOTE>

third
<e>[/quote]</e></QUOTE>

fourth</r> |

결국 가져오기(importer)를 개선하게 될 수도 있겠네요…

수정 완료


저는 포럼 마이그레이션에 대해 꽤 까다로운 편이라, 가져오기(importer) 기능을 계속 개선하고 있습니다. 가져오기 기능이 비추천(deprecated) 상태이고, 일부 수정 사항은 제 포럼에 다소 특화되어 있어서 PR을 만들까 고민 중입니다. 하지만 이 브랜치에는 제 모든 수정 사항이 포함되어 있으니, 누군가에게 유용할 수 있습니다:

인용문 문제, 몇 가지 흔히 추가되는 BBCode 지원, YouTube 링크 파싱 오류 수정, 그리고 멘션/심플멘션(mentions/simplementions) 확장 기능 지원을 추가했습니다. example.com과 www.example.com으로 된 링크가 포럼에 있는 경우와 같이 여러 사이트 접두사(prefix)를 지원하도록 하는 등 더 개선할 부분이 많습니다.

비바닐라(non-vanilla) 기능도 일부 지원하지만, 확장 기능이 없는 표준 phpBB 포럼에서 실행하는 데에는 문제가 되지 않을 것입니다. 어쨌든 제 버전을 사용하는 것을 권장합니다.

가장 쉬운 사용법은 제 브랜치를 어딘가로 받아온 다음, 컨테이너 내부의 가져오기 스크립트 디렉토리를 바인드 마운트(bind mount)로 덮어쓰는 것입니다.

예를 들어, 제 변경 사항을 어딘가로 받아오기:

git clone --filter=blob:none --no-checkout https://github.com/ftc2/discourse.git discourse_dev
cd discourse_dev
git sparse-checkout set --cone
git switch phpbb_import
git sparse-checkout set script/import_scripts

그 다음 import.yml 컨테이너 설정에 이 내용을 추가하세요:

docker_args:
  - '-v /path/to/discourse_dev/script/import_scripts:/var/www/discourse/script/import_scripts'

그 후 가져오기 컨테이너를 다시 빌드하세요. 빌드 후에는 빌드 과정에서 제 파일이 덮어써질 수 있으므로, 제 저장소를 받아온 위치에서 리셋(reset)을 실행하는 것이 좋습니다.

cd /path/to/discourse_dev
git reset --hard HEAD
chown -R 1000:1000 .