Skip to content

About

경상국립대 학우들을 위한 교내 정보 제공 카카오톡 챗봇 서비스

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

커넥트 지누 아이콘

커넥트 지누

경상국립대학교 종합 정보 챗봇 서비스

2024.03 - 운영 중

서비스 상태 운영중 카카오톡 친구 2,818명

🔷 프로젝트 개요

경상국립대학교 학우들이 학교 생활에 필요한 정보를 빠르게 확인할 수 있도록 돕는 서비스입니다.

공지사항, 학식, 학사일정, 셔틀버스 시간표 등 학교 생활에 필요한 정보를 제공합니다.


🔷 기술 스택

Backend

NestJS TypeScript Python

Database & ORM

PostgreSQL TypeORM

Infrastructure & Monitoring

Docker Docker Compose GitHub Actions GCP Compute Engine Supabase Sentry

Testing

Jest

🔷 서비스 아키텍처

image

🔷 프로젝트 기능 소개

✔︎ 학교 & 학과 공지사항 조회

notice

  • 116개의 학과, 169개의 게시판에서 실시간으로 공지사항을 스크래핑하여 제공합니다.
  • 사용자는 자신의 단과대학 및 학과를 선택하여 맞춤형 공지사항을 제공받을 수 있습니다.
  • 공지사항을 클릭하면 원본 게시글로 이동할 수 있습니다.

✔︎ 학식 메뉴 조회

diet

  • 4개 캠퍼스, 9개의 식당 학식 메뉴를 조회할 수 있습니다.
  • 원하는 캠퍼스 및 식당을 선택하면 해당 날짜의 메뉴를 한눈에 확인할 수 있습니다.
  • 매주 새로운 학식 메뉴가 자동으로 업데이트됩니다.

✔︎ 학사일정 조회

calendar

  • 매월 주요 학사 일정을 한눈에 확인할 수 있습니다.
  • 개강, 중간·기말고사, 수강신청 등 중요한 일정을 놓치지 않도록 도와줍니다.
  • 학사 일정이 업데이트되면 자동으로 반영됩니다.

🔷 사용자 요청 처리 흐름

image
  • 카카오 챗봇은 사용자의 발화를 미리 정의된 의도와 매칭하고, 각 의도에 연결된 API를 호출하는 구조입니다.
  • 예를 들어 "내일 기숙사 식당 점심 알려줘" 와 같은 자연어 요청이 들어오면, NLU가 식단 조회 의도로 분류 후 연결된 식단 API를 호출해 결과를 반환합니다.

🔷 설계 과정과 이유

제한된 기간과 팀 상황 안에서 왜 그렇게 설계했는지를 남기기 위해 작성했습니다.

각 의사결정은 문제 → 원인 → 해결 → 결과/트레이드오프 → 느낀 점 순서로 정리했습니다.

1. 데이터 모델링

drawSQL-image-export-2026-04-30

캠퍼스/단과대학/학과(Campus/College/Department)

  • 캠퍼스, 단과대학, 학과는 서로 계층적인 관계를 가지고 있습니다.
  • 4개의 캠퍼스, 17개의 단과대학, 116개의 학과가 있습니다. (2024년 기준)
  • 캠퍼스, 단과대학, 학과는 각각 고유한 한글 이름과 영어 이름을 가지고 있습니다.
  • 한글 이름은 사용자에게 보여주는 값으로 사용하고, 영어 이름은 데이터 수집 시 식별자로 사용합니다.

공지사항(Notice)

  • 각 학과에는 0개 또는 1개 이상의 공지사항 게시판이 있습니다.
  • 게시판 정보는 notice_category에 저장하고, 실제 공지 내용은 notice에 저장했습니다.
  • notice_category에는 학과 ID, 게시판 ID, 마지막으로 수집한 공지 번호를 저장합니다.
  • notice에는 제목, 작성일처럼 사용자에게 보여줄 공지 데이터를 저장합니다.
  • 이렇게 분리하면 게시판별 수집 상태와 실제 공지 데이터를 따로 관리할 수 있습니다.

학식(Cafeteria)

  • 학식 데이터는 식당 정보와 날짜별 메뉴 정보로 나누었습니다.
  • cafeteria에는 캠퍼스, 식당명, 식당 타입, 외부 식당 ID 같은 정보를 저장합니다.
  • cafeteria_diet에는 날짜, 요일, 시간대, 메뉴명처럼 매일 바뀌는 정보를 저장합니다.
  • 식당 정보와 식단 정보를 분리해 같은 식당 정보를 반복해서 저장하지 않도록 했습니다.

학사일정(Academic Calendar)

  • 학사일정은 일정 유형, 시작일, 종료일, 내용을 기준으로 저장했습니다.
  • 개강, 시험, 수강신청처럼 기간이 있는 일정이 많아 시작일과 종료일을 따로 두었습니다.
  • 특정 학과나 사용자보다 학교 전체에서 공통으로 사용하는 정보에 가까워 독립 테이블로 관리했습니다.
  • 일정 유형을 저장해 특정 유형의 일정 필터링(예: 대학생, 대학원생 등)이 가능하도록 했습니다.



