본 내용은 내일배움캠프에서 활동한 내용을 기록한 글입니다.
팀원들이 모르는 부분을 혼자만 앓고 있는 게 아니라 적극적으로 질문하는 점
문제가 발생했을 때 팀원들과 공휴하면서 해결하는 점
늦은 시간까지 과제를 진행해도 끝까지 열심히 노력하는 점
서로 존중하면서 적극적으로 의견을 나누는 점
프로젝트 파일 관리의 부족
코드 양식에 대해 조금 더 구체적인 설계 부족
프로젝트 파일 관리의 부족은 아무래도 각자의 작업 파일을 조금 더 카테고리화 시켜서 분리해서 작업하는 방법을 생각해볼 수 있음. 즉, 설계 단계에서 기능별로 폴더를 생성시켜서 폴더 구조를 정형화 시킬 필요가 있어 보임
이번에 프로젝트를 하면서 각자가 맡은 부분을 진행할 때, 변수나 메서드의 형식이 너무나도 달라서 서로 혼동이 있었음. 그렇기에 서로 조금 더 구체적인 규칙(양식)을 만들 필요가 있어 보임. 예를 들면, 데이터베이스에서 데이터를 조회할 때는 get~, 생성할 때는 create~, 수정할 때는 update~, 삭제할 때는 delete~ 와 같이 정할 필요가 있어 보임
드디어 이번에 진행한 팀프로젝트가 끝났음
조금 더 난이도 있는 과제를 하고 싶었지만, 혼자만의 욕심으로 팀원들을 힘들게 할 수 없었기에 지금까지의 과제에 대한 약간의 복습이라고 생각하면서 진행함
특히 팀원들이 에러에 대한 질문을 하면 나도 에러를 해결하는 능력을 기를 수 있고, 다른 사람들에게 나의 생각을 설명하는 것을 연습하는 좋은 기회가 되었음
이번 과제에서 AWS의 S3와 Multer를 이용해서 이미지를 업로드하는 코드를 구현했음
Insomnia에서 이미지를 업로드하면 S3에 가서 이미지에 대한 URL를 받아옴
이 때, 이미지의 데이터는 S3에 쌓이게 됨
데이터베이스에서 이미지를 삭제하는 것과는 무관하게 계속 쌓이기만 함
그렇게 쌓이면 안된다고 느꼈기에 삭제하는 방법을 찾아봄
찾아보니 S3에 저장된 이미지를 삭제하는 기능을 추가하려면 AWS SDK를 이용하여 deleteObject 메서드를 사용하면 된다고 함
우선 버킷에서 데이터를 삭제할 함수를 만듦
// S3 이미지 삭제 함수
export const deleteImage = async (key) => {
try {
const params = {
Bucket: process.env.AWS_BUCKET,
Key: key,
};
await s3.deleteObject(params);
} catch (err) {
console.log(err);
throw new HttpError.InternalServerError(PETSITTERMESSAGES.PETSITTER.SERVICE.ERROR);
}
};
...
// 펫시터 자격증 삭제
deleteCertificate = async (petsitterId, certificateId) => {
const deletedCertificate = await this.prisma.certificate.delete({
where: { petsitterId, certificateId },
});
const existingImageKey = extractKeyFromUrl(deletedCertificate.imageUrl);
await deleteImage(existingImageKey);
return deletedCertificate.certificateId;
};
}
// URL에서 S3 key 추출 함수
const extractKeyFromUrl = (url) => {
const urlParts = url.split('/');
// URL의 마지막 부분이 key가 됩니다.
const key = urlParts.slice(3).join('/');
return key;
};
위에서 작성한 코드는 단일 객체, 즉 한 장의 이미지를 삭제할 때의 코드임
그럼 여러 장의 이미지(객체)를 삭제하려면 어떻게 해야 할까?
아래는 기존에 S3의 객체를 삭제하지 않고 데이터베이스의 이미지 URL만 삭제하는 코드
// 펫시터 정보 수정
updatePetsitter = async (
petsitterId,
petsitterName,
petsitterCareer,
petsitterProfileImage,
title,
content,
region,
price,
images,
petsitter
) => {
const updatedPetsitter = await this.prisma.$transaction(async (tx) => {
const updatedData = await tx.petsitter.update({
where: { petsitterId },
data: {
// 입력된 데이터가 있으면 수정하고 없으면 생략
...(petsitterName && { petsitterName }),
...(petsitterCareer && { petsitterCareer }),
...(petsitterProfileImage && { petsitterProfileImage }),
...(title && { title }),
...(content && { content }),
...(region && { region }),
...(price && { price }),
},
});
// 비밀번호는 제외하고 반환
updatedData.password = undefined;
// 사진이 있는 펫시터 정보
let houseImage = petsitter.houseImage;
// 이미지 수정
if (images.length !== 0) {
await tx.houseImage.deleteMany({ where: { petsitterId: petsitter.petsitterId } });
houseImage = await Promise.all(
images.map(async (image) => {
return await tx.houseImage.create({
data: { petsitterId: petsitter.petsitterId, imageUrl: image.location },
});
})
);
}
return [updatedData, houseImage];
});
return updatedPetsitter;
};
// 펫시터 정보 수정
updatePetsitter = async (
petsitterId,
petsitterName,
petsitterCareer,
petsitterProfileImage,
title,
content,
region,
price,
images,
petsitter
) => {
const updatedPetsitter = await this.prisma.$transaction(async (tx) => {
const updatedData = await tx.petsitter.update({
where: { petsitterId },
data: {
// 입력된 데이터가 있으면 수정하고 없으면 생략
...(petsitterName && { petsitterName }),
...(petsitterCareer && { petsitterCareer }),
...(petsitterProfileImage && { petsitterProfileImage }),
...(title && { title }),
...(content && { content }),
...(region && { region }),
...(price && { price }),
},
});
// 비밀번호는 제외하고 반환
updatedData.password = undefined;
// 기존 이미지 URL을 가져옴
const existingImages = await tx.houseImage.findMany({
where: { petsitterId: petsitter.petsitterId },
});
// 사진이 있는 펫시터 정보
let houseImage = petsitter.houseImage;
// 이미지 수정
if (images.length !== 0) {
// S3에 있는 기존 이미지 삭제
for (const img of existingImages) {
const existingImageKey = extractKeyFromUrl(img.imageUrl);
if (existingImageKey) {
await deleteImage(existingImageKey);
}
}
// 데이터베이스에 있는 기존 이미지 삭제
await tx.houseImage.deleteMany({ where: { petsitterId: petsitter.petsitterId } });
houseImage = await Promise.all(
images.map(async (image) => {
return await tx.houseImage.create({
data: { petsitterId: petsitter.petsitterId, imageUrl: image.location },
});
})
);
}
return [updatedData, houseImage];
});
return updatedPetsitter;
};