Loading the catalog…
Loading the catalog…
1. 빈자리 취소석 자동 매칭 서비스, 샥 "샥(syak)"은 뷰티 샵의 예약 취소로 발생하는 빈자리 취소석을 사용자에게 자동으로 매칭해 주는 서비스다. 사용자는 취소석 알림을 통해 비어 있는 예약 슬롯을 빠르게 확보할 수 있고, 제휴 샵은 노쇼나 갑작스러운 취소로 인한 매출 타격을 방지한다. 이번 주에는 서비스의 전국 단위 확장과 이를 안정적으로 제어하기 위한 내부 백오피스 웹( syak_admin ) 구축, 그리고 백엔드( syak_BE )와 프론트엔드( syak )의 인프라 및 성능 최적화 작업을 수행했다. 2. 전국 확장과 관리자 시스템 도입 단계의 병목 현상 서비스 대상 지역을 전국으로 확장하고 이를 운영할 관리자 도구를 도입하는 과정에서 여러 시스템적 병목과 설정 오류가 발생했다. 첫째, 로컬 개발 환경에서 Docker Compose로 백엔드를 실행할 때 데이터베이스와 Redis 연결 실패( ECONNREFUSED )로 애플리케이션 컨테이너가 즉시 종료되었다. 호스트 컴퓨터 기준의 연결 설정이 컨테이너 내부 네트워크에 그대로 적용된 것이 원인이었다. 둘째, 관리자 페이지에서 전체 샵 목록을 조회할 때, 4만 행이 넘는 데이터에 대해 JSONB 내부의 전화번호 필드( detail->>phone )를 정렬 조건과 함께 조회하자 Postgres의 JSONB detoast 비용으로 인해 statement timeout (57014) 에러가 발생하며 서버가 중단되었다. 셋째, 운영 환경에서 NVIDIA FLUX 모델을 사용한 마케팅 이미지 생성 API가 500 에러를 반환했다. 이미지 생성 프롬프트 레시피가 담긴 JSON 파일이 Docker 빌드 단계에서 운영 컨테이너 내부로 복사되지 않아 발생한 문제였다. 넷째, 운영 환경의 쿠키 설정 오류가 확인되었다. COOKIE_SAME_SITE=none 환경에서 COOKIE_SECURE=false 로 잘못 설정되어 있어, 최신 브라우저 스펙에 의해 클라이언트의 쿠키 저장이 거부될 위험이 있었다. 3. 안정성과 효율성을 고려한 아키텍처 판단 Docker 환경의 통신 문제를 해결하기 위해, 호스트 기준인 localhost 주소 대신 Compose 서비스명( db , redis )을 사용하도록 환경변수를 덮어쓰고 데이터베이스와 Redis가 준비된 후에 애플리케이션이 실행되도록 의존성 조건을 강화했다. JSONB 조회 타임아웃 문제를 해결하기 위해, 한 번의 쿼리로 대량의 JSONB 필드 정렬과 상세 조회를 동시에 처리하는 구조를 폐기했다. 대신 1단계에서 인덱스를 타는 기본 필드로 목록을 페이징 조회한 후, 해당 페이지에 노출할 샵 ID들만 대상으로 2단계 상세 조회를 수행하도록 쿼리를 분리했다. 이미지 생성 API의 안정성을 높이기 위해 Dockerfile 빌드 단계에 레시피 JSON 파일을 명시적으로 포함했다. 외부 설정 누락이나 파일 누락 등의 오류는 서버 자체의 결함이 아니므로 ImageGenConfigError 라는 커스텀 에러를 정의해 503(Service Unavailable) 응답으로 명확히 구분하여 반환하도록 설계했다. 쿠키 거부 문제를 예방하기 위해 운영 환경의 쿠키 설정을 COOKIE_SECURE=true 로 정정하여 HTTPS 환경에서 안전하게 전달되도록 조치했다. 관리자 웹은 백엔드와 동일 출처 구조로 Nginx가 프록시하도록 설계하여 CORS 설정 없이 HttpOnly , SameSite=Strict 쿠키 세션을 온전히 활용할 수 있게 했다. 4. 변경 전과 변경 후 4-1. Docker Compose 환경변수 및 의존성 수정 ( syak_BE ) 기존에는 컨테이너 내부 통신 주소가 호스트 기준으로 고정되어 연결 실패가 일어났다. 이를 서비스명을 통한 내부 라우팅 방식으로 변경하고 헬스체크 대기 옵션을 적용했다. # docker-compose.yml services: app: build: . ports: - "3000:3000" env_file: - .env environment: DATABASE_URL: postgresql://syak:syak_dev_password@db:5432/syak_dev SUPABASE_DATABASE_URL: postgresql://syak:syak_dev_password@db:5432/syak_dev REDIS_URL: redis://redis:6379 depends_on: db: condition: service_healthy redis: condition: service_healthy restart: unless-stopped 4-2. 이미지 생성 API 안정화 및 에러 분리 ( syak_BE ) 도커 이미지 빌드 시 필요한 설정 파일을 포함하고, 설정 누락 예외를 500 에러가 아닌 503 에러로 안전하게 분리했다. // src/contexts/admin/infrastructure/MarketingImageService.ts export class ImageGenConfigError extends Error {} let cached: Recipes | null = null; function loadRecipes(): Recipes { if (!cached) { const p = resolve(process.cwd(), 'scripts/marketing/image-recipes.json'); try { cached = JSON.parse(readFileSync(p, 'utf8')) as Recipes; } catch { throw new ImageGenConfigError(`이미지 레시피 파일을 찾을 수 없습니다 (${p}). Dockerfile의 COPY 확인 필요`); } } return cached; } // src/contexts/admin/interface/AdminController.ts try { const result = await runImageGeneration(this.sbClient, count); res.json(result); } catch (err) { if (err instanceof ImageGenConfigError) { console.error('[generateMarketingImages] config', err.message); res.status(503).json({ code: 'IMAGE_GEN_UNAVAILABLE', message: err.message }); return; } next(err); } 4-3. 취소석 알림 버튼 그라데이션 애니메이션 효과 추가 ( syak ) 사용자의 알림 신청 유입률을 높이기 위해 지도 우하단 버튼에 움직이는 그라데이션 테두리 효과를 도입하고, 미지원 브라우저용 폴백을 마련했다. /* src/index.css */ @property --shak-angle { syntax: "<angle>"; initial-value: 0deg; inherits: false; } @keyframes shak-spin { to { --shak-angle: 360deg; } } .shak-glow::before { content: ""; position: absolute; inset: -3px; border-radius: inherit; padding: 3px; background: conic-gradient( from var(--shak-angle), #ec4899, #f59e0b, #fde047, #ec4899, #8b5cf6, #ec4899 ); -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); mask-composite: exclude; animation: shak-spin 2.6s linear infinite; z-index: -1; } @supports not (background: conic-gradient(from var(--shak-angle), red, blue)) { .shak-glow::before { background: linear-gradient(135deg, #ec4899, #f59e0b, #8b5cf6); animation: none; } } 5. 결과 인프라 최적화와 백오피스 체계 구축을 통해 서비스 운영의 안정성과 확장성이 크게 강화되었다. 첫째, 경북 구미시 703곳의 데이터 수집을 시작으로 대전·울산·세종·강원·충청·제주 및 남부 지방 전역을 포함하는 전국 64,221곳의 샵 데이터 수집과 5,767곳의 예약 연동 백필을 무인 파이프라인으로 완주했다. 이와 함께 SEO 대상 지역이 147개 지역으로 대폭 확장되었다. 둘째, 새로 구축된 관리자 페이지를 통해 운영진은 대용량 샵 데이터를 카테고리 및 지역 필터로 타임아웃 없이 안전하게 조회할 수 있게 되었다. SSE 실시간 스트림을 연동하여 검토 대기 중인 도입 문의가 발생하면 실시간으로 상단 종 알림 배지가 활성화되는 모니터링 환경을 갖췄다. 셋째, 매일 08:20 KST에 실행되는 GitHub Actions 자동화 프로세스가 인스타그램, 쓰레드, 메타 광고 지표를 수집하고 Gemini AI의 조언을 덧붙여 Supabase에 성공적으로 기록하기 시작했다. 관리자는 수집된 지표를 바탕으로 NVIDIA FLUX 기반의 고품질 피드 이미지를 관리자 화면에서 직접 생성하고 제어할 수 있게 되었다.
What RADAR observed and classified to build this opportunity. It is what the source published, not a verification that the offer is still active.
Docker 네트워크와 JSONB 조회 성능 병목을 해결하고 취소석 매칭 관리자 페이지를 구축하여 전국 6만 4천 곳의 서비스를 안정화하다. 1. 빈자리 취소석 자동 매칭 서비스, 샥 "샥(syak)"은 뷰티 샵의 예약 취소로 발생하는 빈자리 취소석을 사용자에게 자동으로 매칭해 주는 서비스다. 사용자는 취소석 알림을 통해 비어 있는 예약 슬롯을 빠르게 확보할 수 있고, 제휴 샵은 노쇼나 갑작스러운 취소로 인한 매출 타격을 방지한다. 이번 주에는 서비스의 전국 단위 확장과 이를 안정적으로 제어하기 위한 내부 백오피스 웹( syak_admin ) 구축, 그리고 백엔드( syak_BE )와 프론트엔드( syak )의 인프라 및 성능 최적화 작업을 수행했다. 2. 전국 확장과 관리자 시스템 도입 단계의 병목 현상…
Open source