-
운송장에 옵션이 안 보이는데요? - hard delete의 대가
"옵션 두 개 시켰는데 한 종류만 두 개 왔어요"과일 매장의 택배 시스템 운영 흐름은 다음과 같다.고객이 온라인으로 상품과 옵션(예: 사과 1kg / 사과 2kg)을 골라 결제하면,매장은 운송장을 출력해 박스를 포장하고 택배사에 넘긴다. 언제부턴가 CS 채널에 비슷한 클레임이 줄줄이 올라오기 시작했다."한 상품에서 1kg, 2kg 두 옵션을 시켰는데 1kg 두 개로 왔어요." 처음엔 매장에서 상품을 잘못 담은 단순 실수로 가볍게 봤다.그런데 같은 패턴의 클레임이 며칠 사이 적지 않게 쌓였다.여러 주문이 비슷한 모양으로 어긋나 있다는 게 분명해졌고, 그제야 시스템 쪽을 의심하기 시작했다. 결론부터 말하자면 이 문제는 옵션 삭제 정책을 hard delete에서 soft delete로 바꾸는 것으로 마무리됐다..
-
한번 더 고민하기 - 주니어의 확장성 회고
TL;DR주니어가 확장성 있는 설계에 다가서는 가장 단순한 방법은, 구현 직전에 한번 더 스스로에게 되묻는 습관이다.랭킹에서는 "이 데이터가 정말 일회성인가" 를, 매출 집계에서는 "같은 데이터를 읽는 경로를 몇 개로 둘 것인가" 를 묻지 않아 흔들렸다.AI 가 구현 비용을 덜어준 지금 그 시간을 구현 전의 고민에 옮겨 쓸 수 있는 시대다.두 경험에서 얻은 구현 전 사전질문 세 가지이 데이터는 정말 일회성인가, 아니면 재활용 가능한가?누군가 이 기능을 확장한다면, 지금의 구조가 그 방향을 막지는 않는가?이 코드를 처음 읽는 동료가 몇 번이나 멈추게 될까?주니어로 개발을 하다 보면 가장 많이 고민하는 건 아래와 같다."이 코드 동작하나?" 일정이 붙고, 요구사항이 쏟아지고, 구현해야 할 기능이 쌓이는 와중..
-
실시간 랭킹은 없다
우리가 보는 순위는 이미 과거다 "30분 전"무신사를 열었다. 실시간 랭킹 탭에 "30분 전", "16분 전" 같은 표기가 붙어 있었다.오늘의집도 마찬가지였다. "2026.04.10 04:56 기준"이라고 적혀 있다. "실시간"이라는 단어를 쓰면서 왜 갱신 시점을 명시할까. 지금 이 순간의 데이터가 아니라는 뜻 아닌가."실시간"이라고 적혀 있는 랭킹이 정말 지금 이 순간의 데이터일까? 아니다. 그리고 이건 버그가 아니라 설계다. 커머스 프로젝트를 공부하고 Redis Sorted Set 기반 랭킹 시스템을 구현하면서 이 사실을 체감했다.DB로 충분할 거라고 생각했던 초기 판단이 부하 테스트에서 어떻게 깨졌는지,그리고 왜 빅테크가 준실시간이라는 선택지를 가져가는지를 정리해보겠다.DB로 충분하지 않을까처음엔 ..
-
택배가 안 움직이는데요? - 배송 추적 시스템에서 놓친 조건
배송 조회 외부 서비스 호출 제한에 걸린 이야기택배 서비스를 열고 나서 얼마 지나지 않아 관리자 쪽에서 바로 얘기가 나왔다."운송장은 등록됐는데 배송이 안 움직여요."처음에는 단순히 집하가 늦는 건가 싶었다. 택배는 원래 실시간으로 움직이지 않고, 어떤 건은 하루 가까이 상태 변화가 없기도 하니까 이상한 일처럼 보이지는 않았다.그런데 문제는 점점 움직이지 않는 택배 운송장이 쌓인다는 점이었다. 한두 건이 아니라 여러 주문이 비슷하게 멈춰 있었고, 이미 배송이 진행 중인 걸로 보이는 주문도 화면에서는 그대로였다. 그때부터 이건 단순한 배송 지연이 아니라 시스템 문제라고 판단했다. 이번 글은 그 장애를 어떻게 추적했고,결국 원인이 배송 조회 외부 서비스의 초당 API 호출 제한이었다는 걸 어떻게 확인했는지 ..
인기글 + 내용
-
@Transactional을 final class에 붙이면 안되는 이유(AOP의 동작원리)Spring(boot) 2025.01.12 23:06
업무를 하던 도중 for문을 돌며 데이터를 DB에 넣어주는 코드를 발견했다.그리고 데이터를 저장하는 연산이라 for문을 호출하는 메서드에 @Transactional을 붙여야 할 것 같아 해당 내용을 검토를 받고 어노테이션을 붙여주고자 했다.하지만 그 코드에 @Transactional을 붙이자 스프링부트 앱이 실행이 안되는 현상이 발생했다. 결론적으로 원인은 final class에 @Transactional을 붙여서 생긴 문제였고,final class에 @Transactional을 붙이면 안되는 이유는 아래와 같았다.1. @Transactional은 Spring AOP를 기반으로 동작하고, 2. AOP는 CGLIB Proxy를 생성하는 것 기반으로 동작한다.3. 추가적으로 @Transactional을 붙..
-
99클럽 코테 스터디 2일차 TIL + 면접 특강 후기항해99 2024.07.24 02:06
오늘의 학습 키워드 - 면접에서 매력적인 지원자가 되는 방법 및 일반 면접 팁공부한 내용 본인의 언어로 정리하기역량의 핵심 이해대학생은 정량적 스팩에 집중하는 경향그러나 취업은 사람이 평가하므로 절대적인 기준 x자소서와 면접의 평가표가 존재하지만, 평가자는 결국 느낌에 의존→ 같이 일하고 싶은 사람을 뽑게됨면접을 잘 봤다고 생각하지만 떨어지는 이유착각 포인트말을 잘했다모두 답변을 했다청산유수로 받아 쳤다긴장을 하나도 안했다떨어지는 면접누가 봐도 훈련된 정답만 이야기 → 진정성 결여나만 부각 되는 이야기들(함께 x)모든지 이끌고 주도해야 직성이 풀린다고 보일 때다양한 경험을 보면 현 직장에 만족하지 못하고 떠날 것 같을 때로열티 결여 (곧 재취준 각이 보일 때) / 꼰대들의 편견을 못깬 상태 → 최근 ..
-
한번 더 고민하기 - 주니어의 확장성 회고카테고리 없음 2026.04.17 17:06
TL;DR주니어가 확장성 있는 설계에 다가서는 가장 단순한 방법은, 구현 직전에 한번 더 스스로에게 되묻는 습관이다.랭킹에서는 "이 데이터가 정말 일회성인가" 를, 매출 집계에서는 "같은 데이터를 읽는 경로를 몇 개로 둘 것인가" 를 묻지 않아 흔들렸다.AI 가 구현 비용을 덜어준 지금 그 시간을 구현 전의 고민에 옮겨 쓸 수 있는 시대다.두 경험에서 얻은 구현 전 사전질문 세 가지이 데이터는 정말 일회성인가, 아니면 재활용 가능한가?누군가 이 기능을 확장한다면, 지금의 구조가 그 방향을 막지는 않는가?이 코드를 처음 읽는 동료가 몇 번이나 멈추게 될까?주니어로 개발을 하다 보면 가장 많이 고민하는 건 아래와 같다."이 코드 동작하나?" 일정이 붙고, 요구사항이 쏟아지고, 구현해야 할 기능이 쌓이는 와중..
-
[BE] 고도화 - 메시지 전송프로젝트 - 과일맛집 2025.11.30 19:16
이전 글에서 노쇼 제품의 재고가 어떻게 처리되는지에 대해 정리했었다. 모두가 예약한 과일을 제때 찾아가면 좋겠지만, 실제 운영에서는 일부 유저가 반복적으로 노쇼를 하고 있다.현재 서비스에는 노쇼에 대한 별도의 패널티가 없었기 때문에,이를 최소한의 수준에서라도 안내하고 경고할 수 있는 기능을 추가하고자 했다. 이번 개선에서 구현한 기능은 크게 두 가지다.1. 관리자 페이지에서 유저의 노쇼 횟수 확인2. 노쇼 이력이 있는 유저가 페이지에 접속하면 경고 메시지를 전달 이번 글은 이 중 노쇼 경고 메시지 전송 과정을 정리한 글이다.메시지 전송 흐름노쇼가 발생하고, 유저가 경고 메시지를 보기까지의 흐름을 간단히 정리하면 아래와 같다. 1. 배치가 노쇼 예약을 찾고 재고/상태를 갱신한다. 2. 노쇼로 판정된 유저에..