"목표를 시각화하는 것이다. 지금껏 공책에 계획을 세우고 진행과정을 적었다. 하지만, 자주 확인하는 것도 아니고, 눈에 잘 들어오는 것도 아니었다. 그래서 개인 웹사이트를 만들어, 목표를 개시해두고 진행과정을 표시해둘 수 있으면 좋겠다고 생각했다."
완성된 웹 사이트
바로가기
웹사이트 호스팅은
Netlify
를 이용하였다.
GitHub를 연결하면 바로 정적 웹사이트를 호스팅 해주는 서비스 이다.
쉽고 간편한데다가, 무료이다!
Netlify
업비트에서 제공하는 코인시세 API
를 활용한다.ajax
로 파싱한다.$(function() {
$.ajax({
url: "https://api.upbit.com/v1/ticker?markets=원화-코인",
dataType: "json",
success: function(data) {
console.log(data[0].trade_price)
}
})
})
코인 시세와 다르게 실시간 주가는 직접만든 API 라 그런지 2~3초의 딜레이가 발생한다.
AWS Lambda
를 활용한다.import json
import urllib.request
from bs4 import BeautifulSoup
def lambda_handler(event, context):
url = "https://www.marketwatch.com/investing/stock/종목코드/"
soup = BeautifulSoup(urllib.request.urlopen(url).read(), "html.parser")
a_tags = soup.find_all('bg-quote',{"class":"value"})
result_list = []
for i in a_tags:
result_list.append(i.get_text())
return {
'statusCode': 200,
'body': json.dumps(result_list)
}
python
에서 html 데이터를 추출 하기 위해 BeautifulSoup 패키지를 사용한다.
from bs4 import BeautifulSoup
pip install bs4 -t .
업비트에서 제공하는 환율 API
를 사용한다.$(function() {
$.ajax({
url: "https://quotation-api-cdn.dunamu.com/v1/forex/recent?codes=FRX.KRWUSD",
dataType: "json",
success: function(data) {
console.log(data[0].cashSellingPrice)
}
})
})
푼 문제 수를 가져오는 것은 위와 같은 방식을 사용한다면 쉽게 해결된다고 생각했다. 하지만, 1일 단위의 변동량을 계산하기 위해서는 데이터를 저장할 수 있는 공간이 필요했다. 전혀 접해보지 않았던 영역의 문제라 오랜 시간 헤매었다. 그러다가 NoSQL 방식의
AWS DynamoDB
를 활용한다면 쉽게 해결할 수 있다는 사실을 알게 되었다.
const AWS = require('aws-sdk');
const axios = require('axios');
const cheerio = require('cheerio');
const url = "https://www.acmicpc.net/user/gonudayo";
const url2 = "https://github.com/gonudayo?tab=overview&from=";
let today = new Date();
let year = today.getFullYear();
let month = ("0" + (today.getMonth() + 1)).slice(-2);
let date = ("0" + today.getDate()).slice(-2);
let resultArr = [];
let problems = 0;
var string;
var no = 0;
const getBoj = async () => {
try {
return await axios.get(url);
} catch (error) {}
};
//백준에서 총 푼 문제 수를 파싱한다.
getBoj().then(html => {
const $ = cheerio.load(html.data);
let parentTag = $("tbody tr");
parentTag.each(function(i, elem) {
let itemObj = $(this).find("td").text();
resultArr.push(itemObj);
});
problems = resultArr[1];
});
const getGithub = async () => {
try {
return await axios.get(url2 + year + "-01-01");
} catch (error) {}
};
//깃허브에서 총 커밋 수를 파밍한다.
getGithub().then(html => {
const $ = cheerio.load(html.data);
let parentTag = $("body div.js-yearly-contributions");
parentTag.each(function(i, elem) {
let itemObj = $(this).find("h2").text();
string = itemObj;
});
no = (string.replace(/[^0-9]/g, '')).slice(0, -4);
});
const ddb = new AWS.DynamoDB.DocumentClient({
region: 'ap-northeast-2'
});
exports.handler = async (event, context, callback) => {
const requestId = context.awsRequestId;
await getBoj().then(() => getGithub().then(() => createMessage(requestId).then(() => {
callback(null, {
statusCode: 201,
body: '',
headers: {
'Access-Control-Allow-Origin': '*'
}
});
}).catch((err) => {
console.error(err);
})));
};
function createMessage(requestId) {
const params = {
TableName: 'Message',
Item: {
'messageId': requestId,
'timevalue': Number(year + month + date), // 1일 단위기에 date까지 저장한다.
'countvalue': problems,
'commitvalue': no
}
};
return ddb.put(params).promise();
}
node.js
에서 html 데이터를 추출 하기 위해 axios, cheerio 모듈을 사용한다.
npm
명령어를 사용하여 axios-cheerio
를 설치한다.npm install axios -t .
npm install cheerio -t .
수시로 실행하여 데이터베이스에 불필요한 공간을 차지하지 않기 위해, 당일 23시59에 함수가 자동으로 실행되게 설정한다.
WriteMessage
함수의 트리거를 Amazon EventBridge
로 만든다. cron(58,59 14 * * ? *)
//서울 기준 23시 58분과 59에 한번씩 실행WriteMessage
함수를 처음(혹은 시간이 꽤 흐른 뒤) 실행하면 푼 문제 수 값이 반드시 '0' 으로 나온다. 뒤 이어 바로 실행하면 정상적인 값이 나오기 때문에 두번 실행하는 방법을 선택했다. (해당 문제의 원인을 안다면 제게 알려주십시오...)const AWS = require('aws-sdk');
const ddb = new AWS.DynamoDB.DocumentClient({
region: "ap-northeast-2"
});
var table_name = "Message";
exports.handler = (event, context, callback) => {
let today = new Date();
let tdaysago= new Date(Date.parse(today) - 2 * 1000 * 60 * 60 * 24); //이틀전
let startYear = tdaysago.getFullYear();
let endYear = today.getFullYear();
let startMonth = ("0" + (tdaysago.getMonth() + 1)).slice(-2);
let endMonth = ("0" + (today.getMonth() + 1)).slice(-2);
let startdate = ("0" + tdaysago.getDate()).slice(-2);
let enddate = ("0" + (today.getDate() -1)).slice(-2);
const params = {
TableName: table_name,
ProjectionExpression: "#timevalue, messageId, countvalue, commitvalue",
FilterExpression: "#timevalue between :start and :end",
ExpressionAttributeNames: {
"#timevalue": "timevalue",
},
ExpressionAttributeValues: { //이틀 전부터 오늘 데이터까지 스캔
":start": Number(startYear + startMonth + startdate),
":end": Number(endYear + endMonth + enddate)
}
};
ddb.scan(params, onScan);
function onScan(err, data) {
if (err) callback(null, err);
else callback(null, data);
}
};
참조 : AWS 개발자 가이드 : Node.js 및 DynamoDB 데이터 쿼리 및 스캔
$(function() {
$.ajax({
url: "API 주소",
dataType: "json",
success: function(data) {
$.each(data, function(index, item) {
function createArray(rows, columns) { //2차원 배열을 만든다.
var arr = new Array(rows);
for (var i = 0; i < rows; i++) {
arr[i] = new Array(columns);
}
return arr;
}
var arr = createArray(data.Count, 3); //arr[data.Count][3]
var j = 0;
for (var i = 0; i < data.Count; i++) {
if (item[i].countvalue != 0&&item[i].commitvalue != 0) {
arr[j][0] = item[i].timevalue;
arr[j][1] = item[i].countvalue;
arr[j][2] = item[i].commitvalue;
j++;
}
}
arr.sort(function(a, b) { //날짜 내림차순 정렬
return b[0] - a[0];
});
if(Math.floor(arr[0][0]/10000)!=Math.floor(arr[1][0]/10000)) arr[1][2]=0;
//깃허브 총 커밋 수는 연도별로 수집하기에 새해가 되면 초기화
var baekjoon_rate = arr[0][1] - arr[1][1];
var github_commit = arr[0][2] - arr[1][2];
document.getElementById('baekjoon').innerHTML = arr[0][1] + '(+' + baekjoon_rate + ')';
document.getElementById('github').innerHTML = arr[0][2] + '(+' + github_commit + ')';
if (baekjoon_rate == 0) document.getElementById('baekjoon').style.color = "#FF0000";
else document.getElementById('baekjoon').style.color = "#01DF01";
if (github_commit == 0) document.getElementById('github').style.color = "#FF0000";
else document.getElementById('github').style.color = "#01DF01";
//변동 값이 0 이면 적색, 1 이상이면 녹색으로 나타나도록 한다.
})
}
})
})
넓게 본다면 개발자는 그저 완벽한 코딩만 해서 끝나는 게 아니다. 고객이 원하는 바(혹은 문제를 해결)를 이룰 수 있도록 비즈니스를 하는 것이다. 그 수단 중 하나가 프로그래밍인 것이다.
나는 가장 가까이 있는 고객인 나의 요구를 해결하는 일을 해보았다.
다음에는 내 친구를 위한 서비스를 제공하는 웹사이트를 만들어보겠다.
서비스 범위를 점차 늘리며, 동시에 실력도 늘린다.