📋 프로젝트 개요

  • 속초시립 도서관의 신규 웹사이트 구축 개발 프로젝트입니다.
  • 이용자 홈페이지 및 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 메인 페이지
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();
        }
    }
}

📸 프로젝트 스크린샷

속초시립 도서관 스크린샷 1
메인 페이지
속초시립 도서관 스크린샷 2
회원가입 페이지
속초시립 도서관 스크린샷 3
게시판
속초시립 도서관 스크린샷 6
메뉴 관리
속초시립 도서관 스크린샷 4
배너 관리
속초시립 도서관 스크린샷 5
퀵메뉴 관리