BACKEND ENGINEER — 조창훈

용어집 → 계약 확정 → 시나리오 검증 → 연동.

코딩 에이전트와 함께 사내 폐쇄망 철도 전력 관제 백엔드 설계 · 운영. 기능 하나를 용어집 → 폴더 규칙 → 계약 확정 → 구현 → 리뷰 · 시나리오 → 연동 6단계로 만듭니다. 이 방식으로 푼 문제는 해결한 문제에 따로 정리.

강조된 단계에 마우스 → 링에서 그 단계가 커짐

배포 시간
~9.5→~2.5분

마이그레이션 잡 단일화 + 배포 잡 병렬화

cutover 사고
9건

이틀간 SEV 포함 — 전부 근본 원인과 재발 방지까지

테스트 콘솔 로딩
6.2→0.9초

SSE 첫 바이트 즉시 전달 · 2회 실측 평균

AI 응답
10–20→0.2–1.3초

Malang · 호출 수·요청 단위·리전 왕복 분리

SCROLL6단계부터

01 — 일하는 방식

기능 하나를 에이전트와 만드는 6단계

  • 적용 대상: SPOS 서버(커밋 1,700+) · 테스트 콘솔 Flow Lab. 구현의 상당 부분을 Claude Code · Codex로 진행
  • 출발점: 에이전트는 세션마다 기억이 리셋되고, 정하지 않은 부분은 추측으로 채움
  • 그래서: 프롬프트 요령 대신 용어 · 구조 · 계약 · 검증을 저장소와 이슈에 고정

단계 · 하는 일 · 효과

  1. 용어집 mattpocock skills의 domain-modeling으로 서비스 용어를 GLOSSARY.md에 정리. 개념마다 승인 용어 1개 + 쓰지 않는 말을 함께 기록하고, 큰 결정은 ADR로 남김. 예: ‘정정’과 ‘수정’을 서로 다른 개념으로 고정 → 사람 · 에이전트 · 클라이언트 · 코드가 같은 단어를 씀 → 요구사항 오해와 이름 불일치 감소
  2. 폴더 규칙 기능보다 폴더 구조를 먼저 설계. 폴더 · 파일마다 책임을 정함: 컨트롤러는 트랜잭션 소유 금지, 판정 모듈은 DB · HTTP import 금지, 라우터 등록은 선언 테이블 한 곳. 규칙은 AST 구조 테스트로 강제 → 문제가 터진 위치를 보면 열어 볼 파일이 정해짐 → 에이전트 탐색 범위 축소, 규칙 위반은 CI에서 차단
  3. 계약 확정 이슈 발행(범위 · 완료 조건). 첫 구현이면 요청 · 응답 스키마와 API 초안을 들고 클라이언트와 협의 → 문제를 찾으면 설계부터 수정 → 확정 후 구현 착수 → 수정이 코드가 아니라 문서 단계에서 끝남 → 재작업 감소, 에이전트가 추측할 공백 제거
  4. 구현 이슈 단위로 에이전트에 위임. 착수 전 흐름표(요청 → 권한 · lock → DB 변경 → side effect → 응답 · 에러)를 한글 의사코드로 승인, 호출자 · 형제 경로 영향 조사 → 코드 전에 이해를 검증 → 같은 기준을 쓰는 경로를 한 번에 수정, 누락 감소
  5. 리뷰 · 시나리오 show-me로 변경점(diff · 호출 흐름 · 화면)을 눈으로 확인 → code-review 스킬로 리뷰 → Playwright로 실제 사용자 시나리오를 작성 · 실행 → “다 됐습니다” 보고 대신 확인된 변경점과 시나리오 결과로 완료 판정
  6. 연동 · 배포 테스트 콘솔 Flow Lab으로 클라이언트 연동 전에 연동 · 실사용 테스트 → 클라이언트 연동 → 서버 반영 → 클라이언트와 붙는 시점에 남은 수정 최소화

결과 지시 단위: “이 파일 고쳐줘” → “이 이슈 구현해줘” · 이 방식으로 푼 문제 8개 보기 →

예시 · 기능 하나가 6단계를 지나는 모습

실제 프로젝트 화면이 아니라, 같은 흐름을 가상의 기능 “환불 요청 API”로 재현한 예시입니다.

