Skip to content

(한림대학교 졸업작품) 한림대학교 정보과학대학 소프트웨어학부 웹애플리케이션

Notifications You must be signed in to change notification settings

wtgs9817/Capstone-Design

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

81 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🎓 Hallym Software Graduation Self-Check Web App

한림대학교 정보과학대학 소프트웨어학부 학생들을 위한
졸업 자가진단 및 정보 커뮤니티 플랫폼입니다.


⭐ update

  • 25/10/19 - nGrinder 추가
  • 25/09/18 - Redis 추가
  • 25/06/16 - 모니터링 시스템 추가(prometheus + grafana)

⏳ 개발 기간

  • 2025년 3월 ~ 2025년 5월 (총 2개월)

👨‍👩‍👧‍👦 팀 정보


👍 개선점

좋아요 기능 동시성 문제 해결 및 Redis 도입을 통한 성능 개선 / nGrinder 기반 성능 검증

좋아요 기능은 다수의 사용자가 동시에 요청을 보낼 경우 동시성 문제에 취약하며, 경쟁 상태가 발생하면 중복 저장, 누락, 좋아요 수 불일치 등의 문제가 생겨 데이터 정합성을 확보하기 어렵습니다. Spring data Redis 에 기본적으로 적용되는 Lettuce를 기반으로 락을 구현하여 해결하려고 진행했습니다. 하지만 Lettuce의 경우 스핀 락 방식으로 직접 구현해서 사용해야 한다는 불편함과 락 획득 실패 시 지속적으로 락 획득을 위해 요청을 한다는 단점이 있어 Redisson 기반 분산락 방식으로 진행하게 되었습니다.

해당 방식의 경우 pub/sub 방식으로 락이 해제될 때 Redis 서버가 해제 이벤트를 브로드캐스트하고, 이를 구독 중인 클라이언트들이 수신하여 재시도하는 구조입니다. 이를 통해 불필요한 반복 요청 없이 효율적으로 락 경쟁을 제어할 수 있습니다.

nGrinder를 통해 현재 DB에 존재하는 4개의 아이디로 1분동안 검증을 진행했습니다.

이전 버전으로 진행했을 때 총 실행 테스트 1,133 / 성공한 테스트 1,130 / 에러 3 이라는 결과가 나왔으며, DB에서 해당 게시글과 좋아요를 확인한 결과 게시글에 저장된 좋아요 수는 8개 이지만, 좋아요를 누른 기록은 3회로 기록되어 있어 데이터 정합성이 깨진 결과를 확인할 수 있었습니다.

성능 개선 버전으로 진행했을 때는 실행 테스트 2421 / 성공한 테스트 2421/ 에러 0 이라는 결과가 나왔으며, DB에서 확인했을 때 게시글의 좋아요 수 3 , 좋아요 기록에도 3개가 저장되어 있어 데이터 정합성이 확보되었고, 동시성 문제도 해결된 것을 확인할 수 있었습니다.

또한 Redis의 단일 스레드 구조를 기반으로, 다수의 요청이 동시에 들어와도 모든 연산이 순차적으로 처리됩니다.이를 활용하여 INCR 명령어를 통해 좋아요 수를 원자적으로 증가시킴으로써 동시성 문제를 해결하고, DB 접근 없이 Redis 캐시에서 데이터를 조회하도록 구성하여 DB 부하를 줄이고 응답 속도를 향상시켰습니다.

이전 버전 TPS : 19.4 / 최고 TPS : 26 평균 응답 속도 : 205.59ms / 최고 응답 속도 : 161ms
성능 개선 버전 TPS 43.1 최고 TPS : 58 평균 응답 속도 : 93.13ms / 최고 응답 속도 : 71ms

TPS는 약 2.2배 향상, 평균 응답 속도는 약 55% 개선되는 성능 향상 효과를 확인했습니다.



Redis 캐시 도입을 통한 조회 성능 최적화 및 DB 부하 감소 / nGrinder 기반 성능 검증

