Discourse의 1RTT 철학을 고려할 때, 아바타 이미지 서빙 코드를 재작성할 때가 된 것 같습니다.
아바타 이미지는 다른 이미지 업로드와 동일하게 처리되어야 합니다. 업로드 시 리사이즈를 거치고 저장된 후, 파일 시스템/S3/CDN에서 직접 서빙되어야 합니다.
현재 Discourse 방식은 아바타 이미지를 서빙하기 위해 프록시 방식을 사용합니다. 이 접근법은 불필요한 HTTP 왕복 횟수와 IP 주소 관련 문제를 유발합니다.
아바타 요청 흐름은 다음과 같습니다:
초기 Discourse HTML이 렌더링됩니다.
브라우저가 아바타 이미지를 감지하고 Discourse 서버에 이미지를 요청합니다.
Discourse 서버는 프록시 역할을 하여 로컬 파일 스토어/S3/CDN에서 이미지를 요청합니다.
Discourse 서버가 이미지를 수신합니다.
Discourse 서버가 이미지를 브라우저로 전송합니다.
모든 커스텀 아바타마다 HTTP 왕복이 1회 추가되고 관련 서버 처리 시간이 발생합니다. 일반적인 주제나 주제 목록에는 30개 이상의 커스텀 아바타 이미지가 포함될 수 있습니다. 제 사이트의 경우, 이를 방지할 수 있는 10K에서 20K에 달하는 추가 RTT 및 관련 서버 부하가 매일 발생합니다.
또한, 아바타 이미지는 서버에서 직접 접근하여 호출됩니다. CDN 수준의 보호를 적용하려면 IP 주소를 화이트리스트에 등록해야 합니다. 이는 서버 IP 주소 대신 게이트웨이를 화이트리스트에 등록해야 함을 의미합니다. 호스팅 업체는 네트워크 트래픽을 균형 있게 분산시키기 위해 정기적으로 변경을 수행합니다. 제 게이트웨이 IP 주소는 변경/진화하게 됩니다. 소프트웨어는 기본 아바타 이미지가 작동하려면 IP 주소를 업데이트하는 것에 의존해서는 안 됩니다. 이는 지원에서 발생한 다음 사건, 아바타 프록시와 CDN 핫링크 보호에 기반하고 있습니다.
성능과 단순성의 관점에서, 아바타 이미지를 Discourse가 지정된 파일 스토어에서 직접 서빙할 수 있을까요?
네, DISCOURSE_REDIRECT_AVATAR_REQUESTS=true 환경 변수를 설정하여 활성화할 수 있는 GlobalSetting이 있습니다.
이 설정을 적용하면 아바타 요청이 프록시를 거치지 않고 파일 스토어로의 302 리다이렉트로 처리됩니다.
단독으로 사용하긴… 사실 좋은 아이디어는 아닙니다. 이렇게 하면 브라우저가 각 아바타마다 두 번의 완전한 HTTP 왕복 통신을 수행해야 합니다. 즉, ‘핫링크 방지’ 문제를 해결할 수는 있겠지만… 활성화하는 것을 권장하지 않습니다. 사용자 경험만 더 나빠질 뿐입니다.
저희는 discourse.org 호스팅에서 이 설정을 사용하고 있습니다. 하지만 Cloudfront CDN에서 실행되는 람다(Lambda) 함수로 이를 보완하고 있습니다. 이 람다 함수가 302 응답을 감지하고 직접 프록싱을 수행합니다. 즉, 프록싱을 애플리케이션 서버에서 CDN으로 이동시킨 것입니다.
"아바타를 자산(asset)으로 직접 링크하도록 변경할 수 있는가"라는 더 일반적인 질문에는, 아바타 URL이 모든 과거 게시물(예: 인용문)에 고정되어 있어 상황이 복잡합니다. 동적인 /user-avatar/ URL 덕분에 사용자가 아바타를 변경해도 기존 링크가 계속 작동하도록 유지할 수 있습니다. 이 시스템을 변경할 계획은 없습니다.
기존 프록싱이 사용자의 사용 사례에 맞게 작동하도록 하는 쉽고 리스크가 낮은 방법(예: 아바타 프록시 요청에 특정 HTTP 헤더를 삽입하는 GlobalSetting 추가)이 있다면, 해당 변경 사항에 대한 PR을 고려해 볼 수 있습니다.
위에서 언급한 옵션들은 현재 제 환경에서는 실현 가능하지도, 선호되지도 않습니다. 이 복잡하게 얽힌 애플리케이션 부분을 해결하는 데 도움을 주고 싶지만, 이 기술 스택에는 매우 초보적인 수준입니다.
현재 제가 제공할 수 있는 도움은 제 과거의 비즈니스 분석(BA) 및 개발 관리(Dev Mgt) 경험에 기반한 것입니다. 따라서 도움이 되는 기분이 들게 하기 위해 제 생각을 공유합니다.
기술적 난제에 직면할 때 저는 먼저 해결책을 더 어렵게 만드는 가정을 살펴봅니다.
그 중 하나의 가정은 업데이트된 아바타 이미지를 새 파일명으로 저장하는 것입니다. 사용자는 오직 하나의 아바타만 가지고 있으며, 우리는 아바타 이름에 대한 기록을 유지하지 않습니다. 저는 사용자가 아바타 이미지를 업데이트할 때 기존 아바타와 동일한 파일명을 사용하여 저장하도록 하는 것을 제안합니다. 이는 기본적으로 /user-avatar/ 링크가 수행하고 있는 작업과 유사합니다. 우회적 해결책(workaround)을 사용하는 대신, 아바타 생성/업데이트 시점에 이 로직을 수행하십시오. 이렇게 하면 과거 게시물에 대한 우려가 향후 생성되는 게시물(baked posts)에서는 해결될 것입니다.
이것이 대대적인 변경(big-bang change)일까요? 아닙니다. 이 변경 사항은 수개월에 걸쳐 점진적으로 사이트 성능을 개선하면서 구현될 수 있습니다. 제 개발 팀은 항상 각 코드 블록마다 기회적 코드 개선 목록(opportunistic code list)을 가지고 있었습니다. 우리는 이러한 개선을 원했지만, 개별적으로 수행해야 할 정도로 긴급하지는 않았습니다. 다른 이유로 코드가 개발을 위해 열릴 때 개발자는 기회적 변경 사항도 함께 수행했습니다. 이는 코드가 열리고 업데이트되는 횟수를 줄여 테스트와 오류를 최소화하는 데 도움이 되었습니다.
저는 이 프로젝트를 다음과 같은 단계로 나누겠습니다:
아바타 이미지 저장 로직을 업데이트하여 현재 파일명을 사용하여 이미지 업데이트를 대체합니다.
아바타 이미지의 모든 사용처를 discourse의 권장 파일 저장/전달 시스템을 활용하는 표준 함수로 대체합니다. 이러한 작업은 수개월에 걸쳐 진행되어 새로운 아바타 이미지 표시 로직으로 점진적으로 전환될 수 있습니다.
위 두 단계가 완료되면, 커뮤니티에게 baked HTML 내의 과거 아바타 이미지를 선호하는 파일 시스템으로 변경하고 다시 생성(rebake)하는 방법과 코드 스니펫을 제공하십시오. 이는 각 discourse 사이트 소유자가 구현할지 여부를 결정할 수 있는 사항입니다. (이 코드 지침과 스니펫은 원시 HTML 변경을 수행하는 데 유용할 것입니다)
당신은 이 모든 것을 고려해 보셨을 것이라고 생각합니다. 또한 오래된 코드를 수정하는 일은 우선순위 목록에 오르지 않는다는 것도 잘 알고 있습니다.
이 노력에 도움이 될 수 있는 부분이 있다면 알려주세요.
참고: 전역 헤더 설정에 대한 PR 제안에 감사드립니다. 추가 조사를 한 후 더 명확한 요구 사항으로 후속 조치를 취하겠습니다. 도움을 주셔서 감사합니다.