학기 중에 Node.js 공부를 하던 도중, 학교 개발 동아리 Megabrain에서 각 동아리원들 코딩 실태 조사(?) 느낌으로 도입했던 Wakatime이라는 서비스가 있었다.
wakatime은 개발 시간 측정 서비스로 각 개발 ide 플러그인으로 구현 되어있다. 모든 동아리원이 플러그인을 적용하여 매주 얼마나 개발을 했는지 확인 용도로 서비스를 사용하고 있었다.
매주 불편하게 discord에 캡쳐하고, 업로드하는 방식이 불편했던 나는 Wakatime에서 제공하는 API를 가져와 우리만의 WakaTime LeaderBoard를 만들어 보자! 생각하여 Wakatime API를 살펴보았다.
https://wakatime.com/developers
해당 사이트에서 API Docs를 읽은 후 바로 개발을 시작하였다.
MySQL + node.js 조합으로 개발 하고자 먼저 동아리방 서버에 있는 MySQL에 megatime 테이블을 만들고 해당 테이블에 동아리원들 이름 및 WakaTime API키를 전부 삽입해 주었다.
해당 DB에 접속 하기 위해 mysql 라이브러리를 통해 동아리방 sql 서버에 연결했다.
import mysql from "mysql";
import dotenv from "dotenv";
dotenv.config();
const connection = mysql.createConnection({
host: process.env.sql_ip,
user: process.env.sql_id,
password: process.env.sql_password,
port: process.env.sql_port,
database: "megatime",
});
connection.connect((error) => {
if (error) throw error;
});
export default connection;
/getUser api
각 유저의 세부 정보를 넘겨주는 api이다. WakaTime API 중에서 users/current/summaries라는 api가 있는데, 이 api를 활용할 때 param으로 7일, 14일, 30일 중 하나를 선택하여 해당 일 수만큼의 코딩 시간 데이터를 받을 수 있다.
connection.query(
`SELECT * FROM megatime.member WHERE member_id LIKE '${id}'`,
async (error, row) => {
if (row.length !== 0) {
const { data } = await axios.get(
`https://wakatime.com/api/v1/users/current/summaries?range=last_${day}_days`,
{
headers: {
Authorization: `Basic ${row[0].api_key}`,
},
}
);
SQL DB에 저장된 동아리원 고유 id 값을 가져와 그 유저의 api key를 Authorization에 삽입하고, api를 받아 와 준다. 만약 30일을 day param으로 넣었다면 배열 안에 30개의 Object가 나에게 돌아오게 된다. 해당 데이터를 다시 프론트엔드로 뿌려주기 위해 데이터를 정렬 및 가공한 뒤 데이터를 넘겨주었다.
data.data.map((i, index) => {
const date = new Date(data.start);
i.editors.map((item) => { // Editor 정보 가공
for (let i = 0; i < newEditorData.length; i++) {
if (item.name === newEditorData[i].name) {
return (newEditorData[i].seconds += item.total_seconds);
}
}
return newEditorData.push({
name: item.name,
seconds: item.total_seconds,
});
});
i.languages.map((item) => { // Language 정보 가공
for (let i = 0; i < newLanguageData.length; i++) {
if (item.name === newLanguageData[i].name) {
return (newLanguageData[i].seconds += item.total_seconds);
}
}
return newLanguageData.push({
name: item.name,
seconds: item.total_seconds,
});
});
i.projects.map((item) => { // Project 정보 가공
for (let i = 0; i < newProjectData.length; i++) {
if (item.name === newProjectData[i].name) {
return (newProjectData[i].seconds += item.total_seconds);
}
}
return newProjectData.push({
name: item.name,
seconds: item.total_seconds,
});
});
date.setDate(date.getDate() + index + 1);
newWeekLabel.push(date.getUTCMonth() + 1 + "/" + date.getUTCDate());
newWeekData.push(i.grand_total.total_seconds);
});
res.send({
username: row[0].username,
weekData: { label: newWeekLabel, data: newWeekData },
day_7_info: data.cummulative_total,
editors: newEditorData,
languages: newLanguageData,
projects: newProjectData,
});
} else {
res.status(500).send("서버 오류");
}
/getUsers api
DB에 저장되어 있는 모든 유저들의 정보를 한 번에 보여주는 API이다.
connection.query(
"SELECT member_id, username, last_7_days, last_14_days, last_30_days, Organization FROM megatime.member",
(error, row) => {
if (error) throw error;
const date = new Date();
try {
const newRow = row.map((item) => {
return (
item && {
...item,
last_7_days: parseDate(item.last_7_days),
last_14_days: parseDate(item.last_14_days),
last_30_days: parseDate(item.last_30_days),
}
);
});
res.send(newRow);
} catch (e) {
res.status(500).send(e);
}
}
);
SQL DB에 저장된 데이터들을 배열로 가공하여 보내주는 방식을 사용하였다. 한번에 7일, 14일, 30일 데이터를 보낼 수 있게 되었다.
스웨거 구축
API 명세서를 쉽게 볼 수 있도록 Swagger 라이브러리를 추가하여 볼 수 있도록 하였다. 스웨거는 정말 편한 거 같다. 프론트 개발을 할 때마다 느끼는 점이다.
결론
누구에게 보여주기 민망한 코드를 작성했던 것 같다. 일단 완성하고 보자라는 마인드가 컸기 때문에 엄청난 콜백 지옥과 스파게티 코드로 가득하다. 시간이 남을 때 node.js에서 nest.js로 전환하면서 리팩토링 하는 과정을 거쳐봐도 좋을 것 같다.
프로젝트 전체 코드는 아래 깃허브에서 확인할 수 있다. 결과물이 궁금하다면 프론트엔드 제작기를 참고하면 될 것 같다.
https://github.com/ShinJongUng/Mega-Waka-Board-be-v2
'백엔드 개발 > Mega Waka Board 프로젝트' 카테고리의 다른 글
[#1/node.js] 서버에서 갑자기 오류를 내뿜는다.. (1) | 2023.01.30 |
---|