26.9.11 / Fri

BaO·2026년 9월 11일

TIL

목록 보기
21/33

파이썬 타입 힌트

  • 타입을 명시할 뿐이지, 강제하지 않으므로 다른 자료형으로 선언하여도 동작함

  • 변수 : 타입

    • num : int = 100
    • title : str = 'ABC'
  • 함수

    • def 함수명(...) -> 타입 [반환 타입 / void]:
num1 : int = 100
print(num1) # 100

def list_sum(nums : list[int]) -> int:
    return sum(nums)

list_sum([10, 20, 30]) # 60

데이터 클래스 - @dataclass

from dataclasses import dataclass

# @dataclass (kw_only=True) -> 키워드 매개변수만 사용
@dataclass
class Product:
    name : str
    price : int = 0
    description : str = ""

# 위치 인수 사용
product = Product('iphone', 10000, 'duo')
print(product) # Product(name='iphone', price=10000, description='duo')

# 키워드 인수 사용
product = Product(
    name = 'iphone',
    description = 'Duo',
    price = 3290000
)
print(product) # Product(name='iphone', price=3290000, description='Duo')

PostgreSQL 함수(Function)와 프로시저(Procedure)를 활용한 트랜잭션 제어

저장 프로그램 ( Stored Program )

함수 (Function)

  • 매개변수와 반환값
  • 단일 트랜잭션, TCL 사용 불가
  • SELECT 구문 내에서 사용 가능
  • ex) AVG(..), SUM(..)

프로시저 ( Procedure )

  • 독립 프로그램
  • 트랜잭션 제어 가능(COMMIT, ROLLBACK 정의 가능)
  • CALL 프로시저명(...);
CREATE OR REPLACE FUNCTION create_order_transaction(
    p_order_name TEXT,
    p_order_email TEXT,
    p_order_phone TEXT,
    p_receiver_name TEXT,
    p_receiver_phone TEXT,
    p_zipcode TEXT,
    p_address TEXT,
    p_address_sub TEXT,
    p_delivery_memo TEXT,
    p_user_id UUID,
    p_items JSONB -- [{"product_id": "uuid", "quantity": 1}, ...]
)
RETURNS JSONB
LANGUAGE plpgsql
SECURITY DEFINER

AS $$
DECLARE
  v_order_id UUID;
  v_order_no TEXT; -- 20260911113021300
  v_total_price INT := 0;
  v_item RECORD;
  v_product RECORD;
BEGIN
  -- 상품이 있는지 체크
  IF p_items IS NULL OR jsonb_array_length(p_items) = 0 THEN
    RAISE EXCEPTION '주문할 상품이 없습니다.';
  END IF;

  -- 주문번호 생성
  v_order_no := TO_CHAR(CURRENT_TIMESTAMP, 'YYYYMMDDHH24MISS');

  -- orders 테이블에 기본 정보를 주문서 추가, 상품 총합 0
  INSERT INTO orders (
    order_no, order_name, order_email, order_phone,
    receiver_name, receiver_phone, zipcode, address, address_sub, delivery_memo,
    total_price, user_id
  ) VALUES (
    v_order_no, p_order_name, p_order_email, p_order_phone,
    p_receiver_name, p_receiver_phone, p_zipcode, p_address,
    p_address_sub, p_delivery_memo, 0, p_user_id
  )
  RETURNING id INTO v_order_id;

  -- products 테이블에서 상품을 조회한 후 order_items 테이블에 상품 정보를 추가
  FOR v_item IN
      SELECT (elem->>'product_id')::UUID product_id,
              (elem->>'quantity')::INT quantity
      FROM jsonb_array_elements(p_items) elem
  LOOP
    -- 구매 수량 검증
    IF v_item.quantity <= 0 THEN
      RAISE EXCEPTION '주문 수량은 1개 이상이어야 합니다.';
    END IF;

    -- 실제 상품 조회
    SELECT id, name, price INTO v_product
    FROM products WHERE id = v_item.product_id AND deleted_at IS NULL;

    -- 상품 조회의 결과가 없는 경우
    IF NOT FOUND THEN
      RAISE EXCEPTION '등록되지 않거나 삭제된 상품 입니다. (ID: %)', v_item.product_id;
    END IF;

    -- 주문 상품 등록
    INSERT INTO order_items (
      order_id, product_id, item_name, price, quantity
    ) VALUES (
      v_order_id, v_product.id, v_product.name, v_product.price, v_item.quantity
    );

    -- total_price 누적
    v_total_price := v_total_price + (v_product.price * v_item.quantity);
  END LOOP;

  -- orders 테이블에 상품 총금액(total_price)을 업데이트
  UPDATE orders
  SET total_price = v_total_price
  WHERE id = v_order_id;

  -- 결과 반환
  RETURN jsonb_build_object(
    'success', TRUE,
    'order_id', v_order_id,
    'order_no', v_order_no
  );

EXCEPTION
  -- 트랜잭션 실패
  WHEN OTHERS THEN
    RAISE EXCEPTION '주문처리 실패: %', SQLERRM;
END;
$$;

0개의 댓글