전체 글 11

Synology NAS에 서비스 빌드 시 겪은 문제

Synology Nas에서 Docker로 배포할 때 Nginx와 Google OAuth 로그인 연동 문제로 시행착오를 많이 겪었습니다. 현재 해결은 된 상황이지만, 지금 보면 얼기설기 해결된 느낌이라 그냥 이렇게도 되는구나 하고 봐주시면 감사하겠습니다.구성서버: Synology NAS 내장 Nginx백엔드: Docker 컨테이너(Spring Boot, HTTP)인증: Google OAuth2 + Spring Security1. 배포서버(NAS)에서 404 not found처음 이런 화면이 나오는 문제를 마주쳤습니다.원인은 포트 매핑과 설정 충돌이였습니다.현재 상황은 내장 Nginx는 NAS 자체에서 실행되고있고, 서비스의 백엔드 컨테이너는 별도로 올라가있습니다.https 포트로 매핑이 되어있는데, NAS..

Dev/Troubleshooting 2026.02.09

좌표, 주소, 장소명이 섞인 위치 데이터 분류 시행착오

빠른 전체 요약이 글은 행정구역 단위 검색을 위한 기준 데이터를 어떻게 만들 것인가애 대하여 Google API 중심 접근을 시도 하였다 한계를 느낀후, 개선점에 대한 글입니다.처음에는 Google Geocoding API 사용- 좌표 → 주소 변환 가능 하나 국가별 주소 체계 차이로 데이터 구조 불안정- 장소명(POI) 검색 한계두번째로는 Google Place API 사용- 장소명 검색 및 좌표 획득 가능- 주소 분류에는 한계가 있음추후 개선 사항으로는 google api에 완전히 의존하는 것 보다는 행정구역 경계 폴리곤 데이터를 얻어, 좌표 검색 기반으로 행정구역을 분류하여 서비스를 제공하는것이 좋을 것이라 생각합니다.우선 이 과정을 겪게 된 이유로는, 프로젝트에서 사진이나 사용자의 ..

Dev/Troubleshooting 2026.02.07

이미지 파일 조회 시 Broken pipe error 해결

프로젝트를 진행중 이미지를 클라이언트측에서 요청하여 조회할 때 Broken pipe error가 발생하며 이미지 컨텐츠를 볼 수가 없는 문제가 있었습니다. 이를 해결하는 과정입니다.전체 파일 구성FileStorageService Interface가 있습니다그리고 local 환경, test docker 환경, 실제 배포 용 docker 환경 별 구현체를 strategy 패턴으로 설계하였습니다.각 구현체에 @ConditionalOnProperty 로 yml 기반 성정 자동 주입을 이용해서 빌드시 프로필 설정에 따라 교체가 편하게 설계하였습니다.사용자가 업로드한 파일의 이미지는 S3에 따로 저장하고, 이미지에서 추출한 메타데이터는 따로 처리합니다.사진 파일 업로드 과정클라이언트가 Content-Type: mu..

Dev/Troubleshooting 2026.02.06

성능테스트 (5) - 시나리오 4

