속초시립 도서관
2024.09 ~ 2024.12
📋 프로젝트 개요
- 속초시립 도서관의 신규 웹사이트 구축 개발 프로젝트입니다.
- 이용자 홈페이지 및 CMS를 개발했습니다.
- 속초시립 도서관 주소
🛠️ 사용 기술
Backend
- Language & Runtime: Java 21
- Framework: Spring Boot, EGovFrame, JPA, QueryDSL, Mybatis
- View Engine: JSP + JSTL
- Logging: log4jdbc-log4j2 + Log4j2
Frontend
- JavaScript, jQuery
Database
- MariaDB
🎯 주요 기능
1. 도서 관련 기능 제공
- 실시간 도서 검색
- 희망도서 신청
- 도서 예약
- 도서 상세 정보 제공
2. 문화/행사
- 문화/행사 등록 및 수정 기능 제공
- 신청자 관리 기능
- 이용자에게 문화/행사 신청 기능 제공
3. 사용자 관리
- 회원가입/로그인
- 개인정보 관리
- 대출 현황 확인
- 비대면 자격 확인
4. CMS
- 배너, 팝업 등 홈페이지 관리 기능
- 게시판 관련 기능
- 문화/행사 관리 기능

검색 페이지

장난감 도서관 메인 페이지

CMS 메인 페이지
💡내 역할
- 유저의 관심도서 기능을 위한 DB 설계 및 개발
- 회원 관련 외부 API 연동 및 기능 개발
- 전역 예외처리
- 게시판 기능 개발
- 홈페이지 관리를 위한 CMS 초기 버전
- 공공 데이터 포털 API를 사용하여 공휴일을 불러와 휴관일을 자동으로 등록시켜주는 기능 개발
- 문화행사 신청자 목록 엑셀 다운로드 기능 개발
- 유지보수를 효율적으로 하기 위한 JPA, QueryDSL 도입
- Klas API를 사용
- 회원 관련 기능 개발 (아이디 찾기, 비밀번호 찾기, 회원가입)
- 챔 검색, 조회, 예약 기능 개발
- 장난감 검색 기능 개발
- 무인 대출 기능 개발
- 이전 프로젝트에서 부족함을 느꼈었던 문화행사 기능을 개선
- 불필요한 데이터까지 불러오는 쿼리를 필요한 데이터만 불러올 수 있도록 수정
- 특정 기간동안 특정 요일만 반복해서 등록할 수 있는 기능 개발
🚀 트러블 슈팅
📦 엑셀 대용량 다운로드 성능 개선 사례
⚠️ 문제 상황
수천 건 이상의 데이터를 엑셀로 출력할 때 메모리 과다 사용으로 인해 성능 저하 또는 OutOfMemoryError 발생
브라우저에서 엑셀 파일 다운로드가 지연되거나 멈추는 현상
❌ 기존 방식: XSSFWorkbook 사용
전체 데이터를 메모리에 적재 후 다운로드를 진행하기 때문에 오류 발생
10만 건 이상에서는 OutOfMemory 또는 GC로 인해 심각한 성능 저하 발생
✅ 개선 방식: SXSSFWorkbook (Streaming 방식) 사용
설정된 행 수를 기준으로 데이터를 스크롤하며 메모리에 로드하고, 해당 행 수를 초과하면 디스크에 임시 파일로 저장하는 방식으로 동작
// 예시 코드
public class SXSSFWorkbookExample {
public static void main(String[] args) {
// rowAccessWindowSize : 메모리에 유지할 행 수 (여기서는 100행)
// compress: 임시 파일 압축 여부 (true: 압축, false: 비압축)
try (SXSSFWorkbook workbook = new SXSSFWorkbook(100, true)) {
Sheet sheet = workbook.createSheet("Sheet1");
// 헤더 행 생성
Row headerRow = sheet.createRow(0);
for (int i = 0; i < 5; i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue("Header " + (i + 1));
}
// 데이터 행 생성 (예: 10000행)
for (int rowNum = 1; rowNum <= 10000; rowNum++) {
Row row = sheet.createRow(rowNum);
for (int cellNum = 0; cellNum < 5; cellNum++) {
Cell cell = row.createCell(cellNum);
cell.setCellValue("Data " + rowNum + "-" + (cellNum + 1));
}
}
// 파일 저장
try (FileOutputStream outputStream = new FileOutputStream("large_excel_output.xlsx")) {
workbook.write(outputStream);
}
// 임시 파일 삭제 (SXSSFWorkbook 객체가 범위를 벗어나면 자동으로 삭제됨)
} catch (IOException e) {
e.printStackTrace();
}
}
}
📸 프로젝트 스크린샷

메인 페이지

회원가입 페이지

게시판

메뉴 관리

배너 관리

퀵메뉴 관리