NeuroWhAI의 잡블로그

티스토리에 글 조회수를 표시하기 위한 개발자의 여정 기록 본문

개발 및 공부

티스토리에 글 조회수를 표시하기 위한 개발자의 여정 기록

NeuroWhAI 2018. 11. 11. 12:20


서두

사실 바로 며칠 전부터 블로그 주인장은 통계를 볼 수 있게 되었습니다.
다만 2018년 1월 1일 이후의 데이터만 존재하고 방문자는 볼 수 없다는게 흠이죠.

소중한 방문자 분들의 시간을 낭비시키기 싫으니 미리 말씀드리는데
조회수 표시는 성공했으나 개인 서버와 도메인이 없거나 개발자가 아닌 사람들은 적용하기 힘든 방법입니다!

아래 사진은 결과물!



본문

아무튼 저는 제 글에 조회수가 작게 나타나면 보기 좋겠다 싶어서 검색을 해봤습니다.
그랬더니 이것저것 나오긴 하더라고요.
가장 마음에 들었던 방법은 구글 스프레시트를 DB이자 서버로 사용해서 표시하는 방법이었는데
저는 공부와 재미를 위해서 직접 개발하기로 하였습니다.

초기 계획은 Rust 언어와 Rocket이라는 웹 프레임워크로 서버를 개발하고 Heroku에 올린 뒤
MongoDB를 사용해서 직접 조회수 데이터를 관리할 생각이었습니다.
그리고 티스토리에서 XMLHttpRequest로 HTTP API를 호출해서 조회수를 받아 표시할 예정이었죠.
그러나 이 방법은 서버 가동 이전의 조회수는 기록이 안된다는 것과 중복 조회를 배제하기 힘들다는 문제가 바로 드러납니다.

그래서 조언을 통해 Google Analytics API를 사용하기로 합니다.
그런데 OAuth2.0 방법이 너무 복잡해서 막히게 됩니다.
금요일 내내 구글링만 하다가 접었을겁니다 ㅠㅠ
그러다가 Service account를 사용하면 인증을 쉽게 수행하고 유지할 수 있다는 걸 알게 됨과 동시에
Rust에 OAuth2.0을 위한 yup_oauth2 라이브러리와 이를 사용한 google_analytics3가 있다는 것도 알아냅니다.
이걸로 적어도 서버는 만들 수 있겠다 싶었죠.
다만 예제나 정보가 부족해서 레퍼런스만 보면서 개발해야 했는데 참... 고됬습니다.
게다가 구름IDE에서 코딩한지라 자동완성도 없고 하이라이팅도 없고... ㅠㅠ


이 상태로 코딩했습니다 ㅠㅠ

토요일에 결국 API 사용에 성공은 합니다.
http://hostname/pv/{ids}/{page_id}로 GET 요청을 보내면 경로에 해당하는 조회수를 응답해주는 형식이었죠.
이제 이걸 Heroku에 올리고 티스토리에서 사용하는 일만 남았었는데 JSFiddle에서 테스트 해보고 넣으려고 했었습니다.
그런데...


...?
어? 시X 뭐야. 이랬죠.
사실 어느정도 예감은 했었습니다.
예전에 어디선가 보안 때문에 https에서는 http 연결을 수행할 수 없다고...
웹 초짜인 저에게 "Heroku에 Rust로 만든 서버를 올리고 SSL 인증서를 발급 받아 HTTPS 연결이 되도록 하자"는 너무 힘든 현실이었습니다.
결국 Heroku에서 돌리는 것은 포기하게 됩니다.
이게 무얼 의미하는가? 무료 호스팅을 사용할 수 없게 되었다 이겁니다.
아니 조회수 하나 표시하자고 돈을 내야 한다고?
하지만 다행히 저는 소중한 방문자분들 덕분에 Paperspace에 무료 크레딧을 조금 가지고 있었습니다.
그리고 또 다행으로 Nginx로 Rocket 서버를 https로 여는 방법이 적힌 gist를 찾게됩니다.
물론 Nginx를 쓰는 방법은 몰랐지만요... ㅠ

