Post

졸업요건 분석기 feat. 바이브코딩

4년전에 구상했던 졸업요건 분석기를 한번 만들어 보자

졸업요건 분석기 feat. 바이브코딩

프로젝트 이름: kuphilGraduate - 건대 철학과 졸업요건 분석기

대학교를 졸업할 때 졸업 요건이 복잡하거나, 트랙별로 정보가 흩어져 있어 많은 학생들이 혼란을 겪습니다. kuphilGraduate는 이러한 문제를 해결하기 위해 개발한 웹 애플리케이션입니다. 사용자가 트랙을 선택하면, 그에 맞는 졸업 요건 정보를 제공하고 현재 이수 상태를 시각적으로 확인할 수 있게 설계되었습니다. 기술적으로는 python3와 django를 기반으로 개발되었습니다. 파일이 업로드 된 후 메모리에서 데이터 분석만 하면 되므로 따로 데이터베이스는 사용하지 않았습니다.

졸업요건 분석기를 왜?

대학교 졸업을 준비하며 가장 많이 듣는 말 중 하나는 “이 과목을 들었어야 했다고?”이다.

에전에 행정조교를 한 적이 있었다. 조교 생활을 하면서 큰 업무라고 한다면 개강하기 전 ‘수업 시간표’를 짜는 일과 학생들의 ‘졸업 사정’을 하는 것이였다.-그리고 가끔 발생하는 학과 보고서…-
시간표는 교내 시스템으로 하면 되지만 졸업 사정은 조금 다르다. 각 학과의 졸업 내규 조건이 존재하기 때문에 학생들의 취득 학점원을 일일이 수기로 확인 해야했다.
더욱이 학생들도 자신의 졸업 요건을 수시로 확인해야 하는데 4학년 2학기가 되어서 졸업에 필요한 과목을 이수하지 않았다는 것을 알게된 학생들이 항상 있었고, 결국 졸업을 하지 못하는 경우도 빈번했다.
당시에는 시각화 프로그램을 만들어 보려다가 너무 어렵다고 생각해서 만들지 못했는데, 바이브 코딩이 떠오른 지금, 빠르게 만들어 볼 수 있었다.

🛠️ 기술 스택

  • Backend: Django (Python)
  • Frontend: Bootstrap 5, HTML/CSS/JavaScript
  • Data Processing: Pandas, openpyxl
  • Database: -
  • Deployment: Render.com

🏗️ 시스템 아키텍처

1. 프로젝트 구조

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
33
34
35
36
37
38
39
40
41
graduateCheck/                          # Django 프로젝트 루트
├── 📁 graduateCheck/                   # Django 프로젝트 설정
│   ├── settings.py                     # 프로젝트 설정 (5.1KB)
│   ├── urls.py                         # URL 라우팅 (1.3KB)
│   ├── wsgi.py                         # WSGI 설정
│   └── asgi.py                         # ASGI 설정
├── 📁 myapp/                          # 메인 Django 앱
│   ├── 📁 views/                      # 뷰 레이어
│   │   ├── graduation_check.py         # 졸업요건 분석 뷰 (2.0KB)
│   │   └── file_management.py          # 파일 관리 뷰 (2.1KB)
│   ├── 📁 services/                   # 비즈니스 로직 레이어
│   │   ├── cleaner.py                  # 기본 데이터 정제기 (5.1KB)
│   │   ├── cleaner2.py                 # 고급 데이터 정제기 (23KB)
│   │   └── 📁 graduation/             # 졸업요건 분석 서비스
│   │       ├── graduation_analyzer.py  # 메인 분석기 (9.9KB)
│   │       ├── common_required.py      # 공통필수 분석기 (6.1KB)
│   │       ├── major_required.py       # 전공필수 분석기 (5.3KB)
│   │       ├── field_trip.py          # 학술답사 분석기 (3.0KB)
│   │       ├── year2025.py            # 2025년도 요건 분석기 (9.9KB)
│   │       └── context.py             # 분석 컨텍스트 (258B)
│   ├── 📁 models/                     # 데이터 모델 레이어
│   │   └── graduation_requirement.py  # 졸업요건 모델 (2.3KB)
│   ├── 📁 config/                     # 설정 관리
│   │   └── 📁 requirements/           # 졸업요건 설정
│   │       ├── base.py                # 기본 요건 클래스 (1.5KB)
│   │       ├── year_2024.py           # 2024년도 요건 (3.5KB)
│   │       ├── year_2025.py           # 2025년도 요건 (3.1KB)
│   │       └── __init__.py            # 패키지 초기화
│   ├── 📁 templates/                  # 템플릿 레이어
│   │   ├── base.html                  # 기본 템플릿 (1.9KB)
│   │   ├── upload.html                # 업로드 페이지 (10.0KB)
│   │   ├── result.html                # 결과 페이지 (9.6KB)
│   │   ├── cleanup.html               # 정리 페이지 (2.5KB)
│   │   └── 📁 includes/               # 재사용 컴포넌트
│   │       └── modal.html             # 모달 컴포넌트 (1.7KB)
│   └── 📁 templatetags/               # 커스텀 템플릿 태그
├── 📁 media/                          # 업로드된 파일 저장소
├── 📁 logs/                           # 로그 파일
├── db.sqlite3                         # SQLite 데이터베이스 (128KB)
├── manage.py                          # Django 관리 스크립트
└── render.yaml                        # 배포 설정 (Render.com)

