동아리연합회 홈페이지 리뉴얼
레거시 Django 데이터와 계정을 Spring Boot로 이전하고, 기존 로그인과 신규 SSO가 이어지도록 전환한 프로젝트입니다.
Period
2026.03 — Present
Tech stack
Overview
기존 동아리연합회 홈페이지는 Django·SQLite 기반으로 운영됐습니다. 게시판과 작성자 관계 일부를 문자열로 저장했고, 첨부파일은 게시글의 file1~file5 컬럼과 서버 로컬 디스크에 보관했습니다.
Spring Boot·MariaDB 기반 서비스로 전환하면서 데이터의 관계를 새 스키마에 맞게 복원하고, 미디어 파일을 S3로 이전했습니다. 계정 이관 이후에도 기존 운영진이 비밀번호를 재설정하지 않고 로그인할 수 있도록 Django 비밀번호 해시 검증을 지원했습니다. 일반 사용자는 Cognito SSO로 로그인하고, 필요한 경우 기존 홈페이지 계정을 연결할 수 있게 했습니다.
동아리연합회 홈페이지 메인 화면
제가 맡은 핵심 과제는 데이터를 옮기는 것에서 끝나지 않고, 이관된 계정과 파일을 새 서비스에서 계속 사용할 수 있게 만드는 것이었습니다.
Architecture
NCP 레거시 서버
├─ Django SQLite
│ └─ Python 데이터 변환·검증
│ └─ SSM 포트포워딩 ─→ AWS MariaDB ─→ Spring Boot
│
└─ 서버 로컬 MEDIA_ROOT
└─ Boto3 분할 업로드 ─→ AWS S3
└─ S3 키·원본 ID 매핑 ─→ MariaDB
로그인
├─ 기존 운영진 계정 ─→ Django PBKDF2 검증 ─→ 성공 시 BCrypt로 전환
└─ 일반 사용자 ──────→ Cognito SSO ──────→ 기존 계정 연결 또는 신규 가입Tech Stack
| 영역 | 기술 | 사용 목적 |
|---|---|---|
| 백엔드·인증 | Java 17, Spring Boot, Spring Security | 역할별 로그인, 기존 비밀번호 검증, SSO 계정 연결 |
| 데이터 이관 | Python, SQLite, PyMySQL | 레거시 데이터 정제·변환 및 MariaDB 적재 |
| 데이터베이스 | MariaDB, JPA | 게시글·게시판·파일·계정 관계 관리 |
| 미디어 | Boto3, AWS S3 | 서버 로컬 파일의 객체 스토리지 이전 |
| 운영 접근 | AWS Systems Manager | 외부에서 직접 접근할 수 없는 MariaDB에 포트포워딩 |
My Role
- 레거시 SQLite와 신규 JPA 스키마를 비교하고 테이블·컬럼별 이관 정책 수립
- 회원, 동아리, 게시글, 공동연습실·강의실 예약 데이터의 변환 및 검증 스크립트 구현
- 게시글·첨부파일의 원본 ID와 신규 ID 매핑, S3 업로드 및 DB 반영 절차 구성
- Django PBKDF2 비밀번호를 사용하는 기존 계정의 로그인 호환성 구현
- Cognito SSO 로그인, 기존 계정 연결 및 신규 가입 흐름 구현
Problem
관계가 문자열과 고정 컬럼에 묶인 레거시 데이터
레거시 게시글은 게시판을 FK가 아닌 게시판명 문자열로 저장했습니다. 일부 게시글은 게시판명이 없음으로 남아 있어 단순한 컬럼 복사만으로는 신규 board_id를 결정할 수 없었습니다.
첨부파일은 게시글 한 행의 file1~file5에 기록돼 있었습니다. 신규 구조에서는 파일마다 file 행을 생성하고, 새로 발급된 post.id를 FK로 연결해야 했습니다. 원본 게시글 ID를 그대로 사용하면 첨부파일이 다른 게시글에 연결될 수 있었습니다.
데이터 이관 후 발생할 수 있는 로그인 단절
레거시 계정의 비밀번호는 Django PBKDF2 형식으로 저장돼 있었습니다. 비밀번호 원문은 알 수 없으므로 모든 계정을 사전에 BCrypt로 변환할 수 없었습니다. 기존 운영진 계정을 이관하더라도 신규 서비스가 이 해시를 검증하지 못하면 사용자는 로그인할 수 없습니다.
일반 사용자의 인증은 Cognito SSO로 전환해야 했습니다. 이때 기존 홈페이지 계정과 SSO 계정을 연결하지 않으면 과거 계정의 데이터가 새 로그인과 분리될 수 있었습니다.
서버에 종속된 미디어
기존 파일은 Django 인스턴스의 로컬 MEDIA_ROOT에 저장됐습니다. 운영 미디어는 약 20GB 규모였고, 원본 서버의 RAM은 약 1GB였습니다. NCP 서버에서 AWS 폐쇄망 MariaDB에 직접 접근할 수도 없어, 파일 전송과 DB 반영을 하나의 프로세스로 처리하기 어려웠습니다.
Troubleshooting
변환 정책을 코드와 리포트로 명시
이관 스크립트의 기본 실행을 dry-run으로 구성했습니다. 원본 건수를 이관·생성·거부·의도적 제외로 나눠 대사하고, 제외와 경고 사유를 CSV 리포트로 남겼습니다.
게시판명이 유실된 게시글은 제목의 활동보고서·회의록 키워드와 작성자의 동아리·분과 정보를 이용해 대상 게시판을 추론했습니다. 미인증 가입 시도, 더미 게시글, 중복 예약 등은 각각의 정책에 따라 처리했습니다. 실제 적재 전에는 대상 스키마와 테이블 상태를 검사하고, 적재 후에는 정합성 검사 SQL을 실행하도록 했습니다.
새 게시글 ID와 S3 파일 연결
게시글은 작성 시각순으로 새 ID를 발급합니다. S3 업로드 단계에서는 원본 게시글 ID, 원본 파일명, S3 키를 매핑 JSON에 저장했습니다. DB 반영 단계에서는 같은 SQLite 스냅샷으로 원본 post.id → 신규 post.id 관계를 계산해 file.post_id에 적용했습니다.
신규 게시글이 없는 더미 게시글의 첨부파일 2건은 DB 매핑 대상에서 제외했습니다. 이를 통해 S3 업로드 성공 여부와 DB에서 실제로 연결할 수 있는 파일을 구분했습니다.
저사양 서버에서 중단 가능한 미디어 업로드
NCP 서버에서 S3로 직접 전송하고, DB 반영에는 작은 매핑 JSON만 로컬 PC로 가져오는 2단계 절차를 사용했습니다. Boto3 동시 전송 스레드를 2개, 멀티파트 청크를 5MB로 제한하고 서버에 2GB 스왑을 구성했습니다.
업로드를 500개 단위로 실행하고 성공한 파일의 S3 키를 체크포인트에 저장했습니다. 재실행하면 이미 기록된 파일은 건너뛰므로 서버가 중단돼도 이어서 처리할 수 있었습니다. 운영 중 추가된 강의실 서류 2건은 전체 매핑을 다시 반영하지 않도록 별도 증분 매핑으로 분리했습니다.
기존 비밀번호와 신규 SSO의 연결
기존 비밀번호 해시를 원형대로 이관했습니다. 로그인 시 저장된 형식을 판별해 Django PBKDF2 또는 BCrypt로 검증하고, PBKDF2 계정이 비밀번호 인증에 성공하면 해당 해시를 BCrypt로 교체하도록 했습니다. 비밀번호 재설정을 모든 운영진에게 요구하지 않으면서 계정을 점진적으로 전환할 수 있는 방식입니다.
일반 사용자는 Cognito 토큰을 검증한 뒤 이미 연결된 계정이면 로그인합니다. 연결되지 않은 경우에는 기존 홈페이지 계정을 비밀번호로 확인해 SSO 계정과 연결하거나 새 계정으로 가입할 수 있게 했습니다. 운영진과 동아리 계정은 기존 운영 방식에 맞는 별도 로그인 경로를 유지했습니다.
Result
- 2026년 11월 2일 SQLite dry-run 기준 원본 대상 24,990건 중 원본 데이터 24,620건을 이관 대상으로 판정하고 연습실 4건을 생성했습니다. 정책에 따른 제외는 370건, 변환 거부는 0건으로, 원본 기준 이관률은 **98.5%**였습니다.
| 항목 | 확인된 결과 |
|---|---|
| 회원 | 565건 이관 대상, 미인증 가입 299건 제외 |
| 동아리 | 77건 이관 대상 |
| 게시글 | 2,277건 이관 대상, 더미 2건 제외 |
| 공동연습실 예약 | 19,619건 이관 대상 |
| 강의실 예약 | 1,935건 이관 대상 |
미디어 매핑 파일에는 게시글 첨부파일 4,247건, 강의실 서류 1,678건, 이미지 보유 동아리 44곳의 S3 키가 기록됐습니다. 게시글 첨부 2건은 게시글 이관 정책에 따라 DB 매핑에서 제외했고, 강의실 서류 1건은 DB에 파일명이 있으나 원본 파일을 찾지 못해 누락 건으로 구분했습니다.
계정 전환에서는 이관된 비밀번호 해시를 그대로 검증하는 경로와 SSO 계정 연결 경로를 구현했습니다. 기존 계정의 인증 정보와 과거 데이터를 유지하면서 새 로그인 방식으로 전환할 수 있는 구조를 마련했습니다.
Retrospective
데이터 이관의 완료 기준은 행을 복사한 수만으로 정할 수 없었습니다. 게시글의 새 ID가 파일 FK와 맞는지, 기존 비밀번호를 새 서비스가 검증할 수 있는지, 사용자가 SSO 로그인 후 과거 계정에 접근할 수 있는지까지 확인해야 했습니다.
원본 건수 대사와 사유별 리포트, 파일 체크포인트, 계정 연결 흐름을 각각 설계하면서 데이터 이전과 서비스 연속성을 함께 다루는 경험을 얻었습니다. 다음 개선에서는 S3 객체 존재 여부와 DB 파일 키, 실제 UPDATE 행 수를 자동으로 대조해 운영 검증을 강화하고자 합니다.