서버 이전 후 Discourse가 작동하지 않습니다

저희 Discourse 인스턴스는 수년 동안 Digital Ocean에서 호스팅되어 왔으며, 여전히 Ubuntu 18을 사용 중이어서 문제가 발생하기 시작했습니다. 그래서 새로운 Droplet을 생성하고全新的 Discourse를 설치한 후, 부트스트랩을 실행하고 이전 Droplet에서 최신 백업을 다운로드하여 복원했습니다. 이 과정에서 오류는 발생하지 않았습니다.

하지만 새로운 인스턴스에 로그인하면 화면이 다음과 같이 보입니다:

그리고 콘솔에는 다음과 같은 메시지가 표시됩니다:

Uncaught SyntaxError: unexpected token: private identifier
admin-13326e7ca61effcc233d500e3263c63074c9823b7e1d0c1680b6f68e23565d5a.js:76:99
ℹ️ Discourse v3.3.0.beta2-dev — https://github.com/discourse/discourse/commits/2a2eaf835f — Ember v5.5.0 app.js:213
Uncaught (in promise) Error: There is no route named admin
    handlersFor https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    isActiveForRoute https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    isActiveForState https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    get isActive https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    get class https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    Re https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    a https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    tag https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    track https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    d https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    Ke https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    tag https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    track https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    d https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    Je https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    flush https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    <anonymous> https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    evaluate https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    evaluateSyscall https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    evaluateInner https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    evaluateOuter https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    next https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    _execute https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    execute https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    sync https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    render https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    _renderRoots https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    Nt https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    _renderRoots https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    _renderRootsTransaction https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    _renderRoot https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    _appendDefinition https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    appendOutletView https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    invoke https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    flush https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    flush https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    _end https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
    _boundAutorunEnd https://discourse.gomomentum.org/assets/vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9
vendor.ff29780b9fed784cce2d843dcb93a803-608f4f77d8437d715d8d39c739c0c8bbe0fe51c9305e55f1ec7d0bee19f5571f.js:9:384138

이 문제를 트러블슈팅하는 데 어디서부터 시작해야 할지 조언을 주시면 감사하겠습니다. 감사합니다!

사이트를 안전 모드로 열어보시고 로딩이 되는지 확인해 보실 수 있을까요?

그렇게 해봤습니다. 똑같이 보이고, 같은 오류가 발생합니다.

아, 그러니까 관리자나 모더레이터 권한이 없는 다른 계정으로 로그인해서 테스트해 봤는데, 제가 볼 때 정상적으로 로딩됩니다. 저는 세 가지 다른 유형의 계정에 접근할 수 있는데, 실험 결과는 다음과 같습니다:

  • 관리자 계정 → 오류 발생
  • 모더레이터 계정 (관리자 대시보드에 대한 제한된 접근 권한) → 오류 발생
  • 일반 계정 → 정상 작동

문제는 사이드바 메뉴에 “관리자” 링크가 포함된 경우에만 발생하는 것 같습니다. 위에서 첨부한 스크린샷에서 “검토” 항목 바로 아래에 표시되었을 링크가 바로 그 링크입니다. 혹시 도움이 될까요?

또한, 관련이 있다면 백업을 가져온 기존 인스턴스는 최신 버전의 Discourse가 아니었습니다. 3.1.2 정도였던 것 같습니다. 물론 새 인스턴스는 최신 버전입니다.

문제는 관리자용 자바스크립트 파일 중 하나에 구문 오류가 있어 admin 라우트가 등록되지 않는 부작용이 발생한다는 것입니다.

콘솔에서 구문 오류가 발생한 파일을 확장하거나 접근할 수 있나요? 현재 정보가 제한적이라 무엇이 문제인지 파악하기 어렵습니다.

네, 가능합니다. 다만 해당 파일은 최소화(minified)된 JavaScript 한 줄로만 구성되어 있습니다. 전체 내용을 여기에 붙여넣어 보았지만 허용된 글자 수를 초과합니다. 온라인 언미나이파이(unminify) 도구를 사용하여 오류가 발생하는 코드 블록을 확인했습니다.

(P.prototype.handlersFor = function (e) {
    var t = this.names[e];
    if (!t) throw new Error("There is no route named " + e);
    for (var r = new Array(t.handlers.length), n = 0; n < t.handlers.length; n++) {
        var i = t.handlers[n];
        r[n] = i;
    }
    return r;
}),

이 정보가 도움이 될까요, 아니면 전체 파일을 게시할 방법을 찾아야 하나요?

오렌지 클라우드가 활성화된 상태로 Cloudflare를 사용 중인가요? 그렇다면 비활성화하세요.

오늘이나 어젯일에 시작된 것으로 보이는 비슷한 문제가 있습니다. 관리자 라우트가 작동하지 않고, 메뉴가 깨져 있습니다.

Uncaught (in promise) Error: There is no route named admin

Cloudflare와 관련된 문제를 겪는 다른 사람이 있는지 확인하기 위해 검색하다가 이 주제를 찾았습니다.

Cloudflare 캐시를 지우거나 개발 모드를 켜면 문제가 사라지지만, 캐싱이 시작되는 순간 문제가 다시 발생합니다.

수정: 이것이 관련이 있는지 확실하지는 않지만, 관리자 계정으로 로그인했을 때 콘솔에 표시되는 일부 오류입니다.

해당 코드 줄은 다음과 같습니다:

class d extends t.default{static#e=dt7948.g(this.prototype,"currentUser",[a.service])#t=void dt7948.i(this,"currentUser")

제 메뉴는 여기서 잘립니다:

해당 메뉴를 열 때 “no route named admin” 오류가 발생합니다. “admin” 링크가 위치해야 할 부분에서 잘리는 것일 수 있습니다.

Cloudflare의 모든 규칙을 비활성화해야 합니다. Rocket Launcher와 WAF 관련 항목도 포함됩니다.

Cloudflare 설정을 깔끔하게 유지하면 Discourse와 충돌하는 문제가 발생하지 않습니다.

이 사이트에서는 Rocket Loader가 꺼져 있습니다. 최근 Cloudflare 설정에 변경 사항이 있었던 것 같지 않습니다. (방금 감사 로그를 확인했습니다.)

@Ryan_Hyer 님, 스크린샷을 다시 보고 있습니다. 관리자 메뉴 항목이 표시되어야 하는 바로 그 지점에서 잘리는 것인가요? 제 사이트에서도 동일한 위치에 같은 문제가 발생하고 있습니다.

WAF와 같은 기능이 활성화되어 있다면, Cloudflare가 내부 동작 방식을 변경하여 웹사이트에 영향을 미칠 수도 있습니다.

Cloudflare의 “자동 미니파이” 기능이 비활성화되어 있는지, 그리고 캐시를 삭제했는지도 확인해 주세요.

이 기능은 최신 JS 기능(현재 Discourse가 사용 중)에서 작동하지 않기 때문에 비추천(deprecated)되었습니다.

Cloudflare와 Safari 15에서 발생한 문제로 인해 해당 변경 사항을 되돌렸습니다.

따라서 @Ryan_Hyer 님이 다시 Discourse를 업그레이드하시면 모든 것이 정상으로 돌아갈 것입니다.

(하지만 여전히 Cloudflare의 JS “최적화” 기능 중 Rocket Loader와 자동 미니파이어(auto-minify) 등을 모두 비활성화하는 것을 강력히 권장합니다)

감사합니다! Git pull을 실행했는데 이미 최신 상태라고 나오네요. 즉, 해당 변경 사항이 아직 제공되지 않는 건가요?

우리가 Cloudflare를 사용하는 용도는 DNS와 DDoS 보호뿐이며, 그 외에는 아무것도 사용하지 않습니다. 하지만 네, 오렌지 클라우드(프록시 모드)는 켜져 있었습니다. 방금 꺼보았는데 사이트가 정상적으로 작동하는 것 같습니다. 정말 훌륭하네요! 여러분 감사합니다!

기본값에서 아무런 조정 없이 오렌지 클라우드를 활성화하는 것은 사실상 "제 사이트를 망쳐주세요"라는 뜻입니다.

클라우드플레어(Cloudflare)를 사용하는 경우 설정해야 할 사항에 대한 가이드를 제공합니다.

고맙습니다. 그게 문제였네요. 자동 미니파일을 비활성화하고, 캐시를 비운 뒤, 강제 새로고침을 했더니 다시 잘 작동했습니다.