2. 핵심 컴포넌트

📊 ExcelStructureDetector

가장 도전적이었던 부분은 다양한 엑셀 파일 형식을 자동으로 감지하는 것이었습니다.

이중 정제 시스템 (Dual Cleaner Architecture)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# services/cleaner2.py (23KB) - 고급 정제기
class ExcelStructureDetector:
    """엑셀 파일 구조 자동 감지"""
    def __init__(self):
        self.column_keywords = {
            'year': ['년도', '학년도', '이수년도'],
            'semester': ['학기', '이수학기'],
            'course_type': ['이수구분', '과목구분'],
            'course_name': ['과목명', '교과목명'],
            'credits': ['학점', '이수학점'],
            'grade': ['성적', '등급']
        }

# 감지된 구조를 바탕으로 데이터를 정제하는 클래스
class FlexibleCleaner:
    def clean_dataframe(self, df: pd.DataFrame):
        """감지된 구조에 따라 데이터프레임을 정제"""
        structure = self.detector.detect_structure(df)
        
        if structure['format_type'] == 'credit_confirmation':
            return self._process_credit_confirmation_format(df, structure)
        else:
            return self._extract_data(df, structure)

Fallback 메커니즘

1
2
3
4
5
6
7
8
9
# services/graduation/graduation_analyzer.py
def smart_clean_dataframe(df: pd.DataFrame):
    """스마트 데이터 정제 - cleaner2 우선, 실패시 기존 cleaner 사용"""
    try:
        result = clean_dataframe_v2(df)  # 고급 정제기 시도
        return result
    except Exception as e:
        result = clean_dataframe(df)     # 기본 정제기로 fallback
        return result

주요 기능:

  • 📋 전체성적표 vs 취득학점확인원 형식 자동 구분
  • 🔍 헤더 행과 데이터 시작 행 자동 감지
  • 📝 컬럼 매핑 자동 생성 (과목명, 이수구분, 학점, 성적 등)

특별한 처리 사항:

  • 🔄 취득학점확인원: 한 행에 여러 과목이 나열된 형식 처리
  • 📊 전체성적표: 일반적인 테이블 형식 처리
  • 🧹 데이터 정제 및 유효성 검증

💡 핵심 기능 구현

1. 파일 업로드 및 처리

1
2
3
4
5
6
7
8
9
10
11
12
13
def analyze_graduation(request):
    if request.method == 'POST':
        excel_file = request.FILES['excel_file']
        student_id = request.POST.get('student_id')
        student_type = request.POST.get('student_type', 'normal')
        internship_completed = request.POST.get('internship_completed', 'no')
        
        # 학번에서 입학년도 추출
        admission_year = int(student_id[:4])
        
        df = pd.read_excel(excel_file)
        analyzer = GraduationAnalyzer()
        result = analyzer.analyze(df, student_type, admission_year, internship_completed)