2. 제한된 리소스 환경에서의 인스턴스 분리

문제

  • 서비스 초기에 GCP 프리티어 단일 인스턴스에서 API 서버, 스크래핑 작업, 모니터링을 함께 운영했습니다.
  • 스크래핑 작업이나 메트릭 수집 시 API 응답이 눈에 띄게 느려지는 문제가 발생했습니다.

원인

  • 배치 작업이 CPU와 메모리를 많이 사용하면서 API 서버가 사용할 자원이 부족해졌습니다.
  • 메모리가 부족해지면서 스왑 메모리를 사용하게 되었고, 이로 인해 디스크 I/O가 증가했습니다.
  • 여러 작업이 동시에 실행되면서 컨텍스트 스위칭이 증가해 전체적인 성능이 저하되었습니다.
image

해결

  • 문제를 해결하기 위해 역할에 따라 인스턴스를 분리하는 구조로 개선했습니다.
    1. API 서버 전용 인스턴스
    2. 스크래핑 작업 전용 인스턴스
    3. 모니터링 전용 인스턴스
  • 구글 계정 2개를 사용해 프리티어 인스턴스를 추가로 확보하여, 비용을 늘리지 않으면서도 작업을 나눠서 실행할 수 있었습니다.
  • 스크래핑 작업은 Github Actions Runner를 활용하여 주기적으로 실행되도록 구성했습니다.
image

결과

  • 리소스 경쟁이 줄어들면서 전체 시스템의 성능이 개선되었습니다.
  • 서비스 간 장애 전파 가능성을 줄였습니다.
  • 수직 확장(서버 스펙 증가)이나 수평 확장(인스턴스 추가)을 하지 않고도 문제를 해결할 수 있었습니다.
  • 결과적으로 성능 개선과 비용 절감을 동시에 달성할 수 있었습니다.

트레이드오프

  • 배포 대상과 운영 지점이 늘어나 환경 변수, 네트워크, 모니터링 설정을 더 꼼꼼히 관리해야 했습니다.

느낀 점

  • 인프라 자원은 정말 비싸다는 것을 느꼈습니다.
  • 프리티어 자원을 최대한으로 활용하면 비용 지출 없이도 충분히 서비스를 운영할 수 있다는 것을 배웠습니다.



3. 교내 데이터 수집 방식 분리

문제

  • 교내 페이지를 HTTP 요청 기반으로 수집했을 때 응답은 정상이어도 실제 데이터가 비어 있는 경우가 있었습니다.
  • 동일한 페이지를 브라우저에서는 정상적으로 확인할 수 있었지만, 코드로 수집할 경우 데이터가 누락되는 문제가 발생했습니다.

원인

  • 일부 페이지는 서버에서 완성된 HTML을 반환하는 SSR 방식이 아니라, JavaScript 실행 이후 데이터가 렌더링되는 CSR 구조였습니다.
  • 따라서 단순 HTTP 요청으로는 초기 HTML만 받아오게 되어 실제 데이터가 포함되지 않았습니다.
  • 브라우저에서는 JavaScript가 실행되면서 추가 API 요청을 통해 데이터를 가져오고 화면에 렌더링되기 때문에 차이가 발생했습니다.

SSR

CSR

해결

  • 페이지 렌더링 방식에 따라 수집 방식을 분리했습니다.
    1. SSR 페이지 → HTTP 요청 기반 수집 유지
    2. CSR 페이지 → Selenium 기반 브라우저 렌더링 수집 적용
  • 모든 페이지를 Selenium으로 처리하는 대신, 필요한 경우에만 선택적으로 적용하도록 설계했습니다.
  • 이를 위해 페이지 구조를 분석하여 CSR 여부를 판단하는 기준을 정리하고, 수집 로직을 분기 처리했습니다.
image

결과

  • 데이터가 비어 오는 문제를 해결하고 수집 정확도를 크게 개선할 수 있었습니다.
  • 필요한 페이지에만 Selenium을 적용하여 실행 시간과 리소스 사용량을 최소화할 수 있었습니다.

느낀 점

  • 데이터를 잘 수집하기 위해서는 웹 통신 과정에 대한 이해가 꼭 필요하다는 것을 느꼈습니다.
  • 특히 네트워크 탭을 통해 실제 API 요청 흐름을 분석하면서 문제를 해결할 수 있었던 경험이 인상 깊었습니다.
  • 이 경험을 통해 기능 구현 전에 동작 원리를 먼저 이해하려는 습관이 중요하다는 것을 배웠습니다.

🔷 팀원 소개

Dongho Jang
장동호
JangDongHo
hykim02
김희영
hykim02
hayeonkang
강하연
hayeonkang
brainVRG
남민우
brainVRG
minseob
김민섭
minseob

About

경상국립대 학우들을 위한 교내 정보 제공 카카오톡 챗봇 서비스

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages