
소프트웨어 개발에서 버전 관리는 항상 골치 아픈 문제였습니다. 특히 지속적 배포 (CD) 환경에서는 더욱 그렇죠. 기존의 Semantic Versioning(SemVer) 은 많은 개발자들이 사용하고 있지만, 제품의 실제 개발 주기와 맞지 않는 경우가 많았습니다.예를

Firebase 는 실시간 데이터베이스와 간편한 백엔드 서비스로 많은 개발자들의 사랑을 받고 있습니다. 하지만 모든 것이 완벽할 순 없죠. Firebase 를 사용하다 보면 한 가지 큰 벽에 부딪히게 됩니다. 바로 검색 기능입니다.Firebase 는 기본적으로 완전 일
고객정보 암호화는 참으로 다루기 어렵다. 일단 고객의 비밀번호는 단방향 암호화로 바로 처리 가능하다.만약 고객의 주민번호나 신용카드 번호라면? 이 부분은 검색을 하지도 않을테고, 대놓고 암호화하라는 지침이 내려와있다. 하지만, 고객의 전화번호나 이메일이라면?이 부분부터
안녕하세요, 여러분! 개발자에게 버전 관리는 애증의 존재죠. 특히 여러 명이 함께 빠르게 제품을 만들어가는 환경에서는 일관되고 효율적인 버전 관리 시스템이 정말 중요하다고 생각합니다.저희 팀도 제품의 성장 과정을 한눈에 파악하고, 릴리스 시점을 명확히 하고자 LINE에
안녕하세요, 개발자 여러분! UI 개발에서 아이콘은 정말 빼놓을 수 없는 요소죠. 디자이너에게 SVG 파일을 받아서 프로젝트에 적용하곤 하는데, 매번 import 경로를 신경 쓰고, width, height, fill 같은 속성을 일일이 설정하는 게 번거로울 때가 많았
안녕하세요, 다시 만나 반갑습니다! 지난 1편에서는 SVG 원본 파일들을 React 컴포넌트(.tsx)로 변환하고, 이를 JavaScript(.js)와 타입 정의 파일(.d.ts)로 컴파일하는 과정을 함께 살펴봤습니다. 이제 우리 손에는 잘 구워진 컴포넌트 재료들이 가
드디어 대망의 마지막 편입니다! 지난 1 편에서는 SVG 파일을 React 컴포넌트로 만들고 컴파일하는 과정 을, 2 편에서는 컴파일된 결과물들을 스타일별로 나누어 모노레포 패키지로 만들고, 각 패키지에 필요한 진입점 파일들을 자동으로 생성하는 마법 같은 이야기 를 함
3년 전 저는 각 지자체에서 제공하는 공공시설 위치 CSV를 받아 보고 깜짝 놀랐습니다. 컬럼 이름은 제각각이고 좌표는 WGS84와 TM 좌표가 뒤섞여 있었죠. 게다가 사용자 제보로 들어오는 위치는 주소도, 위도·경도도 빠져 있는 경우가 많아 결국 지도에 찍을 수가 없
3년 전 공공기관 위치 데이터를 정제하고 나니 지도 위 마커 수가 순식간에 3배 가까이 늘었습니다. 스크롤이 버벅이고, 핀을 탭하려면 3초씩 기다려야 했죠. 그날 밤 저는 "이대로는 사용자들이 바로 앱을 삭제하겠다"를 되뇌며 클러스터링을 도입하기로 마음먹었습니다. 혹시
3년 전, 저는 서울 곳곳의 생활 편의 시설 데이터를 모아 위치 기반 앱을 만들고 있었습니다. 처음엔 직접 EC2에 REST API를 올리는 쪽을 고민했는데, 야근 끝에 로그를 뒤지다 보니 "굳이 서버를 굴려야 하나?"라는 생각이 확 스치더라고요. 사용자 제보, 공공데
고객용 페이지와 관리자 대시보드가 같은 Next.js 프로젝트 안에 엮여 있어서 역할 검증이 꼬이던 경험이 있나요? 저는 최근 프로젝트에서 그런 혼선을 겪었고, 덕분에 Firebase Auth와 App Router를 다시 뜯어보게 됐어요.이메일·비밀번호 로그인과 SNS
실시간 장바구니가 들쑥날쑥하면 고객 지원 팀이 고생하고, 개발자도 밤샘하게 되죠. 저는 최근 Firestore 기반 쇼핑몰을 다루면서 “장바구니 수량이 왜 갑자기 0이 되나요?” 같은 티켓을 여러 건 받았고, 덕분에 데이터를 지키는 방어 패턴을 차근차근 정리했습니다.이
Firestore만으로 글로벌 쇼핑몰 검색을 구현하려니 막막했어요. Algolia나 ElasticSearch를 붙일 예산은 없고, 그렇다고 where("name", ">=", query) 같은 편법은 다국어 데이터를 만나면 바로 깨지더라고요.저는 결국 “직접 키워드를
글로벌 사용자들이 동시에 몰리는 장바구니 화면에서 “USD가 왜 갑자기 KRW로 바뀌죠?”라는 문의를 받았을 때 진짜 식은땀이 났어요. 거창한 i18n 솔루션을 도입하기엔 일정이 촉박했고, 프런트에서 빠르게 통화를 전환할 수 있는 경량 설계를 찾기 시작했습니다.저는 R
Intro 제가 만든 서비스에는 신청자 → 담당 매니저 → 본부 관리자 순으로 진행되는 승인 프로세스가 있습니다. 이메일로 시트를 주고받던 시절에는 누가 승인했는지 추적하기가 정말 어려웠고, 권한이 없는 사람이 URL만 알면 민감한 데이터가 보이는 상황도 있었습니다.
제가 맡은 서비스는 이메일과 전화번호 같은 개인정보를 다룹니다. 초반에는 단순히 컬럼을 암호화해 저장했지만, 검색 조건에 암호화된 값이 들어오면 쉽게 깨졌고, 복호화 과정에서 서버가 느려지는 문제도 있었습니다. 결국 AES-256과 Prisma Middleware를 결
저는 대량의 인증서를 PDF로 발급해야 하는 업무를 맡았습니다. 디자인이 조금만 바뀌어도 Figma에서 다시 편집해 일일이 PDF로 내보내곤 했죠. 이 반복적인 작업을 끝내고 싶어 Canvas와 jsPDF를 엮어 자동 생성 파이프라인을 만들었습니다.React 컴포넌트를
저는 이전까지 백엔드를 EC2에 직접 배포하고, 프론트는 수동으로 S3에 올리는 방식으로 운영했습니다. 릴리스마다 사람이 SSH에 접속해 컨테이너를 재시작해야 했고, 실패하면 원복하기도 힘들었죠. 그래서 GitHub Actions와 Docker, Elastic Bean
저는 공간 예약 트래픽이 한밤중에도 몰리는 SaaS를 운영합니다. REST 중심으로 구축했던 예전 시스템은 폴링이 잦아서 공석이 나도 바로 반영되지 않았고, 동시에 두 명이 같은 시간을 잡으면 뒤늦게 충돌이 일어나곤 했죠. 그래서 이번엔 NestJS + GraphQL
저는 한동안 프론트, 백엔드, 테스트 프로젝트가 제각각인 상태에서 새 기능을 동시에 출시해야 했습니다. npm과 yarn이 섞인 채로 서로 다른 버전의 Node를 요구하다 보니 새 작업보다 의존성 정리가 더 힘들었죠. 그래서 "같은 팀이니까 코드도 한 팀이 되자"라는
현장에서 예약 현황을 확인해야 하는 운영자는 대부분 모바일 브라우저를 씁니다. 그런데 네트워크가 약한 체육관이나 지하층에서는 이미지가 느리게 뜨고, 파일 업로드도 꼭 실패했습니다. 그래서 PWA를 본격적으로 적용하고, S3 업로드와 오프라인 캐싱을 같이 다듬었습니다.@
tags:🖥️프로그래밍TechStacktitle: Winston과 CloudWatch로 구조화 로깅 파이프라인 다듬기created: 2025-02-14 10:10modified: 2025-02-14 10:10uploaded: "false"저는 새벽 배포 후에만 터지는
저는 개발 환경에서 HTTPS가 안 되면 손이 꽁꽁 묶이는 타입입니다.그런데 운영에서는 AWS ALB가 SSL을 끝단에서 맡고 있어서, 서버는 HTTP만 떠야 했어요.두 세계를 넘나드는 서버 부팅 로직을 직접 짜보면서 얻은 팁을 공유하고 싶습니다.NODE_ENV를 기준
저는 본인확인 콜백을 다루면서 두 번이나 세션이 비는 사고를 맞았어요.브라우저는 GET으로, 일부 모바일 브라우저는 POST로 돌아오고, 로드밸런서는 세션을 가끔 잊어버리더군요.그래서 세션만 믿지 말고 메모리 캐시를 함께 쓰는 하이브리드 전략을 직접 설계했습니다.토큰
저는 인증 콜백을 띄울 때마다 마음 한구석에서 "혹시나" 하는 불안을 느꼈어요.모바일 딥링크와 웹 브라우저를 동시에 지원해야 했고, return_url을 잘못 열어주면 순식간에 오픈 리다이렉트가 될 수 있다는 걸 알았죠.그래서 Express 미들웨어 앞단에 방어막을 치
저는 매번 EC2를 새로 열 때마다 sudo yum update부터 pm2 startup까지 반복하는 제 손을 보며 현타를 느꼈어요.그래서 결국 한 번에 끝내는 초기화 스크립트를 작성했고, 그 과정에서 자동화 습관이 몸에 배었습니다.똑같은 일을 세 번째 반복하고 있다면
저는 채팅에 이미지를 올리다가 갤럭시 단말에서만 실패한다는 제보를 받고 진땀을 뺐습니다. 똑같은 파일이 아이폰에서는 잘 올라가는데, 갤럭시에서는 50%에서 멈춰버리더군요. 그래서 Supabase 스토리지 업로드 흐름을 전면 점검하며 기기별 안정성을 높였습니다.갤럭시 단
저는 결제 버튼을 눌렀는데 아무 반응이 없을 때만큼 식은땀이 흐르는 순간이 없습니다. 모바일 네트워크에서 결제 위젯이 멈추기라도 하면 “결제가 됐나요?”라는 문의가 줄을 서죠. 그래서 프런트엔드와 백엔드 모두에 자동 재시도와 웹훅 이중 검증을 도입해 사용자가 느끼는 불
저는 교육부 공공데이터 API를 직접 호출했다가, 브라우저에서 CORS와 인증 키 노출 문제를 동시에 맞닥뜨렸습니다. 그래서 Next.js 서버 라우트에 프록시를 만들어 키를 감추고 에러 처리를 한 곳에서 담당하게 했습니다.서비스 키는 .env에 두고, 요청에 serv
저는 무료 이벤트 신청을 처리하면서 “누가 먼저 클릭하느냐”에 따라 좌석이 중복되는 문제를 겪었습니다. 결제 없는 신청이라 서버에서 한 번에 검증하고 생성해야 안전하더라고요. 그래서 좌석 검증과 신청 생성을 하나의 서버 액션으로 묶었습니다.이벤트가 활성 상태인지, 이미
저는 본인인증 DI가 같은 계정이 여러 개 생기는 문제를 겪었습니다. 사용자에게 “이미 인증한 계정이 있어요”라고 안내하고 싶었지만, RLS 때문에 클라이언트가 마음대로 프로필을 조회할 수 없었죠. 그래서 서비스 롤 클라이언트를 이용해 중복 계정을 탐지하는 API를 만
저는 친구 초대와 학력 인증 등 여러 이벤트에 스탬프를 주다 보니, “스탬프가 몇 개 쌓였는지”를 일일이 계산해 리워드를 지급하는 일이 번거로웠습니다. 그래서 스탬프 적립과 리워드 생성 로직을 한 번에 처리하는 파이프라인을 만들었습니다.스탬프를 지급할 때마다 현재 개수
저는 채팅이 잠깐이라도 멈추면 손이 먼저 차가워지는 타입입니다. 상담팀이 "읽음 표시가 늦어요"라고 말하던 날, 실시간 로직을 처음부터 다시 점검했죠. Supabase Realtime만 믿기엔 모바일 환경이 너무 가변적이어서, 옵티미스틱 업데이트와 폴백 전략을 같이 쓰
저는 Supabase Storage에 저장된 암호화 파일을 직접 내려받으려다가, 브라우저가 알아보기 힘든 바이너리만 던져준다는 사실을 깨달았습니다. 그래서 서버에서 복호화한 뒤 사용자에게 적절한 헤더와 함께 전달하는 방식을 만들었습니다.파일 경로와 버킷을 받아 Supa
저는 초대 코드 이벤트를 운영하면서 “누가 언제 스탬프를 받았지?”를 추적하기 어려웠습니다. 초대받은 사람과 초대한 사람 모두에게 보상을 주려면 흐름을 하나로 묶어야 했죠. 그래서 초대 코드 검증, 히스토리 저장, 스탬프 지급을 한 API에서 처리하도록 만들었습니다.초
저는 AI로 문서를 검증하는 작업을 수동으로 돌리다가, 한 번에 너무 많은 요청을 보내 Supabase가 버거워하는 모습을 봤습니다. 그래서 cron 엔드포인트를 만들어 제한된 수의 레코드만 안전하게 처리하도록 만들었습니다.CRON_SECRET Bearer 토큰으로 인
저는 내부 자료를 Supabase Storage에 보관하다가 “혹시 평문으로 남아 있지는 않을까?” 하는 걱정에 잠이 오질 않았습니다. 권한 관리가 탄탄해도 스토리지 키가 유출되면 그대로 열람될 수 있으니까요. 그래서 서버에서 파일을 업로드하는 순간 AWS KMS와 A
저는 React Native 클라이언트가 보낸 Bearer 토큰으로 Next.js Server Actions를 호출했는데, Supabase가 “세션이 없습니다”라고 답하는 상황을 겪었습니다. 헤더에 토큰이 있는데도 쿠키가 없다고 여긴 거죠. 그래서 서버 측 클라이언트
저는 학교 기록을 검증하려고 직접 PDF를 열어 정보를 옮겨 적다가 손목이 남아나지 않았습니다. 그래서 Next.js API Route에서 CLOVA OCR API를 호출해 텍스트를 자동으로 추출하는 파이프라인을 만들었습니다. PDF를 페이지별로 쪼개고, 안전한 동시성
저는 코드 리뷰에서 들여쓰기 이야기가 나오면 마음이 쿵 내려앉습니다. “이 줄 끝에 세미콜론이 왜 없죠?”라는 한 마디가 기능 토론 시간을 순식간에 갉아먹거든요. 그래서 eslint.config.mjs, package.json의 lint-staged, 그리고 .husk
저는 어느 날 components/ 폴더를 열었다가 “이건 게시판 버튼인가, 프로필 버튼인가?”를 구분하지 못하고 노트를 덮은 적이 있습니다. 체감상 500개가 넘는 파일이 한 자리에 섞여 있었거든요. 그래서 Feature-Sliced Design(FSD) 패턴을 도입
저는 채팅방이 30개가 넘는 순간, 최근 메시지를 한꺼번에 불러오다가 Supabase가 429를 뿜는 걸 보고 멘붕에 빠졌습니다. 한 번에 모든 방을 조회하는 건 무리였던 거죠. 그래서 mapWithConcurrencyLimit라는 유틸 함수를 만들어 병렬 호출 개수를
저는 본인인증 팝업이 뜨자마자 브라우저가 멈추거나 갑자기 닫혀버리는 바람에 고객센터 전화가 폭주하던 시절을 아직도 기억합니다. 그래서 “팝업을 열고 닫는 과정, 그리고 후속 검증까지 모두 신뢰할 수 있게 만들자”는 목표로 Next.js 기반 인증 플로우를 다시 설계했습
저는 포인트 적립 기능을 만들다가 “이 API를 누가 호출해도 되나?”라는 질문에 막혔습니다. 클라이언트에서 직접 포인트 테이블을 만지면 보안이 너무 약했고, 서버에서 중복 로직을 반복하기도 싫었습니다. 그래서 Supabase RPC와 서비스 롤 키를 결합해 트랜잭션을
AI 문서 인증 체인을 만들면서 가장 먼저 부딪힌 벽은 “요청 타임아웃”이었습니다.OCR은 파일 크기에 따라 수 초씩 걸리고, LLM 호출은 네트워크 지연이 잦았습니다.저는 이 긴 작업을 클라이언트 요청 하나에 억지로 묶기보다, chain이라는 내부 플래그를 두고 스텝
종이 문서 인증을 눈으로 확인하던 시절, 저는 늘 마감 직전에 머리를 쥐어뜯었습니다.그러다 보니 OCR과 AI 검증을 각각 따로 호출하느라 요청이 꼬이고, 실패 로그를 추적하기도 힘들었습니다.그래서 이번에는 OCR부터 AI 비교, 자동 승인까지 이어지는 하나의 흐름을
저는 최근까지 Next.js에서 Edge, Node.js, 클라이언트를 적절히 분리하는 일을 감으로만 해왔습니다.문서 인증 파이프라인을 붙이면서 서버 리소스가 확 튀는 걸 보고, Next.js가 말하는 Fluid Computing 개념을 제대로 정리해야겠다고 마음먹었습
위치 기반 혜택 지도를 만들다 보니, 지도 초기화 타이밍과 현재 위치 이동이 서로 꼬여 UX가 흔들렸습니다.저는 React Native에서 네이버 지도 SDK를 써서 클러스터링, 현재 위치 자동 이동, 경계 계산을 전부 커스텀했습니다.위치 권한과 현재 위치를 비동기로
카카오 로그인을 붙이는데 iOS와 Android가 서로 다른 인증 플로우를 요구해 한 번에 정리하기가 쉽지 않았습니다.저는 Expo AuthSession과 Linking을 조합해 두 플랫폼을 하나의 함수에서 처리했습니다.공통으로 사용할 리다이렉트 URI를 AuthSes
네이티브 앱 안에 토스 결제 위젯을 넣었더니, 약관 동의 상태나 결제 요청 타이밍이 꼬여 오류가 났습니다.저는 공식 SDK를 감싸는 컴포넌트를 만들어 위젯 로딩과 결제 요청을 안정화했습니다.PaymentWidgetProvider로 토스 SDK 컨텍스트를 구성하고, 결제
바텀시트 안에 들어가는 콘텐츠가 매번 달라지다 보니, 고정 스냅 포인트로는 사용성을 맞출 수가 없었어요.저는 @gorhom/bottom-sheet를 기반으로 콘텐츠 높이에 맞춰 스냅 포인트를 계산하고, iOS/Android 오버레이를 분리했습니다.콘텐츠 레이아웃 이벤트
iPhone에서 ActionSheet가 홈 인디케이터와 겹치고, Android에서는 취소 버튼이 없을 때 닫히지 않는 문제가 있었습니다.저는 Expo ActionSheet를 감싸는 커스텀 훅을 만들어 안전 영역과 플랫폼별 닫기 패턴을 맞췄습니다.Safe Area 값을
Android에서 뒤로가기를 눌렀을 때 앱이 곧장 종료되는 문제가 있어, 홈 탭인지 여부를 확인해 제어해야 했습니다.저는 Expo Router와 BackHandler를 이용해 더블백(exit) 패턴을 구현하고 안내 토스트를 띄웠습니다.루트 경로인지 확인하는 헬퍼를 전달
로그인을 기준으로 푸시 알림 초기화를 제어하지 않으면 알림이 뒤늦게 도착하거나 아예 빠지는 일이 잦았어요.저는 Expo 기반 프로젝트에서 토큰 등록과 라우팅까지 한 번에 묶어 지연과 중복을 없애는 루틴을 만들었습니다.로그인 여부를 확인한 뒤에만 Expo 토큰을 발급하고
OTA 업데이트를 배포해도 사용자가 앱을 다시 시작하지 않으면 새 기능이 묻히고는 했습니다.저는 Expo Updates를 사용해 앱이 켜질 때와 포그라운드로 복귀할 때 업데이트를 확인하고, 모달로 바로 알려주도록 만들었습니다.Updates.checkForUpdateAs
입력창이 키보드를 따라 올라가는 Sticky 뷰가 간헐적으로 원래 위치로 돌아오지 않는 버그가 있었습니다.저는 react-native-keyboard-controller의 KeyboardStickyView를 래핑해 플랫폼별 이벤트 차이를 흡수했습니다.키보드가 숨길 때
Expo 프로젝트에서 이미지와 문서를 동시에 업로드해야 했는데, 플랫폼별 URI 스킴과 포맷 차이가 상당했습니다.저는 ImagePicker와 DocumentPicker 자산을 하나의 ReactNativeFile 타입으로 통합하고, FormData/base64 변환을 지
장기 미접속 사용자를 깨우는 로컬 알림을 만들었는데, 기기마다 중복 예약이나 권한 누락이 빈번했어요.저는 React Native에서 Expo Notifications를 활용해 스케줄링, 취소, 멱등성을 모두 잡는 유틸을 정리했습니다.알림마다 고유 식별자를 생성해 새 스