Skip to main content

나의 블로그 여정기

ghdwlsgur
Blog Owner

요즘은 자기 PR도 굉장히 중요한 시대인 것 같습니다. 자기 자신을 스스로 다른 사람들에게 어떻게 알리느냐에 따라서 내가 받는 평가에 플러스 요인이 되기도 하죠. 이처럼 개발자 및 엔지니어에게도 스스로 배운 지식을 공유하고 기록하는 것이 유행인 것처럼 블로그도 하나의 필수 요소가 되는 것 같아요. 최근에는 네이버가 진행하는 주간일기 챌린지로 젊은 세대들이 네이버 블로그에 많이 유입되는 양상이 보이기도 합니다.

한 해를 마무리 하는 기념으로 2021년, 2022년 그동안 제가 겪었던 다양한 블로그 여정에 대해서 공유 드리고자 하며 2023년은 그동안 제가 배운 지식을 직접 말로 풀어 설명하고 고랭으로 개발한 툴에 대해서 소개드리고 쿠버네티스 및 AWS-ANS 자격증 취득을 목표로 삼았습니다.

블로그를 쓰는 목적은 개발자 및 엔지니어로서 정보를 공유하고 글을 작성하면서 학습한 개념들을 다시 한 번 정리하며 내가 제대로 알고 있는 것과 알고 있지 않은 것을 구분하고 꼬리 물기 방식으로 알고 있지 않은 것에 대해서는 거듭 확장하며 학습해나가고자 시작하였습니다.

인터넷에서 찾고 읽어버리며 지나가는 인스턴트 같은 지식들 중 오래 기억하며 실무에 활용할 가치가 높은 값진 지식들도 있는데 이러한 지식들은 꼭 제 손으로 타이핑을 하며 기록해나가야 했고 이 기록물이 남아야 제 기억에 남는 듯한 만족감을 주었고 내용을 다시 한 번 정리하는 것과 그렇지 않은 것은 굉장한 차이가 있었습니다.

이러한 확신에도 불구하고 위 방식으로 얻는 지식 습득의 효율에 대한 의구심이 들 때쯤 2022년 5월 경 참석했던 AWS 서밋 코리아 세미나에서 에반젤리스트 Jeff barr 형님(나보다 나이 많으면 형님)도 항상 블로그에 배운 것들을 손으로 타이핑하는 습관이 있다고 해서 제 의구심은 금방 사라지고 강한 확신으로 꾸준하게 학습을 이어나가게 되었습니다.

이 확신을 가지고 제가 사용해 본 여러 블로그는 벨로그, 미디움, 노션 - 우피, 티스토리, jekyll (API 정의서로 사용), docusaurus 등이 있습니다.

벨로그는 개발에 대한 지식이 매우 전무하던 불과 2년전 가장 처음 사용했던 블로그로 UI와 UX가 직관적이며 마크다운조차 친숙하지 않던 저에게 마크다운 고수(자칭고수랄까 ?)가 되게 도와준 플랫폼입니다. 가장 중요한 가격 또한 무료였구요. 이 벨로그는 제 노트처럼 편하게 사용했던 것 같아요. 마크다운이 아직 친숙하지 않은 사람들에게 추천드립니다 !

다음으로 미디움은 외국사람들이 많이 사용하고 일정 게시글을 보기 위해서 유료 멤버쉽 회원으로 전환해야 하는 비용 부담이 따르기도 합니다. 하지만 다른 블로그보다 알차고 귀중한 지식 공유가 활발하게 이루어지고 있는 블로그 플랫폼인 것 같아요. 그래서 저는 글을 쓰는 목적이 아닌 읽기 및 정보를 찾기 위해 미디움을 자주 들어가곤 합니다. 아직 미디움의 수준에 맞는 글을 작성하기에는 제 글쓰기 실력과 지식이 많이 부족한 것 같네요 ㅠㅠ... (언넝 쿠버네티스 고수로 도약하기를) 미디움은 기업들의 기술블로그로도 많이 활용되고 있답니다. 개인적으로 여러 블로그 플랫폼 중에 미디움이 가장 질이 뛰어난 내용들이 많이 게시되어 있다고 느꼈습니다.