커뮤니티 게시판의 경우 수정이나 삭제보다 조회 비율이 압도적으로 높습니다.
실제 운영 환경을 가정했을 때, 다수의 사용자가 동시에 조회 요청을 보낼 경우 DB 부하 증가와 응답 속도 저하가 예상되었습니다. 또한 AWS RDS를 사용하고 있어 네트워크 왕복 비용과 디스크 I/O 부하까지 고려해야 했습니다.
이러한 상황에서 Redis 캐싱을 도입하여 DB 접근 빈도를 최소화하고, DB까지 도달하지 않고도 캐시에 저장된 데이터를 직접 반환함으로써 조회 성능을 최적화했습니다. 데이터 정합성을 위해 게시글이 추가·수정·삭제될 때마다 캐시를 무효화하고, 최신 데이터를 재캐싱하여 DB와의 일관성을 유지했습니다.
성능 검증을 위해 nGrinder300명의 가상 사용자를 생성해 동시에 조회 API를 호출하는 부하 테스트를 수행했습니다.

그 결과, 평균 응답속도는 540ms → 29ms, TPS는 542 → 9,913으로 개선되어 DB 부하 감소와 조회 성능 향상 효과를 수치로 검증할 수 있었습니다.


이전 버전

TPS : 542.1 / 최고 TPS : 715
평균 응답 속도 : 540.06ms / 최고 응답 속도 : 425ms
총 실행 테스트 : 28,366 / 성공한 테스트 : 28,366 / 에러 : 0

성능 개선 버전

TPS : 9,913.1 / 최고 TPS : 13,346
평균 응답 속도 : 29.38ms / 최고 응답 속도 : 21ms
총 실행 테스트 : 517,551 / 성공한 테스트 : 517,551 / 에러 : 0

TPS는 약 18.39배 향상, 평균 응답 속도는 약 94.6% 개선되는 성능 향상 효과를 확인했습니다.



캐시 스탬피드 문제 대응 구조 설계

캐시가 만료되는 시점에 다수의 사용자가 동시에 API를 요청하면, 모든 요청이 캐시 미스로 인해 DB로 쏠리면서 부하가 급격히 증가하고, 이후 각 요청이 동일한 데이터를 다시 캐시에 저장하면서 불필요한 중복 작업이 발생하게 됩니다.
이를 해결하기 위해 락 기반으로 캐시가 만료되어 데이터가 존재하지 않을 때, 하나의 스레드 또는 인스턴스만 락을 획득해 DB에서 데이터를 조회하고, 조회된 데이터를 캐시에 저장한 뒤 락을 해제하도록 하여, 동일 시점의 다중 요청 중 단 한 번만 DB 접근이 이루어지도록 했습니다.
이후의 요청들은 갱신된 캐시 데이터를 조회하도록 하여, DB 부하를 최소화하고 캐시 스탬피드 문제를 효과적으로 방지했습니다.



모니터링 : 애플리케이션을 실제로 운영한다고 가정했을 때 애플리케이션의 CPU·메모리 사용량이나 특정 API의 요청이 비정상적으로 집중될 경우, 문제를 빠르게 인지하고 대응하기가 어려웠습니다. 특히 장애 발생 시 원인을 즉시 추적하지 못하면 서비스 안정성에 치명적인 영향을 줄 수 있었습니다.
이러한 문제를 해결하기 위해 Spring Boot 애플리케이션과 Nginx를 대상으로 Grafana + Prometheus 기반의 모니터링 시스템을 구축하였습니다. 이를 통해 CPU 사용량, 메모리 사용량, HTTP 요청 수, 상태 코드 등을 실시간으로 수치화하고 시각화하였습니다. 또한 비정상적인 HTTP 상태 코드가 반복적으로 발생하거나 특정 API의 요청이 과도하게 몰리는 상황을 즉시 감지할 수 있도록 하여, 문제 발생 시 원인 파악과 확장/장애 대응이 가능하도록 설계했습니다.
이 모니터링 시스템을 통해 서비스 운영 시 애플리케이션 상태를 수치 기반으로 관리할 수 있었고, 장애가 발생하기 전 또는 발생 직후 신속하게 대응하는 역량을 확보할 수 있었습니다.
실제로 게시글 수정 기능이 정상적으로 처리가 되는 것처럼 보였지만 모니터링 시스템에서 403 응답 코드가 확인이 되어 이를 통해 문제를 확인하고 분석하여 해결할 수 있었습니다.
이를 통해 시스템 안정성이 향상되었고, 문제 해결 능력과 운영 역량을 향상할 수 있었습니다.

