AWS Cognito๋ก ๋น๊ณต๊ฐ S3 ๊ฐ์ฒด์ ์ก์ธ์คํ๋ ๋ฐฉ๋ฒ

์๋๋ฆฌ์ค
๊ณ ๊ฐ์ ์ํด ์ผ๋ถ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฐ๋ฐํ๋ค๊ณ ๊ฐ์ ํด ๋ด
์๋ค. ๊ทธ๋ฌ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ ์ฝ๋์ ๊ด๋ จ๋ PDF, Word, Excel ๋ฑ์ ํ์ผ์ด ์์ต๋๋ค. ์๋๋ฆฌ์ค์ ๋จ์ํ๋ฅผ ์ํด ์ด๋ฌํ ํ์ผ์ด AWS์ ๋จ์ผ ๋น๊ณต๊ฐ(private) S3 ๋ฒํท์ ์ ์ฅ๋์ด ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
์ฌ์ฉ์๋ ์ ํ๋ฆฌ์ผ์ด์
์ URL ๋งํฌ๋ฅผ ํตํด ๋น๊ณต๊ฐ S3 ๋ฒํท์์ ์ด๋ฌํ ๊ด๋ จ ํ์ผ์ ์ก์ธ์คํ ์ ์์ด์ผ ํฉ๋๋ค. ์ฐ๋ฆฌ ์๋ฃจ์
์ ์ฌ๋ด ์ํํธ์จ์ด๋ฅผ ์ํ ์ด์ ๊ฐ๋ฅํ(portable) ์๋ฃจ์
์ผ๋ก ์๋ํด์ผ ํฉ๋๋ค.
์๊ฐ
์ด ๋ฌธ์์ ๋ชฉ์ ์ Cognito ์ฌ์ฉ์ ํ์ ์ฌ์ฉํ์ฌ ๋น๊ณต๊ฐ S3 ๋ฒํท์ ํ์ผ์ ๋ค์ด๋ก๋ํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ฃผ๋ ๊ฒ์
๋๋ค. Cognito ์ธ์๋ Cognito์์ Authorizer๊ฐ ์๋ API Gateway๋ก์ ํ๋ฆ๊ณผ API Gateway์ Lambda์ ํ๋ ฅ๋ ๋ณด์ฌ์ค๋๋ค.
AWS ์ฝ์์ ๊ฐ ๋จ๊ณ์ ๋ํด ๊ฐ๋ฅํ ๋ง์ ์คํฌ๋ฆฐ์ท์ด ๊ณต์ ๋์์ต๋๋ค. ํนํ ์ด๋ณด์๋ฅผ ์ํด ๋จ๊ณ๋ฅผ ๋ ๋ช
ํํ๊ฒ ํ๊ธฐ ์ํด ๋ง์ ์๊ฐ ์๋ฃ๊ฐ ์ถ๊ฐ๋์์ต๋๋ค.
๋ฐฐ๊ฒฝ
์ด ๋ฌธ์์์ ๊ฐ๋ฐ๋ ๋ด์ฉ์ ๋ ์ ์ดํดํ๊ธฐ ์ํด ์ผ๋ถ ์ฌ์ ์ฝ๊ธฐ๊ฐ ์ ์ฉํ ์ ์์ต๋๋ค. ํนํ AWS ์ด๋ณด์๋ฅผ ์ํ ๋ค์ ๋งํฌ๊ฐ ์ ์ฉํฉ๋๋ค:
๋ฌด์์ ํด์ผ ํ๋์?
์ด๋ฌํ ์์
์ ๋ํด ๋ง์ ํ๋ฆ์ด๋ ๋ฐฉ๋ฒ์ ์ฝ๋ฉํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์๋ ์๋์์ ๋ณด์ฌ์ฃผ๋ ๋ฐฉ๋ฒ์ ๊ตฌํํฉ๋๋ค. ์๋๋ฆฌ์ค ๊ตฌํ ๋ฐฉ๋ฒ์ ๋ํ ๊ฐ๋ตํ ์ค๋ช
์ด ์๋ ์ด๋ฏธ์ง์ ์ ์๋์ด ์์ต๋๋ค.
์๋ ์ด๋ฏธ์ง๋ Cognito ์ฌ์ฉ์ ํ, S3 ๋ฒํท, API Gateway ๋ฉ์๋, Lambda ํจ์ ๋ฑ๊ณผ ๊ฐ์ ์ผ๋ถ ์์๋ฅผ ์์ฑํด์ผ ํจ์ ๋ณด์ฌ์ค๋๋ค. AWS ํ๊ฒฝ์์ ๋ชจ๋ ์ํฐํฐ๋ฅผ ์์ฑํ ํ ๋ชจ๋ ํจ๊ป ํ๋ ฅํ์ฌ ์๋ํ ์ ์๋๋ก ์ ์ ํ๊ฒ ๊ตฌ์ฑํด์ผ ํฉ๋๋ค.

