1. 프로젝트 개요
- 제목 : 덕후감
- 부제 : 도서 이미지 OCR 및 ISBN 매칭 서비스
- 소개 : 책 읽는 즐거움을 공유하고, 지식과 감상을 나누는 책 덕후들의 커뮤니티 서비스
- 기술 스택
2. 담당한 작업
- 도서 도메인 코어 및 API 개발
- 도서 엔티티 설계 및 DTO, Repository 계층 구현
- 도서 등록, 수정, 삭제(논리/물리) 기능 및 RESTful API 구현
- QueryDSL을 활용한 동적 쿼리 작성 및 커서 페이징 도서 목록 조회 기능 구현
- 외부 API 연동 및 데이터 처리
- Naver 도서 검색 API 연동을 통해 도서 정보 조회 기능 구현
- OCR Space API 연동을 통해 도서 ISBN 이미지 인식 기능 구현
- 인프라 연동 및 성능 최적화
- AWS S3를 활용한 이미지 업로드 및 Thumbnailator 기반 이미지 리사이징 파이프라인 구축
- S3 서버 로그 주기적 업로드 및 수명 주기(Lifecycle) 정책 설정
- Redis를 도입해서 Naver 도서 검색(ISBN) 결과 글로벌 캐싱 처리
- Swagger 기반 API 명세서 자동화
3. 기술적 성과
Backend
Java 17 | Spring Boot 3.4.0 | Spring Data Jpa | QuertDSL 5.0.0
DataBase & Search Engine
PostgreSQL | H2 Database | Redis | ElasticSearch 8.12.0 | LogStash
Infra & Monitoring
AWS EC2 | AWS S3 | Docker | Github Actions | Prometheus | Grafana
Libraries
CodeCov | MapStruct | Spring Retry | Caffeine Cache | Thumbnailator | Crypto
- 데이터 재사용성을 고려한 하이브리드 캐싱 전략 구축
- Naver API(ISBN)는 재사용성이 높아 Redis 글로벌 캐시를 적용하여 API 응답 속도와 TPS를 향상
- OCR 이미지는 재사용성이 낮아 Caffeine 로컬 캐시를 유지해 네트워크 오버헤드 방지
- 대용량 트래픽을 고려한 커서 페이징 도입
- 데이터가 많아질수록 느려지는 Offset 페이징 대신, QueryDSL을 활용해 마지막 조회 지점(Cursor)을 기준으로 데이터를 가져오는 No-Offset 페이징을 구현하여 도서 목록 조회 성능을 일정하게 유지
- 클라우드 스토리지 최적화
- 원본 이미지를 그대로 S3에 올리지 않고, 이미지 리사이징(Thumbnailator)을 거치도록 처리하여 스토리지 비용을 절감하고 클라이언트의 이미지 로딩 속도를 개선
4. 문제점 및 해결 과정
- Soft Delete(논리 삭제) 적용 후 Unique 제약조건 충돌 문제
- 문제 : 도서를 삭제 처리(deleted_at 갱신)한 후, 동일한 도서를 다시 등록하려고 할 때 DB의 기존 Unique 제약조건에 걸려
DataIntegrityViolationException이 발생하는 문제 확인
- 해결 : 일반 Unique 제약조건을 제거하고, PostgreSQL의 부분 인덱스인
WHERE deleted_at IS NULL조건을 활용해서 활성 상태인 데이터에 대해서만 Unique를 보장하도록 DB구조와 엔티티 설정 개선
- 클라우드 운영 환경(PostgreSQL) 한글 데이터 정렬 실패 현상
- 문제 : 로컬(H2) 환경과 달리 운영 환경(PostgreSQL)에서 도서 목록 ‘제목순(한글)’ 정렬 요청 시, 정렬이 무시되고 무작위 순서로 노출되는 현상 발생
- 해결 : 클라우드 DB의 기본 언어셋(Collation)이 영어로 설정되어 한글 정렬 가중치를 판단하지 못하는 것이 원인임을 파악.
대상 테이블 컬럼의 정렬 규칙을 바이트 단위 정렬 방식인
COLLATE "C"로 강제 변경하는 DDL을 실행하여 UTF-8 인코딩 환경에서의 한글 가나다순 정렬을 정상화함.
- 관련 문서 : 클라우드 운영 환경(PostgreSQL) 한글 데이터 정렬 실패 및 무작위 반환 현상 해결
- API 명세서 스펙 불일치로 인한 썸네일 이미지 렌더링 실패
- 문제 : Naver 도서 검색 API 연동 후 프론트엔드에서 텍스트는 출력되나 썸네일 이미지를 렌더링하지 못하는 문제 발생
- 해결 : 네트워크 페이로드 분석 결과, API 명세서에는 썸네일이 Base64 인코딩 문자열(
format: byte)로 정의되어 있으나 백엔드에서 원본 URL 문자열을 그대로 바이패스한 것이 원인임을 파악.
RestTemplate으로 이미지를 바이트 배열로 다운로드한 뒤 Base64로 인코딩하여 반환하도록 리팩토링하여 명세 스펙을 준수하고 렌더링 문제를 해결함
- 관련 문서 : API 명세서 스펙(format: byte) 누락으로 인한 이미지 렌더링 실패 해결
- 외부 API 모킹(Mock) 테스트 시 한글 URL 인코딩 불일치 문제
- 문제 :
MockRestServiceServer를 활용한 외부 API 연동 테스트 중, 영어 키워드는 통과하지만 한글 키워드 검색 시 AssertionError가 발생하며 테스트가 실패함
- 해결 :
RestTemplate이 내부적으로 Non-ASCII 문자를 전송할 때 자동으로 UTF-8 기반 퍼센트 인코딩을 수행한다는 동작 방식을 파악함.
테스트 코드의 가짜 서버가 기대하는 URL(expectedUrl) 세팅 시 URLEncoder.encode를 명시적으로 적용하도록 수정하여, 실제 로직과의 인코딩 불일치를 해소하고 테스트 커버리지를 확보함
- 관련 문서 : MockRestServiceServer 외부 API 모킹 테스트 시 URL 인코딩 불일치 해결
5. 협업 및 피드백