DB : 이전 프로젝트에서는 팀장님의 로컬 환경에 구축된 데이터베이스를 사용하여, PC가 종료될 경우 팀 전체의 작업에 제한이 있었습니다. 이러한 문제를 해결하기 위해, 이번 프로젝트에서는 AWS에서 제공하는 관계형 데이터베이스 서비스(RDS)를 사용했습니다. 이를 통해 항상 안정적으로 접근하고 협업이 가능한 환경을 구축할 수 있었습니다.


배포 문제 : 이전 프로젝트에서는 WAR 방식으로 배포를 진행하였으며, 이 과정에서의 JDK 버전, 설정 경로, WAS 버전 등 환경 차이로 인한 오류가 발생했었습니다. 또한, 배포 과정 자체도 복잡하고 수동 작업이 많아 효율성이 떨어졌습니다.
이번 프로젝트에서는 Docker 기반의 배포방식을 사용하여 이러한 문제를 해결하고자 했습니다. 개발 및 테스트가 완료된 환경을 Docker 이미지로 패키징한 뒤, 해당 이미지를 팀원들과 공유하고, 각자의 로컬에서 동일한 이미지 기반의 컨테이너로 실행함으로써 환경 차이에서 발생하던 오류를 해결할 수 있었습니다. Docker 의 경우 WAR 방식과 달리 실행 환경 자체를 이미지로 패키징하기 때문에 애플리케이션을 빌드한 개발자의 환경 그대로를 다른 PC 에서 재현 가능하다는 점에서 안정성과 유지보수성을 개선시킬 수 있었습니다. 이로인해 배포 시간을 단축하고 협업중에 발생하는 환경문제를 해결했습니다.


Spring Boot + JSP 조합에서 발생한 문제 : 이전 프로젝트에서는 기존의 Spring Boot + JSP 단일 구조를 사용하여 동적 데이터 처리, 클라이언트 응답, JSP 렌더링을 모두 WAS가 전담하는 방식으로 구현했습니다. 이 구조는 프로젝트 규모가 작을 경우에는 큰 문제가 발생하지 않았지만, 실무 수준의 대규모 트래픽이나 복잡한 비즈니스 로직 환경에서는 WAS에 부하가 생기고, 응답 지연 및 유지보수의 어려움이 발생할 수 있는 구조적인 문제가 있다는 걸 알 수 있었습니다.
이번 프로젝트에서는 (Nginx + React) + Spring Boot 구조를 사용하여 WAS 는 동적 데이터 처리, 클라이언트 응답에 집중하고 웹서버(Nginx)에서는 React 에서 렌더링된 정적 리소스를 받아서 클라이언트에 보여주고 React 에서 rest api 를 통해 WAS 로 보내는 요청을 받아 WAS 쪽으로 요청을 전송하고 응답을 받아 다시 React 로 보내주는 리버스 프록시 역할을 하며 모든 작업을 전담하던 이전 방식과 달리 역할을 분리하여 서버의 부하를 줄이고 유지보수 측면에서도 실무에서 적용 가능한 구조로 개선되었다고 판단합니다.



📌 프로젝트 개요

기존 학과 홈페이지의 정보 접근성과 커뮤니케이션 한계를 보완하여,
졸업요건·이수과목·학년별 커리큘럼 정보를 손쉽게 조회할 수 있는 졸업 자가진단 기능과,
취업정보 게시판, 공지사항 연동, 학생 간 소통을 위한 커뮤니티 기능을 추가 구현했습니다.
이를 통해 신입생·전과생·편입생도 학사정보에 쉽게 접근하고, 재학생 간 유기적인 소통이 가능한 환경을 제공합니다.


⚙️ 핵심 기능

  • 🎓 졸업 자가진단
    필수 과목 이수 여부, 전공별 커리큘럼 안내, 학년별 추천 교과목

  • 📢 학과 공지사항 연동
    학과 홈페이지 공지를 실시간 연동

  • 💬 선후배 커뮤니티 게시판
    자유로운 질의응답 및 경험 공유 공간

  • 🖥️ 모니터링 시스템
    Spring Boot Actuator, Nginx exporter, Node exporter 기반 시계열 메트릭을 prometheus로 수집
    grafana로 시각화하여 정상 범위를 벗어난 이상 징후를 실시간으로 인지하고 문제해결을 할 수 있도록 설계


