상세 컨텐츠

본문 제목

바이브코딩으로 만든 중고거래 서비스를 제출 가능한 수준까지 보안 강화하기

개발

by 코드스키 2026. 7. 27. 15:11

본문

시큐어코딩 수업 과제로 중고거래 플랫폼을 만들었다. 처음엔 AI한테 대충 시켜서 빠르게 굴러가는 걸 만들었는데(요즘 말로 바이브코딩), 막상 제출하려고 다시 보니 "이거 그대로 내면 안 되겠다" 싶은 게 잔뜩 보였다. 최소 요구사항은 채웠지만 보안 약점이 여기저기 있었고, UI와 문서도 대충 짜맞춘 티가 났다. 그걸 하나씩 뜯어고쳐 제출 가능한 상태로 만든 과정이다.

Spring Boot 중고거래 서비스 시큐어코딩 개선 과정 대표 이미지
Spring Boot 중고거래 서비스 시큐어코딩 개선 과정 대표 이미지

스택과 최초 상태

기본 구성은 Spring Boot 3, Java 21, Thymeleaf, Spring Security, JPA다. 상품 등록·조회, 사용자, 관심상품, 그리고 CarrotCoin이라는 모의 지갑 기능이 있었다. 지갑은 실제 가상자산 연동이 아니라 모의 결제 흐름이다.

Spring Boot로 구현한 중고거래 서비스 UsedCarrot 홈 화면
Spring Boot로 구현한 중고거래 서비스 UsedCarrot 홈 화면

핵심 기능은 슬라이드의 최소 요구사항 대비 대체로 구현돼 있었다. 문제는 디테일이었다. 상세 페이지의 버튼이 역할별로 분리가 안 돼 있어서 누가 눌러도 같은 동작이 나오고, 마이페이지와 관심상품 사이 내비게이션이 끊겨 있었다. 초기에 만든 요구사항 문서(SRS 등)와 실제 구현이 어긋나 있었고, 판매자 상태를 바꾸는 드롭다운이 필요 이상으로 노출돼 있었다. 이런 게 전형적인 바이브코딩 냄새다. 돌아가긴 하는데, 왜 이렇게 됐는지 설명이 안 되는 부분들.

보안 약점을 찾아 고치기

과제의 진짜 목표는 "개발 과정에서 확인한 보안 약점이 무엇이고 어떻게 고쳤는가"를 보이는 거였다. 그래서 대충 고치지 않고 제대로 파고들었다.

가장 신경 쓴 건 권한과 접근 제어였다. 판매자 상태 변경 같은 민감한 동작이 UI에 과하게 노출돼 있으면, 화면에서 안 보이게 하는 걸로는 부족하다. 서버 쪽에서 그 요청을 할 권한이 있는지 실제로 검증해야 한다. Spring Security를 쓰고 있으니 인증·인가 규칙을 다시 잡고, 화면 노출과 서버 검증을 분리했다. 화면에서 버튼을 숨기는 건 편의일 뿐이고, 진짜 방어는 요청을 처리하는 컨트롤러/서비스 계층에 있어야 한다는 원칙을 지켰다. Spring Security의 메서드 시큐리티(@PreAuthorize 등)를 서비스 계층에 붙여서, 컨트롤러를 우회해서 호출되더라도 같은 권한 검증을 통과해야 하게 만들었다.

역할별로 분리한 상품 상세 화면 — 구매자 시점에서는 판매자 상태 변경 UI가 노출되지 않음
역할별로 분리한 상품 상세 화면 — 구매자 시점에서는 판매자 상태 변경 UI가 노출되지 않음

버튼 역할 미분리처럼 보이는 UI 문제도 사실 보안과 연결된다. 하나의 동작이 여러 맥락에서 재사용되면 의도치 않은 경로로 상태가 바뀔 수 있다. 역할을 나누고, 각 동작이 필요한 검증을 거치게 정리했다. 모의 지갑/온체인 결제 흐름도 값 검증과 상태 전이를 다시 봤다. 모의라도 결제는 결제라, 금액이나 상태를 신뢰할 수 없는 입력으로 다뤄야 한다.

Sepolia 테스트넷 기반 모의 지갑 결제 내역 화면
Sepolia 테스트넷 기반 모의 지갑 결제 내역 화면

전반적으로 "믿을 수 없는 입력"이라는 관점을 코드 전체에 적용했다. 사용자가 보내는 값, URL 파라미터, 폼 데이터를 그대로 믿지 않고 서버에서 다시 검증하는 것. 시큐어코딩 수업의 핵심이 결국 이거였다. 관리자 대시보드 쪽에는 감사 로그(audit log)도 남기게 했는데, 로그인·로그아웃·지갑 연결·메시지 전송 같은 이벤트를 시간·사용자·결과와 함께 기록해두면 나중에 "누가 언제 무엇을 했는지"를 서버 쪼기 없이 바로 확인할 수 있다는 게 실무적으로 크게 느껴졌다.

관리자 대시보드 — 사용자/상품/신고/지갑 거래/감사 로그 관리
관리자 대시보드 — 사용자/상품/신고/지갑 거래/감사 로그 관리
로그인·지갑 연결·메시지 전송 이벤트를 기록하는 감사 로그(Audit Log)
로그인·지갑 연결·메시지 전송 이벤트를 기록하는 감사 로그(Audit Log)
Spring Security 공식 문서 — Method Security
Spring Security 공식 문서 — Method Security

증거 기반 보고서 만들기

과제는 GitHub 공개 저장소에 코드를 올리고 README에 실행 방법을 명시하는 것, 그리고 개발 전 과정과 보안 약점 수정 내역을 담은 보고서를 제출하는 것이었다. 나는 보고서를 말로만 채우지 않고 증거로 채우고 싶었다.

그래서 각 기능과 수정 지점을 실제로 로그인해서 화면을 캡처하고, 정상 관리자 화면·결제 흐름·지갑 연결 같은 걸 스크린샷으로 남겼다. 그걸 표지·목차·아키텍처·결제 흐름·표·캡션·페이지 번호까지 통일해서 22쪽짜리 제출용 PDF로 만들었다. 자동 캡처에서 생긴 긴 빈 배경은 PDF 전용 사본에서 잘라내고, 원본 스크린샷은 건드리지 않았다. 캡처가 실제로 렌더링되는지, 이미지가 깨지지 않는지 전 페이지를 눈으로 검수했다.

이렇게 하고 나니 보고서가 "했다고 주장하는 문서"가 아니라 "한 걸 보여주는 문서"가 됐다. 바이브코딩으로 빠르게 시작하는 건 좋지만, 제출까지 가려면 결국 왜 이렇게 만들었는지를 하나하나 설명할 수 있어야 한다는 걸 이 과제로 배웠다.

참고

  • Spring Security — 인증/인가와 메서드 보안
  • OWASP — 서버 사이드 입력 검증, 접근 제어
  • 시큐어코딩 관점의 "신뢰할 수 없는 입력" 원칙

같이 읽기

검증하지 않은 입력이 실제 명령 실행 취약점으로 이어진 사례는 ipTIME N2V CVE-2025-55423 Command Injection 분석에 정리했다.

공식 자료

관련글 더보기