접기 가능한 세부 정보에 최대 중첩 깊이 추가

내장된 [details] 기능에 대해 최대 중첩 깊이를 추가하거나, 관리자가 이 한도를 설정할 수 있는 사이트 설정을 도입하는 것을 제안합니다.

문제

최근 제 Discourse 포럼에서 한 사용자가 24단계의 중첩된 [details] 섹션을 포함하는 게시물을 작성했습니다.

이로 인해 여러 문제가 발생했습니다:

  1. 브라우저 성능: 여러 단계를 확장하면 Firefox가 매우 느려지거나 반응이 없게 된다는 보고가 있었습니다.
  2. Markdown 엔드포인트 타임아웃: 해당 주제의 .md 엔드포인트에 액세스하는 속도가 극도로 느려졌습니다. 요청 처리에 19.8초와 31.1초가 걸리는 것을 관찰했습니다.
  3. 서버 오류: Markdown 엔드포인트가 간헐적으로 “Oops” 오류 페이지를 반환했습니다. Discourse 로그에도 Markdown 변환 중 Pitchfork 워커 타임아웃 경고가 표시되었습니다.
  4. 자원 고갈 가능성: 검색 엔진과 AI 크롤러가 .md 엔드포인트를 자주 요청하므로, 깊게 중첩된 게시물이 반복적으로 비용이 높은 처리를 트리거하여 서버 자원을 소모할 수 있습니다.

문제가 된 게시물을 제거한 후, Markdown 엔드포인트는 HTTP 200을 반환했으며 약 1.7초 만에 응답했습니다.

영향을 받은 주제는 다음과 같습니다:

https://meta.appinn.net/t/topic/87672

(문제가 된 답변은 이미 제거되었습니다.)

제안된 개선 사항

다음 중 하나를 적용하는 것이 유용할 것이라고 생각합니다:

  • [details] 중첩을 2~3단계와 같은 합리적인 깊이로 제한합니다.
  • details_max_nesting_depth와 같은 사이트 설정을 추가하여 관리자가 최대 중첩 깊이를 구성할 수 있도록 합니다.

하위 호환성을 위해 기본값은 무제한으로 유지하되, 필요할 때 관리자가 한도를 강제할 수 있도록 하는 것이 좋습니다.

사용자가 설정된 한도를 초과할 경우, Discourse는 명확한 검증 메시지와 함께 게시물을 거부할 수 있습니다.

임시 해결책: 플러그인

[details] 중첩을 최대 2단계로 제한하는 작은 플러그인을 만들었습니다:

GitHub - scavin/discourse-details-depth-limit · GitHub

이 플러그인은 서버 측에서 게시물을 검증하며, 2단계 이상의 중첩된 접이식 섹션을 포함하는 게시물을 거부합니다.

로컬 Discourse 개발 환경에서 성공적으로 테스트했습니다.

비슷한 문제를 겪고 있는 관리자를 위해, 공식 솔루션이 제공될 때까지 이 플러그인은 임시 해결책으로 사용될 수 있습니다.

내장된 Details 플러그인에 구성 가능한 한도가 포함된다면, 우발적이거나 과도한 중첩에 대한 유용한 안전장치로 작용할 것이라고 생각합니다.

3개의 좋아요

Hi @scavin, 보고해 주시고 재현 단계를 공유해 주셔서 감사합니다.

말씀해 주신 Markdown 엔드포인트 지연 문제를 조사하던 중 MarkdownEndpoint::CookedProcessor#replace_details에서 문제를 발견했습니다. 중첩된 <details> 요소가 반복적으로 변환되어 지수적으로 처리 시간이 증가하는 문제가 있었습니다.

수정 사항을 담은 초안 PR을 업스트림에 열었습니다:

https://github.com/discourse/discourse/pull/44461

8단계 중첩 수준에서, 이 수정으로 재귀 변환 횟수가 255회에서 8회로 줄었고, 제 로컬 벤치마크에서 약 31배의 성능 향상이 확인되었습니다. 해당 PR은 GitHub CI 초기 검사를 통과했습니다.

또한, 제안해 주신 details_max_nesting_depth 사이트 설정을 내장 Details 플러그인에 구현하고 있습니다. 기존 동작을 유지하기 위해 무제한 중첩을 나타내는 값으로 0을 사용했습니다. 초기 구현은 완료되었으나, 통합 테스트는 아직 진행 중입니다.

성능 수정 사항은 서버 측 Markdown 변환 문제를 해결하며, 설정 가능한 제한은 특히 브라우저 측 성능을 위해 추가적인 안전장치 역할을 할 것입니다.

제안된 설정에 대한 피드백과, 해당 설정을 동일한 PR에 포함할지 별도로 제출할지에 대한 의견을 듣고 싶습니다.

3개의 좋아요

빠른 조사와 수정에 감사합니다!
새로운 설정을 기다리지 않고 성능 수정 사항을 독립적으로 검토하고 병합할 수 있도록, 두 개의 PR로 나누는 것이 더 좋다고 생각합니다.
또한, 하위 호환성을 위해 기본값을 0으로 하는 구성 가능한 깊이 제한에 동의합니다.

1개의 좋아요

@scavin 감사합니다. 둘을 분리하는 것이 이점이 있다는 점은 이해합니다. 다만 두 변경 사항은 모두 동일한 근본적인 보고서를 다루고 있으며, 현재 구현 및 CI 테스트가 완료된 상태입니다. 모든 PR에서 유지보수자 편집을 활성화해 두었으므로, Discourse 팀의 선호에 따라 두 커밋을 함께 검토하거나 분리하는 방식을 따르겠습니다.

2개의 좋아요

@scavin님, 리포트 감사합니다. @Ethsim2님, PR 감사합니다 :+1: PR을 더 간결하게 업데이트했고, 최대 중첩 깊이를 10으로 설정했습니다. 어쨌든 그 이상을 지원할 필요가 있을 것 같지는 않네요.

3개의 좋아요