🧑‍💻 주요 기술 스택

🖼️ Frontend

  • React
  • HTML / CSS / JavaScript
  • Figma (와이어프레임 설계)

🧠 Backend

  • Java
  • Spring Boot
  • Spring Data JPA
  • Redis

🗄️ Database

  • MySQL
  • AWS RDS
  • ERD 기반 설계

🌐 인프라 / 배포

  • AWS EC2 (서버 배포)
  • Nginx (리버스 프록시 & 정적 리소스 서빙)
  • Docker (개발 환경 컨테이너화)

🖥️ Monitoring

  • Spring Boot Actuator (애플리케이션 레벨 메트릭 수집)
  • nginx exporter (Nginx 웹 서버 상태 정보 수집)
  • node exporter (서버의 자원 메트릭 수집)
  • prometheus (시계열 메트릭 수집 및 저장)
  • grafana (수집한 메트릭 시각화)

🧰 기타 도구

  • GitHub (협업 및 버전 관리)
  • Notion (프로젝트 진행 일지)
  • VS Code / IntelliJ (개발 환경)
  • nGrinder (성능 테스트)

프로젝트 구조도

캡스톤디자인_진짜최종

모니터링 구조도

캡스톤디자인_모니터링_아키텍쳐


ERD

https://www.erdcloud.com/d/GY9Xrhxdv5uLzPhDA

image


API 명세서

https://www.notion.so/215093794d9780af93a5c95188562951?v=215093794d978017b619000c8b379007&source=copy_link

image


👤 회원가입

  • 학교 이메일 기반 인증 코드 발송 및 검증 후 회원가입 진행한다. (학교 학생 외 가입 차단)

image
  • 사용자 비밀번호를 BCrypt 해시 알고리즘으로 암호화하여 보안성 강화(Spring Security의 BCryptPasswordEncoder 사용)
  • 해시값은 복호화가 불가능한 단방향 암호화 방식이며, 로그인 시 입력값을 동일한 방식으로 해싱한 뒤 저장된 해시값과 비교하여 인증을 수행한다.

🎉 메인화면

  • 사용자는 홈페이지 메인 화면에서 프로젝트 전반의 정보를 확인할 수 있다.

🧑‍💻 로그인

  • 사용자는 학교 이메일을 통해 본인 인증 후 회원가입을 진행한다.
  • 가입 완료 후 로그인하여 서비스를 이용할 수 있다.
  • 로그인 시 JWT(Json Web Token) 이 생성되고, 클라이언트 localstorage 에 저장 (토큰 유효기간 1시간)
  • 토큰의 서명, 만료 시간, 사용자 ID 검증하여 토큰의 유효성을 판단

📘 졸업 자가진단 페이지

  • "현재 이수 과목 등록" 버튼을 눌러 이수한 과목을 체크한 뒤 저장할 수 있다.
  • 과목 정보를 수정할 경우, 선택된 과목을 해제한 후 다시 저장하면 반영이 된다.
  • 저장된 과목 정보를 바탕으로 졸업 자가진단 결과를 확인할 수 있다.

  • 우측 트랙 배너를 클릭하면 전공별 트랙 및 학년별 추천 과목을 확인할 수 있다.

🗣️ 커뮤니티 페이지

  • 사용자는 글쓰기 버튼을 눌러 게시글을 작성하고 등록할 수 있다.

  • 작성한 게시글은 본인이 수정하거나 삭제할 수 있다.
  • 게시글 내에서 공감(좋아요) 버튼을 누를 수 있으며, 댓글 작성 후 본인의 댓글에 한해 수정/삭제가 가능하다.

🖥️ 모니터링 화면

NGINX image

Spring Boot image

  • CPU 사용률, 네트워크 트래픽, HTTP 요청 응답 상태 등의 시계열 메트릭을 실시간으로 시각화하고 모니터링함으로써, 비정상적인 수치나 연결 요청 실패 등 이상징후를 조기에 탐지하고 빠르게 대처할 수 있도록 구성

About

(한림대학교 졸업작품) 한림대학교 정보과학대학 소프트웨어학부 웹애플리케이션

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published