Browsing Tag

AWS

NCP

[NCP] 삶의 질을 높여주는 Image Optimizer를 이용한 이미지 리사이징

안녕하세요. ManVSCloud 김수현입니다.

오늘은 Image Optimizer에 대한 포스팅을 해보았습니다.
Image Optimizer에 대한 글은 이미 네이버 클라우드 플랫폼에서도 많은 글과 영상으로 만들어두어 접근하기 쉬운 상태입니다.

제가 직접 Image Optimizer를 사용해본 소감에 대해 써보았으니 사용 전에 어떻게 사용하면 좋을지 참고하실 때 도움되리라 생각됩니다.


왜 Naver Cloud Platform의 IMAGE OPTIMIZER인가?

  • 쉬운 사용법
    (크기, 워터마크, 필터 등 UI를 통해 원하는 효과를 체크하고 수치만 입력하면 됩니다.)
    ([예시 보기]가 있어 예시를 통해 쉽게 사용할 수 있습니다.)
  • 미리 보기 제공
    (미리 보기를 제공하여 조금 더 간편함을 느낄 수 있었습니다.)
  • 콘솔에서 효과 추가
    (콘솔에서 원하는 효과만 선택하여 넣는 방식입니다.)

타 클라우드를 이용한 이미지 리사이징 경험

우선 이미지 리사이징에 대한 경험은 크게 네이버 클라우드 플랫폼과 AWS 에서 사용해보았습니다. AWS에서는 이미지 자동 리사이징을 진행해보았으며 Azure 역시 Azure Event Grid를 이용하여 이미지 리사이징이 가능한 것을 금방 찾을 수 있었습니다.

개발자가 아닌 입장에서 코드 개발 부분이 정말 막막했었습니다.

물론 이미지 자동 리사이징을 이용하여 이미지 사이즈가 고정적이지 않을 경우 개발적인 부분이 사용될 수 밖에 없겠지만 이미지 사이즈가 고정적으로 정해져있는 상태에서 빠르게 추가하는 방식으로 사용할 수는 없을까라는 생각을 하게되었습니다.

네이버 클라우드에서 Image Optimizer 서비스를 이용하면 가능합니다.
물론 자동 리사이징의 경우 동일하게 개발적인 요소가 사용되겠지만 Image Optimizer를 이용한다면 고정적인 사이즈에 대해서 리사이징은 충분히 쉽게 가능하겠다라고 생각했습니다.


Image Optimizer를 이용한 이미지 리사이징

🏆 Object Storage

우선 Object Storage를 생성해주어야합니다.
Object Storage에 이미지를 업로드 하고 Image Optimizer를 이용하여 해당 이미지에 여러 효과를 줘보도록 하겠습니다.

버킷 이름은 고유합니다.
원하시는 고유한 버킷 이름을 정해주도록 합시다.
파일에 대한 공개 여부를 설정하는 곳입니다.
생성한 Bucket에 이미지를 리사이징 할 이미지를 업로드 해줍시다.

image 라는 폴더를 하나 생성한 후 image 폴더 안에 이미지를 업로드 했고
해당 폴더를 공개하여 외부에서 접근할 수 있도록 해주었습니다.


🎨 Image Optimizer

이제 Image Optimizer를 생성해줄 차례입니다.

Image Optimizer 프로젝트를 생성해주고 프로젝트 이름을 입력한 뒤
원본 이미지 저장소는 위에서 만들어준 Object Storage를 선택해줍시다.

서비스 프로토콜과 서비스 도메인을 정해주어야합니다.

“고객 보유 도메인”을 선택할 경우 당연히 DNS와 연결도 해주어야합니다.
그리고 HTTP로 하니까 계속 오류가 발생해서 HTTPS로 설정해주었습니다.
HTTP로 설정하니까 CDN 도메인 접속 시 이미지를 정상적으로 불러오지 못해서 이런저런 테스트를 해봤는데 HTTPS에서만 정상 접근이 가능하다는 걸 알게됐습니다.
(음?.. HTTP는 왜 있는거지..? 내가 설정을 잘못한 부분이 있는건가..?)

위 이미지 처럼 다음 및 생성을 해주고 최종 설정은 다음과 같이 설정했습니다.
HTTP에서 이미지를 정상적으로 못불러와서 ALL로 설정하고 HTTPS에서 정상 이미지 출력이 확인되었습니다.

자, 그럼 이제 쿼리스트링을 만들어 봅시다.

크기, 워터마크, 필터 별로 원하는 쿼리스트링을 만들 수 있습니다.
리사이즈를 해주고 가로,세로 길이 변경 및 품질을 변경해줬으며 흑백으로 출력되도록 해줬습니다.
이게 참 마음에 들었던 게 이대로 클릭하고 수치만 입력했는데 쿼리스트링이 자동으로 만들어져서 자동 입력된다는게 좋았습니다.
쿼리스트링 입력 후 생성된 부분에 대해 변환 이미지 미리보기를 실행할 수 있습니다.
미리보기 결과입니다. 멋지지않나요?

미리 보기와 같이 이미지가 실제로 잘 반영되었을지 URL로 접속하여 결과를 보도록하겠습니다.


Result

제가 원하는대로 이미지가 잘 변환되었습니다.
잘 출력됐네요.

하지만 Image Optimizer에 등록되지 않은 쿼리스트링을 사용할 경우 404 Error가 발생하게됩니다.

쿼리스트링을 수동으로 입력하지 않고 자동으로 이미지를 변환하기 위해서는 Cloud Functions을 사용해야할 것으로 보입니다.


Personal Comments

Image Optimizer에 대한 포스팅을 8월부터 준비중이었으나 8월 말에 네이버 클라우드 플랫폼 공식 블로그에서 Image Optimizer에 대한 포스팅이 먼저 올라왔습니다.

아래 포스팅에서 이미 기능적인 설명이 다 적혀져있어서 오늘 포스팅은 기능적인 부분은 제외하고 AWS에서 이렇게 사용해봤는데 이런 경우엔 네이버 클라우드의 Image Optimizer가 좋은 것같다라는 경험을 이야기 해보고싶었습니다.

아래 네이버 클라우드 플랫폼 공식 블로그에 포스팅된 Image Optimizer에 대한 글도 참고하면 훨씬 사용에 도움될 것입니다.


NCP

[NCP] AWS to NCloud Server Migration – #2편

안녕하세요. ManVSCloud 김수현입니다.

오늘 “AWS TO NCLOUD SERVER MIGRATION – #2편”에서는 간단한 Install과 제가 기본적으로 설정하는 설정값들을 보여드리며 정보를 공유하고자 합니다.


Base Install

[root@manvscloud-web-pub-kr1 ~]# cat /etc/redhat-release
CentOS Linux release 7.8.2003 (Core)

“[NCP] AWS TO NCLOUD SERVER MIGRATION – #1편”에서 생성한 서버에 기본 설치와 설정 작업을 진행하기로 했습니다.

🧩 Nginx 설치
vi /etc/yum.repos.d/Nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
[root@manvscloud-web-pub-kr1 ~]# yum install nginx -y

CentOS 7에서는 위와 같이 repo를 추가 후 설치를 진행하면 설치간에 큰 어려움은 없을 것입니다.

이후 LB를 붙이면 Nginx Access Log에서 LB의 로그로 나오기때문에 Client IP를 보기 위해서는 nginx -V 2>&1 | grep ‘http_realip_module’ 로 확인하여 http_realip_module이 있는지 확인이 되어야합니다.

RPM 설치 시 이 모듈이 들어가있는데 컴파일로 설치를 진행할 경우 이 부분을 잘 체크해주셔야합니다.

[root@manvscloud-web-pub-kr1 ~]# nginx -V 2>&1 | grep 'http_realip_module'
configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-compat --with-debug --with-file-aio --with-google_perftools_module --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_mp4_module --with-http_perl_module=dynamic --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_xslt_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E'
🔮 PHP 설치
[root@manvscloud-web-pub-kr1 src]# yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
[root@manvscloud-web-pub-kr1 src]# yum -y install epel-release yum-utils
[root@manvscloud-web-pub-kr1 src]# yum-config-manager --disable remi-php54
[root@manvscloud-web-pub-kr1 src]# yum-config-manager --enable remi-php74
[root@manvscloud-web-pub-kr1 src]# yum install -y php php-json php-cli php-gd php-pear php-common php-mysqlnd php-fpm php-mbstring php-opcache php-process php-xmlrpc php-pdo php-xml php-bcmath php-devel php-zip php-mcrypt
[root@manvscloud-web-pub-kr1 src]# yum groupinstall " Development Tools" -y
[root@manvscloud-web-pub-kr1 src]# yum install ImageMagick ImageMagick-devel -y
[root@manvscloud-web-pub-kr1 src]# pecl install imagick
[root@manvscloud-web-pub-kr1 src]# echo "extension=imagick.so" >> /etc/php.ini
[root@manvscloud-web-pub-kr1 src]# systemctl enable php-fpm
[root@manvscloud-web-pub-kr1 src]# systemctl start php-fpm

PHP는 remi를 이용하여 설치를 진행했습니다.
Migration할 때 주의할 점 중 하나는 PHP의 모듈을 맞춰주는 것입니다.
기존 서버와 이전하는 서버에서 php -m 로 확인해줍시다.

🧿 MariaDB 설치
vi /etc/yum.repos.d/MariaDB.repo
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.5/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
yum install MariaDB-server MariaDB-client -y

MariaDB도 repo만 추가해주면 쉽게 설치할 수 있습니다.
MariaDB의 버전은 baseurl 부분에서 10.5 부분을 원하시는 버전으로 변경하면 원하시는 버전으로 설치가 가능합니다.

🎫 Memcached

Memcached의 경우 개인 사이트 운영에 큰 효과를 가져다주지 못한다는 평이 있었으나 개인 블로그 용도뿐만 아니라 다양한 테스트를 해볼 예정이기에 memcached를 도입하기로 했습니다.

[root@manvscloud-web-pub-kr1 ~]# yum clean all
[root@manvscloud-web-pub-kr1 ~]# yum update -y
[root@manvscloud-web-pub-kr1 ~]# yum install memcached -y
[root@manvscloud-web-pub-kr1 ~]# cat /etc/sysconfig/memcached 
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS=""

/etc/sysconfig/memcached 값을 아래와 같이 변경해주었습니다.

[root@manvscloud-web-pub-kr1 ~]# cp -avp /etc/sysconfig/memcached /etc/sysconfig/memcached_org
[root@manvscloud-web-pub-kr1 ~]# vi /etc/sysconfig/memcached
PORT="11111"
USER="memcached"
MAXCONN="2048"
CACHESIZE="4096"
OPTIONS=""

[root@manvscloud-web-pub-kr1 ~]# systemctl enable memcached
[root@manvscloud-web-pub-kr1 ~]# systemctl start memcached

php-memcached도 설치해줍시다!

[root@manvscloud-web-pub-kr1 ~]# yum install php-memcached -y

php.ini를 보면 session.save_handler가 files로 되어있습니다.

이를 memcached로 변경해줄 것입니다.
아래처럼 작업을 진행할 수 있습니다.