01 용어집GLOSSARY.md
용어정의쓰지 않는 말
환불 요청고객이 결제 금액의 반환을 신청한 상태취소, 반품
환불 승인운영자가 요청을 받아들여 지급이 확정된 상태처리 완료
부분 환불주문 항목 일부만 반환일부 취소

ADR-0007 · “주문 취소”와 “환불”은 다른 개념 — 취소는 결제 전, 환불은 결제 후

02 폴더 규칙트리 + 파일별 책임
src/
├── api/refunds/router.py      # 경로 · DTO만. 트랜잭션 금지
├── services/refund_service.py # 트랜잭션 · 흐름 소유
├── domain/refund_policy.py    # 순수 판정. DB · HTTP import 금지
├── repositories/refund_repo.py # 쿼리만
└── tests/architecture/
    └── test_layers.py         # 위 규칙을 AST로 검사

“금액 계산이 틀림” → domain/refund_policy.py부터 열면 됨

03 이슈 발행이슈 트래커

환불 요청 API 추가 #예시 · opened

backendIn Progress계약 협의 필요

범위
고객 환불 요청 생성 · 조회. 승인은 다음 이슈
완료 조건
☑ 계약 확정 ☐ 구현 ☐ 리뷰 ☐ 시나리오 테스트 ☐ 연동
03 계약 확정요청 · 응답 초안 → 협의 → 수정
POST /orders/{id}/refund-requests
{
-  "amount": 12000
+  "items": [{ "orderItemId": 3, "quantity": 1 }]
   "reason": "SIZE"
}
201 { "refundRequestId": 41, "status": "REQUESTED" }
409 REFUND_ALREADY_REQUESTED

협의 중 발견: 클라이언트 화면은 항목 단위 → 금액 필드 대신 items[]로 설계 수정

04 구현흐름표(한글 의사코드) 승인 후
환불요청_생성(주문ID, 항목들):
  주문을 잠그고 읽는다            # FOR UPDATE
  결제 전이면 → 409 주문_취소_대상
  이미 요청 중이면 → 409 중복_요청
  금액 = 환불정책.계산(항목들)    # domain, 순수 함수
  환불요청 저장, commit
  commit 후 → 운영자 알림 발행   # side effect
  201 응답
05 show-me변경점 확인
 src/
 ├── api/refunds/
+│   └── router.py         # POST refund-requests
 ├── services/
+│   └── refund_service.py
 └── domain/
+    └── refund_policy.py

 환불요청_생성
   주문 잠금
+  중복 요청 검사
   금액 계산

diff를 파일 목록이 아니라 구조 · 흐름 단위로 보고 의도와 맞는지 확인

05 code-review리뷰 결과
  • 높음refund_service.py:48 · 알림 발행이 commit 전 → rollback 시 잘못된 알림
  • 중간router.py:21 · quantity 0 허용 → DTO 검증 추가
  • 통과계층 규칙 · import 방향 위반 없음

지적 사항 수정 → 같은 리뷰 재실행 → 0건 확인

05 Playwright실제 사용자 시나리오
test('고객이 항목 하나를 환불 요청한다', async ({ page }) => {
  await page.goto('/orders/1001')
  await page.getByRole('button', { name: '환불 요청' }).click()
  await page.getByLabel('티셔츠 · 1개').check()
  await page.getByRole('button', { name: '요청 보내기' }).click()
  await expect(page.getByText('환불 요청됨')).toBeVisible()
})
✓ 1 passed · 중복 요청 시나리오 ✓ · 결제 전 주문 ✓

사고 → 남긴 규칙

문제(사고)판단(남긴 규칙과 장치)
스냅샷 마이그레이션이 신규 환경 빌드를 깨뜨림체인을 pg_dump baseline으로 스쿼시 + create_all 전면 금지 테스트 + 일회용 Postgres 실측
배포 중 자동 취소로 반쪽 배포배포 잡 취소 불가 + 호스트별 직렬화
git clean이 시크릿 마운트를 삭제clean 예외 + 시크릿 주입 실패 시 fail-fast
pgbouncer·asyncpg 충돌, 커넥션 슬롯 고갈pgbouncer 경유 강제 + 접속 설정 표준화, 설정 테스트로 봉인
신규 API의 프록시 등록 누락으로 404라우터 등록 + 프록시 spec + 실호출 검증을 한 세트로
같은 판정 지식 3벌 복제로 drift“2벌째가 개입 시점” + 진실표 단일 소유 + AST 재선언 탐지