그래도 일단 해보기라도 하자는 마음으로 월 17달러나 드는(물론 크레딧이 있으니 현금은 안썼지만...) Ubuntu 서버를 하나 파고
글에 적힌 대로 진행해봤습니다.
하지만 결국 'Getting the certificates' 단계에서 막히게 됩니다.
certbot이 서버에 특정 파일을 만들고 letsencrypt의 인증 서버가 이 파일에 접근할 수 있으면 인증이 완료되는 그런 시스템인 듯 했는데
아무리 해도 404 에러를 받는다는 로그가 나오는 겁니다.
이걸로 몇 시간을 삽질하다가 결국 일요일로 넘어갑니다.

토요일 밤에 잠깐 든 생각은 퍼미션이나 webroot 설정이 문제가 아닐까?하는 것이었기에 아침부터 확인 작업을 했습니다.
그래서 테스트 더미 파일을 의심이 되는 경로에 넣고 직접 URI를 입력해서 나오나 안나오나 확인을 해봤는데
분명히 웹루트를 /var/www/letsencrypt로 설정했음에도 /var/www/html로 동작한다는걸 알아냈습니다.
그래서 설정의 문제인가 싶으면서도 분명히 gist에 적힌 대로 했는데 안될리가 없어라는 생각이 들기도 했죠.
그러다가 default 페이지의 설정을 잠깐 훑어보는데 제가 적었던 설정과 좀 다른 부분이 있는겁니다.
default 예제에 있던 포트 설정은
port 80;
port [::]:80;
이랬는데
저는 port[::]:80;만 있었던거죠.
gist의 문서에도 해당 내용이 살짝 있었는데 제가 이해를 못해서 그냥 무작정 따라치기만 한게 원인이었습니다.
그래서 port 80;과 port 443;도 추가하니 뭔가 달라지기 시작했습니다.
404 에러 대신 다른 에러가 뜬거죠.
...
하지만 곧 해결했습니다.
설정에서 return 301 ... 리디렉트 부분을 주석처리 하니 더미 파일을 불러올 수 있었습니다.
이 상태로 letsencrypt 인증도 성공하게 되었습니다.
얏호!

서버를 실행하고 대망의 첫 https 접속을 하는데 잠깐 안되다가 갑자기 되더군요.
뭐... 되니까 된거죠 ㅎㅎ


와! 샌즈!

진짜 고생 많이 했고 이제 적용할 일만 남은거죠. ㅎㅎ
JSFiddle에서 테스트 하고 바로 딱!


딱.. 어..?
하...
아.. 진정하고 에러를 보니 CORS라는 무슨 한국형 메르스도 아니고 이상한 키워드가 보이네요.
뭐 찾아보니 A도메인 사이트에서 B도메인으로 접속하려면 뭔가 또 보안 때문인지 쉽게는 안된다고 하네요.
그래도 다행히 이건 제 서버에서 해결할 수 있는 문제였습니다.
응답에 헤더 몇개만 추가하면 되는거였죠.
뭐 이 요청을 Cross-Origin에서도 허용하겠다는 그런 의미의 헤더?
코드를 수정하고 다시 빌드하고 다시 실행하고 JSFiddle에서 다시 테스트를 했습니다.


와!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
끼얏호!
바로 티스토리로 달려서 스킨 편집을 했습니다.


와 진짜 너무 감격이었습니다. ㅠㅠㅠ

아래는 사용한 스크립트입니다.
function httpGetAsync(theUrl, callback) {
	var xmlHttp = new XMLHttpRequest();
	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
			callback(xmlHttp.responseText);
	}
	xmlHttp.open("GET", theUrl, true);
	xmlHttp.send(null);
}

function isPostPage(theUrl) {
	return /^\/[0-9]+$/g.test(theUrl)
}

let pathName = location.pathname;
if (pathName && pathName.length > 1 && isPostPage(pathName)) {
	let pvUrl = "https://neurowhai.cf/pv/ga:167060084" + pathName;
	httpGetAsync(pvUrl, function(res) {
		var checkExists = setInterval(function() {
			let boxPv = document.getElementById('box_pv');
			if (boxPv) {
				boxPv.innerText = "조회수 : " + res;
				clearInterval(checkExists);
			}
		}, 100);
	});
}

쓰고 보니 진짜 노가다 많이 했네요 ㅠㅠ
이렇게 길게 쓰다니;;

물론 아직 끝은 아닙니다.
Paperspace 크레딧을 다 쓰기 전에 기존 서버로 이전을 하던가 더 싼 서버로 옮겨야 합니다.
흠...
뭐... 아직 크레딧 다 쓰려면 좀 남았으니 나중에 생각하죠 ㅎㅎ


그럼 이만!




Comments