AWS ํ๊ฒฝ์ ๋ชจ๋ ์์๋ฅผ ์ญ์์ผ๋ก ์์ฑํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์๋ฅผ ๋ค์ด API ๋ฉ์๋์ ํจ๊ป Lambda๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ๋จผ์ Lambda ํจ์๋ฅผ ๊ฐ๋ฐํ๋ฉด API Gateway ๋ฉ์๋ ์์ฑ ์ ์ด ํจ์๋ฅผ ์ฝ๊ฒ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค.
๊ฐ์
๋ค์ ์ง๋ฌธ์ ๋ํ ๋ต๋ณ์ ์ฐพ์๋ณด๊ฒ ์ต๋๋ค. ์ด ๋ฌธ์์ ๋ชจ๋ ๋จ๊ณ๋ฅผ ๊ตฌํํ๋ ค๋ฉด AWS ๊ณ์ ์ด ์์ด์ผ ํ๋ค๋ ์ ์ ๊ธฐ์ตํ์ธ์.
- ๋น๊ณต๊ฐ S3 ๋ฒํท์ ์ด๋ป๊ฒ ์์ฑํ๋์?
- ๋น๊ณต๊ฐ S3 ๋ฒํท์ ๊ฐ์ฒด์ ์ก์ธ์คํ๊ธฐ ์ํ ์ฌ์ฉ์ ์ ์ ์ ์ฑ ์ ์ด๋ป๊ฒ ์์ฑํ๋์?
- ๋น๊ณต๊ฐ S3 ๋ฒํท์ ๊ฐ์ฒด์ ์ก์ธ์คํ๊ธฐ ์ํ Lambda ํจ์๋ ์ด๋ป๊ฒ ์์ฑํ๋์?
- Lambda ํจ์๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ Gateway API๋ ์ด๋ป๊ฒ ์์ฑํ๋์?
- ์น ํด๋๋ก ์ฌ์ฉํ ๊ณต๊ฐ S3 ๋ฒํท์ ์ด๋ป๊ฒ ์์ฑํ๋์?
- Cognito ์ฌ์ฉ์ ํ์ ์ด๋ป๊ฒ ์์ฑํ๊ณ ์ค์ ์ ๊ตฌ์ฑํ๋์?
- ์๋๋ฆฌ์ค๋ ์ด๋ป๊ฒ ํ ์คํธํ๋์?
1. ๋น๊ณต๊ฐ S3 ๋ฒํท์ ์ด๋ป๊ฒ ์์ฑํ๋์?
S3๋ AWS์์ ์ง์ญ ๊ธฐ๋ฐ(region-based) ์๋น์ค ์ค ํ๋์
๋๋ค. S3 ๋ฒํท์ ํญ๋ชฉ์ ๊ฐ์ฒด(object)๋ผ๊ณ ํฉ๋๋ค. ๋ฐ๋ผ์ AWS์์ S3 ๋ฒํท์ ๋ํด ๊ฐ์ฒด์ ํ์ผ ์ฉ์ด๋ ์๋ก ๋ฐ๊ฟ ์ฌ์ฉํ ์ ์์ต๋๋ค.
"๋ชจ๋ ๊ณต๊ฐ ์ก์ธ์ค ์ฐจ๋จ"(Block All Public Access) ์ฒดํฌ๋ฐ์ค๋ฅผ ์ ํํ ์ํ๋ก ์ ์งํ์ธ์. ์ฌ๊ธฐ์ ๋น๊ณต๊ฐ S3 ๋ฒํท์ด ์์ฑ๋์์ต๋๋ค.

