지난 몇 달간 Discourse 코어에서 업로드와 관련된 많은 커밋이 이루어졌다는 점을 눈치채셨을 것입니다. 이는 Discourse 코어 내에서 코드베이스의 jQuery file upload 사용법을 대체하려는 전반적인 노력의 일환이었으며, 이는 더 넓은 차원에서 코드베이스의 jQuery 자체 사용법을 대체하려는 노력의 일부이기도 합니다. jQuery file uploader는 매우 오래된 프로젝트로, 거의 처음부터 Discourse 코어의 일부였습니다. 저는 다른 프로젝트에서도 제 경력 내내 이 라이브러리를 사용해 온 것 같습니다. 하지만 이제 이 ‘믿을 만한老将(노장)’을 은퇴시킬 때입니다:
우리는 jQuery file upload(그리고 곧 또 다른 라이브러리인 resumable.js도)를 대체하여 Uppy라는 라이브러리를 도입했습니다. Uppy는 훨씬 더 현대적인 업로드 라이브러리로, 플러그인으로 쉽게 확장할 수 있으며 우리가 적용하는 다양한 워크플로우를 모두 처리할 수 있습니다. 특히, 이를 통해 Discourse 클라이언트에서 API를 통해 대용량 파일을 전송해야 하는 대신 S3로 직접 다중 부분(multipart) 업로드를 수행할 수 있게 되었습니다.
현재 컴포저(Composer)는 모든 업로드에 Uppy를 사용하며, 앱의 다른 많은 부분(아바타 업로드, 프로필 배경 업로드 등)에서도 이를 활용하고 있습니다. 마지막으로 남은 몇몇 부분도 향후 몇 주 내에 Uppy로 전환될 예정입니다. 대부분의 사용자에게는 거의 눈에 띄지 않는 변경일 것이지만, 플러그인 및 테마 컴포넌트 개발자들은 몇 가지 변경 사항을 적용해야 합니다.
플러그인 API
프리프로세서(Preprocessors)
모든 업로드 프리프로세서는 이제 Uppy 플러그인으로 작성되어야 합니다. 이러한 플러그인은 작성하기가 비교적 간단하며, 단순한 프로미스 기반 워크플로우를 사용합니다. 업로드 프리프로세서는 Uppy가 파일을 S3 또는 /uploads.json 엔드포인트로 업로드하기 전에 파일을 수정하거나 메타데이터를 추가할 수 있습니다. 자체 프리프로세서를 작성할 때 참고할 수 있는 코어 내의 여러 프리프로세서가 이미 존재합니다:
- discourse/app/assets/javascripts/discourse/app/lib/uppy-checksum-plugin.js at 6662101208089def86ed18a81ac90d1c52670569 · discourse/discourse · GitHub
- discourse/app/assets/javascripts/discourse/app/lib/uppy-media-optimization-plugin.js at 6662101208089def86ed18a81ac90d1c52670569 · discourse/discourse · GitHub
컴포저용 업로드 프리프로세서는 플러그인 API를 통해 api.addComposerUploadPreProcessor로 등록됩니다:
업로드 핸들러(Upload Handlers)
업로드 핸들러는 Uppy 플러그인으로 작성되지 않으며, 이전과 동일한 방식으로 동작하지만 약간의 변경 사항이 있습니다. 이제 파일이 업로드 핸들러에 등록된 확장자와 일치하면, 일치하는 모든 파일이 한 번에 전송됩니다. 이전에는 업로드 핸들러에 한 번에 하나의 파일만 전송되었지만, 이제 대신 배열로 전송됩니다:
업로드 핸들러에 의해 처리된 파일은 Uppy 업로드 파이프라인에서 추가로 처리되지 않습니다. 프리프로세서는 업로드 핸들러가 호출되기 전에 실행됩니다.
S3 다중 부분 직접 업로드
앞서 언급했듯이, Uppy 사용은 UI에서 S3로 직접 다중 부분 업로드를 수행할 수 있게 해줍니다. 이 기능을 활성화하려면 enable_direct_s3_uploads 사이트 설정을 true로 설정해야 합니다.
우리가 호스팅을 제공하는 경우, 해당 S3 버킷에는 이미 관련 권한이 적용되어 있습니다. 하지만 자체 호스팅(self-hosting)을 사용하는 경우, 이 기능이 작동하려면 버킷에 여러 권한과 CORS 규칙을 설정해야 합니다.
CORS 규칙의 경우, rake s3:ensure_cors_rules를 실행하여 s3:ensure_cors_rules rake 작업을 실행하기만 하면 됩니다. Discourse 인스턴스에서 S3 자격 증명으로 설정한 액세스 키와 시크릿 키에 대해 S3:GetBucketCors 및 S3:PutBucketCors 권한이 활성화되어 있는 한, 이 작업은 버킷에 다음 규칙을 추가합니다.
{
"AllowedHeaders": [
"Authorization",
"Content-Disposition",
"Content-Type"
],
"AllowedMethods": [
"GET",
"HEAD",
"PUT"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": [
"ETag"
],
"MaxAgeSeconds": 3000
}
권한의 경우, Discourse 인스턴스에서 S3 자격 증명으로 설정한 액세스 키와 시크릿 키에 대해 다음 권한이 활성화되어 있어야 합니다.
{
"Sid": "YourSid",
"Effect": "Allow",
"Action": [
"s3:PutObjectVersionAcl",
"s3:PutObjectAcl",
"s3:PutObject",
"s3:GetObjectAcl",
"s3:GetObject",
"s3:DeleteObject",
"s3:CreateMultipartUpload",
"s3:CompleteMultipartUpload",
"s3:AbortMultipartUpload"
],
"Resource": [
"YOUR_RESOURCE"
]
}
이는 수개월에 걸쳐 진행된 과정이며, 아직 완료되지 않았습니다! Discourse 코어에서 jQuery file uploader와 resumable.js를 완전히 제거하기 전에 이 토픽에 다시 게시하겠습니다. 여기에 게시한 내용에 대해 궁금한 점이 있다면 알려주세요!

