GitHub "permanent link" 봇이 내 게시글 의미를 망쳐놨다

약 1년 전, 저는 GitHub의 Discourse 인스턴스에 게시글을 올린 적이 있습니다. 해당 게시글에는 <span>https</span>://github.com/OWNER/REPO/tree/BRANCH/path 형태의 URL 여러 개가 포함되어 있었으며, GitHub.com이 이러한 URL을 어떻게 처리하는지에 대해 논의하기 위한 것이었습니다. 게시글이 올라간 직후, "Github 링크가 영구 링크로 대체되었습니다"라는 메시지와 함께 시스템이 생성한 편집이 적용되었는데, 이는 discourse-github 플러그인에서 비롯된 것으로 보입니다. 특정 코드를 인용하는 게시글이라는 일반적인 경우에서 브랜치 이름을 현재 커밋 ID에 대한 영구 링크로 대체하는 것은 유용한 기능일 수 있지만, GitHub URL 처리 방식을 논의하는 특수한 경우에서는 이 편집이 제 게시글의 의미를 파괴했습니다. 저는 운 좋게도 봇의 편집을 바로 알아차렸고, 봇과 여러 차례 씨름한 끝에 봇의 패턴이 일치하지 않도록 <span> 태그를 추가하는 우회 방법을 결국 찾아냈습니다. 예를 들어 다음과 같이요:

https://github.com/OWNER/REPO/tree/<span>BRANCH</span>/PATH

하지만 다른 작성자들은 봇의 편집을 알아차리지 못해 독자를 혼란스럽게 하는 게시글을 남길 수 있습니다.

특정 게시글에 대한 원치 않는 GitHub 영구 링크 편집을 피하는 가장 좋은 방법은 무엇일까요? 일반적으로 봇이 게시글을 망가뜨릴 위험을 감수하며 자동 편집을 하는 것은 잘못된 것이라 생각합니다. (1) 게시글이 저장될 때 링크를 편집할지 작성자에게 묻거나, (2) 봇이 기존 링크를 제거하지 않고 영구 링크를 추가하는 방식이 더 안전할 것입니다. (다른 웹사이트, 아마도 Reddit 등에서 기존 정보를 삭제하지 않고 정보를 추가하는 봇을 본 기억이 납니다.) Discourse 유지보수 담당자들이 이러한 옵션들이 드문 사용 사례를 위해 너무 번거롭거나 작업량이 많다고 판단한다면, (3) 게시글 저장 후 편집을 피하는 방법에 대한 정보를 작성자가 볼 수 있도록 링크가 포함된 알림을 표시하는 것이 대안이 될 수 있습니다. 이는 (a) UI에 전용 배너를 표시하거나 (b) 봇이 게시글 끝에 텍스트 한 줄을 추가하는 방식으로 구현할 수 있습니다.

작성자가 편집을 옵트아웃(opt-out)하기 위한 가장 합리적인 설계가 무엇인지 확신이 서지 않습니다. discourse-github 플러그인의 링크 대상 기반 사이트 전체 제외 설정은 이 목적에 잘 적합하지 않아 보입니다. 아마도 제가 현재 사용 중인 <span> 태그 우회 방법이 충분할지도 모릅니다. Discourse에 변경 사항이 없더라도, 이 게시글이 문제를 알아차린 작성자들이 우회 방법을 더 쉽게 발견하는 데 도움이 되기를 바랍니다.

참고: 저는 처음에 “영구 링크” 봇이 GitHub 인스턴스에 특화된 것이라고 가정하여 이 문제를 GitHub 포럼에서 제기한 적이 있습니다. 하지만那里的 한 댓글 작성자가 이것이 일반적인 Discourse 기능임을 알려주어, 이제 이 문제를 이곳에서 제기합니다.

관심 가져주셔서 감사합니다!

2개의 좋아요

