티스토리 뷰

반응형

📌 NestJS + Prisma + Next.js로 만드는 웹 애플리케이션 첫걸음 - 애자일 쇼핑몰 프로젝트 - 결제 시스템 연동 (Stripe 활용)

1. 결제 시스템이 필요한 이유

쇼핑몰 애플리케이션에서는 상품을 구매하기 위한 결제 기능이 필수적입니다.
이를 위해 신뢰할 수 있고, 보안이 강화된 결제 시스템을 연동해야 합니다.

결제 시스템 적용 시 고려할 점

  • 안전한 결제 처리 (결제 정보 암호화)
  • 여러 결제 수단 지원 (카드, 계좌이체, 간편 결제 등)
  • 결제 성공/실패 처리 및 환불 시스템 구축
  • 사용자 친화적인 결제 UX/UI 설계

💡 이 챕터에서는 Stripe를 활용하여 Next.js에서 결제 시스템을 구현하는 방법을 다룹니다.


2. Stripe 결제 시스템 개요

2.1. Stripe란?

Stripe는 온라인 결제를 쉽게 구현할 수 있는 글로벌 결제 플랫폼입니다.

  • 간단한 API로 카드 결제, Apple Pay, Google Pay 지원
  • 보안 강화 (PCI DSS 준수, 3D Secure 지원)
  • 국내외 다양한 통화 및 결제 수단 지원

Stripe는 전 세계적으로 널리 사용되며, 빠르고 안전한 결제 처리가 가능합니다.


3. Stripe 설정 및 API 키 발급

3.1. Stripe 계정 생성 및 API 키 확인

  1. Stripe 공식 사이트에 가입
  2. 개발자 대시보드 → API 키 관리에서 Publishable KeySecret Key 확인
  3. .env 파일에 API 키 추가
STRIPE_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxx
STRIPE_PUBLIC_KEY=pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxx

이제 Stripe API를 사용할 준비가 되었습니다.


4. 백엔드(NestJS) - 결제 API 구현

4.1. Stripe 패키지 설치

NestJS에서 Stripe를 사용하려면 stripe 및 @nestjs/stripe 패키지를 설치해야 합니다.

npm install stripe @nestjs/stripe

4.2. Stripe 모듈 설정 (stripe.module.ts)

💡 Stripe 모듈을 생성하여 서비스에서 사용 가능하도록 설정합니다.

import { Module } from '@nestjs/common';
import { StripeService } from './stripe.service';

@Module({
  providers: [StripeService],
  exports: [StripeService],
})
export class StripeModule {}

4.3. Stripe 서비스 (stripe.service.ts)

💡 Stripe API를 호출하여 결제 세션을 생성하는 서비스를 구현합니다.

import { Injectable } from '@nestjs/common';
import Stripe from 'stripe';

@Injectable()
export class StripeService {
  private stripe: Stripe;

  constructor() {
    this.stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
      apiVersion: '2022-11-15',
    });
  }

  async createCheckoutSession(items: { id: number; name: string; price: number; quantity: number }[]) {
    const session = await this.stripe.checkout.sessions.create({
      payment_method_types: ['card'],
      line_items: items.map((item) => ({
        price_data: {
          currency: 'usd',
          product_data: { name: item.name },
          unit_amount: item.price * 100, // Stripe는 금액을 센트 단위로 처리
        },
        quantity: item.quantity,
      })),
      mode: 'payment',
      success_url: 'http://localhost:3000/payment/success',
      cancel_url: 'http://localhost:3000/payment/cancel',
    });

    return { id: session.id };
  }
}

이제 Stripe API를 호출하여 결제 세션을 생성할 수 있습니다.


4.4. 결제 API 컨트롤러 (payment.controller.ts)

💡 프론트엔드에서 결제 요청을 보낼 수 있도록 컨트롤러를 구현합니다.

import { Controller, Post, Body } from '@nestjs/common';
import { StripeService } from './stripe.service';

@Controller('payment')
export class PaymentController {
  constructor(private readonly stripeService: StripeService) {}

  @Post('checkout')
  async checkout(@Body() items: { id: number; name: string; price: number; quantity: number }[]) {
    return this.stripeService.createCheckoutSession(items);
  }
}

이제 /payment/checkout 엔드포인트를 통해 결제를 시작할 수 있습니다.


5. 프론트엔드(Next.js) - Stripe 결제 연동

5.1. Stripe 패키지 설치

npm install @stripe/stripe-js

5.2. Stripe Checkout 버튼 생성

💡 결제 버튼을 누르면 Stripe Checkout으로 이동하도록 구현합니다.

import { loadStripe } from '@stripe/stripe-js';
import { api } from '../utils/api';

const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY);

export default function CheckoutButton({ cartItems }) {
  const handleCheckout = async () => {
    const res = await api.post('/payment/checkout', cartItems);
    const stripe = await stripePromise;
    stripe.redirectToCheckout({ sessionId: res.data.id });
  };

  return <button onClick={handleCheckout}>결제하기</button>;
}

이제 사용자가 결제하기 버튼을 누르면 Stripe 결제 창으로 이동합니다.


5.3. 결제 성공/실패 페이지 추가

💡 Stripe에서 결제 완료 후 리디렉션될 페이지를 생성합니다.

결제 성공 페이지 (pages/payment/success.tsx)

export default function PaymentSuccess() {
  return (
    <div>
      <h1>결제가 완료되었습니다!</h1>
      <p>주문이 정상적으로 처리되었습니다.</p>
    </div>
  );
}

결제 실패 페이지 (pages/payment/cancel.tsx)

export default function PaymentCancel() {
  return (
    <div>
      <h1>결제가 취소되었습니다.</h1>
      <p>다시 시도해 주세요.</p>
    </div>
  );
}

이제 결제가 완료되면 success 페이지로, 취소되면 cancel 페이지로 이동합니다.


6. Stripe 웹훅(Webhook) 설정

6.1. Stripe에서 결제 완료 후 주문 데이터 저장

Stripe 웹훅을 활용하면 결제가 완료된 후 서버에서 주문 데이터를 자동으로 저장할 수 있습니다.

💡 NestJS 웹훅 컨트롤러 (payment.controller.ts)

import { Controller, Post, Req } from '@nestjs/common';
import { Request } from 'express';

@Controller('payment')
export class PaymentController {
  @Post('webhook')
  async handleWebhook(@Req() req: Request) {
    const event = req.body;

    if (event.type === 'checkout.session.completed') {
      console.log('✅ 결제 성공:', event.data.object);
      // 결제 성공 시 주문 데이터 저장 로직 추가
    }

    return { received: true };
  }
}

이제 Stripe 결제가 완료되면 백엔드에서 주문 데이터를 자동으로 처리할 수 있습니다.


🎯 마무리하며

이번 챕터에서는 Stripe를 활용하여 Next.js에서 결제 시스템을 연동하는 방법을 살펴봤습니다.

  • 백엔드(NestJS)에서 Stripe API를 활용한 결제 세션 생성
  • 프론트엔드(Next.js)에서 Stripe Checkout 연동
  • 웹훅(Webhook)을 활용하여 결제 완료 후 주문 데이터 자동 저장

다음 단계에서는 5.3. 주문 내역 및 배송 상태 관리를 다룰 예정입니다. 🚀

 

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함
반응형