사고 → 원인 분석 → 규칙 문서화 → 테스트 · CI로 기계화 → CLAUDE.md · 런북 반영 → 다음 세션의 에이전트가 읽고 시작

이 사이트도 같은 방식으로 제작

$ claude "포트폴리오를 뜯어고쳐줘 — 해결한 문제, 사고 방식, 에이전트 활용법. WebGL로."
▸ 읽기   기존 케이스 스터디 8편 · SPOS 설계 문서 11편 · 테스트 콘솔 작업 노트
▸ 제외   내부 주소 · 이슈 번호 · 노선·기관명 · 사람 이름 · 개인 사진
▸ 설계   문제 → 판단 → 결과 · 파티클 형태 9종 · 데모 7종
▸ 구현   Vite · TypeScript · Three.js · GLSL · GSAP · Lenis
▸ 검증   타입 체크 · 프로덕션 빌드 · 헤드리스 브라우저(데스크톱·모바일)
✓ 남은 일 사실관계 · 표현 최종 검토 = 사람

02 — 테스트 콘솔 · 6단계 연동

클라이언트 연동 전에 돌리는 테스트 콘솔

  • 서버 변경마다 관제 웹 · 현장 앱을 거쳐 확인 → 피드백 지연
  • 판단: 서버 API를 두 역할로 바로 실행하는 사내 테스트 콘솔 Flow Lab 구축(백엔드 개발자용 “두 번째 클라이언트”)

2026.06 – 현재Next.js · TypeScript커밋 130+유닛 테스트 600+브라우저 테스트 12종

Flow Lab — 요청 기록 패널 (재현 데모)

작업계획plan · 예시

야간 전차선 점검 현장대기 → 단전지조

버튼을 누르면 오른쪽 패널에 그 동작이 일으킨 요청이 한 묶음으로 쌓입니다. 토큰과 비밀번호는 가려집니다.

요청 기록0건

아직 기록이 없습니다.

판단

  • 역할별 확인 관제사 · 안전관리자 세션 분리(HttpOnly 쿠키), 401 시 세션 복원 후 재시도. 한 역할의 로그인이 다른 역할 화면을 대신하지 않음
  • 개발 계정 노출 브라우저는 콘솔 서버 라우트만 호출, 허용 목록 서버 주소만 통과. 계정 정보는 서버 전용 환경변수에만
  • 요청 추적 버튼 하나 = 요청 묶음 하나. upstream 주소 · 상태 · 소요 시간 · 본문 표시, 비밀번호 · 토큰 · 키 값 가림
  • 전 구간 확인 작업 등록 → 계획 → 결재 게이트 → 단전 · 급전 조작 → 증빙 업로드(브라우저 봉투 암호화) → 알림 → SSE 갱신을 한 화면에서

결과

계통도 로딩

6.2s→0.9s

원인 브라우저가 SSE 첫 바이트를 5초 checkpoint까지 대기. 판단 프록시가 upstream 헤더 직후 SSE 주석 바이트 전송, 가짜 이벤트 · 업무 상태 생성 없음. 수정 전후 2회씩 실측.

계획 선택 시 요청

14회→3회

원인 phase 7개를 두 번씩 읽는 fan-out. 판단 열린 탭만 조회, 범위별 캐시 + 진행 중 요청 공유, SSE 수신 시 현재 탭만 재조회.

완료 기준 타입 에러 0 · 유닛 전부 통과 · 외부 요청 없는 API fixture로 헤드리스 브라우저 테스트 · 별도 모델 코드 리뷰 · 실행 명령과 미검증 범위 기록.

03 — 이전 작업

이전 프로젝트의 문제와 판단

2026.02 – 04AI 서비스 백엔드

Malang

NestJS · Prisma · PostgreSQL · OpenAI · Vertex/Gemini · ElevenLabs

문제
전화형 한국어 발화 연습, AI 응답 10–20초. 사용자는 말한 직후 반응을 기대
판단
지연을 호출 수 · 요청 단위 · 리전 왕복 · fallback으로 분리 → RULE 확정 분기는 모델 없이, slot 추출 + 응답 생성 single-call, 가까운 provider 리전
결과
0.2–1.3초. reason code로 경로 구분, 대화 의미 유지를 테스트로 고정