티스토리는 개발자, 엔지니어 뿐만 아니라 일반 사용자도 많이 사용할 만큼 익숙한 블로그죠 (생략), jekyll은 API 정의서로 사용했으며 bash 또는 자바스크립트 코드 화면을 분할하여 작성할 수 있어서 API 정의서로 활용하기 좋은 것 같습니다!

노션은 아직도 정말 잘 활용하고 있는 메모장으로 노션을 정해진 규격의 블로그처럼 호스팅할 수 있게 도와주는 우피가 있답니다! 디자인도 나름 깔끔해서 좋고 무엇보다 노션의 기능을 활용할 수 있어서 플러스 요인이었지만 비용이 들어간다는 점에서 지금은 우피를 사용하고 있지 않아요. 블로그는 몇년이고 사용할 것이기에 달마다 과금이 된다면 시간이 지나고 종합적으로 따졌을 때 꽤 요금을 지불할 수도 있겠네요.

이처럼 벨로그, 미디움, 우피, 티스토리, jekyll 등을 거쳐 지금은 docusaurus를 사용하고 있습니다. 지금 읽고 있는 이 글도 docusaurus를 사용한 블로그에 게시된 글입니다. docusaurus는 리액트에 대한 전반적인 지식이 필요해요. 제겐 취준생 시절 개인 프로젝트로 MERN 스택을 사용해서 웹서비스를 만든 경험이 많은 도움이 됐어요!

그렇다면 왜 docusaurus를 선택했을까요 ?

다양한 블로그 플랫폼들을 전전하면서 개발자 및 엔지니어라면 저만의 플랫폼을 직접 구축하고 운영하는 경험쯤은 필요하다고 생각했습니다. 운영이라고 하기엔 정적페이지 뿐이지만..뭐 그렇다고 할게요. 또한 디자인도 제가 직접 구축할 수 있는 자유도가 굉장히 맘에 들었습니다! 엔드포인트인 도메인도 제 블로그만을 위한 출입구 역할을 하기도 하고요. 또한 서버를 사용하지 않기에 비용이 무료라는 점이 가장 강력한 이유이기도... 글을 게시하는 용도로 사용하면서 오랫동안 서버 비용을 충당하면서 가동하기엔 너무 큰 리소스 낭비겠죠? 다만 유의해야할 점은 깃헙 페이지로 호스팅 시에 깃헙 페이지에는 몇 가지 제약이 따릅니다. 다름 아닌 1GB 정도의 정적 파일을 깃헙 리포에 업로드할 수 있고 월 100GB 이하의 트래픽으로 운용이 가능하다는 점이었죠. (월 100GB면 제겐 엄청나게 충분한 트래픽 용량입니다. 부족했으면 좋겠네요...)

정적페이지 용량은 1GB로 충분할 것 같지만 정적컨텐츠인 이미지를 사용하다보면 금방 초과하기에 저는 S3를 사용했어요. 여기서부터 쉬운 설명을 위해 제 블로그의 아키텍처를 그려보도록 하겠습니다 !

blog-review1

다음 그림처럼 아키텍쳐를 그려보았는데 처음 구성하고 블로그를 작성하는 지금 시간이 꽤 지난 터라 S3설정과 circleci 야믈 파일을 다시 살펴보았습니다.

참고로 메인페이지의 URL에 path를 붙이지 않기 위해서는 저장소명을 도메인 URL로 바꾸셔야 합니다!!! 위 그림처럼 설정한 이유는 두 가지입니다. 배포 후에 딜레이 없이 새로 게시한 포스트가 배포된 블로그에 반영되도록 하기 위함이고 S3 스토리지에 매번 이미지를 업로드 해야 할 불편함을 없애기 위해서입니다. 앞에서 말한 github pages 제약점 중 1GB가 넘으면 안되기 때문에 이미지와 같은 컨텐츠 파일들은 스토리지에 올린 것입니다.

사용자인 제가 깃헙 저장소에 변경사항을 수정 및 이미지를 static/img 폴더에 추가해서 푸쉬를 하면 트리거에 따라 circleci 에이전트가 실행되고 야믈 파일에 설정된 대로 두 개의 job으로 나누어서 S3에 이미지를 업로드하고 깃헙 페이지에 배포를 하게 됩니다.

여기서 주의해야 할 사항이 몇 가지 있는데요. 깃헙 페이지의 경우 배포 후에 변경사항을 바로 반영하지 않지만 저장소에 pull을 진행할 경우 바로 반영되어서 중간 과정에 github pull을 추가하였습니다. 여기서 커밋 메시지에 [skip ci]를 추가하지 않을 경우 무한 루프가 발생될 수 있기에 꼭 커밋 메시지에 추가해주셔야 합니다 !

다음으로 S3 버킷 정책으로 접근 제어를 하는 방법입니다. 퍼블릭 액세스 차단 편집에서 새 퍼블릭 또는 액세스 지점 정책을 통해 부여된 버킷 및 객체에 대한 퍼블릭 액세스 차단을 체크해주고 아래 처럼 버킷 정책을 수정합니다.

Resource에는 버킷 - 속성 - Amazon 리소스 이름(ARN)을 기입해주고 aws:Referer에는 허용할 레퍼러 도메인을 기입해줍니다. 저는 제 블로그 도메인을 레퍼러로 설정하였습니다.

{
"Version": "2012-10-17",
"Id": "https referer policy",
"Statement": [
{
"Sid": "Allow get requests originating from https://ghdwlsgur.github.io/*",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "[Amazon 리소스 이름]",
"Condition": {
"StringLike": {
"aws:Referer": "[허용할 레퍼러]"
}
}
}
]
}

위 처럼 설정할 경우 레퍼러 없이 요청되거나 aws:Referer에 기입되지 않은 레퍼러로 요청될 경우 403 Forbidden을 응답 코드로 반환해 응답을 거부하게 됩니다. 자 그럼 직접 테스트를 진행해보겠습니다. 제 블로그의 경우 레퍼러에 와일드 카드를 사용하여 https://ghdwlsgur.github.io/*로 설정되어 다른 레퍼러 및 레퍼러 없이 요청하게 된다면 403 응답코드를 반환 받습니다. 테스트에는 제가 만든 gostat을 사용할게요 ! (만든 보람이 있군요)

blog-review2

여기까지 설정하실 경우 위 사진처럼 요청 헤더에 레퍼러를 올바르게 기입한다면 컨텐츠를 요청할 수 있게 됩니다.

그렇다면 왜 레퍼러를 설정할까요 ?

레퍼러를 설정해주지 않을 경우 제 이미지 링크를 사용하여 무단으로 웹 사이트에 호스팅할 수 있게 됩니다. 만약 제 이미지를 무단으로 사용하는 웹사이트의 방문객이 많을 경우 엄청난 양의 트래픽 비용을 이미지 링크 하나로 인해서 부담하게 될 수도 있습니다.

한 가지 사례로 허핑턴 포스트가 오트밀의 이미지를 가져와 기사에 무단으로 사용했는데 이때 원본 이미지를 호스팅하고 있는 오트밀이 이미지에 대한 네트워크 비용을 모두 지불해야 했습니다.

CORS 정책

레퍼러 설정에 이어서 CORS 정책도 같이 설정해주도록 합니다. Amazon S3 - 버킷 - 권한에서 쭉 내리다보면 CORS 설정이 있습니다. 저는 다음과 같이 설정하였습니다.

[
{
"AllowedHeaders": ["Referer"],
"AllowedMethods": ["GET"],
"AllowedOrigins": ["https://ghdwlsgur.github.io/*"],
"ExposeHeaders": ["ETag", "x-amz-meta-custom-header"]
}
]

제 도메인에서는 이미지를 가져오기만 할 것이기에 GET으로 설정 그리고 당연히 허용 도메인은 저의 도메인인 https://ghdwlsgur.github.io 뒤에 와일드카드를 추가하여 모두 허용해 줄 것입니다.