지금까지 시나리오 1~3은 업로드, 조회, 공간쿼리의 개별 테스트였다면, 이번엔은 전반적인 실제 사용 패턴을 테스트 진행해보겠습니다.테스트 시나리오 4 - 혼합 시나리오 테스트목적 : 실제 사용자 행동 패턴 시뮬레이션참고math.random()으로 0~1사이 숫자를 뽑아서 0.7미만이면 조회, 0.7 70%는 조회20%는 글 좋아요같은 기타 기능10%는 업로드시스템 한계 확인 및 스파이크 테스트를 위해 300VUser까지 점진적으로 부하를 올립니다.테스트 결과"metrics": { "total_requests": 62537, "requests_per_second": "104.11", "avg_response_time_ms": 298, "p95_response_time_ms": 148..

성능 테스트 (4) - 시나리오 3

테스트 시나리오 3 - 공간 쿼리 테스트목적: PostGIS 공간 검색 성능 측정참고느린 쿼리 기준은 500ms 이상데이터 볼륨Location: 425,094개Guide: 50,000개평균 Media/Guide: 3개조회 인덱스 추가한 상태테스트 내용*ST_DWithin 반경 검색 (고정위치에서 50%, 랜덤 위치 잡아서 30%, 그리고 가이드 등록되어 있는 공간 20%)여러 반경 크기 테스트 (5km, 10km, 20km, 50km)테스트 결과{ "metrics": { "avg_duration_ms": 1393, "p95_duration_ms": 6361, "success_rate": 0.7122988819198255, "slow_queries_count": 1490, "s..

성능 테스트 (3) - 시나리오 2

테스트 시나리오 2 - 조회 API 테스트목적 : 조회 API 성능 측정 및 이슈 확인참고이전 VUser를 150까지 설정 했지만, 스트레스 테스트를 위해 200까지 점진적으로 부하를 올립니다.사용자가 페이지 읽는 시간을 1~4초로 랜덤으로 넣습니다.전체 조회는 0.5s (무거운 쿼리, 아직 페이징 처리 되어있지 않음), 상세 조회는 0.3s 이상 걸리면 실패로 분류하였습니다.테스트 당시 캐싱이 적용되어 있지 않았습니다.테스트 내용*가이드는 사진 데이터를 포함한 게시글 입니다주변 가이드 검색 (30%)특정 가이드 상세 조회 (70%)테스트 결과먼저 처음 결과와, 개선 후 결과를 먼저 비교해보고 해결 흐름을 설명하겠습니다.개선 전 (의도적 N+1 허용) "metrics": { "total_queri..

성능 테스트 (2) - 시나리오 1

테스트 방법K6로 부하를 생성해서, 나오는 결과를 측정합니다. RPS, 응답시간과 에러율 등을 확인힙니다.또한 Prometheus를 이용하여 CPU 사용률, 메모리, DB 커넥션등 서버 메트릭을 수집힙니다.위의 정보들을 Grafana로 시각화 하여 확인합니다.추가적으로 필요시 스레드, 힙, 패킷 덤프 등을 떠서 확인해봅니다.확인해야 할 것들RPS(처리량, 초당 요청 수)- 부하 증가시 RPS가 감소한다면 병목 발생HTTP 응답시간 P95- P95가 급격히 올라가면 시스템 포화 상태- 비효율적인 로직이나 쿼리 개선 필요활성 HTTP 요청 수- 계속 증가하면 (처리 속도 병목 발생이외에도 JVM Heap Memory와 GCDB Connection waiting 등의 메트릭을 확인하였습니다.사전 작업: Ne..

성능 테스트 (1) - 목표 설정

최근 진행한 프로젝트의 성능을 평가하고 개선하기 위하여 성능 테스트와 모니터링을 하게 되었습니다.현재 서버는 Synology NAS에서 3 tier 형태의 간단한 구조로 구성되어 있습니다. 웹 서버(Nginx) - WAS(Tomcat) - DB(PostgreSQL, Redis)처음에 테스트하기 전에는 Fetch Join을 통해 N + 1 같은 문제도 방지했고, 추가적인 캐싱이나 페이지네이션, 비동기 처리 정도 추가해주면 훨신 좋아지지 않을까? 라고 생각했으나, 의도치 않은 문제들이 많이 나올 수 있다는 것을 알았습니다.목표성능ShotHotspot South Korea 검색 페이지Locationscout.net South Korea 검색 페이지현재 테스트 하는 서비스와 성격이 비슷한 서비스들의 한국 검색 ..

blocking & non-blocking

들어가기전 용어 정리- 동기 (Synchronous) : 작업 완료를 기다린 후 다음 작업 수행- 비동기 (Ayynchronous) : 작업 완료를 기다리지 않고 다음 작업 수행- 블로킹 (Blocking) : 스레드가 I/O 완료까지 멈춰서 대기- 논블로킹 (Non-blocking) : 스레드가 I/O 요청 후 즉시 다른 일 수행Spring MVC + RestTemplate최근 진행한 프로젝트에서 사용한 전통적인 방식입니다.Spring MVC는 서블릿 기반으로 하나의 요청에 하나의 스레드를 할당합니다. DB 조회나 API 호출 같은 I/O 작업이 필요하다면 해당 작업이 끝날 때까지 해당 스레드는 Blocking 상태로 대기합니다.즉 Tomcat(서블릿 컨테이너)가 Thread Pool을 여러개 가지고 ..

Dev/Etc 2026.01.31

아키텍처 구조에 관한 고민 (2) - 고려해야 할 점들

아키텍처 구조 고민하면서 적용하면 좋을 패턴들에 대해 정리해보겠습니다.검증검증하는 위치는 유스케이스가 아닌 유스케이스의 입력 모델의 생성자에서 입력 유효성을 검증하는 것이 좋습니다.유스 케이스 구현체가 자신의 로직에 집중할 수 있다.모든 어뎁터에서 동일한 규칙을 적용할 수 있다.유스케이스의 입력 모델은 생성된 순간부터 항상 유효해야 한다.검증 책임은Controller / Adapter형식검증 (@Valid)외부 입력 신뢰성UseCase Input Model생성 시 검증UseCase ServiceUseCase 규칙흐름 제어Domain Model핵심 비즈니스 규칙위와 같이 입력은 컨트롤러에서, 의미는 유스케이스에서, 규칙은 도메인이 책임을 갖습니다.추가적으로 @Validation은Http 요청 검증외부 입력..

Dev/Architecture 2026.01.30