2. 졸업요건 설정 관리

입학년도별로 다른 졸업요건을 체계적으로 관리합니다.

1
2
3
4
5
6
7
8
9
10
# myapp/config/requirements/year_2024.py
REQUIREMENTS_2024 = {
    'normal': {
        'total_credits': 130,
        'major_required': 21,
        'major_elective': 39,
        'general_education': 30,
        # ...
    }
}

데이터 플로우

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
graph TD
    A[엑셀 파일 업로드] --> B[ExcelStructureDetector]
    B --> C{파일 형식 감지}
    C -->|전체성적표| D[일반 테이블 파서]
    C -->|취득학점확인원| E[특수 형식 파서]
    D --> F[FlexibleCleaner]
    E --> F
    F --> G[과목명/구분 매핑]
    G --> H[GraduationAnalyzer]
    H --> I[CommonRequiredAnalyzer]
    H --> J[MajorRequiredAnalyzer]
    H --> K[FieldTripAnalyzer]
    H --> L[Year2025RequirementAnalyzer]
    I --> M[결과 통합]
    J --> M
    K --> M
    L --> M
    M --> N[결과 렌더링]

💡 인터랙티브 도움말

인턴십 의무 이수제에 대한 상세 정보를 툴팁으로 제공:

1
2
3
4
5
6
7
<div class="form-text">
    2017~2020학번은 인턴십 의무 이수제가 적용됩니다.
    <i class="bi bi-exclamation-circle-fill text-info ms-1" 
       data-bs-toggle="tooltip" 
       data-bs-title="상세 정보...">
    </i>
</div>

🚀 개발 과정에서의 도전과 해결

1. 다양한 엑셀 파일 형식 대응

문제: 포털시스템에서 제공하는 엑셀 파일이 두 가지 형식으로 제공됨

  • 전체성적표: 일반적인 테이블 형식
  • 취득학점확인원: 한 행에 여러 과목이 나열된 특수 형식

해결:

  • 파일 내용을 분석하여 형식을 자동 감지
  • 각 형식에 맞는 전용 파서 구현
  • 정규표현식을 활용한 패턴 매칭

2. 복잡한 졸업요건 로직

문제: 입학년도, 학생유형별로 다른 졸업요건 해결:

  • 설정 파일을 통한 요건 관리
  • 전략 패턴을 활용한 유연한 분석 로직

3. 사용자 경험 개선

문제: 복잡한 업로드 과정과 결과 해석의 어려움 해결:

  • 단계별 안내 제공
  • 시각적 피드백과 상세한 설명
  • 에러 상황에 대한 친절한 메시지

📊 결과 및 성과

주요 기능

  • 자동 파일 형식 감지: 99% 정확도
  • 졸업요건 분석: 철학과 내규 100% 반영
  • 다양한 학생 유형 지원: 일반학생, 편입생, 다전공자, 부전공자

사용자 피드백

  • 📈 수동 계산 대비 시간 단축: 30분 → 5초
  • 🎯 정확도 향상: 인적 오류 방지
  • 💡 편의성: 언제든지 접근 가능한 웹 서비스

🔮 향후 개선 계획

  1. 기능 확장
    • 다른 학과 지원
    • 모바일 앱 개발
  2. 성능 최적화
    • 대용량 파일 처리 개선
    • 캐싱 시스템 도입
  3. 사용자 경험
    • 실시간 분석 진행률 표시
    • 졸업 시뮬레이션 기능

💭 마무리

이 프로젝트를 통해 실제 사용자의 문제를 해결하는 소프트웨어를 만드는 경험을 할 수 있었습니다. 특히 다양한 데이터 형식을 처리하는 유연한 시스템 설계와 사용자 중심의 UI/UX 개발에 대해 많이 배웠습니다.

가장 보람찼던 점은 복잡하고 번거로웠던 졸업요건 확인 과정을 5초 만에 끝낼 수 있는 시스템으로 만들었다는 것입니다.


🔗 관련 링크

This post is licensed under CC BY 4.0 by the author.