blog-review3

잘 적용된 모습입니다.

![logging1](https://[S3 BUCEKT ARN]/blog/AWS-Workshop/AWS-Workshop_logging1.png)

이미지를 S3에 업로드 또는 풀하는 과정은 이미지명에서 _으로 폴더명과 파일명을 구분하도록 하였고 이에 따라 /blog/AWS-Workshop 폴더를 생성하고 해당 폴더 안에 AWS-Workshop_logging1 이라는 이미지 파일을 업로드하는 것입니다. 코드 푸쉬후에도 마크다운 수정 또는 수동으로 S3에 이미지를 업로드할 필요 없이 이미지가 잘 표시되는 것을 확인할 수 있습니다. 이에 대한 자동화 구성은 circleCI의 아래 구성 파일 스크립트에서 확인하실 수 있습니다.

.circleci/config.yml

# Project Environment ====================================
# AWS_ACCESS_KEY
# AWS_ACCESS_SECRET
# AWS_REGION
# BUCKETNAME
# GA_MID
# GITHUB_TOKEN
# GITHUB_USERNAME
# USERNAME
# API_KEY 채널톡 API
# GTM_ID GoogleTagManager
# TELEGRAM_CHAT_ID
# TELEGRAM_BOT_TOKEN
# webpack 5.76.3 userkey
#===========================================================

version: 2.1
orbs:
aws-cli: circleci/aws-cli@3.1.5
jobs:
aws-cli-cred-setup:
executor: aws-cli/default
steps:
- aws-cli/setup:
aws-access-key-id: AWS_ACCESS_KEY
aws-secret-access-key: AWS_ACCESS_SECRET
aws-region: AWS_REGION
- run: >-
aws iam get-login-profile --user-name ${USERNAME}
upload-image:
docker:
- image: docker:22.06-rc-git
resource_class: small
steps:
- checkout
- setup_remote_docker:
docker_layer_caching: true
version: 20.10.17
- run:
name: Download and install awscli
command: |
apk update && apk upgrade && apk --no-cache add py-pip
pip install awscli
- run:
name: Configure aws credentials
command: |
aws configure set aws_access_key_id ${AWS_ACCESS_KEY} --profile default
aws configure set aws_secret_access_key ${AWS_ACCESS_SECRET} --profile default
aws configure set region ${AWS_REGION} --profile default
- run:
name: Create upload.sh and remove.sh
command: |
cd static/img

if [ $(ls | grep "\_" -c) -gt 0 ]; then
ls | grep "\_" > upload-file.txt
for filename in `cat upload-file.txt`;
do
echo "aws s3 cp" $filename $(echo $BUCKETNAME/$(echo $filename | cut -d '_' -f1)/) >> upload.sh;
echo rm -rf $filename >> remove.sh;
done;
fi

- run:
name: Execute command that $(sh upload.sh)
command: |
cd static/img

if [ $(ls | grep "\_" -c) -gt 0 ]; then
git config --global user.email "$GITHUB_USERNAME@users.noreply.github.com"
git config --global user.name "$USERNAME"

sh upload.sh && sh remove.sh
rm -rf remove.sh upload-file.txt upload.sh
git add .
git commit -m "[skip ci] delete image file"
git push origin master
fi

deploy-website:
docker:
- image: cimg/node:18.10.0
resource_class: small
steps:
- checkout
- run:
name: Deploy to GitHub Pages
command: |
git config --global user.email "$GITHUB_USERNAME@users.noreply.github.com"
git config --global user.name "$USERNAME"

export API_KEY=$API_KEY
export GA_MID=$GA_MID
export GTM_ID=$GTM_ID
export GISCUS_REPO_ID=$GISCUS_REPO_ID
export GISCUS_CATEGORY_ID=$GISCUS_CATEGORY_ID

echo "machine github.com login $GITHUB_USERNAME password $GITHUB_TOKEN" > ~/.netrc
yarn install && GIT_USER=$GITHUB_USERNAME USE_SSH=true yarn deploy
- run:
name: Update Website immediately
command: |
git pull
git add .
git commit --allow-empty -m "[skip ci] Circleci Trigger"
git push origin master

workflows:
aws-credentials-validate:
jobs:
- aws-cli-cred-setup:
context: aws
build_and_deploy:
jobs:
- upload-image:
filters:
branches:
only:
- master
- deploy-website:
filters:
branches:
only:
- master
requires:
- upload-image

위 스크립트의 각 job을 하나의 단계로 설명드리자면 다음과 같습니다.

  • aws-cli-cred-setup

    aws-cli ORB를 사용하여 AWS CLI를 설치하고 AWS 자격증명을 구성하는 단계로 AWS_ACCESS_KEY, AWS_ACCESS_SECRET, AWS_REGION 환경 변수를 사용하여 자격증명을 설정하고 aws iam get-login-profile 명령어를 사용하여 사용자의 로그인 프로필을 가져옵니다.

  • upload-image

    Docker 컨테이너를 사용하여 이미지를 업로드하는 단계입니다. docker 이미지를 가져오고 원격 Docker 환경을 설정 후 awscli를 다운로드하여 설치합니다. 이미지 파일을 핸들링하기 위해 upload.sh와 remove.sh 스크립트를 생성 후 스크립트에 작성된 내용에 따라 이미지를 AWS S3에 업로드하고 로컬에서는 S3에 업로드한 이미지를 삭제합니다. 현재 깃허브 저장소의 상태에 따라 Git에 커밋하고 push합니다.

  • deploy-website

    GitHub Pages로의 배포를 위해 Git 사용자 정보를 구성하고 환경 변수 설정과 함께 yarn install 및 yarn deploy를 실행하여 웹사이트를 배포하는 단계입니다. 변경된 내용을 Git에 커밋하고 push하여 웹사이트를 업데이트합니다.

위 스크립트 상단에 환경변수를 보면 아시겠지만 현재 제가 사용하는 플러그인은 채널톡, 구글 애널리틱스, 텔레그램, GISCUS 등이 있습니다. 채널톡은 메인 화면에서만 확인할 수 있으며 개인적으로 소통할 수 있는 창구로 활용하고 있으며 구글 애널리틱스는 방문자 통계 등을 확인하고 있습니다. 이밖에도 댓글 기능을 Giscus를 사용하여 구성하였고 댓글 알림으로 텔레그램을 사용했습니다. 이와 관련하여 https://github.com/ghdwlsgur/comment의 README.md에 상세하게 정리하였습니다.

정적페이지의 경우 제가 서버를 운용하는 것이 아닌 빌드 후 해당 파일을 업로드하여 배포하는 방식이기 때문에 기능적 한계가 있습니다. 하지만 이러한 기능적 한계를 다양한 플러그인으로 해결할 수 있기 때문에 정적페이지를 템플릿을 활용하여 블로그 구축을 고려할 때 다양한 플러그인을 사용할 수 있는지 고려하고 정적페이지를 커스텀하기 위해서는 해당 정적페이지 템플릿이 어떤 언어로 구성되었는지와 어떤 프레임워크에서 실행되는지 잘 고려하는 것이 중요합니다.

또한 제 블로그가 구글이나 네이버 등 포털 사이트에 노출시키기 위해서 제가 작성한 게시글에 대해서 꾸준하게 인덱싱을 해줘야 합니다. 즉, 도메인을 자주 변경하지 않는 것이 좋으며 처음 사용한 도메인을 오랫동안 유지하는 것이 중요합니다. 구글의 색인 생성은 Google Search Console에서 만들 수 있습니다.

정적페이지 템플릿은 https://jamstack.org/generators/에서 확인하실 수 있습니다. 자신이 평소에 사용하는 언어나 자신있는 언어 또는 사용했던 프레임워크 위에 구성된 템플릿 잘 선택하여 우리 모두 멋있는 블로그를 효율적으로 운용해봐요!

제 블로그 여정기는 여기서 마치겠습니다.

감사합니다.