푸시 알림 서버까지 만들고도 로컬 알림을 선택한 이유
·
Project/Landit
이 글은 Velog에서 이전한 글입니다. Velog 원문 보기푸시 알림 서버까지 만들고도 로컬 알림을 선택한 이유Landit에는 사용자가 학습을 이어가도록 매일 20시에 리마인더를 보내는 기능이 필요했다.이 알림 하나를 위해 EventBridge Scheduler, SQS, Push Device, 발송 이력, Expo Ticket과 Receipt까지 백엔드 구조를 설계하고 구현했다. 처음에는 서버가 최신 학습 상태를 확인한 뒤 Expo Push Service로 알림을 보내는 방식이 자연스럽다고 생각했다.그런데 구조를 완성해 갈수록 질문이 달라졌다.서버 푸시를 안정적으로 만들 수 있는가가 아니라, 현재 제품이 이 복잡성을 정말 필요로 하는가?결론부터 말하면 첫 학습 리마인더의 구현 방향을 앱의 로컬 알림으..
Sentry 500은 서버 장애가 아니었다. WAF Count 뒤에 있던 취약점 스캐너
·
Project/Landit
이 글은 Velog에서 이전한 글입니다. Velog 원문 보기Sentry 500은 서버 장애가 아니었다. WAF Count 뒤에 있던 취약점 스캐너2026년 7월 25일 20시 5분, 운영 서버에서 서로 다른 Sentry 이슈 세 개가 37초 안에 발생했다.두 건은 multipart 요청을 읽다가 본문이 갑자기 끝났다는 오류였다. 나머지 한 건은 form body의 % 인코딩이 깨져 발생했다.처음 보이는 모양은 애플리케이션 장애였다. 운영 ECS task 한 곳에서 500이 연달아 발생했고, Sentry는 예외 체인이 다른 두 multipart 오류를 별도 이슈로 묶었다.하지만 같은 시각의 Grafana, ALB access log, WAF 로그를 맞춰 보니 상황이 달랐다. 특정 task에 자동화된 취약..
Spring Boot 4에서 사라진 ObjectMapper Bean
·
Backend/Spring
이 글은 Velog에서 이전한 글입니다. Velog 원문 보기Spring Boot 4에서 사라진 ObjectMapper Bean배포 파이프라인은 거의 끝까지 정상적으로 진행됐다.테스트가 통과했고 Docker 이미지도 만들어졌다. ECR 업로드와 ECS 강제 배포도 성공했다. 그런데 마지막 Verify ECS service 단계에서 배포가 멈췄다.처음 보이는 에러는 타임아웃이었다.The action 'Verify ECS service' has timed out after 12 minutes.하지만 타임아웃은 원인이 아니었다. 새로 배포한 애플리케이션이 시작되지 못하고 종료된 결과였다.ECS에서는 무슨 일이 벌어지고 있었을까실패 당시 PRIMARY deployment의 상태는 다음과 같았다.{ "statu..
테스트 주도 개발 | 켄트 백
·
Project/Book
이 글은 Velog에서 이전한 글입니다. Velog 원문 보기테스트가 코드를 이끄는 방식켄트 백의 '테스트 주도 개발'은 개발자가 코드를 작성하는 순서를 바꾸자고 말하는 책이다.내가 지금까지 코드를 작성한 흐름은기능을 먼저 구현하고어느 정도 완성된 뒤에 테스트한다.하지만 TDD는 이 흐름을 역행한다.먼저 테스트를 작성하고그 테스트를 통과하는 코드를 만들고마지막으로 코드를 정리한다.처음에는 "이게 무슨 말이지?" 생각했다.당연히 그럴만한게 이전까지의 나에게 테스트 코드란내가 작성한 코드를 검증하는 것이었기 때문이다. 당연히 코드가 있어야 테스트 코드를 작성할 수 있다고 생각했다. 코드도 없는데 어떻게 테스트를 작성할 수 있을까?하지만 이 의문이 바로 TDD의 출발점이다.테스트를 먼저 작성한다는 것은 '내가..
앱 웹뷰 도입 후 Refresh Token 구조를 다시 설계한 이유
·
Project/척척학사
이 글은 Velog에서 이전한 글입니다. Velog 원문 보기들어가며척척학사는 본래 웹 서비스 중심으로 운영되고 있었다.기존 인증 구조에서는 사용자가 로그인하면 서버가 Access Token과 Refresh Token을 발급했다.refresh_token- user_id PK- token- expiry이 구조에는 하나의 가정이 숨어 있었다.한 사용자는 동시에 하나의 Refresh Token만 가진다.웹 서비스만 운영할 때는 이 가정이 크게 문제 되지 않았다.대부분의 사용 흐름이 브라우저라는 하나의 진입점에서 시작됐고, 같은 계정으로 여러 클라이언트 환경에 동시에 로그인하는 상황도 많지 않았다.그런데 별도 앱 서비스가 붙으면서 상황이 달라졌다.척척학사는 웹, 앱 서비스가 별도의 기능을 가지고 있었다.앱: ..
[Saynow] LLM Workflow 개선기 - availableOptions를 버리고 RAG로 간 이유
·
Project/Saynow
이 글은 Velog에서 이전한 글입니다. Velog 원문 보기SayNow의 AI 서버를 손보면서 처음에는 프롬프트만 잘 고치면 된다고 생각했다. 메뉴 추천 요청에서 하트가 깎이고, That’s all. 같은 자연스러운 답변이 실패처럼 처리되는 문제였기 때문이다.하지만 테스트를 계속하다 보니 이건 단순한 프롬프트 문제가 아니었다. LLM을 어느 단계에서 어떻게 쓰는지, 그리고 어떤 정보를 어디에 저장할지에 가까운 문제였다.이 글은 SayNow에서 next-question, feedback, 도움 요청을 어떤 workflow로 나눴는지 정리한 글이다.모든 LLM 작업을 같은 구조로 묶지 않았다LLM을 쓰는 구조는 여러 가지가 있다.가장 단순한 구조는 단일 모델 호출이다. 입력을 넣고 응답을 받는다. 분류, ..
[Saynow] 프롬프트 개선기 - Prompt 1에서 9까지
·
Project/Saynow
이 글은 Velog에서 이전한 글입니다. Velog 원문 보기SayNow는 영어 회화 상황을 연습하는 서비스다. 사용자가 AI의 질문에 답하면, AI 서버는 그 발화가 시나리오에 필요한 정보를 채웠는지 판단한다. 백엔드는 그 결과를 보고 다음 질문을 이어가거나, 세션을 끝내거나, 하트를 깎는다.처음에는 단순한 슬롯 채우기 문제처럼 보였다. 카페 주문 시나리오라면 drink, size 같은 슬롯이 있고, 사용자가 Small iced Americano, please.라고 말하면 두 슬롯을 채우면 된다.문제는 사용자가 항상 슬롯 값만 말하지 않는다는 점이었다.Can you recommend a menu?Can I see the menu?What beans do you use?That’s all.이런 말은 틀린..
[특강] AI 프로젝트를 위한 AI 모델 선택 노하우
·
Etc
이 글은 Velog에서 이전한 글입니다. Velog 원문 보기영어 회화 서비스에 Realtime API를 써도 될까?2026.05.23.온라인 강의, 박성준 멘토님.영어 회화 서비스에서 중요한 건 결국 두 가지다.사용자가 실제로 대화하고 있다는 느낌을 받아야 하고, 피드백도 빠르게 돌아와야 한다.기존에는 이 지점에서 병목이 컸다. 음성을 텍스트로 바꾸고, LLM이 답변을 만들고, 다시 음성으로 변환하는 과정을 순서대로 거치면 아무래도 느릴 수밖에 없다. 사용자는 “대화하고 있다”기보다 “응답을 기다리고 있다”는 느낌을 받게 된다.그런데 이제는 상황이 조금 달라졌다. OpenAI Realtime API 같은 선택지가 생기면서, 초반 PoC 단계에서는 직접 모델을 띄우지 않고도 꽤 자연스러운 음성 대화 경험..
[Saynow] 스피킹 서비스에서 STT와 TTS는 어디에 둬야 할까?
·
Project/Saynow
이 글은 Velog에서 이전한 글입니다. Velog 원문 보기들어가며소프트웨어 마에스트로 17기 연수생으로 참여하며, 팀원들과 서비스를 기획했다.우리 팀이 찾은 핵심 가치는 영어를 완벽하게 말해야 한다는 부담감, 강박증을 없애주기이다.캐치프라이즈로는 "내 영어를 진짜 외국인이 알아들을 확률은?"를 잡았다.따라서, 핵심 가치를 기능으로 구현하기 위해서 스피킹 서비스를 만들기로 결정했다.자연스럽게 따라오는 질문이 있다.사용자의 음성은 어디에서 텍스트로 바꿀까?AI가 만든 다음 질문은 어디에서 음성으로 바꿀까?처음에는 단순해 보였다.사용자가 말하면 음성 파일을 서버로 보내고 -> AI 서버가 STT로 텍스트를 만들고 -> 답변을 분석한 뒤 다음 질문을 만들고 -> 그 질문을 TTS로 음성 파일로 변환해 S3 ..
알고리즘 스터디 1주차
·
Algorithm/소마 알고리즘 스터디
이 글은 Velog에서 이전한 글입니다. Velog 원문 보기1번 문제: BFS문제: https://leetcode.com/problems/minesweeper/description/풀이 소요 시간: 30분알고리즘: BFSfrom collections import dequed = [[-1,-1], [-1,0], [0,-1], [1,1], [1,0], [0,1], [1,-1], [-1,1]]class Solution: def updateBoard(self, board: List[List[str]], click: List[int]) -> List[List[str]]: R, C = len(board), len(board[0]) q = deque([(click[0], click[1..