728x90
들어가며
이 글에서는 커밋 정보를 DAG(유향 비순환 그래프) 형태로 시각화하기 위해 Mermaid.js, GitGraph.js 두 가지 도구를 활용한 구현 과정을 공유합니다.
브라우저 기반 Git 구조 표현을 통해 커밋 흐름을 직관적으로 확인할 수 있도록 구성했습니다.
흐름 요약
- DB → 커밋 + 브랜치 조인 쿼리 실행
- Java Builder → Mermaid 문자열 or GitGraph JSON 생성
- Spring Controller → 요청 처리 및 응답 반환
- JavaScript → AJAX 호출 및 콜백 연결
- mermaid.js / gitgraph.js → 브라우저 렌더링
DAG 구조 설계 기반
- 커밋 테이블(`tb_commit`)에는 `parentCommitSeq`, `mergeFromCommitSeq` 를 통해 커밋 간의 방향성과 병합 정보를 포함
- 이를 기반으로 노드 간 연결 관계를 시각화할 수 있음
- DAG 순회 방식은 DFS 기반으로 구현 (커밋 시각화용 데이터 생성 시 사용)
커밋 정보 조회 (MyBatis)
- `tb_commit` 과 `tb_branch` 테이블을 조인하여 시각화에 필요한 커밋 ID, 부모 커밋, 병합 커밋, 브랜치명, 메시지를 조회
SELECT C.SEQ
, C.BRANCH_SEQ
, B.BRANCH_NAME
, C.PARENT_COMMIT_SEQ
, C.MERGE_FROM_COMMIT_SEQ
, C.REBASE_ORIGIN_SEQ
, C.COMMIT_MESSAGE
FROM tb_commit C
JOIN tb_branch B ON C.BRANCH_SEQ = B.SEQ
WHERE C.DEL_YN = 'N'
AND B.GROUP_NAME = #{groupName}
AND B.PROJECT_NAME = #{projectName}
ORDER BY C.SEQ
Java 단 데이터 빌더 구성
MermaidBuilder
- Mermaid.js 문법 형식으로 String 스크립트를 생성
- branch, checkout, commit, merge 명령어를 순서대로 조합
// Mermaid.js 문법 예시
builder.append("branch \"feature\"\n");
builder.append("checkout \"feature\"\n");
builder.append("commit id: \"Add Login\"\n");
`MermaidBuilder.java` 전체 코드
Feat: Mermaid.js 깃 그래프
GitGraphDataBuilder
- 커밋 정보를 JS 객체 형태(List<Map<String, Object>>)로 변환
- 클라이언트 측 GitGraph.js가 바로 사용할 수 있도록 구조화
map.put("seq", commit.getSeq());
map.put("branchName", commit.getBranchName());
...
`GitGraphDataBuilder.java` 전체 코드
Feat: GitGraph.js 깃 그래프
백엔드 서비스 (Spring)
@Service
@RequiredArgsConstructor
public class CommitGraphService {
private final CommitGraphMapper commitGraphMapper;
private List<CommitGraphDto> selectCommitGraphList(CommitGraphDto commitGraphDto) {
return commitGraphMapper.selectCommitGraphList(commitGraphDto);
}
public String generateCommitGraphByMermaid(CommitGraphDto commitGraphDto) {
List<CommitGraphDto> list = selectCommitGraphList(commitGraphDto);
MermaidBuilder builder = new MermaidBuilder(list);
return builder.build();
}
public List<Map<String, Object>> generateCommitGraphByGitGraph(CommitGraphDto commitGraphDto) {
List<CommitGraphDto> list = selectCommitGraphList(commitGraphDto);
GitGraphDataBuilder builder = new GitGraphDataBuilder(list);
return builder.build();
}
}
- MyBatis 를 통해 조회한 커밋 시각화 목록을 바탕으로 `MermaidBuilder` 와 `GitGraphDataBuilder` 를 이용해 데이터를 build 하여 return
- `generateCommitGraphByMermaid` : Mermaid용 문자열 응답
- `generateCommitGraphByGitGraph` : GitGraph용 JSON 응답
시각화 렌더링
Mermaid.js
<pre class="mermaid"></pre>
<script>
function fnGenerateGraphByMermaid() {
const groupName = $('[name=groupName]').val();
const projectName = $('[name=projectName]').val();
const url = `/group/\${groupName}/project/\${projectName}/commit-graph/mermaid`;
const data = {
groupName: groupName,
projectName: projectName,
}
CommonUtils.fnPost(url, JSON.stringify(data));
}
function fnDrawGraphByMermaid(data) {
$('.mermaid').text(data)
mermaid.init(undefined, ".mermaid");
}
</script>
- Post 요청 후 응답받은 문자열을 callback 함수 `fnDrawGraphByMermaid` 로 렌더링
GitGraph.js
<div id="gitGraph"></div>
<script>
function fnGenerateGraphByGitGraph() {
const groupName = $('[name=groupName]').val();
const projectName = $('[name=projectName]').val();
const url = `/group/\${groupName}/project/\${projectName}/commit-graph/gitgraph`;
const data = {
groupName: groupName,
projectName: projectName,
}
window.CallbackMap['fnDrawGraphByGirGraph'] = fnDrawGraphByGirGraph;
CommonUtils.fnPost(url, JSON.stringify(data));
}
function fnDrawGraphByGirGraph(commitList) {
GitGraphBuilder.draw({
divId: "gitGraph",
commitList: commitList,
defaultBranch: "main",
options: {
orientation: "vertical-reverse",
displayHash: false,
displayAuthor: false,
displayBranchLabel: true,
}
});
}
</script>
- Post 요청 후 응답받은 문자열을 callback 함수 `fnDrawGraphByGirGraph` 로 렌더링
- 공통적으로 사용되는 GitGraph.js 로직은 별도 JavaScript 파일로 분리하여 모듈화
- `GitGraphBuilder.js` 전체 코드
더보기
- 모듈화 후 core.js 에 import 하여 전역에서 사용
function draw({
divId,
commitList,
defaultBranch = "main",
options = {}
}) {
const template = GitgraphJS.templateExtend(GitgraphJS.TemplateName[options.templateName || "Metro"], {
commit: {
message: {
displayHash: options.displayHash ?? false,
displayAuthor: options.displayAuthor ?? false,
},
},
branch: {
label: options.displayBranchLabel ?? true,
}
});
const canvas = document.getElementById(divId);
const gitgraph = GitgraphJS.createGitgraph(canvas, {
orientation: options.orientation || "vertical-reverse",
template: template,
});
const branchMap = {};
branchMap[defaultBranch] = gitgraph.branch(defaultBranch);
commitList.forEach(commit => {
const branchName = commit.branchName;
const parentCommitSeq = commit.parentCommitSeq;
if (!branchMap[branchName]) {
const parentBranchName = _findParentBranch(commitList, parentCommitSeq);
if (parentBranchName && branchMap[parentBranchName]) {
branchMap[branchName] = branchMap[parentBranchName].branch(branchName);
} else {
branchMap[branchName] = gitgraph.branch(branchName);
}
}
branchMap[branchName].commit({
subject: commit.commitMessage,
tag: commit.rebaseOriginSeq ? "rebase" : (commit.mergeFromCommitSeq ? "merge" : undefined),
});
if (commit.mergeFromCommitSeq) {
const mergeBranchName = _findParentBranch(commitList, commit.mergeFromCommitSeq);
if (mergeBranchName && branchMap[mergeBranchName]) {
branchMap[branchName].merge(branchMap[mergeBranchName]);
}
}
});
function _findParentBranch(commitList, parentSeq) {
const parentCommit = commitList.find(c => c.seq === parentSeq);
return parentCommit ? parentCommit.branchName : null;
}
}
export {
draw,
}
렌더링 결과 출력
Mermaid.js
GitGraph.js
커밋 데이터를 DAG 구조로 구성하고, 이를 시각화 도구에 맞게 가공해 출력하는 과정은 GitHub 클론 프로젝트의 전체 흐름을 사용자에게 직관적으로 보여주는 중요한 기능입니다.
Mermaid.js, GitGraph.js 각각의 특징과 활용 방식에 따라 시각화 전략을 선택할 수 있도록 구성했습니다.
다음 글에서는 페이지 공통 요소인 사이드바를 위한 Interceptor 기반 구조 설계와 적용 방식에 대해 다룰 예정입니다.
관련 커밋
728x90
'Java | Spring > GitHub Clone Project' 카테고리의 다른 글
[GitHub Clone] 05. 커밋 / 머지 / 리베이스 기능 구현 (1) | 2025.04.17 |
---|---|
[GitHub Clone] 04. 그룹 / 프로젝트 / 브랜치 도메인 설계 및 CRUD 구현 (1) | 2025.04.14 |
[GitHub Clone] 03. 회원 기능 및 로그인 (Session → Spring Security) (1) | 2025.04.11 |
[GitHub Clone] 02. 프로젝트 구조 및 초기 설정 (2) | 2025.04.09 |
[GitHub Clone] 01. 프로젝트 소개 및 기술 스택 정리 (0) | 2025.04.07 |