Skip to content

[WTH-511] v3 마크다운 게시글 본문 Tiptap HTML 변환 - #111

Closed
hyxklee wants to merge 4 commits into
mainfrom
feat/WTH-511-markdown-to-tiptap-conversion
Closed

hyxklee wants to merge 4 commits into
mainfrom
feat/WTH-511-markdown-to-tiptap-conversion

Conversation

@hyxklee

@hyxklee hyxklee commented Sep 21, 2026

Copy link
Copy Markdown
Member

배경

v3 에디터는 게시글 본문을 마크다운 원문으로 저장했고, V3 → V4 이관 시 post.content 를 무가공 복사했습니다 (docs/migration/v3-to-v4/08_post_comment.sql). v4 는 Tiptap(HTML 기반) 에디터라 이관된 글에서 ## 제목, **굵게** 같은 기호가 그대로 노출되고 줄바꿈이 뭉쳐 보입니다.

슬랙에서 FE 측이 요청한 건이며, FE 가 제시한 Tiptap 태그 스펙에 맞춰 서버에서 변환합니다.

변경 내용

1. MarkdownToTiptapHtmlConverter (신규)

마크다운 → Tiptap 호환 HTML 변환기. commonmark-java + jsoup 사용.

  • needsConversionrestoreMarkdownSource → commonmark 렌더 → Tiptap 스펙 후처리 → 살균
  • Tiptap 은 태그 없는 텍스트(bare text)를 허용하지 않아 <li>/<td> 내부 <p> 래핑, 테이블 colspan/rowspan 명시 등 후처리가 필요합니다
  • <p> 한 덩어리로 이관된 본문, <br> 혼재 데이터도 마크다운 원문을 복원해 변환합니다
  • 단일 줄바꿈 → <br>, 연속 빈 줄 → <p></p> 로 보존해 줄바꿈 뭉침을 해결합니다
  • weeth-client 확장 구성에 맞춰 h4 이상은 <p><strong> 으로, 이미지는 링크로 강등합니다 (Heading levels [1,2,3] / Image 확장 부재)

2. 변환 적용 범위 — 출처 기반 판정

본문 내용만으로는 사용자가 의도한 - 대시로 시작하는 문장 과 마크다운 리스트 마커를 구분할 수 없습니다. 내용 기반 휴리스틱만 쓰면 v4 정상 글이 리스트로 바뀌는 등 하위호환이 깨집니다.

그래서 내용이 아니라 출처로 판정합니다:

// Post.kt
fun hasLegacyMarkdownContent(legacyClubId: Long, editorMigratedAt: LocalDateTime): Boolean =
    board.club.id == legacyClubId && createdAt.isBefore(editorMigratedAt)

PostMapper 가 상세·목록 응답 양쪽에서 이 조건을 통과한 글만 변환하고, 아니면 저장된 본문을 그대로 반환합니다.

3. 기존 본문 보존

  • 이미 <pre><code> 인 내용은 코드 펜스로 격리해 마크다운 재파싱에서 보호 (언어 클래스 유지)
  • Tiptap 테이블의 colwidth 속성 보존

설정

동아리 식별자를 설정 파일에 남기지 않기 위해 환경 변수로만 주입합니다. 두 값이 모두 있어야 변환이 동작하며, 없으면 기존과 동일하게 본문을 그대로 내려줍니다 (local/test 는 자동으로 꺼집니다).

LEGACY_CONTENT_CLUB_ID=<V3 -> V4 이관 대상 동아리 TSID>
LEGACY_CONTENT_EDITOR_MIGRATED_AT=2026-09-20T00:00:00

검증

  • ./gradlew test 통과 — 변환기 33개, PostMapperTest 8개(변환 적용/미적용/설정 없음/상세 경로), PostEntityTest 에 판정 경계 4케이스
  • 아키텍처 테스트(Konsist) 12개 통과, ktlint 통과
  • weeth-client 에서 라운드트립 검증 14개 통과 — 실제 editorExtensionsnew Editor({content}).getHTML() 파싱. 별도 PR 로 올립니다

범위 밖

  • DB 백필 마이그레이션 — 조회 시점 변환으로 선제 대응하고 별도 판단합니다. 변환기가 멱등이라 나중에 백필해도 충돌하지 않습니다
  • 댓글 본문 변환 (평문이며 FE 렌더 이슈)
  • <a> 의 target/rel — FE Link 확장이 렌더 시 자체 부여합니다

확인 필요

  • 에디터 전환 시각: 2026-09-20T00:00:00 으로 잡았습니다. 이보다 늦게 잡으면 v4 초기 글이 변형되고, 이르게 잡으면 v3 글 일부가 안 고쳐집니다
  • 목록 API 응답 시간: 페이지 내 글 수만큼 변환이 돌아 CPU 비용이 붙습니다. 백필 전까지 모니터링이 필요합니다

🤖 Generated with Claude Code

https://claude.ai/code/session_01R5mXcTtT9nQdHVET2CYWNy

@coderabbitai

coderabbitai Bot commented Sep 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: e93fe419-02b1-4caf-8809-290a922c2c1e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@JIN921 JIN921 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오... 신기하다 수고하셧습니다~!!

@woneeeee woneeeee left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

근데 왜 dev로 머지 안하시고 바로 main으로 머지하시는건가요...?

@hyxklee

hyxklee commented Sep 21, 2026

Copy link
Copy Markdown
Member Author

이거 핫픽스 하려고 했던 건데, 그냥 DB data 변경해서 해소했서용 ㅋㅋㅋㅋ

@hyxklee hyxklee closed this Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants