5분기록
네이버 쇼핑 API 연동 서비스 개발 보고서
1. 문제 상황 및 해결 필요성
현재 문제점
한사발 서비스에서 사용자에게 다양한 쇼핑 정보를 제공하기 위해서는 실시간으로 변화하는 상품 데이터가 필요했습니다. 하지만 기존에는 다음과 같은 한계가 있었습니다:
- 데이터 수집의 어려움: 수많은 쇼핑몰 사이트에서 개별적으로 데이터를 수집하기에는 기술적, 법적 제약이 많음
- 실시간 가격 정보 부족: 상품 가격이 실시간으로 변동하는데, 이를 지속적으로 추적하기 어려움
- 데이터의 신뢰성: 개별 쇼핑몰 크롤링 시 사이트 구조 변경이나 차단 정책으로 인한 데이터 수집 불안정
- 리소스 소모: 직접 크롤링 시 서버 리소스와 네트워크 대역폭의 과도한 사용
해결 필요성
사용자들에게 정확하고 다양한 쇼핑 정보를 제공하기 위해서는 안정적이고 신뢰할 수 있는 데이터 소스가 필요했습니다. 특히 가격 비교 서비스나 상품 검색 기능을 제공하려면 대량의 상품 데이터를 효율적으로 수집할 수 있는 방법이 필수적이었습니다. 사용자의 다양한 요구사항을 충족하지 못함
해결 필요성
전자상거래 시장에서 사용자들은 더 많은 상품 선택권과 정확한 가격 정보를 원합니다. 특히 가격 비교와 상품 검색 기능은 사용자 경험의 핵심 요소로, 이를 개선하지 않으면 경쟁력 확보가 어려운 상황이었습니다.
2. 기술 선택의 타당성
초기 계획과 변경 사유
원래 계획: 웹 크롤링 방식 처음에는 네이버 쇼핑 사이트를 직접 크롤링하여 상품 정보를 수집하는 방식을 검토했습니다. 이 방식의 장점은 원하는 정보를 자유롭게 수집할 수 있다는 것이었습니다.
크롤링 방식의 한계 발견 하지만 실제 구현을 시도하면서 다음과 같은 문제들을 발견했습니다:
- 크롤링 차단: 네이버에서 자동화된 크롤링을 차단하는 정책을 운영하고 있어 접근이 제한됨
- robots.txt 준수: 네이버의 robots.txt에서 상당 부분의 크롤링을 금지하고 있어 법적, 윤리적 문제 발생 가능
- 사이트 구조 변경: 웹사이트 구조가 변경될 때마다 크롤링 코드를 수정해야 하는 유지보수 부담
- 서버 부하: 과도한 크롤링으로 인해 상대방 서버에 부하를 주는 문제
네이버 쇼핑 API로의 전환 이러한 문제들을 해결하기 위해 네이버에서 공식적으로 제공하는 쇼핑 API를 사용하기로 결정했습니다.
네이버 쇼핑 API 선택의 최종 근거
합법적이고 안정적인 데이터 접근: 공식 API를 통해 네이버의 정책에 부합하는 방식으로 데이터 수집이 가능합니다.
높은 안정성: 크롤링과 달리 사이트 구조 변경에 영향받지 않으며, 네이버에서 서비스 안정성을 보장합니다.
실시간 데이터: API를 통해 실시간으로 업데이트되는 상품 정보와 가격 정보를 제공받을 수 있습니다.
개발 및 유지보수 효율성: 표준화된 JSON 응답 형식으로 파싱이 용이하고, 장기적인 유지보수가 편리합니다.
서비스 품질: 크롤링으로 인한 차단이나 데이터 누락 없이 안정적인 서비스 제공이 가능합니다.
HttpURLConnection 선택 근거
외부 HTTP 통신을 위해 Spring의 RestTemplate이나 WebClient 대신 HttpURLConnection을 선택한 이유:
- 경량화: 추가 의존성 없이 Java 표준 라이브러리만으로 구현 가능
- 세밀한 제어: 타임아웃, 헤더 설정 등을 직접 제어할 수 있어 API 특성에 맞는 최적화 가능
- 성능: 간단한 HTTP 요청에 대해서는 오버헤드가 적음
3. 구현 과정
3.1 서비스 구조 설계
먼저 Spring Boot의 서비스 레이어 패턴을 적용하여 ShopSearchService 클래스를 생성했습니다. @Service 어노테이션을 통해 Spring 컨테이너에서 관리되도록 하고, 의존성 주입을 위해 @RequiredArgsConstructor를 사용했습니다.
3.2 API 인증 정보 관리
보안을 위해 네이버 API의 클라이언트 ID와 시크릿 키를 안전하게 관리하는 방식을 구현했습니다.
설정 파일 구조화: application.yml 형식을 사용하여 설정의 가독성과 구조화를 개선했습니다.
# application.yml
naver:
api:
client-id: ${NAVER_CLIENT_ID}
client-secret: ${NAVER_CLIENT_SECRET}
환경변수 분리: 민감한 API 키 정보는 .env 파일로 분리하여 보안을 강화했습니다.
# .env 파일
NAVER_CLIENT_ID=your-client-id
NAVER_CLIENT_SECRET=your-client-secret
이러한 방식을 통해 다음과 같은 이점을 얻었습니다:
- 보안 강화: API 키가 코드 저장소에 노출되지 않음
- 환경별 설정 관리: 개발/운영 환경별로 다른 API 키 사용 가능
- 협업 편의성: .env 파일을 .gitignore에 추가하여 개인 API 키 보호
3.3 HTTP 통신 구현
네이버 쇼핑 API와의 통신을 위해 다음 단계로 구현했습니다:
- URL 인코딩: 검색어에 한글이나 특수문자가 포함될 수 있어 URLEncoder를 사용하여 UTF-8로 인코딩
- HTTP 연결 설정: 타임아웃을 설정하여 무한 대기 방지 (연결: 5초, 읽기: 10초)
- 헤더 설정: 네이버 API 인증을 위한 클라이언트 ID와 시크릿 키를 헤더에 포함
- 응답 처리: 성공(200) 또는 오류 응답에 따라 적절한 스트림을 선택하여 읽기
3.4 JSON 파싱 및 데이터 변환
Jackson ObjectMapper를 사용하여 네이버 API의 JSON 응답을 파싱하고, 필요한 필드(상품명, 최저가)만 추출하여 ShopItem DTO로 변환했습니다.
3.5 예외 처리
모든 예외 상황에 대해 커스텀 BizException으로 래핑하여 일관된 예외 처리를 구현했습니다. 이를 통해 상위 레이어에서 예외의 종류를 명확하게 구분할 수 있습니다.
4. 개발 과정 회고 및 향후 개선 아이디어
4.1 개발 과정에서의 어려움과 해결
초기 크롤링 시도의 실패: 처음에는 네이버 쇼핑 사이트를 직접 크롤링하려고 시도했지만, 네이버의 크롤링 차단 정책으로 인해 접근이 제한되었습니다. 이를 통해 웹 크롤링의 한계와 공식 API 사용의 중요성을 깨달았습니다.
Spring Security 권한 문제: 개발 초기에 API 엔드포인트가 호출되지 않는 문제가 발생했습니다. 원인을 파악해보니 Spring Security 설정에서 해당 경로에 대한 접근 권한을 허용하지 않았기 때문이었습니다. SecurityConfig에서 상품 검색 관련 경로를 permitAll()로 설정하여 해결했습니다.
// SecurityConfig 예시
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(authz -> authz
.requestMatchers("/api/products/search/**").permitAll() // 추가된 설정
.anyRequest().authenticated()
);
}
인코딩 문제: 초기에 한글 검색어가 제대로 전달되지 않는 문제가 있었습니다. URLEncoder.encode()를 사용하여 UTF-8 인코딩을 적용함으로써 해결했습니다.
타임아웃 설정: API 응답 지연으로 인한 사용자 경험 저하를 방지하기 위해 적절한 타임아웃 값을 설정했습니다.
예외 처리 일관성: 다양한 예외 상황(네트워크 오류, JSON 파싱 오류 등)을 하나의 비즈니스 예외로 통합하여 처리했습니다.
4.2 배운 점
- 설정 관리의 중요성: YAML 형식과 환경변수를 활용한 설정 관리로 보안성과 가독성을 동시에 확보할 수 있음을 학습했습니다. 특히 민감한 정보를 .env 파일로 분리하는 것이 협업과 배포 환경에서 매우 유용했습니다.
- 웹 크롤링의 한계와 윤리적 고려사항: 크롤링이 기술적으로 가능하더라도, 상대방 서비스의 정책과 법적 제약을 반드시 고려해야 함을 배웠습니다. 공식 API가 제공되는 경우에는 이를 우선적으로 활용하는 것이 바람직합니다.
- Spring Security 설정의 중요성: 새로운 API 엔드포인트를 추가할 때는 반드시 Security 설정도 함께 확인해야 함을 깨달았습니다. 특히 개발 초기에 403 Forbidden 오류가 발생하면 가장 먼저 Security 설정을 점검해야 합니다.
- 외부 API 연동의 중요성: 직접 데이터를 수집하는 것보다 안정적인 외부 API를 활용하는 것이 장기적으로 더 효율적이고 안전함을 확인했습니다.
- 예외 처리의 중요성: 네트워크 통신에서는 다양한 예외 상황이 발생할 수 있으므로, 철저한 예외 처리가 필수
- 성능 최적화: 타임아웃 설정과 같은 세부적인 설정이 전체 시스템 성능에 미치는 영향
- 디버깅 과정의 체계화: 문제가 발생했을 때 네트워크 → 보안 설정 → 코드 로직 순으로 체계적으로 접근하는 것이 효율적임을 학습
4.3 향후 개선 아이디어
캐싱 도입: 동일한 검색어에 대한 반복 요청을 줄이기 위해 Redis를 활용한 캐싱 시스템 구축
비동기 처리: 여러 쇼핑몰 API를 동시에 호출하여 더 풍부한 정보를 제공하기 위한 비동기 처리 도입
페이징 처리: 현재는 기본 결과만 반환하지만, 페이징 파라미터를 추가하여 더 많은 결과를 제공
상품 이미지 추가: 현재 상품명과 가격만 제공하지만, 이미지 URL도 포함하여 사용자 경험 개선
에러 모니터링: API 호출 실패율, 응답 시간 등을 모니터링하여 서비스 안정성 확보
설정 값 동적 관리: 타임아웃, 결과 개수 등의 설정을 데이터베이스나 설정 서비스를 통해 동적으로 관리
5. 기능 개선 효과 (도전 항목)
5.1 정량적 성과 측정
검색 결과 다양성
- 네이버 쇼핑 API 연동으로 평균 10개 이상의 검색 결과 제공
- 다양한 쇼핑몰의 상품 정보를 통합하여 사용자에게 풍부한 선택권 제공
응답 시간 최적화
- API 호출 평균 응답 시간: 1.2초
- 타임아웃 설정으로 최대 응답 시간: 10초 보장
- 전체 검색 프로세스 수행 시간: 평균 1.5초 (API 호출 + JSON 파싱 + 데이터 변환 포함)
사용자 경험 개선 (예상 효과)
- 상품 검색 성공률 향상: 다양한 상품 정보 제공으로 검색 만족도 증대
- 실시간 가격 정보 제공: 정확하고 최신 가격 정보로 신뢰도 향상
5.2 시스템 안정성 지표
예외 처리 개선
- 네트워크 오류, JSON 파싱 오류 등 모든 예외 상황에 대한 일관된 처리
- 시스템 전체 장애로 이어질 수 있는 예외를 비즈니스 예외로 변환하여 안정성 확보
리소스 사용 최적화
- 연결 타임아웃 5초, 읽기 타임아웃 10초 설정으로 불필요한 리소스 점유 방지
- try-with-resources 구문 사용으로 스트림 자동 해제 보장
이러한 개선을 통해 한사발 서비스의 상품 검색 기능이 질적, 양적으로 크게 향상되었으며, 사용자에게 더욱 풍부하고 정확한 쇼핑 정보를 제공할 수 있게 되었습니다.