🍔 핵심 내용
🥑 AWS 로그인 및 S3 버켓 만들기
AWS 회원 가입 후, S3 서비스를 이용해보자.
먼저, IAM 에서 사용자를 등록해주어야한다.
IAM 최종 화면에, access key와 secret access key가 나오는데, 이건 한번 닫히면 다시 못연다. 그렇기 때문에 반드시 잘 기억해 두어야 한다. (여기에서는 .env파일에 저장 및 로그인 할 예정)
IAM 등록 완료 후 S3 버킷 만들기
🍔 코드 리뷰
🥑 .env
DATABASE_URL=비밀
PORT=4000
SECRET_KEY=비밀
AWS_KEY= aws accesskey 입력
AWS_SECRET= aws secret accesskey 입력
받아온 key를 .env에 넣어주자.
🥑 shared.utils.js
import AWS from "aws-sdk";
AWS.config.update({
credentials: {
accessKeyId: process.env.AWS_KEY,
secretAccessKey: process.env.AWS_SECRET,
},
});
부여 받은 키를 통해 로그인 해주는 utils를 하나 만들어 주자. (아래 이어서)
🍔 핵심 내용
🥑 AWS와 내 서버 연결 (shared.utils.js 마무리)
🍔 코드 리뷰
🥑 shared.utils.js
import AWS from "aws-sdk";
AWS.config.update({
credentials: {
accessKeyId: process.env.AWS_KEY,
secretAccessKey: process.env.AWS_SECRET,
},
});
export const uploadPhoto = async (file, userId) => {
const { filename, createReadStream } = await file;
const readStream = createReadStream();
const objectName = `${userId}-${Date.now()}-${filename}`;
const { Location } = await new AWS.S3()
.upload({
Bucket: "kimstaclone-upload",
Key: objectName,
ACL: "public-read",
Body: readStream,
})
.promise();
return Location;
};
AWS.S3 object를 만들어 주고, 여기에는 아래 4개 값이 필요하고 마지막에 promise()로 해주어야 한다.
Bucket: AWS의 버켓이름
key: 파일 이름(중복되지 않는 고유 이름으로 설정)
ACL: 모두 읽음 가능
Body: readStream
우리가 필요한 데이터는 최종 url값이다. 해당 객체의Location의 값에 url 주소가 들어가기 때문에 해당 최종 return 값으로 넣어준다.
🥑 editProfile.resolvers.js
import { createWriteStream } from "fs";
import client from "../../client";
import bcrypt from "bcrypt";
import { protectedResolver } from "../users.utils";
import { uploadPhoto } from "../../shared/shared.utils";
const resolverFn = async (
_,
{ firstName, lastName, userName, email, password: newPassword, bio, avatar },
{ loggedInUser }
) => {
let avatarUrl = null;
if (avatar) {
avatarUrl = await uploadPhoto(avatar, loggedInUser.id);
// const { filename, createReadStream } = await avatar;
// const newFilename = `${loggedInUser.id}-${Date.now()}-${filename}`;
// const readStream = createReadStream();
// const writeStream = createWriteStream(
// process.cwd() + "/uploads/" + newFilename
// );
// readStream.pipe(writeStream);
// avatarUrl = `http://localhost:4000/static/${newFilename}`;
}
let uglyPassword = null;
if (newPassword) {
uglyPassword = await bcrypt.hash(newPassword, 10);
}
const updatedUser = await client.user.update({
where: { id: loggedInUser.id },
data: {
firstName,
lastName,
userName,
email,
bio,
...(uglyPassword && { password: uglyPassword }),
...(avatarUrl && { avatar: avatarUrl }),
},
});
if (updatedUser.id) {
return {
ok: true,
};
} else {
return {
ok: false,
error: "프로필을 업데이트 할 수 없습니다.",
};
}
};
export default {
Mutation: {
editProfile: protectedResolver(resolverFn),
},
};
avatar 부분에 완성된 uploadPhoto를 연결해주자. 그리고 받아온 url 주소값을 avatar 필드에 업데이트 해주게 된다.
아래와 같이, altair graphql 에서 avatar 사진을 올려주게 되면, DB에 해당 url 값이 올라간 걸 확인 할 수 있다.
uploadPhoto에서도 해당 기능을 써야 한다. 이름이 곂치니 다음 내용에서는 이름을 바꿔주자!
🍔 핵심 내용
🥑 AWS 폴더 관리
AWS에 파일을 올리고, 이를 폴더로도 관리 해줄 수 있다. 이를 활용해보자.
🥑 shared.utils.js
import AWS from "aws-sdk";
AWS.config.update({
credentials: {
accessKeyId: process.env.AWS_KEY,
secretAccessKey: process.env.AWS_SECRET,
},
});
export const uploadToS3 = async (file, userId, folderName) => {
const { filename, createReadStream } = await file;
const readStream = createReadStream();
const objectName = `${folderName}/${userId}-${Date.now()}-${filename}`;
const { Location } = await new AWS.S3()
.upload({
Bucket: "kimstaclone-upload",
Key: objectName,
ACL: "public-read",
Body: readStream,
})
.promise();
return Location;
};
함수명을 변경해 주었다. 그리고 objectName: 파일 이름 맨 앞에 폴더명/ 을 넣어 주었다. AWS에서는 자동으로 파일 이름 앞에 / 가 들어가면 폴더로 인식해줘서 폴더 관리를 해준다. (AWS 똑똑하네!) 세번째 인자 값으로 넣어주자.
🥑 editProfile.resolvers.js
import { createWriteStream } from "fs";
import client from "../../client";
import bcrypt from "bcrypt";
import { protectedResolver } from "../users.utils";
import { uploadToS3 } from "../../shared/shared.utils";
const resolverFn = async (
_,
{ firstName, lastName, userName, email, password: newPassword, bio, avatar },
{ loggedInUser }
) => {
let avatarUrl = null;
if (avatar) {
avatarUrl = await uploadToS3(avatar, loggedInUser.id, "avatar"); <-- 세번째 인자 추가
...}
...
세번째 인자 추가, 이제 해당 파일은 avatar/ 폴더로 관리 된다.
🥑 uploadPhoto.resolvers.js
import client from "../../client";
import { uploadToS3 } from "../../shared/shared.utils";
import { protectedResolver } from "../../users/users.utils";
import { processHashtags } from "../photos.utils";
export default {
Mutation: {
uploadPhoto: protectedResolver(
async (_, { file, caption }, { loggedInUser }) => {
let hashtagObj = [];
if (caption) {
hashtagObj = processHashtags(caption);
}
const fileUrl = await uploadToS3(file, loggedInUser.id, "upload"); <--세번째 인자추가
return client.photo.create({
data: {
file: fileUrl,
caption,
user: {
connect: { id: loggedInUser.id },
},
...(hashtagObj.length > 0 && {
hashtags: { connectOrCreate: hashtagObj },
}),
},
});
}
),
},
};
uploadPhoto resolver 에도 해당 함수를 넣고, 세번째 인자도 추가해주자. 이렇게 세팅을 하고 파일을 올려보면
아래와 같이 자동으로 해당 폴더로 파일이 들어 가게 된다.
photo module 끝!
'코딩강의 > 인스타그램클론(expo-노마드코더)' 카테고리의 다른 글
Direct Messages(2) (0) | 2021.04.13 |
---|---|
Direct Messages(1) (0) | 2021.04.07 |
Photos Module(2) (0) | 2021.04.04 |
Photos Module(1) (0) | 2021.03.31 |
User module(3) (0) | 2021.03.27 |