전남고 LMS (교내 학생증) 개발 회고 (2024 1H - 2H)

이원찬·2024년 10월 31일
1

🌟 IDEA

우리 학교는 석식과 도서대출 등 교내 서비스를 이용하려면 학생증이 필요하다. 만약 학생증을 잃어버리가나 두고오면 교내 서비스를 이용 할 수 없게 된다. 그래서 학생증을 삼성월렛이나 애플페이처럼 휴대폰에 넣을 수 있도록 하는 앱을 만들면 어떨까? 라는 생각을 하였다.

🚀 출발

초기에는 전남고 전자학생증으로 이름을 정하려고 했지만 애플리케이션에 전자학생증 기능만 있다면 아쉬울 꺼 같아 개인별 시간표 표시, 급식 메뉴 표시, 학사일정 표시, 공지, 커뮤니티 등 다양한 기능을 추가하게 되어 전남고 학생들이 학업에 도움을 줄 수 있는 앱이 되길바라며, 전남고 LMS로 이름을 지었다.

개발을 시작하며 아래의 기술 스택들이 사용되었습니다.

· HTML, CSS, JS, PWA,
· PHP, MariaDB, Python Flask
· Linux, Docker

🚀 개발 시작

석식과 도서대출 서비스를 이용하기 전 앱을 키고 학생증을 바코드 리더기에 리딩을 하면, 교내 서비스를 이용 할 수 있게 된다.

학생데이터는 어디서??

앱 로그인은 원래 학교 웹사이트의 로그인페이지에 POST 요청을 하여 로그인하는 방식으로 하려고 했으나, 로그인 요청이 학교 웹서버 방화벽에 차단되는 현상이 발생하였다.
학생부 선생님께 부탁을 하여 전교생 학생증 데이터와 학생데이터를 제공받아서 해결하였다.
유저의 앱 방문 시간을 늘리기 위해 개인별 시간표 표시, 급식 메뉴 표시, 학사일정 표시, 공지, 커뮤니티 등 다양한 기능을 추가하였다.

시간표

DB에 위와 같이 시간표 데이터가 저장 되어있고 조회하고자하는 학생의 모든 요일과 과목 시간표를 가져온 후 period 열을 1부터 7까지 순회하며 subject 존재 한다면 출력하는 형식으로 알고리즘을 작성하였다.

<?php
require_once('db_connection.php'); // DB 연결 

function findAllSubjects($class, $student_number) {
    global $conn;
    $subjects = array();

    // 모든 요일과 교시에 대한 과목을 한 번에 조회
    $stmt = $conn->prepare("SELECT day_of_week, period, subject FROM schedule WHERE class = ? AND student_number = ?");
    $stmt->bind_param("si", $class, $student_number);
    $stmt->execute();
    $result = $stmt->get_result();

    while($row = $result->fetch_assoc()) {
        $subjects[$row['day_of_week']][$row['period']] = $row['subject'];
    }

    $stmt->close();
    return $subjects;
}
    $subjects = findAllSubjects($grade . "-" . $class, $number);
?>
    <div class="schedule-card text-left">
        <table>
            <tbody>
                <tr>
                    <td class="text-center">교시</td>
                    <td class="text-center"></td>
                    <td class="text-center"></td>
                    <td class="text-center"></td>
                    <td class="text-center"></td>
                    <td class="text-center"></td>
                </tr>
                <?php for ($i = 1; $i <= 7; $i++) : ?>
                    <tr>
                        <td class="text-center"><?php echo $i; ?></td>
                        <?php foreach (['월', '화', '수', '목', '금'] as $day) : ?>
                            <td class="table-font-size text-center"><?php echo isset($subjects[$day][$i]) ? $subjects[$day][$i] : " "; ?></td>
                        <?php endforeach; ?>
                    </tr>
                <?php endfor; ?>
            </tbody>
        </table>
    </div>
<?php
}
?>

급식 메뉴 & 학사일정

급식 메뉴는 NEIS OPEN API를 활용하였고,학사일정 또한 NEIS OPEN API을 이용하려고 했으나 디테일하게 나오질 않아, 학교 홈페이지를 파이썬을 이용하여 HTML 파싱을 하여 학사일정을 json으로 저장하는 파이썬 코드를 작성하였다. 그리고 작성한 파이썬 코드를 크론탭을 이용하여 매일 자정 12시에 파이썬 스크립트가 실행된다.

자습 출결

선생님께서 맨날 수기로 출결 기록을 하는게 불편하다고 하셔서 간단하게 자습 출결 기능을 추가하였다. 이 기능은 작년 여름방학 자습 출결 웹 애플케이션을 개발 한 적이 있어 비교적 빠르고 쉽게 개발하였지만 위치 확인 부분에서 약간의 어려움이 있었다. 만약 학생이 학교에 있지 않은 상태이면 출결이 불가능하게 만들어야했었다. 그래서 학교 네트워크는 각 사용별로 망이 분리 되어있는데 각각의 망 별로 공인 IP 주소가 다르다. 나는 이점을 이용하였다. 무조건 학교 네트워크에 연결해야만 출석 버튼이 표시되도록 개발하였다.

🖥️ 서버 구축

서버 아키텍처는 위와 같이 설계하였다. 학교인터넷을 포트포워딩하여 서버 운영이 가능은 하나, 서버운영을 위한 공인 IP주소를 받으려면 교육정보원에 문의를 하여 아주 복잡한 상황으로 이어지기 때문에 클라우드의 VM서버를 하나 생성하여 학교 서버와 VM서버와의 P2P 터널을 만든다음 클라이언트의 요청을 VM서버에서 프록시하는 구조로 설계하였다.

