[Change Log]
2020-07-09 : 설치 설명서 개선, FQA 추가.
2020-05-14 : 최초 작성.
개요
작은 티스토리 플러그인
느낌의 프로젝트.
아래처럼 GitHub
스럽게 Tistory Contribition
을 보여준다. 😀
이 블로그의 메인화면
에서 라이브로 볼 수 있고,
전체 코드는 깃허브
에서 확인할 수 있다.
개발 과정
사용된 기술스택
프론트엔드
프론트엔드는 설명할 것이 별로 없다.
토대는 bachvtuan/Github-Contribution-Graph
를 사용했지만,
이대로 사용하기엔 2%
부족한 느낌이 들어 🤔 몇 군데를 손본게 전부이다.
수정사항 :
- 박스에 경계선을 주고 헤더와 푸터 추가.
- 현재 사용중인 스킨에 잘 녹아들도록
반응형
지원.
데모 페이지
와 블로그 메인화면
을 좌우로 늘렸다 줄였다 해보면 차이를 쉽게 알 수 있다.
백엔드
위의 프론트엔드 코드
는 단순히 데이터를 렌더링하는 것에 불과하기 때문에.
데이터를 수집
하고, 저장
하고, 꺼내
오는 무언가가 필요해진다.
1. 수집 단계
기본적으로는 티스토리에서 제공하는 Open API
을 활용했다.
하지만 API
를 사용하기 위한 AccessToken
을 얻으려고 할 때 마다,
사용자가 직접 브라우저
에서 동의버튼을 눌러야 했는데,
매번 손으로 누를수는 없기에 자동으로 AccessToken을 얻어올 수 있는 방법
이 필요했다.
혹시 누군가가 npmjs
에 해결책을 올려놨을까 싶어 찾아봤지만...
결국 바닥에서 직접 쌓아올리는 수 밖에 없었다.
사용자의 아이디
와 비밀번호
를 넣으면 HTTP Response
에서 AccessToken
을 얻어내도록 만들었는데,
구체적인 해결 방법은 다음과 같다.
- 사용자의 아이디와 비밀번호를 담아서
Login API
에 전송한다.
이 단계의 응답에서Session
을 추출할 수 있다. - 이렇게 얻어진 세션값을 담아서
AccessToken과 교환가능한 Code
획득 페이지에 전달한다.
동의버튼이 담긴Response
가 반환되었다면,
정규식을 통해 동의버튼 스크립트에 있는승인링크
를 추출한다. - 다시 세션값을 담아서
승인링크
에 접속한다.
이 때, 응답에서AccessToken과 교환가능한 Code
를 얻을 수 있다. - 얻어진
Code
를 사용하여AccessToken
과 교환한다.
내친김에 좀 더 가다듬어서 npm
에도 배포했지만..
어째 배보다 배꼽이 더 커진 것 같은 느낌이 든다. 😥
2. 저장 단계
이렇게 수집된 데이터를 적당히 가공하고,
가공된 데이터를 이제 어딘가에 저장해야 했다.
제일 먼저 떠오른 방법은 데이터베이스
였지만,
이 플러그인
같은 것에 데이터베이스
까지 붙이기엔 낭비같고...
차라리 게시글에 저장할까?
라는 생각으로 아래처럼 데이터만 저장할 게시글
을 따로 작성하고,
그 게시글
에만 아래처럼 데이터를 저장하기로 했다.
3. 추출 단계
블로그 게시글
에 저장을 하니 데이터를 가져오는 작업
도 쉬워졌다.
서버까지 갈 필요없이 클라이언트에서 fetch
를 사용하면 금방이였다.
Origin
도 같으므로 CORS
에 막힐 위험도 없다.
//
// 스토리지 게시글의 URL을 조합하고,
// 그 게시글의 HTML 문자열을 가져온다.
const url = `${window.location.origin}/${storagePostId}`;
const res = await fetch(storagePostUrl);
const html = await storagePostRes.text();
이렇게 추출된 데이터를 렌더링 함수에 전달하면,
멋진 컨트리뷰션 그래프가 그려진다.
4. 수집 자동화 단계
사용자가 매번 수집기
를 실행시키는 것은 번거롭기 때문에
일정 시간마다 수집기
가 알아서 동작하는 편이 좋다고 생각했다.
하지만 블로거의 컴퓨터
에 계속 상주하는 것은 조금 꺼림칙하므로,
아마존에서 제공하는 Lambda
와 CloudWatch
를 사용하여 자동화를 진행했다.
수집기 함수를 Lambda
로 등록하고,
1분마다 CloudWatch
가 Lambda
를 트리거하도록 하면,
새 게시글이 RealTime
은 아니더라도 NearTime
으로 반영되도록 할 수 있었다.
추가적으로 Lambda
에 수집기 함수를 deploy
하는 과정도 간소화하기 위해,
serverless
프레임워크를 함께 사용했다.
5. 자동화 비용 계산
단순히 만들었다!
정도로만 끝내면 안된다.
실제로 적용해도 괜찮은지 경제성
측면에서 검토가 필요했다.
첫 수집은 전수조사를 하기때문에 대략 6000ms
정도의 소요시간을 보였지만,
두 번째 부터는 이전 수집의 결과도 참고하기 때문에 3000ms
정도로 낮아졌다.
첫 수집만 테스트
를 겸해서 로컬
에서 진행하도록 하고,
그 이후로는 람다
로 진행한다고 가정하고 계산기를 두들겨보았다.
1분
마다 실행시키면 31일
인 달을 기준으로 44640
번이고,
메모리를 그닥 사용하지 않는 연산이므로 128MB
으로 놓고 사용하면
이 경우엔 $0.29
정도만 지불하면 된다.
이번에는 좀 더 나쁜 케이스
를 생각해보자.
각 함수의 최대시간을 10초
로 설정해놓은 상태에서,
모든 함수호출이 최대치를 찍는다고 가정하면.
이 경우에도 $1.00
정도만 지불하면 된다.
물론 프리티어라면 이마저도 다 깍여서 면제된다.
이 정도 비용이라면 라이브로 적용해도 괜찮지 않을까?
How to install?
티스토리
레포지터리
에서 client
폴더에 있는 js
와 css
파일들을 업로드한다.
스토리지 게시글 생성
수집된 데이터가 저장될 게시글
을 생성하고 PostID
를 메모해두자.
예를들어 이 블로그에서 게시글의 URL은 aerocode.net/352
이므로 PostID
는 352
가 된다.
기존의 게시글을 재활용할 수 있지만,
본문의 html
을 전부 깨끗하게 비워야 사용할 수 있다.
HEAD 태그
스킨의 head
태그안에 다음 스크립트를 붙여넣자.
<head>
<!-- 티스토리 컨트리뷰션 라이브러리 시작 -->
<script src="./images/github_contribution.js"></script>
<script src="./images/github_contribution_tistory_plugin.js"></script>
<link href="./images/github_contribution.css" rel="stylesheet" />
<!-- 티스토리 컨트리뷰션 라이브러리 종료 -->
</head>
만약 자신의 스킨이 jQuery
를 사용하지 않는다면,
추가적으로 다음 스크립트도 맨 위에 삽입해야 한다.
<script
src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
crossorigin="anonymous"
></script>
자신의 스킨이 jQuery
를 지원하는지 잘 모르겠다면,
블로그에서 F12
를 누르고 콘솔에 jQuery
를 찍어보면 된다.
BODY 태그
다음에는 렌더링된 그래프가 담길 홀더를 만들고,
그 아래에서 렌더링 함수를 호출한다.
대충 모양새는 다음과 같으며,
렌더링 함수의 두 번째 인자는 PostID
이다.
<body>
<!-- 티스토리 컨트리뷰션이 그려질 홀더 시작 -->
<div id="your_graph"></div>
<!-- 티스토리 컨트리뷰션이 그려질 홀더 종료 -->
<script>
//
// 티스토리 컨트리뷰션 그래프를 렌더링한다.
loadTistoryContributionGraph("#your_graph", 352);
</script>
</body>
이 블로그에서 적용한 것과 똑같은 장소에 적용하고 싶다면, 아래처럼 cover-list
의 최상단에 렌더링 코드를 추가한다. 이 때, 기존 코드
를 삭제하지 말아야 한다.
<s_cover name='cover-list'>
<!-- 티스토리 컨트리뷰션이 그려질 홀더 시작 -->
<div id="your_graph"></div>
<script>
//
// 티스토리 컨트리뷰션 그래프를 렌더링한다.
loadTistoryContributionGraph("#your_graph", 352);
</script>
<!-- 티스토리 컨트리뷰션이 그려질 홀더 종료 -->
<!-- 기존 코드 시작 -->
...
</s_cover>
디버깅
현재 디자인은 포스터
스킨의 CoverPage
를 기준으로 작성되었기 때문에,
다른 곳에 집어넣으면 문제가 있을 가능성이 매우 높다. 😱
그런 경우에는 자신의 블로그에 맞게 스타일을 수정해야 하는데,
각 스킨의 경우마다 스타일이 전부 다르기 때문에,
다른 스킨에서의 적용문의는 힘들다. 😔
이런 특이한 것을 블로그에 적용하려고 하는 분들은,
어느 정도 CSS
에 능통하실 것이라고 믿고있다.
로컬
사전 준비
수집기를 사용하기 위해서는 다음 항목이 필요하다.
각 항목을 클릭하면 해당 페이지로 이동한다.
티스토리 키를 생성할 때는 아래의 규칙을 지켜야 한다.
- 서비스 권한 : PC 어플리케이션
- 서비스 권한 : 읽기 및 쓰기
- 콜백 : https://tistory.com
환경변수 파일
server/.env
경로로 아래 예시처럼 환경변수 파일을 작성해야 한다.
기본 템플릿을 이미 server
폴더에 넣어뒀으니, 여러분은 빈칸만 채우면 된다.
targetBlogName=aerolabs
storageBlogName=aerolabs
storagePostId=352
client=티스토리_클라이언트_키
secret=티스토리_시크릿_키
id=티스토리_아이디
pw=티스토리_비밀번호
updateRange=3
includeMask=001
targetBlogName
(문자열, 필수)
이력을 조사할 블로그의 식별자이다.
그 블로그의 주소가 xxx.tistory.com
이라면 xxx
에 해당한다.
storageBlogName
(문자열, 필수)
이력을 저장할 블로그의 식별자이다.
내 블로그의 주소가 xxx.tistory.com
이라면 xxx
에 해당한다.
storageBlogId
(숫자, 필수)
이력을 저장할 게시글의 식별자이다.
그 게시글의 주소가 ~.tistory.com/xxx
이라면 xxx
에 해당한다.
client
(문자열, 필수)
티스토리 개발자 센터에서 발급받은 AppKey
와 동일하다.
secret
(문자열, 필수)
티스토리 개발자 센터에서 발급받은 SecretKey
와 동일하다.
id
(문자열, 필수)
티스토리 로그인에 사용되는 아이디.
pw
(문자열, 필수)
티스토리 로그인에 사용되는 비밀번호.
updateRange
(숫자)
최근을 기준으로 몇 달 전
의 게시글까지 수집할 것인지 가르킨다.
1
이상 12
이하의 정수이고, 기본 값은 1
이다.
첫 수집때는 12
로 고정된다.
includeMask
(문자열)
3글자 이진수 문자열이며, 수집할 게시글의 공개여부 상태를 결정한다.
이진수 문자열 xyz
에서,
x가 1로 설정되면 비공개
를 포함하여 수집한다.
y가 1로 설정되면 보호됨
을 포함하여 수집한다.
z가 1로 설정되면 공개됨
을 포함하여 수집한다.
실행 (Via NPM)
node.js
가 설치되어 있다면 npm
을 통해 수집기를 실행할 수 있다.
먼저 의존 라이브러리를 설치하기 위해 server
디렉터리에서 아래 커맨드를 입력한다.
# 의존 라이브러리 설치
$ npm install
수집기는 2가지 명령어를 지원한다.
마찬가지로 server
디렉터리에서 아래 커맨드를 입력한다.
# 수집
$ npx ts-node ./src collect
# 초기화
$ npx ts-node ./src clear
데이터를 수집해보자.
데이터가 성공적으로 수집되었다면 스토리지 게시글
이 다음과 같은 형태로 변경된다.
데이터를 초기화해보자.
데이터가 성공적으로 초기화되었다면 스토리지 게시글
의 내용이 비어있는 상태로 변경된다.
실행 (Via Docker)
node.js
를 설치하기가 그렇다면 docker
이미지를 사용할 수 있다.
# 도커 이미지 다운로드
$ docker pull myaerocode/tistory-collector
# 수집
$ docker run \
--rm \
--env-file 환경변수파일_경로 \
myaerocode/tistory-collector ./start.sh collect
# 초기화
$ docker run \
--rm \
--env-file 환경변수파일_경로 \
myaerocode/tistory-collector ./start.sh clear
자동화
배포 (Via NPM)
수집기를 람다에 배포하려면 AWS 인증서
를 위한 환경설정이 필요하다.
AWS-CLI
를 이용하거나 환경변수를 직접 설정한다.
AWS-CLI Configuration :
환경변수 설정 :
- AWS_ACCESS_KEY_ID=xxx
- AWS_SECRET_ACCESS_KEY=xxx
- AWS_DEFAULT_REGION=ap-northeast-2
환경변수 설정이 끝났다면 server
에서 다음 명령어를 실행하여 배포할 수 있다.
# 배포
$ npx serverless deploy
# 제거
$ npx serverless remove
배포 (Via Docker)
수집기를 람다에 배포하려면 AWS 인증서
를 위한 환경설정이 필요하다.
환경변수 파일
에 맨 아래의 값을 덧붙인다.
- AWS_ACCESS_KEY_ID=xxx
- AWS_SECRET_ACCESS_KEY=xxx
환경변수 설정이 끝났다면 다음 명령어를 실행하여 배포할 수 있다.
# 배포
$ docker run \
--rm \
--env-file 환경변수파일_경로 \
myaerocode/tistory-collector ./start.sh deploy
# 제거
$ docker run \
--rm \
--env-file 환경변수파일_경로 \
myaerocode/tistory-collector ./start.sh remove
테스트 실행
성공적으로 배포되면 AWS Lambda Console
에서 수집기 함수들을 확인할 수 있다.
각 함수이름을 클릭하고 테스트
버튼을 누르면 람다를 실행해볼 수 있다.
주기적으로 실행되도록 설정
CloudWatch
를 사용하여 일정시간마다 Lambda
를 호출하도록 설정할 수 있다.
CloudWatch 콘솔
에서 이벤트
- 규칙
항목으로 들어간 뒤 규칙생성
버튼을 누른다.
이벤트 발생조건은 1분마다
로 설정한다.
만약 크론 표현식
에 능통하다면
매주 월수금
, 10일에 가장 가까운 평일
같은 복잡한 조건들도 표현할 수 있다.
이벤트가 발생했을 때 트리거할 대상은 collect
로 설정하고,
세부 정보 구성
을 누르자.
마지막으로 규칙의 이름
을 정하고 설정을 마무리한다.
수집기 기록 조회
CloudWatch
를 통해 수집기의 이력을 조회할 수 있다.
FQA
수집기 실행 관련
- 아이디와 비밀번호를 올바르게 입력했는데 로그인이 실패했어요.
네트워크가 불안정
하거나 로그인이 차단
된 경우에 발생합니다.
네트워크 연결상태
또는 새로운 기기연결로 인한 차단 가능성
을 확인해주세요.
- 티스토리 키를 올바르게 입력했는데 키가 올바르지 않대요.
How to Install? -> 로컬 -> 사전준비
에서 티스토리 API를 생성할 때 지켜야 할 규칙을 다시한번 확인해주세요.
수집기 배포 관련
후기
직접 사용할 프로그램을 만들었다는 경험은 꽤 특별했다. 😃
지금은 500줄도 안되는 토이 프로젝트였지만,
나중에 이것저것 살을 붙여서 좀 더 커다랗게 만들고 싶다.
TODO List
- 잔디를 클릭하면 커버페이지의 리스트가 바뀌게끔 하고싶다.
도커를 사용해서 실행과정과 배포과정을 더 짧게 줄이고 싶다.도커를 이용한 아래의 4개 명령어만 지원하고 싶다.
(완료 2020-05-15)
# 수집
$ docker run COLLETOR_IMAGE collect
# 초기화
$ docker run COLLETOR_IMAGE clear
# 람다에 배포
$ docker run COLLETOR_IMAGE deploy
# 람다에서 제거
$ docker run COLLETOR_IMAGE remove
그럴려면 컨테이너 내부에서 AWS CLI
를 사용해야 할텐데...
환경변수를 사용해서 AWS Shared Credentials
을 설정할 수 있는 방법에 대해 찾아봐야겠다. 🤔~
Special thanks to
영감을 주신 dailyheumsi
님 감사합니다 😍
'# 블로그 > 프로젝트' 카테고리의 다른 글
[프로젝트] 소설위키 (0) | 2020.05.25 |
---|