2024.09 – 106인정산 트랜잭션

갓생루팅

Java · Spring Boot · MySQL · Redis · Kafka

문제
버튼 연타 · 재전송으로 이체 중복, 같은 계좌 동시 갱신, 출금 후 입금 실패
판단
버튼 비활성화 대신 ref_id + DB UNIQUE, PESSIMISTIC_WRITE, SAGA 대신 단일 @Transactional(규모 대비 과함), 알림은 Kafka로 트랜잭션 경계 밖
결과
재실행 로그 없는 수치는 제외, 설계 판단만 기재

실사용 업무백오피스 자동화

ERP 엑셀 자동화

Excel 데이터 · 검증 규칙 · 전표 입력 표준화

문제
ERP 엑셀을 부과내역서 · 재무제표 · 전표 형식으로 매번 수작업 재가공. 표기 차이 · 빈 셀 · 합계 불일치
판단
산출물 형식 먼저 고정 → 업무 필드 매핑 → 검증을 산출물 생성보다 먼저 실행. 애매한 항목은 사람 확인 목록으로
결과
계정과목 · 적요 · 금액 부호 · 차변/대변 입력 규칙 표준화

2024.10 – 115인 · 팀장

손누리

Chrome Extension · FastAPI · MongoDB · S3 · RIFE

문제
수어 번역 요청마다 형태소 분석 · 유사도 · GPT 순차 호출, 3–5초
판단
같은 문장 = 같은 수어 → 번역 캐시, 단어장 로컬 캐시, 형태소 매핑
결과
평균 3.8초 → 1.1초. 프레임 보간으로 수어 영상 전환부 보정

20246인SSAFY 우수상

깻냥

Spring Boot · FCM · Native Alarm · WebRTC

문제
절전 모드 · 제조사 OS에서 알람 지연 · 중복. 정시 알람이 핵심 가치
판단
네이티브 알람 1차 + FCM 데이터 메시지 백업, 재등록 시 기존 예약 취소, 라이브러리 포크로 요일 반복 지원
결과
알람 → 딥링크 → WebRTC 방 자동 입장

2024.052인 · 팀장

선택의왕

Django · Vue.js · OAuth2 · OpenAPI

문제
OTT 추천 요청마다 외부 API 호출 → 지연, rate limit
판단
요청 경로에서 외부 API 제거. 스테이징 → 정규화 → 집계 테이블, 하루 1회 배치
결과
추천은 내부 집계만 조회, 사용자별 결과 캐싱

2025.07 – 08개인

Spring Cloud MSA 실험

Eureka · Config Server · Gateway · OpenFeign · Kafka · Docker

목표
서비스 분리 · 탐색 · 중앙 설정 · 게이트웨이 라우팅을 직접 구성
결과
모놀리스와 MSA 사이 비용 확인
이어진 판단
SPOS에서 MSA 대신 role 기반 모듈러 모놀리스 선택
저장소 보기 ↗

2025.11 –개인 · 진행 중

MongoDash

Kotlin · Spring Boot · MongoDB · Redis · Docker

목표
방문자 클릭 · 호버 수집 → 관심 영역 시각화
판단
5초 · 300건 배치 전송, 호버 지속 시간은 서버 계산. MVP는 insertMany, 병목 측정 후 BulkWrite

04 — 연락

다음 문제를 같이 쪼개 볼까요?

메일 쓰기 ↗ GitHub ↗

자격 · 수상

  • 정보처리기사 · SQLD소프트웨어 공학 · 운영체제 · 네트워크 · RDB/SQL 기본기
  • SSAFY 11기 수료1학기 우수 교육생상
  • SSAFY 11기 자율 프로젝트 우수상깻냥 · 2024.12

주로 쓰는 도구

Backend
Python · FastAPI · Java · Spring Boot · NestJS · Kotlin
Data
PostgreSQL · pgbouncer · MySQL · Redis · MongoDB · SQLAlchemy · Alembic · Prisma
Infra
Docker Swarm · Traefik · GitLab CI · GitHub Actions · GCP · AWS · Firebase
Agents
Claude Code · Codex · MCP(Context7 · Playwright) · GitLab Issues · Linear