개발 공부/프로젝트

[사이드 프로젝트] 가상 주식 거래소 만들기 (10) - 마침내 첫 거래 성사! (HTML/JS 연동과 디버깅)

baby-t 2026. 1. 3. 17:50

1. 들어가며: 모든 것이 연결되다

지난 포스팅까지 백엔드 API와 DB 로직을 모두 완성했습니다. 하지만 API는 호출해 주는 사람이 없으면 무용지물입니다. 이번 포스팅에서는 stock_list.html에 매수/매도 버튼을 달고, 자바스크립트(Fetch API)를 통해 실제로 서버에 주문을 넣는 과정을 담았습니다.

그리고 그 과정에서 마주친 Thymeleaf 버전 호환성 문제와 그 해결책도 공유합니다.

2. UI 구현: 버튼에 생명 불어넣기

기존의 시세표 옆에 '주문' 칸을 만들고, 수량 입력(input)과 매수/매도 버튼(button)을 배치했습니다.

초기 접근 (에러 발생) 처음에는 타임리프 문법을 이용해 단순하게 작성했습니다.

HTML
<button th:onclick="|buyStock('${stock.code}')|">매수</button>

 

하지만 서버를 켜자마자 TemplateProcessingException이 발생했습니다. 로그를 분석해 보니 **"보안상의 이유로 이벤트 핸들러(onclick 등) 내부에 문자열 변수를 직접 넣는 것을 금지한다"**는 내용이었습니다. (XSS 공격 방지)

해결책 (Data 속성 활용) 타임리프가 권장하는 대로, 데이터를 data-* 속성에 따로 담고 자바스크립트에서 꺼내 쓰는 방식으로 변경하여 해결했습니다.

HTML
<button class="btn btn-success" 
        th:data-code="${stock.code}"
        onclick="buyStock(this.getAttribute('data-code'))">매수</button>

3. JS 구현: Fetch API로 주문서 발송

백엔드 컨트롤러가 OrderRequestDto (JSON)를 기다리고 있으므로, 자바스크립트에서도 형식을 맞춰서 보내줘야 합니다.

JavaScript
function buyStock(code) {
    // 1. 입력된 수량 가져오기
    const quantity = document.getElementById('quantity_' + code).value;

    // 2. JSON 데이터 포장
    const requestData = {
        userId: 29, // (테스트용 ID)
        code: code,
        quantity: Number(quantity)
    };

    // 3. 서버로 전송 (POST)
    fetch('/orders/buy', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(requestData)
    })
    .then(response => {
        if (response.ok) {
            alert("매수 성공!");
            window.location.reload(); // 잔액 변화 확인을 위해 새로고침
        } else {
            alert("실패");
        }
    });
}

실제 화면

4. 통합 테스트: 떨리는 첫 거래

모든 코드를 적용하고 서버를 재시작했습니다. DB에는 테스트용 유저(ID: 29)에게 가상의 현금 10억 원을 넣어두었습니다.

  1. 화면: 비트코인 1개 매수 버튼 클릭 -> "매수 성공!" 알림창 등장.
  2. DB 확인 (Orders): BUY 주문 로그가 정확히 생성됨.
  3. DB 확인 (StockHolding): 나의 주식 보유 목록에 KRW-BTC 1개가 추가됨.
  4. DB 확인 (Account): 잔액이 정확히 비트코인 가격만큼 차감됨.

이로써 [클라이언트 -> 컨트롤러 -> 서비스 -> 레포지토리 -> DB]로 이어지는 전체 데이터 파이프라인이 정상 작동함을 검증했습니다.

실제 알림
실제 stockHolding db
실제 order db

5. 마치며

드디어 "가상" 주식 거래소가 "실제" 동작하는 서비스가 되었습니다. 하지만 아직 부족한 점이 있습니다. 매수는 성공했지만, "내가 산 주식 목록(내 잔고)"을 볼 수 있는 화면이 없습니다.

다음 포스팅에서는 [마이페이지 / 내 잔고 조회] 기능을 구현하여, 내가 투자한 주식들의 수익률을 한눈에 볼 수 있도록 만들어 보겠습니다.