✅ 오늘의 목표
- GitHub 조직의 레포지토리와 멤버 목록 불러오기
- 선택한 레포지토리의 커밋 내역 가져오기
- 요일별 커밋 수 계산 및 시각화
🧩 문제 상황 / 배경
- GitHub 조직의 협업 기여도를 주간 단위로 한눈에 파악하기 어려움
- 단순 커밋 수만 보여주는 방식은 누가 언제 활동했는지 파악하기 힘들었음
- 협업 활성화와 주간 기여도 확인을 위한 시각적 커밋 분석 도구 필요
🛠️ 해결 과정 / 코드 정리
🔸 GitHub 조직 정보 병렬 요청
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| export const getOrgsInfo = async (org) => {
try {
const [members, repos] = await Promise.all([
axios.get(`${BASE_URL}/orgs/${org}/members`),
axios.get(`${BASE_URL}/orgs/${org}/repos`),
]);
return {
members: members.data,
repos: repos.data,
};
} catch (error) {
console.log("조직 정보 가져오기 실패", error);
}
};
|
members
와 repos
는 서로 의존적이지 않으므로 Promise.all()
을 사용하여 병렬로 요청- 병렬 요청은 전체 응답 대기 시간 단축과 UX 개선에 효과적.
✅ Promise.all()
을 사용한 이유는?
- 독립적인 비동기 요청을 동시에 처리해 불필요한 대기 시간을 줄일 수 있습니다.
- 모든 요청이 성공해야 결과를 반환하며, 하나라도 실패하면 전체가 실패(reject)되므로 적절한 에러 핸들링이 중요합니다.
- 병렬 요청을 통해 성능 최적화 가능하며, 전체 응답 대기 시간을 줄일 수 있습니다.
1
2
3
| Promise.all([p1, p2, p3])
→ p1, p2, p3가 모두 resolve되면 [v1, v2, v3] 반환
→ 하나라도 reject되면 즉시 error throw
|
Promise.all()
은 단순히 “동시에 요청”하는 것이 아니라, 여러 개의 Promise 객체를 배열 형태로 받아 모두 resolve될 때까지 기다린 후, 결과를 배열 형태로 반환함
[병렬 처리 조건]
- 각 요청이 독립적일 것
- 모든 요청의 결과가 동시에 필요한 경우에 적합
🔸 선택한 레포지토리의 주간 커밋 수 계산 로직
1. 조직 레포의 커밋 정보 불러오기
1
2
3
4
5
6
7
8
9
| // 조직 repo 불러오기
export const getOrgsRepos = async (orgs, repo) => {
try {
const res = await axios.get(`${BASE_URL}/repos/${orgs}/${repo}/commits`);
return res.data;
} catch (error) {
console.log("조직 정보 가져오기 실패", error);
}
};
|
- 주어진 org, repo를 기준으로 해당 저장소의 커밋 내역을 요청
GitHub Organizations Commit 응답 데이터 구조
2. 주간 커밋 수 계산 로직
2-1. 커밋 날짜 기준으로 주간 범위 생성
즉, 5월 13일 커밋한 경우 7일 ~ 13일까지의 데이터를 가져와야함.
1
2
3
4
5
6
7
8
9
| const today = new Date(); // Tue May 27 2025 15:20:15 GMT+0900 (한국 표준시)
today.setUTCHours(0, 0, 0, 0); // Tue May 27 2025 09:00:00 GMT+0900 (한국 표준시)
// ['2025-05-21', '2025-05-22', '2025-05-23', '2025-05-24', '2025-05-25', '2025-05-26', '2025-05-27']
const dateArray = [...Array(7)].map((_, i) => {
const d = new Date(today);
d.setUTCDate(today.getUTCDate() - (6 - i));
return d.toISOString().split("T")[0];
});
|
✅ 왜 UTC 기준으로 생성하나요?
- GitHub의
commit.commit.author.date
는 UTC 기반임 - 클라이언트에서도 UTC 기준으로 일주일을 생성해야 정확한 날짜 매칭이 가능
today.setUTCHours(0,0,0,0)
으로 시간을 자정(00:00:00)으로 초기화 → 날짜 비교에서 시간 요소 제거.
내가 헷갈려서 정리하는 date()
변수
1
2
| console.log(d) // Wed May 21 2025 15:43:16 GMT+0900 (한국 표준시)
console.log(d.toISOString()); // 2025-05-21T06:43:16.454Z
|
setUTCDate(n)
: 날짜를 UTC 기준으로 n일로 설정getUTCDate()
: 현재 날짜 객체의 UTC 기준 일(day) 값을 반환
2-2. 요일별 커밋 수 누적을 위한 초기 상태 구성
1
2
3
4
| const commitCountByDay = dateArray.reduce((acc, dateStr) => {
acc[dateStr] = { total: 0, mine: 0 };
return acc;
}, {});
|
- 커밋 수를 날짜별로 누적 저장하기 위해, 날짜별 키와 초기값을 설정
reduce
로 commitCountByDay = { '2025-05-21': { total: 0, mine: 0 }, ... }
형식으로 초기화.
2-3. 커밋 데이터를 순회하면서 날짜별, 유저별 누적
1
2
3
4
5
6
7
| commit.forEach((commit) => {
const dateStr = new Date(commit.commit.author.date).toISOString().split("T")[0];
const authorLogin = commit.author?.login || commit.commit.author?.name || "anonymous";
commitCountByDay[dateStr].total += 1;
if (authorLogin === curUserLogin) commitCountByDay[dateStr].mine += 1;
});
|
- 날짜(dateStr) 기준으로 커밋을 그룹화하고, 현재 로그인한 사용자(curUserLogin)의 커밋을 별도로 구분해야 함
- 작성자 구분은
login → name → fallback
순으로 식별 total
,mine
각각 날짜 별 커밋 수 누적
전체 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| useEffect(() => {
if (!commits || !curUserLogin) return;
// 커밋 날짜 기준으로 주간 범위 생성
const today = new Date();
today.setUTCHours(0, 0, 0, 0); // 시간 초기화
// 요일 배열
const dateArray = [...Array(7)].map((_, i) => {
const d = new Date(today);
d.setUTCDate(today.getUTCDate() - (6 - i));
return d.toISOString().split("T")[0];
});
const commitCountByDay = dateArray.reduce((acc, dateStr) => {
acc[dateStr] = { total: 0, mine: 0 };
return acc;
}, {});
// 커밋 수 계산
commit.forEach((commit) => {
const dateStr = new Date(commit.commit.author.date).toISOString().split("T")[0];
const authorLogin = commit.author?.login || commit.commit.author?.name || "anonymous";
commitCountByDay[dateStr].total += 1;
if (authorLogin === curUserLogin) {
commitCountByDay[dateStr].mine += 1;
}
});
setCommitCounts(commitCountByDay); // 집계 결과 상태에 반영
}, [commits, curUserLogin]);
|
🔸 커밋 수 차트로 시각화 (Recharts)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| <ResponsiveContainer width="100%" height={300}>
<LineChart
data={chartData}
margin=
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis allowDecimals={false} />
<Tooltip />
<Legend />
<Line type="monotone" dataKey="total" stroke="#5f41b2" name="전체 커밋 수" />
<Line type="monotone" dataKey="mine" stroke="#545d69" name="내 커밋 수" />
</LineChart>
</ResponsiveContainer>
|
total
과 mine
두 개의 라인을 통해 팀 전체와 개인 커밋 비교 가능- 사용자 인터랙션을 고려한
Tooltip
, Legend
적용
✅ 결과 및 느낀 점
- 일별 커밋 수를 시각화하면서 협업 흐름을 쉽게 파악할 수 있게 되었고, 개인의 기여도도 명확해졌음
- API 요청, 데이터 전처리, 시각화까지 전체 흐름을 경험하면서 프론트엔드 데이터 처리 능력을 키울 수 있었음
- Recharts의 직관적인 API 덕분에 해당 프로젝트를 진행하면서 나의 기여도를 확인할 수 있었음.
🖼️ 작업 결과물
Reference
이 포스트는 아래 게시글의 정보 및 이미지가 사용되었습니다.
- GitHub REST API: Commits
- Recharts 공식 문서
- JavaScript ISO Date Formatting
END