+ Precisely separates behavior preservation from policy changes.
- High-value-check extraction is somewhat unnecessary for this goal.
Orders the work so the code runs after every step and judges whether the refactor is worth doing at all.
| Category | Development › Coding |
|---|---|
| Tags | AnalyzingReviewingDeveloperCode |
Plan a refactor of this code. ***Do not rewrite it.*** Plan only. 1. **Name the problems concretely.** Not "it is complex" — what, and why that is a problem. 2. Per problem, the direction **and what it gains and costs.** 3. Set the order: - ***It has to work after every step.*** **Do not plan a single big replacement** - Lowest risk first - If there are no tests, which tests have to exist first 4. **Name what should not be touched.** Working code does not get changed without a reason. 5. ***Judge whether this refactor is worth doing now. If it is not, say so.***
Big-bang rewrites strand you halfway. This sequences by risk, names what not to touch, and can conclude "not now".
ChatGPT is safest and most specific by separating policy changes. Gemini is thorough but changes behavior and invents an effort estimate; [C] was not provided.
+ Precisely separates behavior preservation from policy changes.
- High-value-check extraction is somewhat unnecessary for this goal.
+ Clearly identifies issues and phased safeguards.
- Adding an unknown-method error conflicts with behavior preservation.
| Criterion | ChatGPT | Gemini | Leader |
|---|---|---|---|
| Instruction following | 10 | 8 | ChatGPT +25% |
| Accuracy | 9 | 6 | ChatGPT +50% |
| Specificity | 10 | 9 | ChatGPT +11% |
| Structure | 9 | 9 | Tie |
| Right length | 8 | 7 | ChatGPT +14% |
Scored 1–10 by gpt-5.6-sol with model names hidden (2026-09-24). This is an AI review, not a measurement.
We gave three models the same input and copied their answers unedited. Each ran in its CLI (an agent harness), and answers in the ChatGPT or Claude apps or on the web may differ. Outputs are in Korean.
Environment: Node.js 18 + Express, 결제 모듈(paymentService.js), 실서비스 운영 중, 개발자 2명, 배포는 하루 1~2회
Code: // paymentService.js
function processPayment(order, method) {
if (method === 'card') {
if (order.amount > 500000) {
verifyOwner(order.userId);
}
chargeCard(order);
} else if (method === 'kakaopay') {
if (order.isSubscription) {
chargeKakaoRecurring(order);
} else {
chargeKakaoOnce(order);
}
} else if (method === 'bank') {
if (order.amount > 500000) {
verifyOwner(order.userId);
}
requestBankTransfer(order);
} else if (method === 'point') {
if (order.userPoint < order.amount) throw new Error('포인트 부족');
deductPoint(order);
}
logPayment(order, method);
}
Why I want to refactor: 네이버페이를 새로 추가해야 하는데 이 if-else 분기가 8단계까지 얽혀 있어서 어디에 끼워 넣어야 할지 모르겠고, 잘못 건드리면 기존 카카오페이 결제가 깨질까봐 무섭습니다.
Tests: 테스트 코드 없음. 배포 전에 QA 담당자가 카드/카카오페이/계좌이체 3가지 시나리오를 스테이징에서 수동으로 결제해보는 게 전부입니다.현재는 “대규모 구조 개선”보다 네이버페이 추가를 안전하게 가능하게 만드는 최소 refactor가 적절합니다. 운영 중이고 개발자가 2명뿐이므로, 자동 회귀 테스트를 먼저 확보한 뒤 작은 단위로 진행해야 합니다.
processPayment가 다음을 모두 담당합니다.
네이버페이를 추가할 때 기존 조건문을 직접 수정해야 하므로, 카카오페이 분기나 공통 로그 위치를 잘못 건드릴 위험이 큽니다.
다음 로직이 두 곳에 반복됩니다.
if (order.amount > 500000) {
verifyOwner(order.userId);
}
금액 기준이나 확인 정책이 바뀌면 두 분기를 모두 찾아 수정해야 하며, 한쪽만 수정될 가능성이 있습니다.
kakaopay 안에서 다시 isSubscription을 검사합니다. 새 결제수단이 추가되거나 카카오페이의 결제 유형이 늘어나면 중첩이 계속 깊어집니다.
method도 결제 로그가 기록됨현재 지원하지 않는 결제수단이면 실제 결제는 하지 않지만 마지막의 logPayment(order, method)는 실행됩니다. 이것이 의도된 동작인지 불명확합니다. 잘못된 요청을 성공적으로 처리한 것처럼 보일 수 있습니다.
결제 함수에서 예외가 발생하면 logPayment는 실행되지 않습니다. 반면 정상적으로 결제가 끝나면 모든 결제수단에서 로그가 실행됩니다. 이 동작은 결제 감사 로그인지, 시도 로그인지에 따라 의미가 달라집니다.
현재 자동 테스트가 없으므로 코드 이동 자체가 카카오페이 회귀를 검출하지 못합니다. refactor 전에 최소한 다음 동작을 자동화해야 합니다.
chargeCard 호출, verifyOwner 미호출verifyOwner 후 chargeCardchargeKakaoOnce만 호출chargeKakaoRecurring만 호출deductPoint 미호출deductPoint 호출logPayment 호출외부 결제 API를 실제로 호출하지 않는 단위 테스트여야 합니다. chargeKakaoOnce 등을 가짜 함수나 mock으로 대체해 호출 순서와 호출 여부를 검증합니다. Node.js 18의 node:test와 assert를 사용할 수 있으므로, 별도 테스트 프레임워크를 도입하는 것부터 시작할 필요는 없습니다.
각 단계는 별도 커밋으로 만들고, 각 단계 후 테스트와 기존 QA 시나리오를 통과시킵니다.
코드 구조는 바꾸지 않고 characterization test를 작성합니다.
이 단계가 끝나면 테스트가 없는 상태로 구조를 옮기지 않아도 됩니다.
예를 들어 verifyHighAmountOrder(order) 같은 내부 함수를 만들고, 카드와 계좌이체가 이를 호출하게 합니다.
카드, 카카오페이, 계좌이체, 포인트 처리 내용을 각각 이름 있는 핸들러로 옮깁니다. 처음에는 기존 if-else 안에서 해당 핸들러를 호출하게 해도 됩니다.
즉, 한 번에 dispatch 구조로 바꾸지 않고 다음처럼 점진적으로 진행합니다.
이렇게 하면 각 커밋 후에도 기존 if-else가 남아 있어 동작 경로를 비교하기 쉽습니다.
네이버페이의 실제 요구사항을 정한 뒤 별도 핸들러를 추가합니다.
확정해야 할 사항은 다음입니다.
logPayment를 기존 결제수단과 같은 방식으로 기록하는지네이버페이만 추가하고 기존 카드·카카오페이 로직은 변경하지 않는 것이 안전합니다. 네이버페이 단위 테스트를 먼저 추가한 후 라우팅에 연결합니다.
기존 결제수단의 동작이 핸들러로 옮겨지고 테스트가 통과한 뒤에만 다음 구조로 바꿉니다.
const handlers = {
card: handleCard,
kakaopay: handleKakaoPay,
bank: handleBank,
point: handlePoint,
naverpay: handleNaverPay
};
processPayment는 다음 역할만 담당하게 합니다.
이때 알 수 없는 결제수단의 처리 방식은 별도 합의 전까지 바꾸지 않습니다.
자동 테스트 통과 후 기존 수동 QA에 네이버페이를 추가합니다.
배포 후에는 결제수단별 성공률과 오류 로그를 확인할 수 있어야 합니다.
다음은 명확한 장애나 요구사항이 발견되지 않는 한 변경하지 않는 것이 좋습니다.
chargeCard, chargeKakaoOnce, chargeKakaoRecurring, requestBankTransfer, deductPoint의 내부 구현order 객체의 필드명과 구조500000logPayment의 형식과 저장 위치이 항목들은 현재 작업의 목적이 아니며, 함께 바꾸면 장애 원인을 분리하기 어려워집니다.
가치는 있습니다. 네이버페이 추가가 예정되어 있고, 현재 구조에서는 결제수단을 추가할 때 기존 분기를 직접 수정해야 하므로 운영 리스크가 반복될 가능성이 높습니다.
다만 지금 할 범위는 다음으로 제한하는 것이 좋습니다.
결제 시스템 전체 재설계, 외부 API 추상화, 오류 정책 개편, 로그 시스템 변경까지 동시에 진행하는 것은 현재 팀 규모와 배포 빈도에 비해 위험하고, 이번 네이버페이 추가에 필요한 범위를 넘어섭니다.
| 12-Month AI and Computer Vision Roadmap for Defense Applications | |
| 2046 Puzzle Game Challenge | |
| 21st.dev component prompt | |
| 3D FACTORY | |
| 3D FPS Game |