이미지를 업로드 하는 프로세스들 중 가장 기본적인 방식은 아래와 같다.
다음은 GCP에 전달받은 이미지 파일을 저장하는 로직이다.
export class FilesService {
async upload({ files }) {
const waitedFiles = await Promise.all(files);
/* 이미지를 저장할 GCP bucket과 연결 */
const bucket = process.env.GOOGLE_BUCKET;
const storage = new Storage({
projectId: process.env.GOOGLE_BUCKET_PROJECT_ID,
keyFilename: process.env.GOOGLE_BUCKET_KEY_FILENAME,
}).bucket(process.env.GOOGLE_BUCKET);
/* 전달받은 이미지들을 업로드하기 */
const results = await Promise.all(
waitedFiles.map(
(el) =>
new Promise((resolve, reject) => {
el.createReadStream()
.pipe(storage.file(el.filename).createWriteStream())
.on('finish', () => resolve(`${bucket}/${el.filename}`))
.on('error', () => reject('실패!!'));
}),
),
);
return results;
}
}
1개 이상의 이미지 파일을 브라우저로부터 전달받았다면 먼저 Promise.all()을 이용하여 waitedFiles로 넣어주어 파일의 정보를 저장한다. 이후 저장할 GCP와 연결을 해주고 이미지 저장 시간을 절약하기 위하여 Promise.all()로 이미지들을 Storage에 저장한다. 각각 들어온 파일 정보들을 createReadStream()으로 읽어들이고 해당 파일 정보를 pipe안에 넣어주어 storage에 저장시킨다. 만약 저장에 성공하였다면 resolve()가 호출되고 실패하였다면 reject()가 호출된다.
그런데 우리가 여기서 조금 더 생각해보면, 요즘은 브라우저를 다양한 기기에서 접속할 수 있다. PC가 될 수도 있고 핸드폰 혹은 태블릿에서 브라우저를 열 수 있다. 그럴 때마다 제공되는 서비스에서는 해당 기기에 맞게 이미지의 크기를 조정하여 보여줄 수 있어야 한다. 이럴 때에는 sharp라는 라이브러리를 사용하여 필요한 사이즈로 썸네일을 생성하여 저장해줄 수 있다.