개발 기록
axios.post()만 써도 충분한가요? async/await로 감싸는 이유와 API 구조화 패턴 비교
2025.07.02
프론트엔드에서 API를 호출할 때 가장 많이 쓰는 패턴은 아래와 같다.axios.post('/auth/login', { email, password });하지만 실제 운영 환경에서는 다음과 같은 고민이 생긴다.왜 async/await로 한 번 더 감싸야 하지?에러 핸들링은 어디까지 하는 게 좋을까?res.data.data.data 같은 코드, 어떻게 해결하지?API 클라이언트를 어떻게 구성해야 유지보수가 쉬울까?이 글에서는 위와 같은 질문에 답하면서 현업에서 쓰는 API 호출 방식의 구조화된 패턴을 소개한다.1. 기존 방식 – 단순 호출export const login = (email: string, password: string) => { return axios.post('/auth/login', {..
개발 기록/트러블슈팅 · 환경 설정
http-proxy-middleware에서 onProxyRes만 썼는데 500 에러가? 이유는 selfHandleResponse 때문
2025.06.30
문제 상황: 예상치 못한 500 에러 발생Express + http-proxy-middleware 조합으로 API Gateway를 구성하는 도중, 단순히 로그만 찍기 위해 onProxyRes를 사용했음에도 불구하고 500 Internal Server Error가 발생하는 현상을 마주하게 되었습니다.onProxyRes: (proxyRes, req, res) => { logger.info(`Proxy response from ${req.url}`);}응답을 직접 가공하거나 처리하는 코드는 없었는데도, 프록시가 응답을 제대로 전달하지 못하고 요청이 실패했습니다.이 문제는 다음 옵션을 명시한 뒤에야 해결되었습니다:selfHandleResponse: false배경 지식: selfHandleResponse란?ht..
개발 기록/트러블슈팅 · 환경 설정
학생들과 실제 겪은 merge 충돌 사례와 실무형 해결 전략
2025.05.31
협업 중 merge conflict를 반복해서 겪는 학생에게 전한 이야기요즘 개발 기본을 다질 겸, 과외를 진행하고 있어요최근에 제가 진행하고 있는 개발 과외 수업에서, 학생들이 실제 협업을 해보는 팀 프로젝트를 시작했습니다.그 과정에서 꽤 흥미로운 실전 이슈가 발생했는데요 — 바로 동일 파일에 대해 동시에 여러 명이 commit & push를 하며 발생하는 merge conflict 문제였습니다.학생 A가 main 브랜치에서 작업을 하고, 동시에 학생 B와 C도 같은 파일을 수정해 push를 시도하면서 충돌이 끊임없이 발생하는 상황이었죠.이 문제를 단순히 “주의하세요”로 넘기기보다는, 실제 실무에서는 어떻게 이런 충돌을 방지하고 해결하는지 알려주고 싶었습니다.문제 상황 요약 발생한 상황여러 명이 동시에..
개발 기록
Node.js에서 관례적으로 사용하는 변수 표기법 정리
2025.05.31
1. next vs _next: Express 미들웨어에서 자주 보이는 표기Express에서의 미들웨어 함수는 다음과 같은 시그니처를 가집니다:(req: Request, res: Response, next: NextFunction) => void next – 일반적인 다음 미들웨어 호출용 인자(req, res, next) => { next(); // 다음 미들웨어로 이동}이 표기는 실제로 next()를 호출하는 경우에 사용됩니다. _next – 사용하지 않을 인자에 대한 표시(req, res, _next) => { // 여기서는 next()를 호출하지 않음}변수 앞에 _(언더스코어)를 붙이는 관례는 **“이 변수는 사용되지 않는다”**는 의미ESLint, TypeScript 설정에서 정의한 변수지만 ..
개발 기록/회고
Spring Service에서 객체 생성 책임을 분리해야 하는 이유 – 실무에서 Factory 패턴을 도입한 회고
2025.05.29
– 에스크로 서비스 개발 중 도입한 Factory 패턴 회고도입: 기능 구현은 끝났지만, 찝찝했던 코드에스크로 거래를 등록하는 기능을 만들던 중이었다.비즈니스 흐름은 단순했다.거래 등록 요청을 받아 EscrowTransaction 객체를 만들고, 이를 저장소에 저장하면 되는 구조였다.초기 코드는 다음과 같았다.public Long registerTransaction(TransactionRegisterCommand command) { EscrowTransaction transaction = new EscrowTransaction( command.getBuyerId(), command.getSellerId(), command.getItemId(), co..