Company Project@ 플럭시티2026.01 — 2026.09

VGOLF 스코어카드

라운드 결과 공유 웹 — 인앱브라우저 이미지 저장

Role: Frontend 단독 유지보수·고도화 (인수인계 후, 본업과 병행)

Overview

스크린골프 라운드 결과를 개인·팀·단체(시상 포함) 스코어카드로 보여주고, 카카오·네이버 같은 인앱브라우저에서 이미지로 저장·공유하는 모바일 웹입니다. 원 개발자에게서 인수인계받아 F&B·앱 개발과 병행하며 9개월간 맡았습니다(전체 103커밋 중 본인 46건). 새로 설계한 제품이 아니라 남이 짜 둔 코드를 이해하고 안전하게 바꿔 나가는 일이었고, 그중 웹뷰 파편화로 생기는 저장 문제를 끝까지 파고들어 문서로 남긴 것이 가장 값어치 있는 부분입니다.

이 프로젝트의 핵심

레거시 인수인계 후 9개월 유지보수·고도화

전체 103커밋 중 본인 46건, 본업과 병행

인앱브라우저 이미지 저장 문제 해결

카카오·네이버 웹뷰에서 저장이 동작하지 않던 것을 재현·분석·해결하고 360줄 트러블슈팅 문서로 남김

저장 이미지가 뿌옇게 나오던 문제

devicePixelRatio 기반 스케일 처리로 선명도 확보

캡처 로직을 util + 커스텀 훅(useSaveCardImage)으로 추출해 팀·단체 페이지가 공통으로 사용

나머지 3개 더 보기

i18n 리소스를 public HTTP 로드에서 번들 인라인으로 옮겨 네트워크·캐시·MIME·타이밍 이슈 제거

스코어카드 전면 리디자인 + 히어로 헤더 공통 컴포넌트화

팀 전용 스타일 122줄 제거

백업 페이지(/team_bu, /scores_bu)를 두고 무중단으로 전환해 리스크 최소화

Screens

라운드가 끝나면 이 페이지 링크가 발송된다. 요약(이글·버디·파·보기)과 팀 스코어를 먼저 보여주고, 아래에 전·후반 홀별 표가 이어진다. 참가자 이름은 서비스가 자체적으로 가운데를 가린다.
라운드가 끝나면 이 페이지 링크가 발송된다. 요약(이글·버디·파·보기)과 팀 스코어를 먼저 보여주고, 아래에 전·후반 홀별 표가 이어진다. 참가자 이름은 서비스가 자체적으로 가운데를 가린다.
2인 라운드 결과. 같은 틀이 인원수에 따라 열 수만 달라진다. 치지 않은 홀은 '-'로 비워 두고 합계에서 뺀다.
2인 라운드 결과. 같은 틀이 인원수에 따라 열 수만 달라진다. 치지 않은 홀은 '-'로 비워 두고 합계에서 뺀다.

실제 발송된 결과 페이지입니다. 참가자 이름과 골프장 상호·로고는 알아볼 수 없게 처리했습니다.

자세히

인앱브라우저에서 이미지가 저장되지 않던 문제6

증상은 두 가지였습니다. 카카오·네이버 인앱브라우저에서 스코어카드 저장 버튼이 아무 반응이 없었고, 저장이 되더라도 이미지가 뿌옇게 나왔습니다.

일반 브라우저에서는 재현되지 않아, 웹뷰가 다운로드를 어떻게 다루는지부터 파고들었습니다. 환경마다 동작이 갈리는 지점을 하나씩 좁혀 원인을 특정했습니다.

선명도는 devicePixelRatio를 캡처 스케일에 반영해 해결했습니다

기기 픽셀 밀도를 무시하고 CSS 픽셀 기준으로 그리던 것이 원인이었습니다.

저장 자체는 인앱브라우저 환경을 감지해 별도 저장 오버레이(SaveImageOverlay)를 띄우고 캡처 플로우를 다시 설계해 우회했습니다.

같은 로직을 팀·단체 페이지가 각자 갖고 있지 않도록 util/captureImage.ts와 useSaveCardImage 훅으로 추출했습니다.

원인·환경별 대응·재발 방지를 360줄짜리 트러블슈팅 문서(docs/image-save-troubleshooting.md)로 남겼고, 같은 내용을 블로그에도 정리했습니다.

리디자인 & 리팩토링 — 안전하게 바꾸기4

개인·팀 상세와 단체 결과 페이지에 신규 디자인 적용

히어로 헤더, 순위 메달, 시상 카드

팀·단체 페이지가 각자 갖고 있던 히어로 헤더를 공통 컴포넌트(ScoreHero)로 추출해 팀 전용 스타일 122줄 제거

인라인 SVG 아이콘 모듈화, 반복되던 JSX를 배열 기반 렌더링으로, 포맷 로직은 util로 분리

인수인계받은 레거시라 한 번에 갈아엎지 않고, 백업 페이지(/team_bu, /scores_bu)를 띄워 둔 채 전환한 뒤 안정화되고 나서 정리

문제가 생기면 즉시 되돌릴 수 있는 상태를 유지

스코어 연산 정비3

파 기준을 홀별 par(holePar) 기반으로 바꾸고, 스코어를 실타수 기준 연산으로 정리

값이 어긋나는 경우를 잡기 위한 검증 로직 추가

파 대비 + 부호를 합계에만 표기하도록 표기 규칙을 하나로 통일

설문 기능 & 배포3

설문 페이지 신규 개발

API 연동, 별점 인터랙션, 반응형

POST 응답 상태 분기(완료·중복 제출·오류)와 204 No Content 대응

Gitea Actions 배포 파이프라인(deploy.yml) 운영

성공·실패 알림, 운영 포트와 API 연결 정보 관리

Tech Stack

ReactTypeScriptViteRecoilReact RouterSCSSi18nhtml2canvasAxiosGitea

Links