[root@manvscloud-web-pub-kr1 ~]# cp -avp /etc/php.ini /etc/php.ini_org
[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/php.ini | grep -E "session.save_handler|session.save_path"
  1214	session.save_handler = files
  1222	;     session.save_path = "N;/path"
  1238	;     session.save_path = "N;MODE;/path"
  1247	;session.save_path = "/tmp"
  1332	;       (see session.save_path above), then garbage collection does *not*
[root@manvscloud-web-pub-kr1 ~]# sed -i '1214s/files/memcached/g' /etc/php.ini
[root@manvscloud-web-pub-kr1 ~]# perl -p -i -e '$.==1222 and print "session.save_path = \"127.0.0.1:11111\"\n"' /etc/php.ini
[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/php.ini | grep -E "session.save_handler|session.save_path "
  1214	session.save_handler = memcached
  1222	session.save_path = "127.0.0.1:11111"
  1223	;     session.save_path = "N;/path"
  1239	;     session.save_path = "N;MODE;/path"
  1248	;session.save_path = "/tmp"
  1333	;       (see session.save_path above), then garbage collection does *not*
[root@manvscloud-web-pub-kr1 ~]# systemctl restart memcached
[root@manvscloud-web-pub-kr1 ~]# systemctl restart php-fpm

그냥 블로그만 운영하던 서버다보니 크게 설치할 것들이 별로 없습니다.
이제 기본 세팅만 진행해보도록 합시다.


Default Settings

우선 sshd 설정을 먼저 진행하기로 했습니다.
설정 조건은 아래와 같습니다.

  • SSH 포트를 22에서 15222로 변경할 것
  • manvscloud 사용자 생성 및 sudo로 root권한 사용
  • root로 바로 접속할 수 없도록 설정
  • 접속 시 Password가 아닌 Public Key 파일을 이용하여 로그인
[root@manvscloud-web-pub-kr1 ~]# useradd manvscloud
// 먼저 서버에 key 파일을 업로드 한 뒤 작업을 진행하였습니다.

[root@manvscloud-web-pub-kr1 ~]# chmod 400 manvscloud.pem
[root@manvscloud-web-pub-kr1 ~]# mkdir /home/manvscloud/.ssh
[root@manvscloud-web-pub-kr1 ~]# ssh-keygen -y -f manvscloud.pem > /home/manvscloud/.ssh/authorized_keys
[root@manvscloud-web-pub-kr1 ~]# chown -R manvscloud:manvscloud /home/manvscloud/.ssh
[root@manvscloud-web-pub-kr1 ~]# chmod 700 /home/manvscloud/.ssh
[root@manvscloud-web-pub-kr1 ~]# chmod 600 /home/manvscloud/.ssh/authorized_keys

[root@manvscloud-web-pub-kr1 ~]# id manvscloud
uid=1001(manvscloud) gid=1001(manvscloud) groups=1001(manvscloud)
[root@manvscloud-web-pub-kr1 ~]# gpasswd -a manvscloud wheel
Adding user manvscloud to group wheel
[root@manvscloud-web-pub-kr1 ~]# gpasswd -a manvscloud systemd-journal
Adding user manvscloud to group systemd-journal

[root@manvscloud-web-pub-kr1 ~]# grep -E "wheel|systemd-journal" /etc/group
wheel:x:10:manvscloud
systemd-journal:x:190:manvscloud

[root@manvscloud-web-pub-kr1 ~]# cat << EOF > /etc/sudoers.d/10-manvscloud-users
> # User rules for manvscloud
> manvscloud ALL=(ALL) NOPASSWD:ALL
> EOF
[root@manvscloud-web-pub-kr1 ~]# chmod 440 /etc/sudoers.d/10-manvscloud-users
[root@manvscloud-web-pub-kr1 ~]# passwd -l root
Locking password for user root.
passwd: Success

///etc/ssh/sshd_config 파일 수정

[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/ssh/sshd_config  | grep -E "Port|PermitRootLogin|PasswordAuthentication"
    17	#Port 22
    38	PermitRootLogin yes
    63	#PasswordAuthentication yes
    65	PasswordAuthentication yes
    88	# PasswordAuthentication.  Depending on your PAM configuration,
    90	# the setting of "PermitRootLogin without-password".
    92	# PAM authentication, then enable this but set PasswordAuthentication
   100	#GatewayPorts no


[root@manvscloud-web-pub-kr1 ~]# cp -avp /etc/ssh/sshd_config /etc/ssh/sshd_config_org
[root@manvscloud-web-pub-kr1 ~]# sed -i '38s/yes/no/g' /etc/ssh/sshd_config
[root@manvscloud-web-pub-kr1 ~]# sed -i '65s/yes/no/g' /etc/ssh/sshd_config
[root@manvscloud-web-pub-kr1 ~]# perl -p -i -e '$.==17 and print " Port 15222\n"' /etc/ssh/sshd_config

[root@manvscloud-web-pub-kr1 ~]# systemctl restart sshd

다음은 php설정을 해줄 것입니다.

우선 php.ini 파일과 www.conf 파일을 수정할건데 pm 값을 조정하는 최적화 작업은 기본 설정에서 제외하였습니다.

php.ini파일에서는 아래와 같이 값을 변경해주었습니다.

   date.timezone = "Asia/Seoul"
   expose_php = Off
   short_open_tag = On
   allow_url_fopen = Off
   max_execution_time = 60
   memory_limit = 128M

이번 이전에서 포인트로 정한 php-fpm의 파일 소켓 통신을 설정하는 부분입니다.
www.conf에서 기존 listen이 127.0.0.1:9000로 TCP/IP 소켓 통신이 기본값인데 이를 /run/php-fpm/www.sock 으로 변경하여 Unix Socket 통신이 되도록 하였습니다.

[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/php-fpm.d/www.conf | grep listen | grep -v ";"
    38	listen = 127.0.0.1:9000
    64	listen.allowed_clients = 127.0.0.1
[root@manvscloud-web-pub-kr1 ~]# sed -i '38s$127.0.0.1:9000$/run/php-fpm/www.sock$g' /etc/php-fpm.d/www.conf
[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/php-fpm.d/www.conf | grep listen | grep -v ";"
    38	listen = /run/php-fpm/www.sock
    64	listen.allowed_clients = 127.0.0.1

이 Unix Socket 방식은 TCP의 소켓과 동일하게 API로 데이터를 주고받을 수 있는데 이는 로컬 파일 기반 소켓이라서 Nginx와 함께 쓰기 위해 php-fpm를 같은 로컬내에 존재하도록 하였습니다. 이 방식은 localhost 내에 프로세스 간 통신이라 속도도 우월하고 메모리 소모를 줄일 수 있습니다.

📄 nofile 설정
vi /etc/security/limits.conf
*               soft    nofile          65535
*               hard    nofile          65535

위 설정을 해주지 않으면 파일 열기 최대 개수가 soft/1024, hard/4096이 default인 것으로 기억합니다.

💿 History
[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/profile | grep HISTFILESIZE
    78	HISTFILESIZE=0
[root@manvscloud-web-pub-kr1 ~]# sed -i '78s/0/5000/g' /etc/profile
[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/profile | grep HISTFILESIZE
    78	HISTFILESIZE=5000
[root@manvscloud-web-pub-kr1 ~]# echo export HISTTIMEFORMAT=\"[%F %T] \" > /etc/profile.d/bash_history.sh
[root@manvscloud-web-pub-kr1 ~]# chmod 755 /etc/profile.d/bash_history.sh
[root@manvscloud-web-pub-kr1 ~]# init 6

저는 history를 자주 이용하는 편입니다.
그런데 기본 설정을 하고 다음 날 서버에 접속했는데 history가 하나도 남아있지 않아 확인해보니 HISTFILESIZE가 0으로 되어있어 이를 변경해주기로 하였습니다.

값을 5000으로 변경해주고 HISTTIMEFORMAT을 주어 history에 시간대도 확인할 수 있도록 설정해두었습니다.

Nginx와 MariaDB 설정은 다음 #3편에서 스토리지 추가 및 NAS 연결과 함께 설정을 진행할 것입니다.


Personal Comments

#3편에서는 “ManVSCloud 신규 Architecture” 공개와 함께 스토리지 추가 및 NAS 연결에 대한 포스팅을 진행할 것입니다.

제가 이번에 진행하는 AWS to NCloud 이전 작업에서 설정되는 부분이나 이렇게 이전이 될 수도 있구나하는 걸 재밌게 봐주셨으면 합니다.

긴 글 읽어주셔서 감사합니다.


NCP

[NCP] AWS to NCloud Server Migration – #1편

안녕하세요. ManVSCloud 김수현입니다.

이미지 출처 : https://www.mk.co.kr/news/it/view/2021/08/819941/

네이버 클라우드의 빠른 성장이 지속되고 있습니다.
현재 국내 클라우드 기업중 네이버 클라우드가 독보적으로No.1이라 봅니다.

올해 7월 네이버 클라우드는 공공기관 시장에서 97.64%의 점유율의 성적을 보이며
왜 네이버 클라우드인지 증명해냈습니다.

제 manvscloud.com 블로그도 이제 AWS를 떠나 네이버 클라우드 플랫폼으로 이전하게 되었습니다.

현재 전체적인 환경을 파악하고 있으며 네이버 클라우드 플랫폼에서는 기존 AWS에서 사용하던 아키텍처와 다르게 사용하고 싶어 새로운 아키텍처를 구상하고 있습니다.

네이버 클라우드 플랫폼의 기술력과 발전 가능성을 고려해본다면 먼저 네이버 클라우드를 시작하고 싶다라는 생각이 듭니다.


AWS Env

우선 네이버 클라우드 플랫폼으로 이전하기 전에 기존 AWS 환경에서 구성되어있던 아키텍처와 인스턴스 내 각 서비스들의 버전들을 파악하기로 했습니다.

먼저 기존 아키텍처는 예전에 만들어둔 것으로 가져왔습니다.
조금 추가된 부분이 있다면 AWS 한국 리전에서는 SNS에서 SMS 기능을 선택할 수 없습니다. 그렇기 때문에 추가적인 Lambda 작업이 있었습니다…

(네이버 클라우드는 따로 추가적인 작업없이 간단하게 모니터링 설정에서 SMS 문자 알림을 받을 수 있도록 설정할 수 있기에 이런 고통에서 벗어날 수 있게 되었습니다…😂)

[root@ip-10-0-1-68 ~]# cat /etc/*-release
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"
Amazon Linux release 2 (Karoo)

Linux 버전은 Amazon Linux AMI 2 를 사용하고 있었습니다.
네이버 클라우드로 이전하게 되면 CentOS 7을 사용할 것입니다.
원래 Rocky Linux 8을 써보고 싶었지만 아직 Rocky Linux 소식이 없어 CentOS 7로 결정하게 되었습니다.

[root@ip-10-0-1-68 home]# apachectl -v
Server version: Apache/2.4.46 ()
Server built:   Aug 24 2020 18:54:20

[root@ip-10-0-1-68 home]# php -v
PHP 7.4.15 (cli) (built: Feb 11 2021 17:53:39) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.15, Copyright (c), by Zend Technologies

두번째로 제 블로그는 APM으로 구성되어 있는데 이번 기회에 Apache에서 Nginx로 변경을 결정했습니다. 또한 Nginx 와 php 간에 TCP Socket을 사용하지 않고 Unix Socket을 사용해볼 것입니다. 이는 제가 늘 보고 배우는 Linuxer 님의 Blog를 보고 저도 이를 적용해보기로 마음먹게 되었습니다.

마지막으로 DB입니다. 원래 아키텍처는 WEB과 DB가 나뉘어져 있었습니다.
단, 인스턴스 하나가 죽으면 서비스가 마비가 되어 이번에 네이버 클라우드로 이전하면 WEB과 DB를 하나의 서버로 쓰되 이중화를 구성하기로 했습니다.

최종적으로 아키텍처가 완성되면 추가 블로깅 및 설명해볼 것입니다.


Naver Cloud Platform, Resource Creation

🌏 VPC
manvscloud-vpc
subnet

VPC를 구성하는 부분은 이제 너무 쉬우니 이렇게 구성했습니다!만 보여주고 넘어가도록 하겠습니다.

💻Server
server creation

서버는 하나만 생성해두었습니다.

서버 하나에 기본적인 설치 및 구성을 끝내두고 이미지를 생성하여 생성한 이미지를 이용하여 이중화를 구성할 것입니다.

참고로 오늘은 “AWS TO NCLOUD SERVER MIGRATION”에 대한 전반적인 느낌만 잡아가는 포스팅이며 추가 포스팅에서 완성된 아키텍처와 함께 어떻게 설치가되고 이전을 어떤 방식으로 진행했는지도 함께 적어볼 것입니다.

💾 Object Storage + Global CDN

현재 고민 중인 부분은 cdn을 어떻게 해결할까에 대한 부분입니다.
기존 AWS S3에 생각보다 많은 데이터가 쌓이게 되었고 이를 Object Storage에 넘겨준 뒤 나중에 DB에서도 수정해줘야하는 부분이 있기도 하고 기존에 CDN을 사용하고 있는 방식이 WordPress의 AWS 플러그인이라 이 부분이 잘 될지 확신이 되지 않기에 CDN은 조금 테스트를 진행해본 뒤 결정하게 될 것같습니다.


Personal Comments

이전을 진행하며 조금이나마 이런 기능을 만들어주었으면 좋겠다고 생각되는 부분이 있어
오늘은 네이버 클라우드에 바라는 점이 있다면 몇가지를 써보도록 하겠습니다.

  • SSL 인증서
    : Certificate Manager라는 서비스가 있는데 이는 외부에서 구매한 인증서를 입력하고 추가하는 것이라 추가적인 절차가 필요합니다.
    AWS의 ACM과 같은 서비스가 어서 생겼으면 좋겠습니다.
    (이 기능이 AWS를 사용하는동안 생각보다 매우 편리했기에 네이버 클라우드에도 도입되길 바랍니다.)
  • WAF
    : 네이버 클라우드에서 WAF를 사용하려면 Security Monitoring 라는 서비스에서 [이용 문의]를 통해서 사용이 가능합니다. 아직 AWS WAF처럼 사용자 선택하고 Count/Block 하는 방식이 아닌 신청해서 사용하는 방식으로 보입니다. 물론 네이버 클라우드 플랫폼의 WAF는 주간/월간 보고서 등의 장점도 있지만 사용자 지정 방식의 WAF도 생기다면 부담스럽지 않게 사용해볼 수 있을 것같습니다.
  • 주기적인 이미지/스냅샷 관리
    : 이미지/스냅샷을 사용자가 직접 백업 일정을 지정하고 진행하는 기능이 아직 없습니다.
    물론 Cloud Functions을 이용하면 해서 이런 기능을 만들 수는 있겠지만 개발자가 아닐 경우 난감할 수 있겠다 생각됩니다.
    그렇기 때문에 네이버 클라우드에서는 Backup이라는 서비스를 제공합니다.
    네이버 클라우드에서 직접 고객의 데이터를 백업해주고 보관해주는 서비스인데 상당히 괜찮습니다. 이 서비스만 신청해두면 사실 고객 입장에서는 직접적인 백업 관리를 하지 않아도 되니 용량별 비용만 고려하면 되어 오히려 편할 수 있습니다.

네이버 클라우드 플랫폼은 늘 빠른 업데이트와 기능 추가를 하고 있어 이러한 사용자들의 의견만 있다면 위 기능들 역시 금방 생길 거라 봅니다.

긴 글 읽어주셔서 감사합니다.


IT/Linux/Kubernetes

[AKOS] Amazon EKS Study 시작

안녕하세요. ManVSCloud 김수현입니다.

오늘부터 CloudNet@에서 진행하는 AKOS(AWS Kubernetes Online Study)가 시작되었습니다. 2020년도는 Linuxer님, 2021년도는 가시다(Gasida)님과 함께하고 있습니다.

Kubernetes 스터디도 함께 했고 현재는 AWS의 EKS를 공부하고 있으며
Naver Cloud Platform의 NKS는 아마 따로 공부하게 될 것같습니다.


AWS Kubernetes Online Study

이전에 했던 DKOS(Docker Kubernetes Online Study)에 이어 AKOS(AWS Kubernetes Online Study)는 이제 배웠던 Kubernetes 과정을 이해한 뒤 AWS에서의 Kubernetes를 배워보는 시간이었습니다.

클러스터 구축
파드 생성 및 확인
RDS DB 확인

개인적으로 저는 이미 클라우드 환경에서는 AWS보다 Naver Cloud Platform을 이용해 Kubernetes를 먼저 사용해보았기 때문에 NKS가 조금 더 편하게 느껴졌습니다.

사용하기 편하고 쉬운건 Naver Cloud Platform의 NKS고 활용할 수 있는 범위는 넓은데 난이도가 높은 건 AWS의 EKS라고 해야하나? 개인적으로 그렇게 느껴졌습니다.

네이버 클라우드 플랫폼에서는 기본적으로 서비스를 만들 때 사용자가 편하게 사용할 수 있도록 배려하는 부분이 많다보니 아직 기능적인 부분에서는 다소 추가되어야할 부분이 있으나 추가된 이후가 기대되기는 합니다.


Personal Comments

끊임없이 공부하는 습관은 엔지니어에게 정말 좋은 습관이라고 생각합니다.
물론 부하가 생기지 않도록 컨디션 조절도 중요하지만요…

스케줄을 너무 가득 채워서 많은 것을 흡수 하려고 하면 오히려 번아웃이 한 번 찾아와 다시 시작하기가 너무 힘들더라구요.

오늘도 공부하는 엔지니어 분들 수고가 많으십니다.
과하게 하지말고 꾸준히 합시다.

긴 글 읽어주셔서 감사합니다.

AWS

[AWS] 수명 주기 관리자를 활용한 스냅샷 백업 (Lifecycle Manager)

안녕하세요. ManVSCloud 김수현입니다.

오늘은 오랜만에 AWS에 관련된 포스팅을 작성해보려 하는데
수명 주기 관리자를 이용하여 스냅샷을 관리하는 방법을 알아보도록 하겠습니다.


수명 주기 관리자 (LIFECYCLE MANAGER)

수명 주기 관리자를 이용하면 Snapshot이나 AMI를 생성하고 이를 원하는 기간을 설정하여 보유 및 삭제 할 수 있습니다. 또한 교차 계정 복사를 이용하여 다른 AWS 계정으로 정기적인 공유가 가능하며 교차 리전 복사를 통해 DR 구성도 쉽게 설정할 수 있습니다.

설정 방법은 간단합니다. [EC]-[Elastic Block Store]에서 “수명주기 관리자”를 찾을 수 있습니다.

“수명 주기 정책 생성” 시 아래와 같이 화면이 나타납니다.

여기서 원하는 정책 유형을 선택해주면 되는데 오늘은 EBS 스냅샷 정책으로 진행하였습니다.

대상 리소스 유형은 볼륨과 인스턴스 유형으로 나뉘어 선택할 수 있습니다.
“볼륨”은 개별 볼륨의 스냅샷을 생성하고 “인스턴스”는 인스턴스에 연결된 모든 볼륨을 스냅샷 생성을 진행합니다.

스냅샷 정책에서는 볼륨, 스냅샷을 선택할 수 있으나 AMI의 경우 당연히 인스턴스만 대상으로 지정할 수 있습니다.
우선 저는 인스턴스 단위 선택하였습니다.

간단하게 정책에 대한 설명을 기입해주고 IAM 역할을 선택하는 곳입니다.
기본적으로 기본 역할을 선택할 경우 모든 필수 권한으로 자동 생성이 되나 IAM을 직접 생성하여 특정 사용자에 대해서 권한을 줄 수 있으며 이후 스냅샷 볼륨이 암호화되는 경우 KMS 키를 사용할 권한을 주어야합니다.

위 첨부된 사진에서는 크게 참고할 것이 없습니다.
정책 상태는 생성하는 이 정책을 활성화 할 것인가, 비활성화 할 것인가 선택하는 것이며
파라미터 부분에서 [루트 볼륨 제외]를 선택할 경우 루트 볼륨은 제외하고 스냅샷이 생성됩니다.

이제 가장 중요한 생성 주기를 지정하는 “일정 세부 정보”란입니다.

빈도는 일별, 주별, 월별, 연별로도 가능하며 cron을 이용하여 사용자 지정 표현이 가능합니다.
보존 유형은 개수와 경과 시간으로 설정할 수도 있습니다.

참고로 이런 질문이 있었습니다.
“저는 30분마다 스냅샷을 생성하고 싶은데 불가능한 가요?”

일별로 매 (1,2,3,4,6,8,12,24) 시간마다 설정이 있는데 이는 다 이유가 있습니다…
cron 표현식을 이용하여 30분마다 스냅샷을 생성하도록 설정해두면 아래와 같이 에러가 발생합니다.

“허용되는 최소 예약 빈도는 1시간입니다.” 라고 알려줍니다.
수명 주기 관리자는 1시간 단위로만 가능합니다.

또한 수명 주기 관리자를 써보시면 알겠지만 이게 UTC 09:00에 시작하라고 설정을 해둬도
09:00 시간에 딱 맞춰서 실행되지 않습니다.

UTC 09:00 ~ 09:59 사이에 랜덤으로 실행됩니다.

설정 이후 태그를 지정해줍니다.

정책 생성 마지막에 빠른 스냅샷 복원, 교차 리전 복사, 교차 계정 공유도 선택할 수 있습니다.
오늘은 교차 리전 복사까지만 한 번 해보도록 하겠습니다.

DR(Disaster Recovery)을 위해 이 교차 리전 복사를 이용하여 백업을 하시는 분들이 있습니다.
이 역시 방법이 크게 어렵지 않습니다.

대상 리전을 선택해주고 생성 후 언제 만료되게 할 것인가에 대해 설정해주면 끝!

다만 스냅샷 복사본 암호화 활성화를 하게 될 경우 이제 암호화 키에 대한 권한을 고려해봐야할 것입니다.


Personal Comments

지금까지 수명 주기 관리자 사용법에 대해서 간단하게 알아보았습니다.

위에서 언급했듯 수명 주기 관리자는 1시간 단위로만 가능한데 이를 30분 단위로하는 방법은 전혀 없는 것일까요?

그렇지는 않습니다. Lambda를 이용한다면 충분히 가능합니다.
Lambda를 이용하는 방법이 아닌 또 다른 방법이 있으시다면 공유 부탁드립니다.

긴 글 읽어주셔서 감사합니다.

AWS

[AWS] RDS Log Generation (General, slow query, audit logs)

안녕하세요. ManVSCloud 김수현입니다.

오늘은 오랜만에 AWS에 대한 포스팅입니다.
최근 ISMS-P를 준비가 필요하여 RDS에서 로그를 남기는 방법에 대한 질문을 받은 적이 있어 이를 블로그로도 공유하고자 올립니다.


RDS Log

RDS 생성 또는 수정시 체크할 수 있는 로그 내보내기 옵션입니다.
생각보다 이 기능이 로그를 생성하는 옵션인 것으로 아시는 분들이 있었습니다.
위 내보내기를 전부 체크하여도 에러 로그만 생성되고 나머지 로그가 생성이 되지 않는 것을 확인할 수 있습니다. (에러 로그는 Default가 생성이라 따로 설정하지 않아도 생성됩니다.)

이 기능은 말 그대로 로그를 CloudWatch Logs로 게시할 수 있도록 내보내는 옵션이며
로그를 생성하는 옵션은 따로 존재합니다.

일반 로그와 느린 쿼리 로그를 생성하기 위해서는 아래 첨부된 이미지와 같이 파라미터 그룹 수정이 필요합니다.

일반 로그는 general_log를 검색하면 나오고 슬로우 쿼리는 slow_query_log라고 검색하면 나옵니다.

두 값을 1로 변경 해줍시다. (1로 설정해야 로그가 생성됩니다.)

현재 운영중인 RDS 인스턴스의 파라미터 그룹이 default 파라미터로 설정되어 있다면 사용자 지정 파라미터 그룹을 생성하여 파라미터 수정 및 파라미터 그룹 수정을 진행합니다.
(RDS 인스턴스 [수정]을 이용하여 파라미터 그룹을 변경할 수 있습니다.)

여기서 중요한 점은 또 Down Time의 여부겠죠.
파라미터 그룹을 변경하게 될 경우 또는 파라미터 값을 수정하게 될 경우 재부팅이 필요하여 Down Time이 발생하게 될까요?

정답은 아래와 같습니다.

그렇다면 동적 파라미터와 정적 파라미터를 어떻게 구분하느냐?

파라미터 그룹 내에 파라미터들을 보면 [적용 유형]이 있습니다.
Dynamic이 동적 파라미터, Static이 정적 파라미터로 수정이 필요한 파라미터를 검색하여
해당하는 파라미터의 값이 수정될 경우 재부팅이 필요한가?를 알 수 있으니 이를 확인하여 적절한 시간에 작업을 진행할 수 있습니다.


RDS Audit Log

파라미터 그룹까지 설정하였습니다. 하지만 파라미터 그룹에서 감사 로그는 찾을 수 없습니다. 그 이유로 감사 로그는 파라미터 그룹이 아닌 옵션 그룹에서 설정이 필요하기 때문입니다.

옵션 그룹에서 감사 로그를 설정 해주려면 default 옵션 그룹에서 새로 생성한 옵션 그룹으로 변경이 필요합니다.

새로 생성한 옵션 그룹에서 위와 같이 MARIADB_AUDIT_PLUGIN 옵션을 추가하여 설정할 수 있습니다. 크게 사용하실만한 옵션에 대해서만 간단하게 설명하자면 다음과 같습니다.

  • SERVER_AUDIT_FILE_ROTATE_SIZE : 로그 파일 용량 크기를 제한합니다. (1–1000000000)
    최대 1GB까지 설정 가능하며 Default 값은 1000000 입니다.
  • SERVER_AUDIT_FILE_ROTATIONS : 로그 파일의 로테이션 수를 설정합니다. (0-100)
    최대 100개의 파일까지 생성가능하며 Default값은 9입니다.
  • SERVER_AUDIT_EVENTS : 특정 이벤트 유형으로 제한하여 로그를 남깁니다.
    이를 설정하지 않을 경우 모든 이벤트 유형을 남기게 됩니다.
    Default 값은 CONNECT, QUERY 입니다.
  • SERVER_AUDIT_INCL_USERS : SERVER_AUDIT_EXCL_USERS보다 우선 순위가 높으며 기록할 사용자를 추가합니다. 또한 값이 없을 경우 로깅에 모든 사용자를 로깅합니다.(SERVER_AUDIT_INCL_USERS 값에 admin을 추가하고 SERVER_AUDIT_EXCL_USERS 값이 비어있다면 admin 계정에 대한 로그만 남깁니다.)
  • SERVER_AUDIT_EXCL_USERS : 값에 사용자를 추가할 경우 해당 사용자를 로그에 기록이 남지않습니다. (로그 예외 처리 계정 추가라고 보면 이해가 쉽습니다.)
    값이 없을 경우 로깅에 예외 처리할 사용자가 없다라는 의미가 됩니다.
  • SERVER_AUDIT_QUERY_LOG_LIMIT : 쿼리 문자열 길이를 제한합니다. (0–2147483647)
    Default값은 1024입니다.

옵션 변경 및 옵션 그룹 변경이 완료되었다면 RDS 로그에서 아래 이미지와 같이 Audit.log가 생성되는 것을 확인할 수 있습니다.

Cloudwatch logs로 내보내기 설정을 하게될 경우 CloudWatch 로그 이벤트에서도 로그를 자세히 확인할 수 있습니다.
DB에서 show databases 및 show tables를 입력해보았는데 Audit 로그에 그대로 남았습니다.


Aurora DB, Using advanced auditing

Aurora MySQL에서는 RDS MySQL과 다르게 고급 감사를 사용할 수 있습니다.
설정 방법은 크게 어렵지 않아 어떠한 고급 감사 기능이 있는지 링크만 남겨두도록 하겠습니다.


Personal Comments

오늘은 오랜만에 AWS의 RDS 로그 생성 방법에 대해 알아보았습니다.

아무래도 감사 로그를 남기는 부분은 ISMS-P를 준비하실 때 필요한 부분이니 이 부분은 어느정도 도움이 되시리라 생각합니다.

긴 글 읽어주셔서 감사합니다.

AWS

[AWS] image resizing failure, trouble shooting

안녕하세요. ManVSCloud 김수현입니다.

오늘은 이전에 실패했던 image resizing 실패 원인을 확인 후
정상적으로 resizing 성공 후기를 남겨보려고 합니다.


First Cause

첫번째 원인을 찾았습니다.
CloudFront 트리거 구성 시 Origin Response가 되어야하는데 Request로 설정을 해두었던 것!

Lambda에서 변경 시 위에서 오리진 응답으로 변경하면 됩니다.

만약 Cloudfront에서 변경을 하실 경우 연결된 cloudfront에서 [Behaviors]-[경로 선택 및 Edit] 후 아래 CloudFront Event에서 Origin Response로 변경해줄 수 있습니다.

이 부분은 리눅서님의 도움을 받았습니다.
해당 부분이 Response가 되어야하는 이유는 인지하고 있었는데 다시 한번 포인트를 잡아주시고 놓치고 지나친 부분 찾아주신 리눅서님에게 감사의 인사 올립니다.


Find hints

위 첫번째 원인을 해결하고도 정상적으로 이미지 리사이징이 되지 않았습니다.
그래서 현재 이미지 리사이징이 어떻게 동작하고있고 특정 오류가 발생하는가 확인해보기로 했습니다.


우선 CloudFront의 Cache statistics와 Monitoring을 체크해보았고
각 오류 코드 및 Header값을 확인해보았습니다.

3xx의 정체는 301, 2xx는 200, 4xx는 403으로 보입니다.

http://주소/경로/tom.png?w=110&h=60&f=webp&q=90 [Viewer Request]
Status Code 로301 Move Permanently를 받으며 리다이렉트 되었습니다.
X-Cache : Redirect from cloudfront

https로 리다이렉트 되고 Status Code로 200을 받았습니다.
x-cache : Miss from cloudfront 엣지 로케이션 캐시에 tom.png?w=110&h=60&f=webp&q=90가 없어 Origin에 요청합니다. 여기서 Origin은 tom.png 이미지가 있는 S3 버킷!
이미지도 잘 데려왔습니다.

그런데 이미지 리사이징이 되지않은 상태로 넘어왔습니다.
User가 Cloudfront로 “Viewer request” 했고 (1. User → Cloudfront)
Miss from cloudfront라 Cloudfront가 Origin에게 “Origin request” 하고 (2. Cloudfront → Origin)
Origin으로부터 “Origin reponse” 후 (3. Origin → Cloudfront)
Cloudfront가 다시 User에게 “Viewer response” (4. Cloudfront → User) 되어
이미지를 받았다라고 했을 때 [1], [2], [4] 과정은 문제가 없었을 것이라 생각됩니다.

[1],[4] 요청과 응답에 대한 통신은 정상적으로 되었으며 Miss from cloudfront 응답에
[2] CloudFront는 Origin에게 요청을 했을 것입니다.

그렇다면 [3] 과정에서 정상적으로 동작하지 않는 것이 있다는 것인데?

Cloudfront 설정은 몇번을 반복하여 보아도 더 이상 잘못 설정한 것이 없었습니다.
그래서 Lambda 설정을 조금 더 검토해보기로 했습니다.

Second Cause

원인을 전혀 못찾다가 사내 상사의 도움으로 “Node.js 버전에 맞는 소스 코드를 사용했는가? 소스 코드가 버전에 맞지않아서 그럴 수 있다”라는 힌트를 얻게 되었습니다.

그런데 아무리 생각해봐도 다른 설정은 잘 되어있고 정말 소스 코드쪽이 크게 의심되어 바로 버전과 소스 코드 변경을 진행하였습니다.

Node.js 버전은 12.x 버전으로 변경하였고 소스 코드는 아래와 같이 수정하였습니다.

'use strict';

const querystring = require('querystring'); // Don't install.
const AWS = require('aws-sdk'); // Don't install.
const Sharp = require('sharp');

const S3 = new AWS.S3({
  region: 'ap-northeast-2'
});
const BUCKET = 'mybucket';

exports.handler = async (event, context, callback) => {
  const { request, response } = event.Records[0].cf;
  // Parameters are w, h, f, q and indicate width, height, format and quality.
  const params = querystring.parse(request.querystring);

  // Required width or height value.
  if (!params.w && !params.h) {
    return callback(null, response);
  }

  // Extract name and format.
  const { uri } = request;
  const [, imageName, extension] = uri.match(/\/?(.*)\.(.*)/);

  // Init variables
  let width;
  let height;
  let format;
  let quality; // Sharp는 이미지 포맷에 따라서 품질(quality)의 기본값이 다릅니다.
  let s3Object;
  let resizedImage;

  // Init sizes.
  width = parseInt(params.w, 10) ? parseInt(params.w, 10) : null;
  height = parseInt(params.h, 10) ? parseInt(params.h, 10) : null;

  // Init quality.
  if (parseInt(params.q, 10)) {
    quality = parseInt(params.q, 10);
  }

  // Init format.
  format = params.f ? params.f : extension;
  format = format === 'jpg' ? 'jpeg' : format;

  // For AWS CloudWatch.
  console.log(`parmas: ${JSON.stringify(params)}`); // Cannot convert object to primitive value.
  console.log(`name: ${imageName}.${extension}`); // Favicon error, if name is `favicon.ico`.

  try {
    s3Object = await S3.getObject({
      Bucket: BUCKET,
      Key: decodeURI(imageName + '.' + extension)
    }).promise();
  } catch (error) {
    console.log('S3.getObject: ', error);
    return callback(error);
  }

  try {
    resizedImage = await Sharp(s3Object.Body)
      .resize(width, height)
      .toFormat(format, {
        quality
      })
      .toBuffer();
  } catch (error) {
    console.log('Sharp: ', error);
    return callback(error);
  }

  const resizedImageByteLength = Buffer.byteLength(resizedImage, 'base64');
  console.log('byteLength: ', resizedImageByteLength);

  // `response.body`가 변경된 경우 1MB까지만 허용됩니다.
  if (resizedImageByteLength >= 1 * 1024 * 1024) {
    return callback(null, response);
  }

  response.status = 200;
  response.body = resizedImage.toString('base64');
  response.bodyEncoding = 'base64';
  response.headers['content-type'] = [
    {
      key: 'Content-Type',
      value: `image/${format}`
    }
  ];
  return callback(null, response);
};

개발쪽은 아직 미숙하여 소스 코드는 아래 링크를 참고하였습니다.

소스 코드 변환 후 lambda 재배포하여 다시 한 번 리사이징 테스트를 해보았습니다.


Success

이미지 리사이징이 정상적으로 완료되었습니다!
Node.js 버전과 소스 코드 변경 후 정상적으로 리사이징이 되네요

이번 이미지 리사이징을 계기로 개발쪽 공부도 해야겠다는 생각이 드는데 바쁜 일정으로 올해는 무리입니다…

그래도 이미지 리사이징 성공할 수 있어서 뿌듯합니다.

긴 글 읽어주셔서 감사합니다.

AWS

[AWS] CloudFront 캐시 적중률 늘리기 (cache hit ratio)

안녕하세요. ManVSCloud 김수현입니다.

오늘은 ANOS 2기 스터디 후 6주차 CloudFront 과정을 마친 후 예정되어 있던 포스팅으로
CloudFront 캐시 적중률 늘리기에 대한 주제로 글을 써보려합니다.

이 포스팅을 준비하기 위해 생각보다 많은 공부를 하게되어 생각보다 시간이 소요되었지만 평소한 것들보다 만족스럽다는 생각이 들었습니다.

그럼 [AWS] CLOUDFRONT 캐시 적중률 늘리기 (CACHE HIT RATIO)에 대해 알아보겠습니다.


What is Cache?

캐시 메모리, 캐시 저장소, 캐시 서버 등 캐시는 무엇을 말하는 것일까요?
캐시는 쉽게 말하면 임시로 저장해두는 장소라고 말할 수 있겠습니다.

이 캐시로 인해 우리는 평소보다 조금 더 빠르게 접근이 가능하게되는데
Cache Hit 상태라면 우리가 원하는 것을 Cache가 가지고 있는 것이며
Cache Miss는 Cache가 아직 그것을 가지고 있지 않는 상태입니다.

Cache에 대해서는 이 정도로만 간단히 설명하고 다음으로 넘어가겠습니다.


What is CloudFront?

Fast or Slow 사이트에서 제 테스트 웹 페이지 하나에 대해 속도 측정을 해보았습니다.
(위 링크에서 여러분들의 웹 사이트를 속도 측정 할 수 있습니다. (해외 차단 시 불가))

출발한 패킷이 해외 지역에 도달하는데에 걸리는 시간이 각각 다른 것을 알 수 있습니다.
우리는 이 시간을 Latency라고 부르며 출발지와 거리가 멀 수록 Latency가 크게 발생하게 됩니다.

아프리카와 유럽쪽의 응답시간이 다른 지역에 비해 더 늦다는 것을 확인할 수 있습니다.
반면 한국과 가까운 일본이나 홍콩은 다른 지역보다 빠릅니다.

그렇다면 해외 서비스를 운영할 때 발생하는 컨텐츠의 느린 응답 속도를 해결할 수 있는 방법은 없는 것일까요?

그렇지 않습니다. 이를 해결하기 위해 Contents Delivery Network(CDN)을 이용한다면
지리적 또는 물리적으로 떨어진 대상에게 컨텐츠를 빠르게 제공이 가능해집니다.

CDN 사이트 테스트 시 이전 사이트의 Latency에 비해 비교적으로 낮아진 값을 확인할 수 있었습니다.
또한 CDN 업체의 각 CDN Node로 인해 보다 빠른 통신이 가능하다는 것을 알 수 있었습니다.

CDN을 사용한다면 해외 사용자가 컨텐츠를 다운로드 할 때 Origin에서 직접 컨텐츠를 가져오지 않고 주변 CDN 서버에서 컨텐츠를 가져오므로 속도 보장은 물론 국제 회선으로 발생하는 비용 역시 절감할 수 있게 됩니다.

CloudFront는 CDN 서비스를 제공합니다. 또한 CloudFront는 엣지 로케이션 215개 이상, 리전별 중간 티어 캐시 12개의 글로벌 네트워크를 사용하여 캐싱을 통해 짧은 지연 시간과 높은 처리량 및 안정적인 네트워크 연결(부하 분산)이 제공됩니다.

이런 CDN에 대해 관심이 많으시다면 GSLB 기술에 대해 한 번 알아보는 것도 나쁘지 않을 것같아 링크 추가해봅니다.

세계 지도 png에서 kor.pngtree.com

Cloudfront의 전체를 그림 하나로 표현하기에 부족하겠지만 한 번 만들어보았습니다.

캐싱 데이터가 생성된 Edge로 인해 안전성, 비용, 속도를 보장 받을 수 있으니 Cloudfront는 무조건 사용해야한다?, Cloudfront만 사용하면 무조건 빠르다? 는 정답이 될 수 없습니다.

무조건 사용하지 않습니다. 잘 사용해야합니다.
또한 서비스의 속도는 오직 캐싱만으로 결정되지 않습니다.
Rendering, 압축, 개발 소스 등 역시 속도의 원인이 될 수 있으며 최신화를 위해 정적/동적 데이터 구분하여 설정 및 캐싱 예외 처리, TTL 등 고려해야할 사항이 많습니다.

하지만 이 포스팅의 주제는 Cloudfront의 캐시 적중률을 어떻게하면 높일 수 있을까에 대한 주제이므로 캐시 적중률을 높일 수 있는 방법에 대한 내용을 중점으로 다루겠습니다.


How can CloudFront cache hit rate be increased?

CloudFront의 캐시 적중룔, 어떻게하면 높일 수 있을까요?

AWS 가이드에서는 총 7가지가 있다고 합니다.

CloudFront에서 객체를 캐시하는 기간 지정
Origin Shield 사용
쿼리 문자열 매개 변수를 기반으로 한 캐싱
쿠키 값에 따른 캐싱
요청 헤더 기반 캐싱
압축이 필요하지 않은 경우 Accept-Encoding 헤더 제거
HTTP를 사용하여 미디어 콘텐츠 제공

7가지 중 3가지 정도만 자세히 알아보도록 하겠습니다.
(다소 양이 방대하기때문에 나머지는 최하단 Docs 링크 추가해두었으니 참고 부탁드립니다.)


▶ CloudFront에서 객체를 캐시하는 기간 지정

첫번째 방법으로 CloudFront에서 객체를 캐시하는 기간을 지정해주는 것입니다.
Cache-Control max-age의 수치가 길면 길수록 캐시 적중률이 높아집니다.
다만 오리진이 아닌 캐시된 파일을 불러오기에 객체 최신화에 문제가 있습니다.
그렇다면 Cache-Control max-age 수치를 어떻게 주면 좋을까요?

우선 TTL과 Cache-Control에 대해서 알아봅시다.

브라우저 캐시 TTL은 최종 사용자 브라우저가 리소스를 캐시하는 시간입니다.
이 리소스의 경우 TTL이 만료 될 때까지 브라우저 로컬 캐시에서 제공하며 만료 시 브라우저가 재요청을 하게됩니다. 이때 TTL은 해당 컨텐츠가 있는 원본 서버의 Cache-Control을 참고하게 됩니다. 예를들어 원본 서버에서 Cache-Control 설정이 public; max-age=60로 설정되어있을 경우 60초의 시간 동안 브라우저 로컬 캐시에 저장됩니다.

Cache-Control은 응답을 캐시할 수 있는 사용자와 해당 조건 그리고 기간을 제어하는데
즉, 웹 컨텐츠 캐시 정책을 컨트롤 하는 지시문이라 볼 수 있습니다.

Cache-Crontrol에 대한 링크를 추가하였으니 참고하시면 좋을듯합니다.

Cache-Control 설정은 웹 사이트 성능 최적화에 중요한 역할을 합니다.
Cache-Control은 컨텐츠 유형별로 다른 설정을 해준다면 웹 사이트 성능 최적화에 좋은 결과를 기대할 수 있을 것입니다.

컨텐츠 유형은 크게 정적 컨텐츠(Static Contents)와 동적 컨텐츠(Dynamic Contents)로 나뉩니다.

정적 컨텐츠는 css, js, png, jpg, html 파일 등이 대표적이며, 동적 컨텐츠는 업데이트가 잦아 항상 최신화가 필요하거나 요청마다 다른 응답을 주어야하는 리소스들이 되겠습니다.

정적 컨텐츠는 제가 포스팅 시 업로드한 이미지,영상 파일들이나 우리가 흔히 게임을 하기위해 다운로드를 받는 소프트웨어의 경우 TTL이 높아도 상관이 없습니다.
다만 우리가 보는 뉴스 기사들은 TTL이 높을 경우 빠르게 최신 뉴스를 볼 수 없게 될 것입니다. 그러므로 각 컨텐츠 별로 다르게 설정적 컨텐츠는 제가 포스팅 시 업로드한 이미지,영상 파일들이나 우리가 흔히 게임을 하기위해 다운로드를 받는 소프트웨어의 경우 TTL이 높아도 상관이 없습니다.다만 우리가 보는 뉴스 기사들은 TTL이 높을 경우 빠르게 최신 뉴스를 볼 수 없게 될 것입니다. 그러므로 같은 정적 컨텐츠라도 다르게 설정해줄 필요가 있겠습니다.

제 블로그에 올라간 이미지 파일들은 이미지가 변경되어야 할 이유가 크게 없습니다.
이 경우 아래와 같은 예시로 Cache-Control을 사용할 수 있겠습니다.
예시) max-age = 31536000;(브라우저) 또는 s-maxage=86400(프록시와 같은 공유 캐시에만 적용)
max-age의 최대치는 31536000 입니다.

날씨와 같이 1분 주기로 최신화를 하고 싶다면 아래와 같이 할 수 있겠습니다.
예시) public; max-age=60 또는 no-cache; max-age=60 등의 방법

동적 컨텐츠는 항상 최신화가 필요할 것입니다.
항상 최신화를 위해 아래 예시의 방법이 있습니다.
예시) no-cache, max-age=0 또는 private, no-store 등의 방법

제 블로그 역시 Cache-Control이 적용되어있습니다.

Apache를 이용하여 Cache-Control 헤더를 사용한다면 .htaccess를 이용하여
아래와 같은 방법을 사용할 수 있습니다.

<filesMatch ".(ico|jpg|jpeg|png|gif)$">
 Header set Cache-Control "max-age=2592000, public"
</filesMatch>

<filesMatch ".(css|js)$">
 Header set Cache-Control "max-age=86400, public"
</filesMatch>

제 블로그의 이미지 파일들은 AWS S3에 있습니다.
그렇다면 이 S3에 있는 이미지 파일들에게 Cache-Control 설정은 해줄 수 없을까요?

가능합니다.
우선 S3의 해당 버킷을 선택한 뒤Cache-Control을 설정할 파일 또는 디렉토리를 선택합니다.
그리고 [작업]-[작업 편집]-[메타데이터 편집]을 선택 클릭하면 메타데이터 편집을 통해
Cache-Control을 수정 및 설정할 수 있습니다.

자 그럼 이제 CloudFront에서 객체를 캐시하는 기간을 설정하는 방법에 대해 알아 보겠습니다.

Cloudfront의 [Behaviors]에서 설정할 수 있습니다.

또한 아래 사진처럼 Create Behavior로 Path Pattern을 나누어 우선 순위를 설정한 뒤 각 경로나 파일마다 다르게 설정할 수도 있습니다.

수정이 필요한 Behavior를 선택 후 [Edit]을 누르면 아래와 같은 창으로 이동합니다.
Cache and origin request settings을 선택해줄텐데 직접 수정하려면 아래
[Use legacy cache settings]를 선택해주어야합니다.

[Use a cache policy and origin request policy]를 선택하여 Managed-CachingOptimized를 사용할 경우 관리형 캐시 정책에 대한 아래 Docs를 참고하면 되겠습니다.

legacy cache settings를 선택할 경우 아래 추가로 입력할 수 있는 창이 생깁니다.
Object Caching을 Customize로 체크해줄 경우 아래 TTL 값을 원하는 값으로 수정이 가능하게됩니다.

* [참고] Cache Based on Selected Request Header가 요청 헤더 기반 컨텐츠 캐싱을 지정해주는 것이고 Query String Forwarding and Caching은 쿼리 문자열 매개 변수를 기반으로 한 캐싱, Forward Cookies가 쿠키 값에 따른 캐싱에 해당됩니다. 아래에서 Query String Forwarding and Caching에 대해 추가로 다룰 예정입니다.

지금까지 위에서 다룬 TTL 값을 변경하는 방법을 알아보았습니다.
다만 다음과 같은 특이 케이스가 있을 것입니다.

??? : ” 정적 컨텐츠였는데 지금 이미지 하나를 급하게 최신화 해야합니다. 하지만 Cloudfront에 기존 TTL 값이 너무 높게 설정이 되어있습니다. 어떻게 방법이 없을까요? “

있습니다. [Invalidation]을 사용한다면 캐시가 만료되기 전에 파일의 내용을 갱신할 수 있습니다. 이는 캐시 무효화 기능인데 CloudFront Edge 로케이션에 저장된 캐시를 삭제해줍니다.

여기까지 CloudFront에서 객체를 캐시하는 기간을 지정하여 캐시 히트율을 높이는 첫번째 방법에 대해 알아보았습니다.


▶ Origin Shield 사용

두번째 방법으로는 Origin Shield를 사용하는 방법이 있겠습니다.
Origin shield는 CloudFront 캐싱 인프라의 추가 계층으로 Origin 앞에 추가적인 캐싱 계층을 제공해줍니다. 모든 캐싱 계층에서 Origin에 대한 모든 요청이 Origin shield를 통과하기에 CloudFront 배포의 캐시 적중률을 개선하는데 큰 도움이됩니다.

또한 Origin의 부하를 최소화하며 가용성을 높여 운영 비용을 줄이는 데에 큰 도움이 됩니다.
캐시에 없는 컨텐츠에 대한 요청은 동일한 객체에 대한 다른 요청과 통합되어 Origin으로 가는 요청이 하나만 발생하게 되는데 이로 인해 동시 요청 수를 줄일 수 있으며 최대 로드, 트래픽 급증 중에 Origin의 가용성을 유지할 수 있고 동적 패키징, 이미지 변환 및 데이터 전송과 같은 비용을 줄일 수 있습니다.

Feb 20, Origin Shield 사용 전 (21일에 적용)
Feb 23, Origin Shield 사용 2일 후 (21일에 적용)

(포스팅 당일은 캐싱되지 않은 새로운 컨텐츠가 존재하여 cf-cache-status : MISS가 발생할 수 있습니다.)

제 블로그에 적용 당시 Origin shield입니다.
적용 후 그래프의 캐시 적중률(Hits)이 상승한 것을 볼 수 있습니다.

Origin Shield 설정 – 1
Origin Shield 설정 – 2

위와 같은 방법으로 Origin Shield 설정이 가능합니다.

그외에도 Origin Shield는 CloudFront의 리전 엣지 캐시를 활용하며 CloudFront 위치에서 Origin Shield 로 연결할 때 각 요청에 대해 활성 오류 추적을 사용하여 Default Origin Shield 를 사용할 수없는 경우 요청을 보조 Origin Shield 위치로 자동 라우팅하므로 고 가용성까지 갖췄습니다.


▶ 요청 헤더 기반 캐싱

마지막으로 요청 헤더 기반 캐싱에 대해 알아보겠습니다.

위에서 언급했듯 요청 헤더 기반 캐싱은 Behavior을 [Edit] 시Query String Forwarding and Caching를 선택할 수 있습니다.

이는 Query String을 캐시 구분자로 사용할지 물어보는 것입니다.

# None(캐시 향상) : 이를 선택할 경우 모든 쿼리스트링에 대해 캐시합니다.
# Forward all, cache based on whitelist : whitelist를 선택하여 값을 입력할 경우 whitelist에 입력된 쿼리스트링에 대해서만 캐시가 되지 않고 나머지는 캐시가 됩니다.
# Forward all, cache based on all : all을 선택하게 되면 캐시를 하지 않게됩니다.

None과 all은 캐시 된다/안된다이니 whitelist를 잘 써야봐야겠습니다.
아래 사진으로 예를 들어보겠습니다.

제 블로그는 도메인명 뒤에 ?p가 붙습니다.
ex)https://manvscloud.com/?p=612

만약 제가 포스팅되는 글들은 캐시되지 않고 오리진에서 최신화하여 불러왔으면 좋겠다고 했을 때 위와 같이 설정해줄 수 있습니다.
whitelist에 p를 넣어주면 https://manvscloud.com/? 뒤에 p의 쿼리스트링에 대해서 캐시하지 않고 항상 최신화하게 됩니다.

그렇다면 이 쿼리스트링을 여러개 사용해야한다면 어떤 방법이 있을까요?
예를 들어 이미지가 요청할 때마다 항상 다른 사이즈로 리사이징되어야 하는 경우입니다.

첫 요청 시 /?w=200&h=150&f=webp&q=90 으로 요청했는데
이후 /?w=100&h=300&f=webp&q=90으로 요청이 올 경우 바로 리사이징 된 이미지를 보여주어야합니다.

위와 같은 방법을 사용할 수 있습니다.
각 w,h,f,q 쿼리스트링에 대한 whitelist를 입력하여 해당 쿼리스트링 요청 시 캐싱되지 않고 오리진에서 불러올 수 있도록하는 것입니다.

이 방법을 사용한다면 원하는 것만 최신화 하고 나머지는 항상 캐싱되니
캐시를 잘 사용한다고 볼 수 있겠습니다.

캐시 적중률이 높다는 것은 hit율만 높고 최신화가 되지 않는 것을 말하는 것이 아닙니다.
최신화 되어야할 부분은 최신화 되면서 캐싱이 되어야 비로소 캐시가 잘 적중했다라고 생각됩니다.

지금까지 캐시 적중률을 높이는 3가지 방법에 대해 자세히 알아보았습니다.
이 외에도 나머지 4가지 방법이 더 있습니다.
제일 하단 링크에 추가된 링크를 통해 나머지 4가지 방법도 찾아보시길 바랍니다.


Opinion

검색 엔진 최적화(SEO)에는 웹 사이트 속도와 상관 관계가 있다고 합니다.
조사에 따르면 웹 페이지가 출력되는데에 4초 이상이 소요될 경우 75%의 사람들은 이미 해당 웹 사이트를 종료한다고 합니다.

캐시 적중률을 높여 웹 페이지의 속도를 빠르게 해보시는 것은 어떠신가요?
많은 분들에게 도움되는 포스팅이 되었길 바랍니다.

(원래 추가로 Cloudfront + Lambda@Edge를 활용한 Image Resizing에 대한 포스팅도 첨부하여 이미지 리사이징을 통해 SEO 최적화하는 방법을 더하려 했으나… 왜 안되는지 잘 모르겠습니다?… )

CloudFront의 캐시 적중률을 높여보자는 게 그만 내용이 꽤 길어졌습니다.
처음에 작성하려 했던 양보다 훨씬 많아졌네요…
7가지 중에 3가지만 했는데도 이 정도 양이니…
나머지 4개는 제가 여러분들에게 드리는 숙제인걸로…!
찾아보면서 공부하는 재미가 있더라구요😋 홧팅!!

다음 AWS 공부는 Elasticache나 Elastic Beanstalk을 생각하고 있지만 곧 NCP 시험과 Kubernetes 일정으로 인해 다음 AWS 포스팅까지는 다소 시간이 걸릴듯합니다.

긴 글 읽어주셔서 감사합니다.


References

AWS

AWS Network online study 11주차까지 마무리하며… [3/3]

안녕하세요. ManVSCloud 김수현입니다.

2021-01-10 ~ 2021-03-28 설 휴일을 제외한 약 11주차 과정이 마무리되었습니다.

생각보다 빠르게 11주차가 와서 아쉬우면서도 제가 11주차를 하루도 빠짐없이 다 해냈다는 것을 생각하면 또 한 편으로 보람차고 잘 했다는 생각이 들었습니다.

ANOS를 시작하기 전과 지금의 저를 비교해본다면 스스로가 Level UP 한 것같고 경험치를 상당히 얻은 기분입니다.
물론 ANOS를 마쳤다고 하여 AWS Network를 마무리할 생각은 없습니다.
아직 한 두번 해봤을 뿐 누군가에게 설명할 수 있을 정도는 아니기에 추가적인 복습을 통해 더 공부할 생각입니다.


가장 흥미로웠던 주제 3가지를 뽑자면?

  • CloudFront

물론 1주차부터 11주차까지 모두 재밌는 시간들이었지만 그 중에 굳이 3가지를 뽑자면Cloudfront와 WAF, TGW & R53 Resolver가 될 것같습니다. 특히 CloudFront의 경우 워낙 관심이 많았던 상태였기에 스터디가 마무리된 지금도 더 깊이 알고싶은 서비스 중에 하나입니다.

ANOS 스터디에서는 CloudFront에 대한 내용만 다룰 뿐만 아니라 CloudFront를 배우기 앞서 HTTP Cache와 CDN 기술에 대한 기본적인 지식까지 얻을 수 있으며 왜 CloudFront를 써야하는지 정확하게 알 수 있었던 시간이었습니다.

스터디를 시작하기 전에도 물론 제 블로그는 Cloudfront를 이용하여 정적이미지 파일들을 불러오고 있었지만 다소 정확히 알지 못하는 상태에서 사용 중이었고 Origin Shield가 없어 Hits율이 낮은 상태였습니다.

ANOS를 통해서 CloudFront를 정확히 이해하고 사용할 수 있게되었고 캐싱률도 상승하였으며 조금 더 깊이있게 공부하고 싶어질만큼 흥미로운 6주차 주제 CloudFront였습니다.

  • WAF 웹방화벽

두번째로 흥미로웠던 주제는 WAF입니다.
이 주제는 Legend 급으로 재밌었던… 8주차였습니다.

이 날 이후 제 블로그에는 AWS WAF 기능이 추가됩니다…🙄

제가 대학 전공을 보안학 전공을 하다보니 과거에 해킹과 보안에 관심이 많은 편이었습니다.
WAF를 배우며 오랜만에 공격 테스트도 해보고 방화벽을 통해 탐지/차단까지 실습해보니 재미가 없을 수가 없었습니다!

가끔 제가 설정해둔 WAF의 Sampled requests를 보는 편인데 생각보다 AnonymousIpList(익명 IP) 접속으로 차단되는 게 많은 편이었습니다.

이날 이후로 WAF 잘 쓰고 있어서 웹 공격으로부터 보안이 튼튼한 블로그가 된 것같아 기분이 좋네요.

  • TGW & R53 Resolver

마지막으로 TGW & R53 Resolver입니다. 특히 TGW!!

TGW는 해보면 와… 내가 정말 네트워크를 하고있구나라는 생각이 듭니다.

다소 난이도가 있으나 이거 하나 배워두면 아키텍처의 범위가 상당히 넓어지는 기분입니다.
아직 네트워크 쪽은 다양한 경험을 해보지 못했지만 지금까지의 제가 느낀바로 TGW는 AWS Network의 꽃이 아닐까…생각됩니다.

앞으로 TGW를 이용하여 리전 간 테스트를 종종 할 생각입니다.


ANOS 2기 MEMBER BLOG


마무리

11주라는 시간동안 고생해주신 CloudNet@ 팀, 운영진님들에게 다시 한 번 감사의 인사 드립니다. 아직 현업에서 아직 사용해보지 못한 기능들이 많았었는데 좋은 기회를 얻게 되어 다양한 서비스 실습을 할 수 있어 정말 많이 배웠습니다.

마지막 11주차까지 완주에 성공하신 ANOS 2기 멤버님들도 모두 축하드립니다.

다음 포스팅은 AI 전시회와 NCP DevOps, Kubernetes의 포스팅으로 찾아뵙겠습니다.
긴 글 읽어주셔서 감사합니다.

AWS

AWS NETWORK ONLINE STUDY 6-10주차 [2/3]

안녕하세요. ManVSCloud 김수현입니다.

벌써 3월이 마무리되어갑니다.
이번주 일요일은 AWS NETWORK ONLINE STUDY의 마지막 11주차 스터디가 있는 날입니다. 11주차라는 시간이 벌써 끝나간다는 아쉬움과 함께 하루도 빠짐없이 잘 해냈다는 보람도 있습니다.

오늘은 ANOS 6-10주차 후기 포스팅을 써보려합니다.
6-10주차는 크게 5가지 주제로 나뉘었습니다.

벌써 3월이 마무리되어갑니다.
이번주 일요일은 AWS NETWORK ONLINE STUDY의 마지막 11주차 스터디가 있는 날입니다. 11주차라는 시간이 벌써 끝나간다는 아쉬움과 함께 하루도 빠짐없이 잘 해냈다는 보람도 있습니다.

오늘은 ANOS 6-10주차 후기 포스팅을 써보려합니다.
6-10주차는 크게 5가지 주제로 나뉘었습니다.

# CloudFront
# Security Group & Network ACL
# WAF

# Global Accelerator & VPN
# TGW & R53 Resolver

이번 6-10 주차는 정말 1-5주차보다 더욱 알차고 배울 것이 많은 시간들을 보냈습니다.

CloudFront의 경우 CloudFront에 대해서만 배우는 것이 아니라 Cache에 대해서 배워 왜 CloudFront를 사용해야하고 정적 캐싱과 동적 캐싱에 대해서도 알아보는 시간을 가질 수 있었습니다.

제가 스터디 이후에도 CloudFront 스터디가 끝난 이후에도 해당 주제에 대해서는 추가적인 공부를 더 하였는데 블로그 포스팅으로 하려했으나 바쁜 일정에 아직도 임시글로 머물러있는 상태입니다…

Naver Cloud Platform DevOps 교육과 AI 전시회 참가로 인해 포스팅 거리가 최대 6개까지 늘어버렸군요…
최대한 시간나는대로 전부 포스팅할 예정입니다.

그리고 6-10주차 과정 중 가장 재밌었던 8주차의 WAF는 스터디에서 끝나지 않고 제 블로그에 도입되었습니다?!
아래 링크 참고하시면 WAF 기능 추가 내용 뿐만 아니라 제 블로그 구성도까지 볼 수 있습니다.

나머지 주차의 스터디도 전부 재밌었지만 이후 각각의 주제마다 느껴진 색다른 재미들이 있었다? 가 맞는 것같습니다.

스터디가 11주차까지 마무리되면 Global Accelerator & VPN과 TGW & R53 Resolver는 추가적인 복습을 할 예정입니다.
지금까지 제가 해본 적없던 것이기도 하고 아직 기초 네트워크에 대한 지식이 부족하여 조금 더 넓게 공부하고 싶은 생각이 있기때문입니다.

이번 ANOS를 통해서 매주 일요일마다 꾸준하게 공부할 수 있게 되었습니다.
이후 3기 참가하시는 분들에게 조언을 드리자면! 녹화보다는 생방송 참가 적극 권장드립니다.
일단 생방송으로 함께하는 것이 조금 더 집중에 도움되었습니다.

아마 이번 ANOS 스터디 일정이 마무리되면 NCP 시험과 계획되어 있던 Kubernetes의 CKA 자격증 공부에 집중하게 될 것같습니다.

밀린 포스팅을 업로드 한 뒤 Kubernetes의 내용이 다수 포스팅 될 예정입니다.
이만 글을 마무리하며 마지막 ANOS 11주차 포스팅으로 찾아뵙겠습니다.

CloudNet@ 팀에 다시 한 번 감사의 인사올리며
AWS NETWORK ONLINE STUDY 6-10주차 [2/3] 포스팅을 마무리 하도록 하겠습니다.

긴 글 읽어주셔서 감사합니다.