
Presigned URL이란?
=> 클라이언트 > 서버에게 Presigned URL만 요청.
=> 클라이언트가 직접 > S3에 업로드하는 방식
클라이언트 > 서버
(/test/page.js)
'use client'
export default function Test(){
return (
<div>
<input type="file" accept="image/*" onChange={
async (e)=>{
let file = e.target.files[0]
let fileName = encodeURIComponent(file.name);
let res = await fetch(`/api/post/image?file=${fileName}`);
res = await res.json()
}
}></input>
<img />
</div>
)
}
=> <input> 태그를 통해 클라이언트가 이미지 선택
=> 서버에게 Presigned URL을 달라고 GET 요청
서버 > 클라이언트
npm install aws-sdk
=> AWS 라이브러리 설치
(/api/test/image.js)
import aws from 'aws-sdk'
export default async function handler(req, res){
aws.config.update({
accessKeyId: process.env.ACCESS_KEY,
secretAccessKey: process.env.SECRET_KEY,
region: 'ap-northeast-2',
signatureVersion: 'v4',
})
const s3 = new aws.S3();
const url = await s3.createPresignedPost({
Bucket: process.env.BUCKET_NAME,
Fields: { key : req.query.file },
Expires: 60, // 유효기간 60초
Conditions: [
['content-length-range', 0, 1048576], //파일용량 1MB 까지 제한
],
})
res.status(200).json(url)
}
=> 보안정보는 .env파일 사용
=> 권한 승인 후, Presigned URL을 브라우저로 전송
클라이언트 > S3
(/test/page.js)
'use client'
export default function Test(){
return (
<div>
<input type="file" accept="image/*" onChange={
async (e)=>{
let file = e.target.files[0]
let fileName = encodeURIComponent(file.name);
let res = await fetch(`/api/post/image?file=${fileName}`);
res = await res.json()
//S3 업로드
const formData = new FormData();
Object.entries({ ...res.fields, file }).forEach(([key, value]) => {
formData.append(key, value);
});
let upload = await fetch(res.url, {
method: "POST",
body: formData,
});
console.log(upload);
if (upload.ok) {
setSrc(upload.url + "/" + fileName);
} else {
console.log("실패");
}
}}
></input>
<img />
</div>
)
}
=> 클라이언트는 Presigned URL을 통해 S3로 이미지 전송
=> 이미지 URL을 <img src="">에 저장
클라이언트 단에서 이미지를 저장할 수 있으므로 서버단의 리소스를 줄일 수 있어서 유용한 기능이다.
솔직히 아직까지 서버의 부담이 어느 정도인지 느껴본 적이 없어서 잘 모르겠지만,
요새 트렌드는 이 방식을 사용한다고 한다.
그런데, 하나 의문점은 <img> 태그가 아닌 <Image> 컴포넌트 사용 시 왜 해당 URL을 접근할 수 없는지,,
나는 최적화된 이미지를 출력하고 싶은데 말이다. 흑흑
(next.config.js)
module.exports = {
images: {
remotePatterns: [
{
protocol: "https",
hostname: "s3.ap-northeast-2.amazonaws.com",
port: "",
pathname: `/${process.env.BUCKET_NAME}/**`,
},
],
},
};
=> 외부 이미지를 불러올 때, next.config.js 작업을 하면 <Image> 컴포넌트를 사용할 수 있다 !
'Next.js' 카테고리의 다른 글
loading.js, error.js, not-found.js (0) | 2023.07.09 |
---|---|
.env 파일 <보안작업> (0) | 2023.07.08 |
회원가입/로그인 기능 + JWT (0) | 2023.07.08 |
Next-Auth + Session 방식 (0) | 2023.07.08 |
Next-Auth를 통한 소셜로그인 (0) | 2023.07.08 |

Presigned URL이란?
=> 클라이언트 > 서버에게 Presigned URL만 요청.
=> 클라이언트가 직접 > S3에 업로드하는 방식
클라이언트 > 서버
(/test/page.js)
'use client'
export default function Test(){
return (
<div>
<input type="file" accept="image/*" onChange={
async (e)=>{
let file = e.target.files[0]
let fileName = encodeURIComponent(file.name);
let res = await fetch(`/api/post/image?file=${fileName}`);
res = await res.json()
}
}></input>
<img />
</div>
)
}
=> <input> 태그를 통해 클라이언트가 이미지 선택
=> 서버에게 Presigned URL을 달라고 GET 요청
서버 > 클라이언트
npm install aws-sdk
=> AWS 라이브러리 설치
(/api/test/image.js)
import aws from 'aws-sdk'
export default async function handler(req, res){
aws.config.update({
accessKeyId: process.env.ACCESS_KEY,
secretAccessKey: process.env.SECRET_KEY,
region: 'ap-northeast-2',
signatureVersion: 'v4',
})
const s3 = new aws.S3();
const url = await s3.createPresignedPost({
Bucket: process.env.BUCKET_NAME,
Fields: { key : req.query.file },
Expires: 60, // 유효기간 60초
Conditions: [
['content-length-range', 0, 1048576], //파일용량 1MB 까지 제한
],
})
res.status(200).json(url)
}
=> 보안정보는 .env파일 사용
=> 권한 승인 후, Presigned URL을 브라우저로 전송
클라이언트 > S3
(/test/page.js)
'use client'
export default function Test(){
return (
<div>
<input type="file" accept="image/*" onChange={
async (e)=>{
let file = e.target.files[0]
let fileName = encodeURIComponent(file.name);
let res = await fetch(`/api/post/image?file=${fileName}`);
res = await res.json()
//S3 업로드
const formData = new FormData();
Object.entries({ ...res.fields, file }).forEach(([key, value]) => {
formData.append(key, value);
});
let upload = await fetch(res.url, {
method: "POST",
body: formData,
});
console.log(upload);
if (upload.ok) {
setSrc(upload.url + "/" + fileName);
} else {
console.log("실패");
}
}}
></input>
<img />
</div>
)
}
=> 클라이언트는 Presigned URL을 통해 S3로 이미지 전송
=> 이미지 URL을 <img src="">에 저장
클라이언트 단에서 이미지를 저장할 수 있으므로 서버단의 리소스를 줄일 수 있어서 유용한 기능이다.
솔직히 아직까지 서버의 부담이 어느 정도인지 느껴본 적이 없어서 잘 모르겠지만,
요새 트렌드는 이 방식을 사용한다고 한다.
그런데, 하나 의문점은 <img> 태그가 아닌 <Image> 컴포넌트 사용 시 왜 해당 URL을 접근할 수 없는지,,
나는 최적화된 이미지를 출력하고 싶은데 말이다. 흑흑
(next.config.js)
module.exports = {
images: {
remotePatterns: [
{
protocol: "https",
hostname: "s3.ap-northeast-2.amazonaws.com",
port: "",
pathname: `/${process.env.BUCKET_NAME}/**`,
},
],
},
};
=> 외부 이미지를 불러올 때, next.config.js 작업을 하면 <Image> 컴포넌트를 사용할 수 있다 !
'Next.js' 카테고리의 다른 글
loading.js, error.js, not-found.js (0) | 2023.07.09 |
---|---|
.env 파일 <보안작업> (0) | 2023.07.08 |
회원가입/로그인 기능 + JWT (0) | 2023.07.08 |
Next-Auth + Session 방식 (0) | 2023.07.08 |
Next-Auth를 통한 소셜로그인 (0) | 2023.07.08 |