여러 Git 저장소의 코드를 AST 기반으로 분석하고, 오픈소스 정적 분석 도구를 통합하며, 사용자 피드백(별점 + 코멘트)을 반영한 코드 개선 가능성을 제시하는 온프레미스 웹 대시보드입니다.
- 멀티 저장소 지원: GitHub, GitLab, 로컬 Git 저장소 연결
- 정적 분석 통합: cppcheck (C++), pylint + bandit (Python), PMD (Java), ESLint (JavaScript)
- AST 기반 분석: 파일/함수/클래스 단위 심볼 추출, 복잡도, 의존성 분석
- 코드 메트릭: Cyclomatic Complexity, Maintainability Index, 코드 중복, Fan-in/Fan-out
- 커밋 인텔리전스: 변경 빈도 분석 + ML 기반 커밋 목적 분류 (비지도 KMeans → 지도 Naive Bayes 하이브리드)
- 사용자 피드백: 전체 분석 결과에 대한 별점(1~5) 및 코멘트, 감성 분석
- 우선순위 점수: 정적 발견사항(35%) + 복잡도(20%) + 중복(10%) + 의존성(10%) + 변경빈도(15%) + 피드백(10%)
- 인터랙티브 대시보드: 지표 카드, 심각도/스멜/복잡도 차트, 커밋 목적 분포, Top 개선 대상
- 필터: 저장소, 언어, 기간(1주/1개월/3개월/직접지정), 심각도, 스멜 유형, 우선순위
- 인라인 드릴다운: 추천 항목 클릭 시 파일/함수 상세 findings, 심볼, 커밋 내역 표시
- 리포트 익스포트: Markdown (AI 에이전트 핸드오프용) + JSON (도구 연동용)
| 요구사항 | 버전 | 확인 |
|---|---|---|
| Python | 3.9 이상 | python --version |
| Git | 2.20 이상 | git --version |
| pip | 최신 | python -m pip install --upgrade pip |
외부 정적 분석 도구를 설치하지 않아도 대시보드는 정상 작동합니다. 도구가 없으면 해당 언어는 내장 AST 분석 + 복잡도 측정만 수행하고 정적 분석 findings는 건너뜁니다.
# C++ (cppcheck)
winget install cppcheck
# Python (pylint, bandit)
pip install pylint bandit
# Java (PMD) - https://pmd.github.io 에서 pmd-bin-*.zip 다운로드 후 PATH 등록
# 또는 scoop install pmd
# JavaScript (ESLint)
npm install -g eslint# C++
brew install cppcheck
# Python
pip3 install pylint bandit
# Java
brew install pmd
# JavaScript
npm install -g eslint# C++
sudo apt install cppcheck
# Python
pip install pylint bandit
# Java - https://pmd.github.io 에서 다운로드
# JavaScript
npm install -g eslintgit clone https://github.com/kernullist/into-the-git.git
cd into-the-git# Windows (PowerShell)
.\scripts\setup.ps1
# macOS / Linux
bash scripts/setup.sh# 가상환경 생성
python -m venv venv
# 가상환경 활성화
# Windows:
venv\Scripts\activate
# macOS/Linux:
source venv/bin/activate
# 의존성 설치
pip install -e ".[dev]" # 개발 의존성 포함
# 또는 최소 설치:
pip install -e .make setup # 가상환경 생성 + 의존성 설치 (최초 1회)
make run # 개발 서버 시작
make test # 테스트 실행
make clean # 캐시 정리
make help # 모든 명령어 확인# 설치된 패키지 확인
pip list
# 또는 requirements.txt로 설치 (pyproject.toml 기반 자동 생성)
pip install -r requirements.txtrequirements.txt는 pyproject.toml에서 생성된 고정 버전입니다. 최신 호환 버전이 필요하면 pip install -e ".[dev]"를 사용하세요.
# .env 파일 생성 (Windows)
echo GITHUB_TOKEN=ghp_your_token_here > .env
echo GITLAB_TOKEN=glpat_your_token_here >> .env
# .env 파일 생성 (macOS/Linux)
cat > .env << EOF
GITHUB_TOKEN=ghp_your_token_here
GITLAB_TOKEN=glpat_your_token_here
FLASK_DEBUG=1
EOF환경변수 목록:
| 변수 | 기본값 | 설명 |
|---|---|---|
SECRET_KEY |
랜덤 생성 | Flask 세션 암호화 키 |
DATABASE_URL |
sqlite:///data/dashboard.db |
DB 연결 문자열 |
GITHUB_TOKEN |
없음 | GitHub Personal Access Token |
GITLAB_TOKEN |
없음 | GitLab Personal Access Token |
FLASK_DEBUG |
0 |
디버그 모드 (1 = 활성화) |
MAX_ANALYSIS_TIMEOUT |
3600 |
분석 최대 시간(초) |
WORKER_THREADS |
2 |
백그라운드 워커 스레드 수 |
CLUSTER_MIN_SAMPLES |
30 |
ML 클러스터링 최소 샘플 수 |
CLASSIFIER_CONFIDENCE_THRESHOLD |
0.6 |
지도 분류기 신뢰도 임계값 |
# 개발 서버
python app.py브라우저에서 http://localhost:5000 으로 접속합니다.
# 모든 테스트 실행
python -m unittest discover tests -v
# 55 tests OK 가 출력되면 정상Project 생성 → Repository 연결 → Branch 선택 → 분석 실행 → 대시보드 검토 → 피드백 → 리포트 Export
- 메인 페이지에서 "+ New Project" 클릭
- Project 이름과 설명 입력
- "Create Project" 클릭
Project 페이지에서 "+ Add Repository" 클릭:
| Provider | URL 예시 | 토큰 필요 |
|---|---|---|
| Local Path | C:\Projects\my-repo 또는 /home/user/my-repo |
아니오 |
| GitHub | https://github.com/user/repo.git |
권장 |
| GitLab | https://gitlab.com/user/repo.git |
권장 |
- Repository 카드에서 "Select Branch" 클릭
- 분석할 Branch 선택 (드롭다운에서 자동 조회)
- 분석 기간 선택: 기본값 Last 1 Month
- Last 1 Week / Last 1 Month / Last 3 Months / Custom (날짜 직접 지정)
- "Confirm & Analyze" 클릭
- Project 페이지에서 "Run Analysis" 클릭
- 분석 실행 페이지에서 실시간 로그, 진행률, 상태 확인
- 실행 중인 작업은 Cancel 가능
- 실패한 작업은 Retry 가능 (성공한 저장소 결과 보존)
대시보드 화면 구성:
- 상단: 6개 지표 카드 (Findings, Recommendations, Avg Rating, Feedbacks, Complexity, Changes)
- 중단 좌측: Findings by Severity (막대 차트), Top Functions by Complexity (수평 막대)
- 중단 우측: Code Smell Distribution (도넛 차트), Commit Purpose Distribution (도넛 차트)
- 하단 좌측: Top Improvement Targets (우선순위 순 추천 목록)
- 하단 우측: Recent Feedback (최신 피드백 코멘트)
- 최하단: 별점 + 코멘트 피드백 제출 폼
좌측 사이드바에서 필터 적용:
- Project: 프로젝트 선택
- Repository: 저장소별 필터
- Language: Python / JavaScript / Java / C++
- Period: 1주 / 1개월 / 3개월
- Severity: Critical / Major / Minor / Info
- Smell Type: 분석 실행 시 발견된 카테고리 기준 동적 생성
- Priority: High (75+) / Medium (50-74) / Low (<50)
추천 목록의 항목을 클릭하면 우측 패널에 상세 정보 표시:
- Contributing Signals: 각 신호별 점수와 가중치
- Findings: 파일별 정적 분석 발견사항 (도구, 규칙, 심각도)
- Symbols: 함수/클래스 목록, 복잡도, 라인 위치
- Commit History: 해당 파일의 최근 커밋 내역 (작성자, 목적, 메시지)
대시보드 하단에서:
- 별점 1~5 선택 (클릭)
- 코멘트 작성 (한국어/영어 모두 지원)
- "Submit Feedback" 클릭
제출 시:
- 감성 점수 자동 계산 (긍정/부정 키워드 기반)
- 모든 추천 항목의 feedback_score 재계산
- 대시보드 지표 자동 갱신
- 분석 완료 후 "Export Report" 클릭
- Format 선택:
- Markdown: AI 코딩 에이전트에게 전달할 핸드오프 문서
- JSON: 자동화 도구/API 연동용 기계 판독 형식
- "Generate Export" → "Download" 클릭
# 프로젝트 목록
curl http://localhost:5000/api/projects
# 프로젝트 생성
curl -X POST http://localhost:5000/api/projects \
-H "Content-Type: application/json" \
-d '{"name": "My Project", "description": "프로젝트 설명"}'
# 프로젝트 삭제
curl -X DELETE http://localhost:5000/api/projects/1# 저장소 추가
curl -X POST http://localhost:5000/api/projects/1/repositories \
-H "Content-Type: application/json" \
-d '{"provider": "local", "remote_url": "/path/to/repo", "default_branch": "main"}'
# 저장소 브랜치 조회
curl http://localhost:5000/api/repositories/1/branches
# 저장소 정보 수정 (브랜치 선택)
curl -X PUT http://localhost:5000/api/repositories/1 \
-H "Content-Type: application/json" \
-d '{"selected_branches": ["main"], "default_branch": "main"}'# 분석 실행
curl -X POST http://localhost:5000/api/analysis-runs \
-H "Content-Type: application/json" \
-d '{"project_id": 1, "repository_ids": [1], "period": "1m"}'
# 실행 상태 확인
curl http://localhost:5000/api/analysis-runs/1
# 실행 취소
curl -X POST http://localhost:5000/api/analysis-runs/1/cancel
# 실패한 저장소만 재시도
curl -X POST http://localhost:5000/api/analysis-runs/1/retry \
-H "Content-Type: application/json" \
-d '{"repository_ids": [1], "period": "1m"}'# 발견사항 조회 (페이징 + 필터)
curl "http://localhost:5000/api/analysis-runs/1/findings?page=1&per_page=50&severity=critical&repository_id=1"
# 발견사항 요약
curl http://localhost:5000/api/analysis-runs/1/findings/summary
# 메트릭 조회
curl http://localhost:5000/api/analysis-runs/1/metrics
# 추천 목록
curl http://localhost:5000/api/analysis-runs/1/recommendations# 대시보드 개요 (필터 포함)
curl "http://localhost:5000/api/dashboard/overview?project_id=1&repository_id=1&severity=critical&period=1m"
# 파일 상세 (드릴다운)
curl "http://localhost:5000/api/analysis-runs/1/files/src/main.py"
# 복잡도 트렌드
curl http://localhost:5000/api/analysis-runs/1/complexity-trend# 피드백 제출
curl -X POST http://localhost:5000/api/analysis-runs/1/feedback \
-H "Content-Type: application/json" \
-d '{"rating": 4, "comment": "분석 결과가 매우 유용합니다"}'
# 피드백 조회
curl http://localhost:5000/api/analysis-runs/1/feedback
# 리포트 익스포트 (Markdown)
curl "http://localhost:5000/api/analysis-runs/1/export?format=markdown"
# 리포트 익스포트 (JSON)
curl "http://localhost:5000/api/analysis-runs/1/export?format=json"
# 익스포트 다운로드
curl -O http://localhost:5000/api/exports/1/downloadinto-the-git/
├── app.py # Flask 애플리케이션 진입점
├── config.py # 설정 (환경변수, DB 경로, 토큰)
├── database.py # SQLAlchemy 초기화
├── models.py # 11개 엔티티 데이터 모델
├── requirements.txt # Python 의존성
│
├── connectors/ # Git 저장소 커넥터
│ ├── base.py # 추상 베이스 클래스
│ ├── local.py # 로컬 Git (clone/fetch/branch/commit)
│ ├── github.py # GitHub (토큰 인증)
│ └── gitlab.py # GitLab (토큰 인증)
│
├── analysis/ # 분석 오케스트레이션
│ └── runner.py # 분석 실행기 (ThreadPoolExecutor, timeout, 로그)
│
├── analyzers/ # 정적 분석 어댑터 + AST 엔진
│ ├── base.py # 어댑터 베이스 (subprocess 실행, timeout)
│ ├── adapters.py # cppcheck / pylint / bandit / PMD / ESLint
│ ├── ast_engine.py # 다중 언어 AST 파싱 (Python ast + 정규식)
│ ├── complexity.py # Cyclomatic Complexity, MI (radon + 자체)
│ ├── duplication.py # 코드 블록 중복 탐지 (해시 기반)
│ └── dependency.py # Import/Include 의존성 분석
│
├── commit_intel/ # 커밋 인텔리전스
│ ├── frequency.py # 변경 빈도 계산
│ └── classifier.py # ML 커밋 목적 분류 (KMeans → NaiveBayes)
│
├── scoring/ # 점수 엔진
│ ├── engine.py # 우선순위 점수, 추천 생성
│ └── sentiment.py # 감성 분석 (한/영 키워드)
│
├── normalization/ # 정규화 스키마
│ └── schemas.py # Finding/Metric/CommitSignal 정규화 함수
│
├── api/ # REST API
│ └── routes.py # Flask Blueprint (16+ 엔드포인트)
│
├── templates/ # Jinja2 HTML 템플릿
│ ├── base.html # 공통 레이아웃 (사이드바 + Chart.js CDN)
│ ├── index.html # 프로젝트 목록 + 생성
│ ├── project.html # 저장소 연결 + 브랜치/기간 선택
│ ├── analysis.html # 분석 실행 모니터링
│ ├── dashboard.html # 메인 대시보드 (차트, 필터, 드릴다운)
│ └── export.html # 리포트 익스포트
│
├── static/ # 정적 파일
│ ├── css/style.css # 스타일시트
│ └── js/dashboard.js # 공통 유틸리티 함수
│
├── tests/ # 테스트
│ ├── test_core.py # 55개 단위/통합 테스트
│ └── fixtures/ # 언어별 샘플 코드
│ ├── sample.py
│ ├── sample.java
│ ├── sample.js
│ └── sample.cpp
│
└── data/ # 런타임 데이터 (자동 생성)
├── dashboard.db # SQLite 데이터베이스
├── repos/ # 클론된 저장소
└── reports/ # 익스포트된 리포트
| 엔티티 | 주요 필드 | 관계 |
|---|---|---|
| Project | id, name, description | has many Repositories, AnalysisRuns |
| Repository | id, project_id, provider, remote_url, branches | has many SourceFiles, Findings, CommitSignals |
| AnalysisRun | id, project_id, repository_ids, status, progress, logs | has many Findings, Metrics, Feedbacks, Recommendations, Exports |
| SourceFile | id, repository_id, path, language, size, hash, owner_hint | has many CodeSymbols |
| CodeSymbol | id, file_id, kind, name, location, signature, complexity | belongs to SourceFile |
| Finding | id, run_id, repository_id, file_id, tool, rule_id, severity, category, fingerprint | belongs to AnalysisRun, Repository |
| MetricSnapshot | id, run_id, scope_type, scope_id, metric_name, value | belongs to AnalysisRun |
| CommitSignal | id, repository_id, file_id, commit_sha, author, purpose_category | belongs to Repository |
| Feedback | id, run_id, rating (1-5), comment, sentiment_score | belongs to AnalysisRun |
| Recommendation | id, run_id, target_type, priority_score, rationale, contributing_signals | belongs to AnalysisRun |
| ExportReport | id, run_id, title, format, content | belongs to AnalysisRun |
queued → running → completed
→ failed
→ cancelled
priority_score = (
finding_score × 0.35 +
complexity_score × 0.20 +
duplication_score × 0.10 +
dependency_score × 0.10 +
change_freq_score × 0.15 +
feedback_score × 0.10
) × 10
improvement_score = star_rating × 0.7 + sentiment_score × 0.3
star_rating: 사용자 별점 (1~5)sentiment_score: 키워드 기반 감성 점수 (1.0~5.0)- 긍정/부정 키워드 비율에 따라 계산
- 키워드 없으면 중립 (3.0)
new_feedback_score = (old_feedback_score + improvement_score) / 2
# 전체 테스트 실행 (55 tests)
python -m unittest discover tests -v
# 특정 테스트 클래스만 실행
python -m unittest tests.test_core.TestModels -v
python -m unittest tests.test_core.TestAPI -v
python -m unittest tests.test_core.TestCommitClassifier -v
# 특정 테스트만 실행
python -m unittest tests.test_core.TestRetryPreservation.test_retry_preserves_other_repo_findings -v| 영역 | 테스트 수 | 설명 |
|---|---|---|
| Models | 6 | CRUD, 관계, 라이프사이클 |
| API | 5 | 프로젝트, 저장소, 피드백, 익스포트, 밸리데이션 |
| AST Engine | 4 | Python/JS AST 파싱, 복잡도, import 추출 |
| Complexity | 2 | Python 복잡도, Generic 복잡도 |
| Duplication | 2 | 중복 탐지, 중복 없음 케이스 |
| Dependencies | 1 | 내부/외부 의존성 분석 |
| Commit Classifier | 9 | 규칙 기반 분류, 배치 분류, 클러스터링, 지도 전환 |
| Change Frequency | 1 | 파일/작성자 변경 빈도 |
| Scoring | 2 | finding 점수, 우선순위 점수 |
| Sentiment | 5 | 긍정/부정/중립/한국어/개선 점수 |
| Fixture Files | 10 | 4개 언어 × AST + 복잡도 + 중복 + import |
| Frontend Pages | 6 | 모든 페이지 렌더링 확인 |
| Retry Preservation | 2 | 선택적 재시도, 피드백 재계산 |
pip install gunicorn
# 4 worker로 실행
gunicorn -w 4 -b 0.0.0.0:5000 app:create_app\()
# 백그라운드 실행
gunicorn -w 4 -b 0.0.0.0:5000 app:create_app\(\) --daemonpip install waitress
# waitress 실행
python -c "from waitress import serve; from app import create_app; serve(create_app(), host='0.0.0.0', port=5000)"- SECRET_KEY 설정:
export SECRET_KEY=$(python -c "import secrets; print(secrets.token_hex(32))") - 방화벽:
data/repos/디렉토리에 외부 접근 차단 - 토큰:
GITHUB_TOKEN,GITLAB_TOKEN을 환경변수로만 주입 (코드에 하드코딩 금지) - 리버스 프록시: Nginx 뒤에서 실행하여 HTTPS, rate limiting 적용
server {
listen 443 ssl;
server_name dashboard.example.com;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}# GitHub 인증 오류
→ GITHUB_TOKEN 환경변수 설정 확인
→ Personal Access Token에 repo 스코프가 있는지 확인
# 로컬 경로 접근 불가
→ provider를 "local"로 설정하고 절대경로 사용
→ Windows: C:\Projects\my-repo (역슬래시)
→ Linux/macOS: /home/user/my-repo
# 각 도구가 PATH에 있는지 확인
cppcheck --version
pylint --version
bandit --version
pmd --version
eslint --version
# 없으면 대시보드는 내장 AST 분석만 수행
→ 로그에 "No <language> static analyzers available" 메시지 출력
# SQLite DB 재생성
rm data/dashboard.db # macOS/Linux
del data\dashboard.db # Windows
python app.py # 재시작 시 자동 생성→ MAX_ANALYSIS_TIMEOUT 환경변수로 제한 시간 설정
→ 분석 기간을 1주(1w)로 줄이기
→ 대용량 저장소는 브랜치 필터 사용
→ 로그에서 "WARNING: Truncating analysis to 200 files" 메시지 확인
# 다른 포트로 실행 (Linux/macOS)
FLASK_RUN_PORT=8080 python app.py
# Windows PowerShell
$env:FLASK_RUN_PORT = "8080"
python app.py| Format | 대상 | 용도 |
|---|---|---|
| Markdown (.md) | AI 코딩 에이전트 | Findings, Recommendations, Feedback 포함 핸드오프 문서 |
| JSON (.json) | 자동화 도구 | CI/CD 파이프라인, 알림 시스템 연동 |
| Dashboard HTML | 개발자, 팀장 | 인터랙티브 차트, 필터, 드릴다운으로 직접 탐색 |
이 프로젝트는 오픈소스 도구를 사용합니다. 통합된 외부 도구의 라이선스를 배포 전에 검토하세요:
- cppcheck: GPL v3
- pylint: GPL v2
- bandit: Apache 2.0
- PMD: BSD-style
- ESLint: MIT