이 기능은 좋은 기능이라고 생각합니다. 사람들이 master에 대한 링크를 붙여넣는 경우가 많고, 이런 링크들은 시간이 지나면 거의 항상 구식이 되기 때문입니다. 그래도 의도적으로 브랜치에 대한 링크를 붙여넣을 수 있어야 합니다. 이렇게 할 정당한 이유가 많기 때문입니다. 또한 일반적으로 이 기능은 다소 깨져 있는 것으로 보입니다. 재작성해서는 안 되는 부분을 재작성하고, 재작성해야 할 부분을 파싱하지 못합니다.

다음은 이를 수정하는 데 사용할 수 있는 테스트 케이스 예시입니다:

  1. URL을 그대로 붙여넣어 만든 단순 링크. 이 링크는 재작성되어야 하며 실제로도 재작성됩니다: subdomain-static/forums-enhancements.js at master · ClassicPress/subdomain-static · GitHub
  2. [url](url) 형태의 마크다운 링크. 텍스트와 URL을 명시적으로 지정했으므로 이 링크는 재작성되지 않아야 한다고 생각합니다. 그러나 실제로는 _링크 텍스트_만 재작성되고 _링크 URL_은 재작성되지 않습니다. 이는 버그입니다: https://github.com/ClassicPress/subdomain-static/blob/master/forums-enhancements.js
  3. 백쿼트로 둘러싸인 URL. 이는 링크가 아니므로 재작성되어서는 안 되지만, 실제로는 재작성됩니다: https://github.com/ClassicPress/subdomain-static/blob/master/forums-enhancements.js
  4. 삼중 백쿼트로 둘러싸인 코드 블록 안의 URL. 이는 링크가 아니므로 재작성되어서는 안 되지만, 실제로는 재작성됩니다:
    https://github.com/ClassicPress/subdomain-static/blob/master/forums-enhancements.js
    

위 예시 중 (1)만 재작성되어야 한다고 생각합니다. 이렇게 하면 동작이 더 예측 가능해지고, “단순” 링크만 재작성하게 됩니다. 특정 마크다운 구조가 사용된 링크(특정 의도를 표현하는 방법으로 볼 수 있음)는 그대로 두어야 합니다.

1개의 좋아요

이 기능이 meta.discourse.org에서 활성화되지 않은 것 같습니다?

참고로, 저는 이에 동의하지 않습니다: (2)번 수정: 일반 케이스인 [text](URL) (이를 (2a)라고 부르겠습니다)의 경우, 링크 URL은 (1)번과 동일한 방식으로 다시 작성되어야 한다고 생각합니다. (현재 텍스트는 다시 작성하고 URL은 그대로 두는 동작이 완전히 깨져 있다는 점에는 동의합니다.) 저는 (1)번과 (2a)번 중 어떤 것을 사용할지 결정할 때, URL이 독자에게 표시되는 것이 유용한지 아니면 방해가 되는지에 따라 결정합니다. 링크가 작성 시점의 코드 버전으로 가리켜야 하는지, 아니면 읽는 시점의 버전으로 가리켜야 하는지에 대한 의도에는 근거하지 않습니다. 물론 영구 링크(permanent link) 문제에 대해 알고 있으므로, 필요할 때마다 직접 영구 링크를 생성합니다. 하지만 더 일반적으로, Discourse 관리자가 영구 링크 봇을 활성화하기로 결정했다면, 대부분의 사용자가 브랜치 이름 기반 링크가 소거될 수 있다는 위험을 인식하지 못하고 있다고 생각하기 때문일 것입니다. 그리고 특정 마크다운 링크 구문을 사용한다는 것이 해당 사용자가 문제를 인식하고 있지만 해당 링크가 다시 작성되는 것을 제외하고 싶다는 신호가 된다고 보기는 어렵습니다.

하지만 우리 둘 다 여기서 추측만 하고 있는 것 같습니다. 고급 사용자로서, 필요한 경우 오버라이드할 수만 있다면 기본값이 무엇인지에 대해 크게 신경 쓰지 않습니다.

