-
성능 좋다는 그 모델, 우리한테도 좋을까
성능 좋다는 그 모델, 우리한테도 좋을까"이번엔 진짜 다르다던데요?"새 모델이 나올 때의 흐름은 다음과 같다. 벤치마크 표가 돌고, "이번엔 진짜 다르다"는 후기가 올라오고, 며칠 안에 다들 그 모델로 옮겨 간다. 나도 따라 옮긴다. 안 옮기면 뒤처지는 기분이 들어서다. 흔히 말하는 AI 포모(FOMO)다. 그런데 옮기고 나면 매번 같은 생각이 들었다."진짜 성능이 좋은 건가? 우리한테도 좋은 건가?" Fable이 나왔을 때 처음 의심이 생겼다. 개인적으로는 Opus와 큰 차이를 못 느꼈다. 하지만 확실히 느낀 건 토큰이 훨씬 빨리 닳는다는 것이었다. 내 도메인이 푸는 문제가 쉬워서 차이가 안 났을 수도 있다. 어려운 문제에서는 다를지도 모른다. 그런데 그걸 모른다는 게 문제였다. 차이가 없는 건지, 내..
-
운송장에 옵션이 안 보이는데요? - 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로 충분하지 않을까처음엔 ..
인기글 + 내용
-
@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을 붙..
-
[BE] 예약 시작 시간을 서버 기준으로 통합한 이유프로젝트 - 과일맛집 2026.01.18 20:31
일부 상품은 특정 시점(예: 오후 1시)부터 예약을 시작해야 했다. 가장 단순한 방법은 상품 테이블에 판매가능시간 컬럼을 추가하고,예약 요청 시점에 아직 시간이 되지 않았다면“아직 예약 시간이 아닙니다”라는 에러를 반환하는 방식이다. 하지만 이 접근은 UX 관점에서 여러 문제가 있었다.단순 검증 방식의 문제점사용자는 예약 버튼을 눌러본 뒤에야 예약 불가 사실을 알게 된다예약 가능 여부를 매번 서버 요청으로 확인해야 한다결과적으로 불필요한 실패 요청과 CS 증가로 이어질 수 있다따라서 프론트엔드는 예약 가능 시간을 사전에 인지하고,예약 가능 시점 전후에 맞춰 UI 상태(문구, 버튼 활성화 등)를 제어할 수 있어야 했다.추가 문제: 시간 기준 불일치문제는 여기서 한 단계 더 나아간다. 프론트엔드가 예약 가능..
-
Q. 14258 자바 : XOR그룹백준_Java 2025.10.12 15:51
Q. 14258 자바 : XOR그룹 문제 : boj.kr/14258P5 난이도의 문제이다. 문제를 간단히 설명하자면격자형 그래프가 주어진다. 이 때 인접한 칸에 수가 있다면 "XOR 그룹" 으로 묶을 수 있다.만약, 중간에 수가 빠져있으면, 연결이 되지 않으므로, 한 격자판에 여러 XOR 그룹이 있을 수 있다. 이제 격자 그래프에서 작은 수부터 제거한다. 하나를 지울 때 마다 XOR 그룹이 변하게 되는데, XOR 그룹의 합의 최대값을 구하는 문제이다.처음에는 Flood Fill 방식으로 격자형 그래프를 탐색하고, 작은 수 부터 지워나갈 때 마다 다시 계산하는 방식으로 생각했다.하지만 이 경우 숫자를 지울 때 마다 그룹에 포함된 요소를 다시 계산해야 하므로시간 복잡도가 (1,000)^4으로 시간초과가 나게..
-
DB Lock기타 2025.05.04 23:57
최근 간단한 예약 서비스 과제를 진행하면서, JPA의 Lock을 직접 다뤄야 하는 상황이 생겼다. @Transactional만으로는 동시성 문제가 해결되지 않았고 비관적 락(Pessimistic Lock) 을 적용해 해결했다.이후 해당 내용에 대해 좀 더 자세히 알아보고자 글을 작성하게 되었다. 대표적으로 사용하는 DB중 하나인 MySQL 기준으로 작성할 예정이며 아래와 같은 순서로 작성하겠다. 1. DB Lock의 기본 개념2. Read Lock vs Write Lock3. 비관적 락 vs 낙관적 락4. 교착 상태5. ORM과 Lock (JPA)1. DB LockLock은 왜 사용해야 할까? 예를 들어 캐치테이블 같은 예약 앱을 생각해보자.여러 명의 유저가 동시에 예약을 시도했을 때, 누가 예약을 ..