또한 UPS를 설치하여 학교에 정전이 발생하여도 30분간 서버에 전력을 공급할 수 있도록 UPS를 설치하여 서버의 안정성을 높혔다.

🧑 방문자 분석

앱 런칭을 하고 일 평균 조회수는 500회 이상 꾸준히 유지하고 있고, 방문자는 250명 이상 유지하고 있다. 앱의 기능 중 하나인 시간표 기능과 전자학생증 기능으로 인해 오전과 석식시간인 오후 6시가 가장 많은 것으로 추측된다.

7월 대규모 업데이트!

기존 디자인은 Neumorphism UI 디자인을 사용하였지만 그림자로 인해 화면이 뿌옇게 보이고 접근성이 떨어지는 현상이 생겨 Material 디자인으로 재디자인 하였다. AI 지문 요약은 Google의 gemini-1.5-pro 모델을 사용하였다 gemini-1.5-pro 모델이 멀티모달이고, 비용적인 측면에서 GPT 보다 훨씬 저렴하여 사용하였다. 그러나, 현재 복합적인 이슈로 인해 gemini-1.5-flash 모델을 이용하여 서비스 하고 있다. 사전은 사전 API을 이용하여 개발하려고 했지만 적당한 API 서비스를 찾지못해 다음사전을 리버스 엔지니어링하여 직접 다음사전 REST API를 개발하였다. 이 기능 개발에 관한 내용을 내용이 길어 질 것 같기 때문에 따로 작성해야겠다.

기출문제 추천 알고리즘


기출문제 추천 알고리즘은 가중치기반 추천 알고리즘으로 동작한다. 문제 Database에서 문제를 가져온다. 가져온 문제가 학생과 동갑인 학생들이 고른 문제라면 1점을 추가하고 조회수가 높은 문제, 다운로드 수가 많은 문제, 최근에 출제된 문제등 다양한 옵션들이 있는데 아래 사진과 같이 점수 배정하는 방식으로 알고리즘을 설계하였다.
(간략하게 표시한 사진임. 실제와 다름.)

🧑‍🏫선생님 관리자 페이지

학교 선생님들께서 전남고 LMS앱에 기능들을 쉽게 관리 할 수 있도록 하기위해 개발하였다. 사진에 보이는 거처럼 학생 계정 관리라든지 커뮤니티 관리라든지 앱에 있는 기능들은 쉽게 관리 할 수 있도록 하였다.

선생님 관리자 페이지를 선생님만 접근할 수 있도록 하려면 어떻게 해야할까?

학교 네트워크는 Wi_gen(학생용 무선 인터넷), 교사용 일반 인터넷, 업무용 인터넷 이렇게 세 가지 망으로 분리되어 있다. 선생님 관리자 페이지는 업무용 인터넷을 통해서만 접근할 수 있도록 설정되어 있다. 선생님이 관리자 페이지에 로그인할 때, 업무용 인터넷의 게이트웨이 페이지에 HTTP 요청을 보내고, 서버로부터 10초 이내에 응답이 없으면 업무용 인터넷을 사용하지 않는 것으로 간주하여 리다이렉트되는 구조이다.

Q. 외부 공인 IP 주소로 구분 하면 안됨?

이 기능을 구현한 후에야 “공인 IP 주소로 구분했으면 되겠네”라는 생각이 들었지만, 외부 공인 IP 주소로 구분하는 방식은 출석 체크 기능에 사용하였다.

2024년 하반기

2024년 상반기에는 기능 개발 중심으로 앱을 유지보수 했다면 하반기에는 하드웨어적으로 유지보수를 하였다.
기존에 있었던 9U 허브랙을 폐기하고 위 사진처럼 랙에 옮기고 로그서버를 새로이 구축하였다. 새로운 프로젝트를 위해 서버의 스토리지를 기존 4TB에서 5배인 20TB까지 증설하였다.
로그 서버를 구축한 이유는 법적으로 로그는 1년이상 보존 해야한다고 규정하고 있어 구축하였고 로그 분석을 사용자들의 정보, 추세, 악성 공격 기법 등등 로그 분석을 통하여 다양한 정보를 얻을 수 있어서 구축하였다. 각각의 서버에서 생성된 로그를 로그서버로 보내도록 설계하였다.

결론

이 프로젝트는 선생님의 도움없이, 주변 사람들의 도움 없이는 여기까지 오지 못했을 것이다. 전남고 LMS을 개발한다고 선생님에게 말씀드렸더니 고민없이 바로 300만원 가량 투자를 해주시고 전남대학교에서도 100만원 가까이 투자해주셨다. 이번 프로젝트로 인해 프로덕션 환경에서 무중단 서버 마이그레이션, 앱 유지보수 등 실제 서비스를 운영하는 비슷한 환경에서 제대로 실습을 할 수 있었던 기회였다. 이제 나에게 남은 과제는 전남고 뿐만 아니라 더 나아가 서비스를 확장하고, 후배들에게 이 프로젝트를 잘 인계하여 계속 발전시킬 수 있도록 하는 것이다!

profile
매우 평범한 인문계 고등학생 엔지니어

2개의 댓글

comment-user-thumbnail
2025년 2월 28일

와 정말 대단하시네요. 우분투 저장소 미러사이트 찾아보다가 한국에 전남고등학교가 있길래 뭐지 싶어서 성함도 같이 구글링하다가 들어와봤습니다. 이 프로젝트까지도 보고 대단하다고 댓글달고싶어서 velog 회원가입까지 했네요 ㅋㅋㅋ

1개의 답글

관련 채용 정보