๋น๊ณต๊ฐ ์ก์ธ์ค๋ฅผ ํ
์คํธํ๊ธฐ ์ํด S3 ๋ฒํท์ ์ผ๋ถ ๊ฐ์ฒด๋ฅผ ์
๋ก๋ํ์ธ์. ์ดํ ๊ถํ์ด ์๋ ์ฌ์ฉ์๋ ๊ฐ๋ฅํ ์ก์ธ์ค ๋งํฌ๋ก ์ด๋ฌํ ๊ฐ์ฒด์ ์ก์ธ์ค๋ฅผ ์๋ํ์ธ์.

2. ๋น๊ณต๊ฐ S3 ๋ฒํท์ ๊ฐ์ฒด์ ์ก์ธ์คํ๊ธฐ ์ํ ์ ์ฑ ์์ฑ
AWS์์ IAM(Identity and Access Management)์ ๋ชจ๋ ์๋น์ค์ ๊ธฐ๋ณธ์
๋๋ค! ์ฌ์ฉ์, ๊ทธ๋ฃน, ์ญํ ๋ฐ ์ ์ฑ
์ ์ฐ๋ฆฌ๊ฐ ์ต์ํด์ ธ์ผ ํ ๊ธฐ๋ณธ ๊ฐ๋
์
๋๋ค.
๋ง์ ๊ธฐ๋ณธ ์ ๊ณต(built-in) ์ญํ ์ด ์์ผ๋ฉฐ ๊ฐ ์ญํ ์๋ ๊ถํ์ ์๋ฏธํ๋ ๋ง์ ๊ธฐ๋ณธ ์ ๊ณต ์ ์ฑ
์ด ์์ต๋๋ค. ์ด๋ฅผ "AWS Managed"๋ผ๊ณ ํฉ๋๋ค. ๊ทธ๋ฌ๋ "Customer Managed"(๊ณ ๊ฐ ๊ด๋ฆฌ) ์ญํ ๋ฐ ์ ์ฑ
์ ์์ฑํ๋ ๊ฒ๋ ๊ฐ๋ฅํฉ๋๋ค.
- ๋น๊ณต๊ฐ S3 ๋ฒํท์์ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด ์ฌ์ฉ์ ์ง์ IAM ์ ์ฑ ์ ์์ฑํ์ธ์.
- AWS์ ๊ธฐ์กด ์ ์ฑ
๋ชฉ๋ก์ ์ฐพ๊ณ ์๋์ ๊ฐ์ด ๋น๊ณต๊ฐ S3 ๋ฒํท์์๋ง
GetObject์์ ์ ์ํํ ์ ์ ์ฑ ์ ์์ฑํ์ธ์:

์๋์ ๊ฐ์ด ์ฌ์ฉ์ ์ง์ ์ ์ฑ
์ ์์ฑํ์ธ์. ์๋น์ค๋ก S3๋ฅผ, ์์
(action)์ผ๋ก
GetObject๋ง ์ ํํ์ธ์:
๋ฆฌ์์ค(resource)๋ก "specific"์ ์ ํํ๊ณ ์ ์ฑ
์ด ์ํ๋ ๊ธฐ๋ฅ์ ๊ฐ๋๋ก ๋น๊ณต๊ฐ S3 ๋ฒํท์ ์ง์ ํ์ธ์:

์ ์ฑ
์ ์ด๋ฆ์ ์ง์ ํ๊ณ ์์ฑํ์ธ์.
์ ์ฑ
JSON ์ ์:
JSON
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::private-s3-for-interfacing/*"
}
]
}
3. ๋น๊ณต๊ฐ S3 ๋ฒํท์ ๊ฐ์ฒด์ ์ก์ธ์คํ๊ธฐ ์ํ Lambda ํจ์ ์์ฑ
์ฌ๊ธฐ์๋ Lambda ํจ์์ NodeJS์ ์ต์ ๋ฒ์ ์ ์ฌ์ฉํ์ต๋๋ค. Lambda ํจ์๋ฅผ ์์ฑํ๊ณ NodeJS๋ฅผ ์ ํํ์ธ์.

๊ธฐ์กด ์ฝ๋๋ฅผ ์ ๊ณต๋ ์ํ ์ฝ๋๋ก ๊ต์ฒดํ์ธ์. ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ ํ Lambda ํจ์๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด "Deploy" ๋ฒํผ์ ๋๋ฅด์ธ์.
NodeJS Lambda ์ฝ๋ (Blob์ผ๋ก ๋ฐํ):
JavaScript
const AWS = require('aws-sdk');
const S3= new AWS.S3();
exports.handler = async (event, context) => {
let fileName;
let bucketName;
let contentType;
let fileExt;
try {
bucketName = 'private-s3-for-interfacing';
fileName = event["queryStringParameters"]['fn']
contentType = 'application/pdf';
fileExt = 'pdf';
fileExt = fileName.split('.').pop();
switch (fileExt) {
case 'pdf': contentType = 'application/pdf'; break;
case 'png': contentType = 'image/png'; break;
case 'gif': contentType = 'image/gif'; break;
case 'jpeg': case 'jpg': contentType = 'image/jpeg'; break;
case 'docx': contentType = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; break;
case 'xlsx': contentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'; break;
default: ;
}
const data = await S3.getObject({Bucket: bucketName, Key: fileName}).promise();
return {
headers: {
'Content-Type': contentType,
'Content-Disposition': 'attachment; filename=' + fileName,
'Content-Encoding': 'base64',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token',
'Access-Control-Allow-Methods': 'GET,OPTIONS'
},
body: data.Body.toString('base64'),
isBase64Encoded: true,
statusCode: 200
}
} catch (err) {
return {
statusCode: err.statusCode || 400,
body: err.message || JSON.stringify(err.message)
}
}
}
Lambda ํจ์๋ฅผ ์์ฑํ ๋ ํจ๊ป ์ญํ ์ด ์์ฑ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด ์ญํ ์๋ ๋น๊ณต๊ฐ S3 ๋ฒํท์ ๊ฐ์ฒด์ ์ก์ธ์คํ ๊ถํ์ด ์์ต๋๋ค. ์ด์ ์ด์ ๋จ๊ณ์์ ์์ฑํ "Customer Managed" ์ ์ฑ
์ Lambda ํจ์์ ํจ๊ป ์์ฑ๋ ์ด ์ญํ ์ ์ฐ๊ฒฐํด์ผ ํฉ๋๋ค.

์ด์ ๋จ๊ณ์์ ์์ฑํ ์ฌ์ฉ์ ์ง์ ์ ์ฑ
์ ์ด ์ญํ ์ ์ฐ๊ฒฐํ์ธ์.

4. Lambda ํจ์๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ Gateway API ์์ฑ
์๋์ ๊ฐ์ด AWS Gateway REST API๋ฅผ ์์ฑํ์ธ์. "REST" API๋ฅผ "New API"๋ก ์์ฑํฉ๋๋ค.

AWS GW API๋ฅผ ์์ฑํ๊ณ ์คํํ๋ ค๋ฉด ๋ช ๊ฐ์ง ๋จ๊ณ๊ฐ ์์ต๋๋ค:
- API ์์ฑ
- Resource ์์ฑ
- Method ์์ฑ
- API ๋ฐฐํฌ(Deploy)
REST API์ ๋ํด ์๋์ ๊ฐ์ด
Resource๋ฅผ ์์ฑํ์ธ์:
์์ฑํ ๋ฆฌ์์ค์ ๋ํด
GET ๋ฉ์๋๋ฅผ ์์ฑํ์ธ์. ์ด์ ๋จ๊ณ์์ ์์ฑํ Lambda ํจ์๋ฅผ ์ด ๋ฉ์๋์ ์ฐ๊ฒฐํ๋ ๊ฒ์ ์์ง ๋ง์ธ์.
Lambda Proxy Integration์ด ์ฌ๊ธฐ์์ ์ฒดํฌ๋์์ต๋๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์ ํตํด Lambda ํจ์์์ ๋ชจ๋ ์๋ต ๊ด๋ จ ์ฝํ
์ธ ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.

์๋์ ๊ฐ์ด Gateway API์ ๋ํด CORS๋ฅผ ํ์ฑํํ์ธ์.

AWS Gateway ๋ฉ์๋์ ๊ด๋ จ๋ ๋ชจ๋ ๊ฒ์ ์์ฑํ๊ณ ๊ตฌ์ฑํ ํ ์ด์ API๋ฅผ ๋ฐฐํฌ(deploy)ํ ์๊ฐ์
๋๋ค.

API ๊ฒ์ดํธ ์ก์ธ์ค๋ฅผ ์ ํํ๋ ค๋ฉด Authorizer(์ธ์ฆ์)๋ฅผ ์ ์ํด์ผ ํฉ๋๋ค. ์๋์ ๊ฐ์ด Cognito Authorizer๋ฅผ ์ ์ํ ์ ์์ต๋๋ค.

5. ์น ํด๋๋ก ์ฌ์ฉํ ๊ณต๊ฐ S3 ๋ฒํท
์๋ฃจ์
์๋ ๋ ๊ฐ์ S3 ๋ฒํท์ด ํ์ํฉ๋๋ค. ์ฒซ ๋ฒ์งธ๋ ์ด์ ์น์
์์ ์์ฑ๋์์ต๋๋ค. ๋ ๋ฒ์งธ๋ ์ง๊ธ ์์ฑ๋๋ฉฐ ์น ํด๋๋ก ์ฌ์ฉ๋ฉ๋๋ค.

์น ํด๋๋ก ๊ณต๊ฐ S3 ๋ฒํท์ ์์ฑํ์ธ์. ์ด ๋ฒํท์๋
callback.html ํ์ผ์ด ํฌํจ๋์ด ์์ด Cognito ์ฝ๋ฐฑ ์ฃผ์๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.6. Cognito ์ฌ์ฉ์ ํ ์์ฑ ๋ฐ ๊ตฌ์ฑ
- Callback ์ฃผ์:
https://web-s3-for-interfacing.s3.eu-west-2.amazonaws.com/Callback.html - OAuth 2.0 Flows: "implicit grant" ์ต์ ์ ์ ํํ์ธ์.
- OAuth 2.0 Scopes: email, openid, profile.
Cognito Hosted UI ๋งํฌ์๋ ์ฌ๋ฌ URL ๋งค๊ฐ๋ณ์๊ฐ ํฌํจ๋์ด ์์ต๋๋ค.


7. ์๋๋ฆฌ์ค๋ ์ด๋ป๊ฒ ํ ์คํธํ๋์?
Cognito ์ฌ์ฉ์ ํ์ ์ฌ์ฉํ์ฌ ์ ํ๋ ์ก์ธ์ค๋ฅผ ํ์ฉํ๋ API๋ฅผ ํ
์คํธํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๋ชจ๋ ์ต์ข
์ฌ์ฉ์๋ ์ด ํ๋ก์ธ์ค๋ฅผ ์์ํ๊ธฐ ์ํด ๋งํฌ๋ฅผ ํด๋ฆญํ ์ ์์ต๋๋ค.
LinkToS3Files.html ํ์ผ์ ์ฌ์ฉํ์ฌ ์๋๋ฆฌ์ค๋ฅผ ํ
์คํธํ ์ ์์ต๋๋ค.๊ฒฐ๋ก
์ด ๋ฌธ์๊ฐ AWS ํด๋ผ์ฐ๋ ํ๊ฒฝ์ ์ฒ์ ์ ํ๋ ๋ถ๋ค์๊ฒ ์ ์ฉํ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
ํด๋ผ์ฐ๋ ์ปดํจํ ์๋น์ค
AWS, Azure ๋ฐ Google Cloud ํ๋ซํผ์์ ์ธํ๋ผ ์ค๊ณ, ๋ง์ด๊ทธ๋ ์ด์ , ๊ด๋ฆฌ ๋ฐ ์ต์ ํ ์๋น์ค๋ฅผ ์ ๊ณตํฉ๋๋ค.
์๋น์ค ๋ณด๊ธฐ๋ฌธ์ํ๊ธฐ
AWS ๋ฐ ํด๋ผ์ฐ๋ ์ปดํจํ ์๋ฃจ์ ์ ๋ํ ์์ธํ ์ ๋ณด๋ฅผ ์ป์ผ๋ ค๋ฉด ํ์ ๋ฌธ์ํ์ธ์.
๋ฌธ์