© 2017, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
4PTNZZeaZ
5JF
1B? :D EFD0 FH
• 5YN Z 7X a : Z 5JF @NYO N m
• @NYO N49 SR m
• @NYO N49 SR wn
• @NYO N49 SR
•
1B? a
N. California
Oregon Govcloud
Ohio
N. Virginia
São Paulo
Ireland
Frankfurt
Mumbai
Beijing
Seoul
Tokyo
Sydney
Montreal
London
Paris
Ningxia
Singapore
ERSU Z#
i 5M#
- 9 SR#
, - 1C U
()/ 1 #
https://aws.amazon.com/ko/about-aws/global-infrastructure/
Sweden
Hongkong
Bahrain
– Ue !
4 ?
o
44 ?
:
5YN Z
E a R -
5YN Z
7X a : Z
5JF
FTURX
5JF
J5:
9 SR @ PN U Z
1 DS L J F6N LP.
• U 4
•
• i
• GGD GGDF
• F i
• FF@ 7a Y FF@
• 2 FUSZR HE@ FUSZR 7 WUR
• 5D k 2 7X a G NUX v
1 DS L J F6N LP. a
• i GGD FR bR F 6aPWR #
• 7X a : Z C USUZ i DN T #
• C USUZ 6RTNbU 7NPTR RN R D UbN R 7 Z RZ g#
Custom Origin
EC2 instance
web app
server
Elastic/Application
Load Balancing
Amazon S3
Bucket
CloudFront
Distribution
/image /web_source /login /api
D111111abcdef8.cloudfront.net/
API Gateway
API Endpoint
g e/
t T
• wn 5 6 i 3
• 3
• h qh 3
• HE@ ’ r 3
• w w 3
d
1B? :D EFD
z
i
y
(), )) 5JF @NYO N
1B? :D EFD
SERVICES (ANYTHING)
데이터 상태
변경 시
엔드 포인트로
호출
자원 상태
변경 시
EVENT SOURCE FUNCTION
Node.js
Python
Java
C# 및
자체 라이브러리 패키징
다른 AWS서비스
실행
데이터 저장 및 분석
by s
B R V NbN De T Z 7
i
’ 5JF i
) 0A6 ) - 6#
7DH
d
ID7 5A
j i
s
JLF JL M D
IU aNXF a U #
b
Y
5JF F8?
… 1JIDO d
m v 5XUN
i
i … b
j v
7X a JN PT @ S
1B? :D EFD d
Lambda@Edge
• 5JF @NYO N
… l m g
d U wn
i
• B R F @NYO N
u i
• 7@@ n … A 8 u m
d d wn
j
:D EFD0 FH s !
Edge
Location
Edge
Location
Edge
Location
Edge
Location
Origin server
Edge
Location
Write once, run everywhere
:D EFD0 FH
@NYO N49 SR
CloudFront cache
End user
Origin
server
Viewer request Origin request
Origin responseViewer response
:D EFD0 FH
"config": {
"distributionId": "EXAMPLE”
},
"request": {
"uri": "/me.pic",
"method": "GET",
"httpVersion": "2.0",
"clientIp": "2001:cdba::3257:9652",
"headers": {
"User-Agent": ["Test Agent"],
"Host" : ["d2fadu0nynjpfn.cloudfront.net"]
}
}
:D EFD0 FH l
"config": {
"distributionId": "EDFDVBD6EXAMPLE ”
},
"response": {
"status": "200",
"statusDescription": "HTTP OK",
"httpVersion": "2.0",
"headers": {
"User-agent": [ "mozilla", "safari" ],
"Vary": [ "*" ]
}
…
:D EFD0 FH g /
.
•
x ’
. /
• p2 IURcR R aR
•
• ER aR R HE@
• 8RbUPR e R
U R H R 5SRZ #
• 9dU UZS R U Z N N
•
•
’ p
x
. s
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request,
userAgent = req.headers['User-Agent'] || '',
uri = req.uri,
i = uri.lastIndexOf('/'),
prefix = uri.slice(0, i);
let path = '/pc';
if(userAgent.some(e => e.includes(’Mobile'))) {
path = '/mobile';
}
req.uri = [uri.slice(0, i), path, uri.slide(i)].join('');
console.log(’Redirect to', req.uri, userAgent);
callbck(null, req);
}
. N PPR A :O
• w
HE@ z
HE@ x
• q
6 WRZ @UZW #
u
. N PPR A :O /
• G USSR 2 C USUZ R aR
•
• HE@ R aR R
•
• R aR R HE@ ’
• wn HE@ i
A 8 m
experts.handler = (event, content, callback) => {
const req = event.Records[0].cf.request;
if (/[A-Z]/.test(req.url)) {
cost old = req.uri
req.uri = req.uri.toLowerCase();
console.log(old, 'to lowercase', req.uri);
}
callback(null, req);
}
/2017/photos.png /2017/Photos.png
n
exports.handler = (event, context, callback) => {
const headers = event.Records[0].cf.response.headers;
const customHeaderName = 'X-Amz-Last-Modified';
const headerNameToBeChanged = 'Last-Modified';
if (headers[customHeaderName] !== undefined) {
headers[headerNameToBeChanged] = headers[customHeaderName];
}
callback(null, event.Records[0].cf.response);
};
}
Last-Modified X-Amz-Last-Modified
1 2
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
const headers = request.headers;
……
const expCookieName = 'X-Exp-Name=';
const A = 'A';
const B = 'B';
const AObject = '/experiment-group/control-pixel.jpg';
const BObject = '/experiment-group/treatment-pixel.jpg';
Cookie = header.Cookie
……
1 2
if (Cookie !== undefined) {
for (let i = 0; i < Cookie.length; i++) {
const expIndex = Cookie[i].indexOf(expCookieName);
if (expIndex > 0) {
if (Cookie[i][expIndex + expCookieName.length] === A) {
request.uri = AObject;
callback(null, request);
}
if (Cookie[i][expIndex + expCookieName.length] === B) {
request.uri = BObject;
callback(null, request);
}
}
}
U
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request,
const uri = req.uri.subString(req.uri.lastIndexOf('/'));
const video = uri.replace(/.(html|htm)$/, '.mp4');
const res = {
status: '200’,
statusDesscription: 'HTTP OK',
httpVersion: req.httpVersion,
headers: {
'Content-Type': ['text/html'],
'Content-Encoding': ['UTF-8'],
},
body: html.replace(${SOURCE}, video)
};
callback(null, res);
}
• 7 Z RZ FRPa U e D XUPe2
• F UP G NZ FRPa U e2 GGDF
l A GA xt #
• KFF D RP U Z2 KFF xt
k
z n U
F 9? d :D EFD
'use strict';
exports.handler = (event, context, callback) => {
const headers = event.Records[0].cf.response.headers;
headers['Strict-Transport-Security'] = [{key: "Strict-Transport-Security", value: "max-age=31..."}];
headers['Content-Security-Policy'] = [{key: "Content-Security-Policy", value: "default-src..."}];
headers['X-Content-Type-Options'] = [{key: "X-Content-Type-Options", value: "nosniff"}];
headers['X-Frame-Options'] = [{key: "X-Frame-Options", value: "DENY"}];
headers['X-XSS-Protection'] = [{key: "X-XSS-Protection", value: "1; mode=block"}];
headers['Referrer-Policy'] = [{key: "Referrer-Policy", value: "no-referrer"}];
callback(null, event.Records[0].cf.response);
};
https://tozny.com/blog/making-browser-crypto-safe/
https://tozny.com/blog/secure-https-headers-lambda
• i
• s i
• z i
7@@ ? Z
r
• C USUZ ER aR ER Z R
• IURcR ER aR ER Z R )
z
• ’ i
• ER XUPN j ER XUPN
u i #
u
• ) 0A6 x
• Y
p o
• j m p i
6 UZS e a cZ P R
• @NYO N s
i z i
• B R V . )(
m y J U R ZPR aZ RbR ecTR R#
• /1m
• j wn i …
i
GGD i
7X a : Z ’
a
wn x i
’ x
d
질문에 대한 답변 드립니다.
발표자료/녹화영상 제공합니다.
http://bit.ly/awskr-webinar
더 나은 세미나를 위해 여러분의
의견을 남겨 주세요!

AWS 9월 웨비나 | AWS Lambda@Edge를 통한 엣지 컴퓨팅 서비스

  • 1.
    © 2017, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. 4PTNZZeaZ 5JF 1B? :D EFD0 FH
  • 2.
    • 5YN Z7X a : Z 5JF @NYO N m • @NYO N49 SR m • @NYO N49 SR wn • @NYO N49 SR •
  • 4.
    1B? a N. California OregonGovcloud Ohio N. Virginia São Paulo Ireland Frankfurt Mumbai Beijing Seoul Tokyo Sydney Montreal London Paris Ningxia Singapore ERSU Z# i 5M# - 9 SR# , - 1C U ()/ 1 # https://aws.amazon.com/ko/about-aws/global-infrastructure/ Sweden Hongkong Bahrain
  • 5.
    – Ue ! 4? o 44 ? : 5YN Z E a R - 5YN Z 7X a : Z 5JF FTURX 5JF J5: 9 SR @ PN U Z
  • 6.
    1 DS LJ F6N LP. • U 4 • • i • GGD GGDF • F i • FF@ 7a Y FF@ • 2 FUSZR HE@ FUSZR 7 WUR • 5D k 2 7X a G NUX v
  • 7.
    1 DS LJ F6N LP. a • i GGD FR bR F 6aPWR # • 7X a : Z C USUZ i DN T # • C USUZ 6RTNbU 7NPTR RN R D UbN R 7 Z RZ g# Custom Origin EC2 instance web app server Elastic/Application Load Balancing Amazon S3 Bucket CloudFront Distribution /image /web_source /login /api D111111abcdef8.cloudfront.net/ API Gateway API Endpoint
  • 8.
  • 9.
    t T • wn5 6 i 3 • 3 • h qh 3 • HE@ ’ r 3 • w w 3
  • 10.
  • 11.
    1B? :D EFD z i y (),)) 5JF @NYO N
  • 12.
    1B? :D EFD SERVICES(ANYTHING) 데이터 상태 변경 시 엔드 포인트로 호출 자원 상태 변경 시 EVENT SOURCE FUNCTION Node.js Python Java C# 및 자체 라이브러리 패키징 다른 AWS서비스 실행 데이터 저장 및 분석
  • 13.
    by s B RV NbN De T Z 7 i ’ 5JF i ) 0A6 ) - 6# 7DH d ID7 5A j i s JLF JL M D IU aNXF a U # b Y 5JF F8? … 1JIDO d m v 5XUN i i … b j v 7X a JN PT @ S 1B? :D EFD d
  • 14.
    Lambda@Edge • 5JF @NYON … l m g d U wn i • B R F @NYO N u i • 7@@ n … A 8 u m d d wn j
  • 15.
    :D EFD0 FHs ! Edge Location Edge Location Edge Location Edge Location Origin server Edge Location Write once, run everywhere
  • 16.
    :D EFD0 FH @NYON49 SR CloudFront cache End user Origin server Viewer request Origin request Origin responseViewer response
  • 17.
    :D EFD0 FH "config":{ "distributionId": "EXAMPLE” }, "request": { "uri": "/me.pic", "method": "GET", "httpVersion": "2.0", "clientIp": "2001:cdba::3257:9652", "headers": { "User-Agent": ["Test Agent"], "Host" : ["d2fadu0nynjpfn.cloudfront.net"] } }
  • 18.
    :D EFD0 FHl "config": { "distributionId": "EDFDVBD6EXAMPLE ” }, "response": { "status": "200", "statusDescription": "HTTP OK", "httpVersion": "2.0", "headers": { "User-agent": [ "mozilla", "safari" ], "Vary": [ "*" ] } …
  • 20.
  • 21.
  • 22.
    . / • p2IURcR R aR • • ER aR R HE@ • 8RbUPR e R U R H R 5SRZ # • 9dU UZS R U Z N N • • ’ p x
  • 23.
    . s exports.handler =(event, context, callback) => { const request = event.Records[0].cf.request, userAgent = req.headers['User-Agent'] || '', uri = req.uri, i = uri.lastIndexOf('/'), prefix = uri.slice(0, i); let path = '/pc'; if(userAgent.some(e => e.includes(’Mobile'))) { path = '/mobile'; } req.uri = [uri.slice(0, i), path, uri.slide(i)].join(''); console.log(’Redirect to', req.uri, userAgent); callbck(null, req); }
  • 24.
    . N PPRA :O • w HE@ z HE@ x • q 6 WRZ @UZW # u
  • 25.
    . N PPRA :O / • G USSR 2 C USUZ R aR • • HE@ R aR R • • R aR R HE@ ’ • wn HE@ i
  • 27.
    A 8 m experts.handler= (event, content, callback) => { const req = event.Records[0].cf.request; if (/[A-Z]/.test(req.url)) { cost old = req.uri req.uri = req.uri.toLowerCase(); console.log(old, 'to lowercase', req.uri); } callback(null, req); } /2017/photos.png /2017/Photos.png
  • 28.
    n exports.handler = (event,context, callback) => { const headers = event.Records[0].cf.response.headers; const customHeaderName = 'X-Amz-Last-Modified'; const headerNameToBeChanged = 'Last-Modified'; if (headers[customHeaderName] !== undefined) { headers[headerNameToBeChanged] = headers[customHeaderName]; } callback(null, event.Records[0].cf.response); }; } Last-Modified X-Amz-Last-Modified
  • 29.
    1 2 exports.handler =(event, context, callback) => { const request = event.Records[0].cf.request; const headers = request.headers; …… const expCookieName = 'X-Exp-Name='; const A = 'A'; const B = 'B'; const AObject = '/experiment-group/control-pixel.jpg'; const BObject = '/experiment-group/treatment-pixel.jpg'; Cookie = header.Cookie ……
  • 30.
    1 2 if (Cookie!== undefined) { for (let i = 0; i < Cookie.length; i++) { const expIndex = Cookie[i].indexOf(expCookieName); if (expIndex > 0) { if (Cookie[i][expIndex + expCookieName.length] === A) { request.uri = AObject; callback(null, request); } if (Cookie[i][expIndex + expCookieName.length] === B) { request.uri = BObject; callback(null, request); } } }
  • 31.
    U exports.handler = (event,context, callback) => { const request = event.Records[0].cf.request, const uri = req.uri.subString(req.uri.lastIndexOf('/')); const video = uri.replace(/.(html|htm)$/, '.mp4'); const res = { status: '200’, statusDesscription: 'HTTP OK', httpVersion: req.httpVersion, headers: { 'Content-Type': ['text/html'], 'Content-Encoding': ['UTF-8'], }, body: html.replace(${SOURCE}, video) }; callback(null, res); }
  • 32.
    • 7 ZRZ FRPa U e D XUPe2 • F UP G NZ FRPa U e2 GGDF l A GA xt # • KFF D RP U Z2 KFF xt k z n U
  • 33.
    F 9? d:D EFD 'use strict'; exports.handler = (event, context, callback) => { const headers = event.Records[0].cf.response.headers; headers['Strict-Transport-Security'] = [{key: "Strict-Transport-Security", value: "max-age=31..."}]; headers['Content-Security-Policy'] = [{key: "Content-Security-Policy", value: "default-src..."}]; headers['X-Content-Type-Options'] = [{key: "X-Content-Type-Options", value: "nosniff"}]; headers['X-Frame-Options'] = [{key: "X-Frame-Options", value: "DENY"}]; headers['X-XSS-Protection'] = [{key: "X-XSS-Protection", value: "1; mode=block"}]; headers['Referrer-Policy'] = [{key: "Referrer-Policy", value: "no-referrer"}]; callback(null, event.Records[0].cf.response); }; https://tozny.com/blog/making-browser-crypto-safe/ https://tozny.com/blog/secure-https-headers-lambda • i • s i • z i
  • 34.
  • 35.
    r • C USUZER aR ER Z R • IURcR ER aR ER Z R ) z • ’ i • ER XUPN j ER XUPN u i # u • ) 0A6 x • Y p o • j m p i
  • 36.
    6 UZS ea cZ P R • @NYO N s i z i • B R V . )( m y J U R ZPR aZ RbR ecTR R# • /1m • j wn i … i GGD i 7X a : Z ’ a wn x i ’ x d
  • 37.
    질문에 대한 답변드립니다. 발표자료/녹화영상 제공합니다. http://bit.ly/awskr-webinar 더 나은 세미나를 위해 여러분의 의견을 남겨 주세요!