네, 정확합니다. 현재는 이를 덮어쓸 방법이 없습니다. [url](url) (링크 텍스트와 URL이 완전히 동일한 경우)을 작성하는 것은 봇에게 해당 링크가 재작성되어서는 안 된다는 신호를 보내는 확실한 방법이 될 수 있습니다. 그렇게 작성할 다른 이유는 없기 때문입니다.

링크에 고유한 제목을 부여하고 싶고, 대상 URL에서 제목을 추론하는 것을 원하지 않는다면 해당 방식이 유용합니다. 즉, [제목](url) 형식입니다. 링크에 제목을 부여하는 것 자체가 URL 재작성에 대한 선호를 나타내지는 않으므로, @mattmccutchen의 의견에 동의합니다. URL 재작성 시 1번과 2번 방식이 일관되게 작동해야 합니다.

제목이 URL과 정확히 일치하는 경우 재작성하지 말아야 한다는 근거를 제시할 수는 있지만, 사용자가 제목을 제공하되 URL은 재작성되지 않기를 원한다면 어떻게 해야 할까요? 이를 지정하기 위한 다른 방법이 필요합니다.

생각나는 방안 중 하나는 임베드된 이미지 크기 지정과 유사한 제목 접미사입니다. 다만 사용자가 이를 어떻게 발견할지는 불분명합니다.

임베드된 이미지는 다음과 같이 크기를 지정할 수 있습니다:
![제목|100x200](url)

따라서 discourse-github 플러그인은 (아마도) 다음과 같은 형식을 검색하도록 만들 수 있을 것입니다:
[제목|github-no-rewrite](url)

아, (2)가 텍스트와 URL이 동일한 특수한 경우에만 해당한다는 점을 제가 명확히 인지하지 못했네요. 제 발언은 텍스트와 URL이 다를 수 있는 일반적인 경우에 대한 것이었습니다. 이제 이를 (2a)라고 부르겠습니다.

(2)의 경우, URL만 재작성하고 텍스트는 그대로 두어 일관성이 깨지는 것은 이상하다고 동의합니다. 하지만 제 생각에는 일관성을 피하려면 URL과 텍스트를 모두 재작성하는 것이 둘 다 재작성하지 않는 것보다 훨씬 나을 수 있다고 동일하게 주장할 수 있습니다. 따라서 (2)를 옵트아웃(opt-out)으로 취급해야 한다는 주장을 설득력 있게 느끼지 못합니다. (2a)에 대해 작동하는 옵트아웃이 있어야 하므로, 저는 디자인을 복잡하게 만들지 않고 사용자가 (2)에서도 동일한 옵트아웃을 사용하도록 두는 쪽을 선호합니다. (이것이 시먼 매닝(Simon Manning)의 아이디어이기도 했나요?)

제가 제대로 이해하고 있는지(또는 이것이 가능한지) 확신이 서지 않지만, Inline PDF Previews - #45 by Johani 에서처럼 공백 이스케이프를 사용할 수 있을까요? 그러면 [ text]( url)의 경우 텍스트도 URL도 다시 작성하지 않고, 그 외의 경우에만 자동으로 변경되도록 할 수 있을까요?

이 버전은 그대로 유지되고 재작성되지 않아야 합니다. 확인해 보겠습니다:

https://github.com/correctcomputation/checkedc-clang/blob/master-post-microsoft/clang/docs/checkedc/Setup-and-Build.md

다음과 같이 작성되었습니다:

<https://github.com/correctcomputation/checkedc-clang/blob/master-post-microsoft/clang/docs/checkedc/Setup-and-Build.md>

이 Discourse 인스턴스에서는 GitHub 영구 링크(permalink) 재작성이 완전히 비활성화되어 있어 유효한 테스트가 아닙니다. (이 기능이 “공식” 인스턴스에서 비활성화되어 있다는 점이 이 기능에 대해 무엇을 시사하는지 궁금하네요 :upside_down_face:)

대신 replace_github_non_permalinks.rb / replace_github_non_permalinks_spec.rb를 위한 테스트 케이스로 이 예시를 작성해 보신다면, 해당 링크도 재작성되는 것을 확인하실 수 있을 것입니다.

1개의 좋아요