Saleor Core 한국 로컬라이제이션 분석: Tax, Address, Plugin/App 시스템
분석 대상: /tmp/saleor-core/ (Saleor Core 소스코드)
분석 일자: 2026-03-27
1. Tax 모듈 분석 (Taxes)
1.1 모델 구조
TaxClass
name: 세금 분류명 (예: “Standard”, “Reduced”, “Zero”)ModelWithMetadata상속 — metadata 필드 활용 가능
TaxClassCountryRate
tax_class: FK → TaxClass (null 허용 — null이면 해당 국가의 기본 세율)country: CountryFieldrate: Decimal (퍼센트 값, 예: 10.00 = 10%)- 제약조건: (country, tax_class) 유니크, tax_class=null일 때 country 유니크
TaxConfiguration (채널별 1:1)
channel: OneToOne → Channelcharge_taxes: bool (기본 True)tax_calculation_strategy: “FLAT_RATES” 또는 “TAX_APP”display_gross_prices: bool (기본 True — 세금 포함가 표시)prices_entered_with_tax: bool (기본 True — 입력가격이 세금 포함인지)tax_app_id: 외부 Tax App 식별자use_weighted_tax_for_shipping: bool (배송비에 가중 세율 적용, Saleor 3.21+, FLAT_RATES 전략에서만 동작)
TaxConfigurationPerCountry (국가별 예외)
tax_configuration: FK → TaxConfiguration- 채널 TaxConfiguration의
charge_taxes,tax_calculation_strategy,display_gross_prices,tax_app_id,use_weighted_tax_for_shipping필드를 국가별로 오버라이드 (prices_entered_with_tax는 오버라이드 불가)
1.2 세금 계산 전략: Flat Rate vs Tax App
TaxCalculationStrategy:
FLAT_RATES — 내장 로직으로 국가별 세율 적용
TAX_APP — 외부 앱(Avalara 등)에 [[📒 Saleor Sync Events Tax|sync webhook]]으로 위임
Flat Rate 계산 핵심 로직
saleor/tax/calculations/__init__.py의 calculate_flat_rate_tax():
def calculate_flat_rate_tax(money, tax_rate, prices_entered_with_tax):
tax_rate = Decimal(1 + tax_rate / 100)
if prices_entered_with_tax:
net = money.amount / tax_rate # 세금 역산
gross = money.amount
else:
net = money.amount
gross = money.amount * tax_rate # 세금 가산
return TaxedMoney(net=Money(net, currency), gross=Money(gross, currency))Tax App (Dynamic) 계산
WebhookEventSyncType.CHECKOUT_CALCULATE_TAXES/ORDER_CALCULATE_TAXESsync webhook 발생- 외부 앱이
TaxData객체 반환 (shipping_price_gross/net, shipping_tax_rate, lines[]) - 각 line에
TaxLineData(tax_rate, total_gross_amount, total_net_amount)포함
1.3 Checkout 세금 계산 흐름
flowchart TD A[Checkout 생성/수정] --> B{charge_taxes?} B -->|No| C[세금 0으로 설정] B -->|Yes| D{tax_calculation_strategy?} D -->|FLAT_RATES| E[update_checkout_prices_with_flat_rates] D -->|TAX_APP| F[Sync Webhook: CHECKOUT_CALCULATE_TAXES] E --> E1[국가 코드 결정 shipping > billing > channel default] E1 --> E2[TaxClassCountryRate에서 기본 세율 조회] E2 --> E3[각 라인별 TaxClass → 국가별 세율 조회] E3 --> E4[calculate_flat_rate_tax로 net/gross 산출] E4 --> E5[배송비 세율 계산 가중치 or TaxClass 기반] E5 --> E6[subtotal + shipping = total] F --> F1[Tax App이 TaxData 반환] F1 --> F2[라인별 net/gross 적용] F2 --> F6[subtotal + shipping = total]
1.4 한국 부가세(VAT) 적용 평가
현재 지원 가능한 부분
- 10% 단일 세율: TaxClassCountryRate에 country=“KR”, rate=10 설정하면 즉시 적용 가능
- 세금 포함가 표시:
display_gross_prices=True,prices_entered_with_tax=True(한국 관행과 일치) - Flat Rate 전략: 한국처럼 단일 VAT 국가에 적합
한국 특화 개발이 필요한 부분
| 항목 | 현재 상태 | 필요 작업 |
|---|---|---|
| 10% VAT 기본 세율 | 수동 설정 필요 | 초기 데이터 migration으로 자동화 |
| 세금계산서 발행 | 미지원 | Tax App 또는 별도 Invoice App 개발 필요 |
| 사업자등록번호 | Address/Order에 필드 없음 | metadata 활용 또는 커스텀 필드 추가 |
| 면세 품목 분류 | TaxClass로 가능 (rate=0) | “면세”, “영세율” TaxClass 생성 |
| 현금영수증 | 미지원 | Payment App에서 처리 |
| 원단위 절사 | quantize_price로 가능 | KRW 통화 설정 시 decimal_places=0 확인 필요 (Price Calculation) |
세금계산서 구현 전략
INVOICE_REQUESTEDasync webhook 활용- 외부 Tax Invoice App에서 국세청 전자세금계산서 API 연동
- Order metadata에 사업자등록번호(business_registration_number) 저장
invoice_requestplugin hook 또는 App webhook으로 PDF 생성
2. Address 시스템 분석 (Address)
2.1 Address 모델 필드
| 필드 | 타입 | 한국 매핑 |
|---|---|---|
first_name | CharField(256) | 이름 |
last_name | CharField(256) | 성 |
company_name | CharField(256) | 회사명 |
street_address_1 | CharField(256) | 도로명주소 (예: 테헤란로 521) |
street_address_2 | CharField(256) | 상세주소 (예: 파르나스타워 37층) |
city | CharField(256) | 시/군/구 |
city_area | CharField(128) | 읍/면/동 (address-level3) |
postal_code | CharField(20) | 우편번호 (5자리) |
country | CountryField | ”KR” |
country_area | CharField(128) | 시/도 (address-level1) |
phone | PhoneNumberField | 전화번호 (E.164 형식) |
validation_skipped | BooleanField | 검증 건너뛰기 플래그 |
2.2 주소 검증 시스템
Saleor는 google-i18n-address 패키지(mirumee 개발, Google i18n address data 기반)를 사용한다.
검증 흐름:
CountryAwareAddressForm.validate_address()호출i18naddress.normalize_address(data)— 국가별 규칙으로 정규화i18naddress.get_validation_rules({"country_code": "KR"})— 한국 규칙 로드- 실패 시
InvalidAddressError발생, 에러 필드에 매핑
국가별 규칙 오버라이드 메커니즘:
saleor/account/i18n_rules_override.py에서i18naddress.load_validation_data패치- 현재 일본(JP)만 오버라이드 (city 필드 문제 수정)
- 한국도 동일 방식으로 오버라이드 가능
i18n 필드 매핑:
I18N_MAPPING = [
("name", ["first_name", "last_name"]),
("street_address", ["street_address_1", "street_address_2"]),
("city_area", ["city_area"]),
("country_area", ["country_area"]), # 시/도
("company_name", ["company_name"]),
("postal_code", ["postal_code"]),
("city", ["city"]), # 시/군/구
]2.3 한국 주소 호환성 평가
Google i18n Address의 한국 주소 포맷
Google의 AddressValidationMetadata에서 한국(KR)은 다음과 같이 정의된다:
fmt(영문):%S %C%D%n%A%n%O%n%N%n%Z(도, 시, 구/동, 도로명, 회사, 이름, 우편번호)lfmt(한국어):%N%n%O%n%A%n%D%n%C%n%S%n%Z(이름, 회사, 도로명, 읍면동, 시, 도, 우편번호)required_fields: country_area(시/도), city(시/군/구), street_address, postal_codecountry_area_type: “do_si” (도/시)
현재 호환되는 부분
- 기본 필드 구조가 한국 주소와 잘 매핑됨
country_area→ 시/도 (서울특별시, 경기도 등)city→ 시/군/구 (강남구, 수원시 등)street_address_1→ 도로명주소postal_code→ 5자리 우편번호
도로명주소 API 연동 포인트
flowchart LR A[사용자 주소 입력] --> B[도로명주소 검색 UI] B --> C[juso.go.kr API 호출] C --> D[결과 목록 표시] D --> E[선택된 주소 매핑] E --> F1["street_address_1 = 도로명주소"] E --> F2["city = 시/군/구"] E --> F3["country_area = 시/도"] E --> F4["postal_code = 우편번호"] E --> F5["city_area = 읍/면/동 (선택)"] F1 & F2 & F3 & F4 & F5 --> G[street_address_2 = 상세주소 직접 입력]
연동 방식 옵션:
- 프론트엔드 전용 (권장): Storefront에서 juso.go.kr API 호출, Saleor에는 매핑된 데이터만 전달
- Backend App: Address validation App이 주소 정규화 수행
- i18n_rules_override: 한국 주소 포맷 커스텀 (
country_area_choices에 시/도 목록 추가)
필요한 수정사항
| 항목 | 현재 | 필요 작업 | 난이도 |
|---|---|---|---|
| 한국 주소 필드 순서 | Google i18n 기본값 | i18n_rules_override에 KR fmt 패치 | 낮음 |
| 도로명주소 검색 | 미지원 | Storefront에서 juso.go.kr API 연동 | 중간 |
| 시/도 선택지 | Google 데이터 기반 | 필요 시 VALID_ADDRESS_EXTENSION_MAP 활용 | 낮음 |
| 성+이름 순서 | 이름 먼저 | UI에서 한국일 때 순서 변경 | 낮음 |
3. Plugin 시스템 분석
3.1 아키텍처 개요 (Extending Overview)
Plugin은 Saleor 내장 확장 시스템이다. BasePlugin 클래스를 상속하고, PluginsManager가 등록된 플러그인들의 hook 메서드를 체이닝 방식으로 호출한다.
중요: Saleor는 Plugin 시스템 전체를 App/Webhook 방식으로 전환하는 과정에 있다(“We are in the process of deprecating plugins in favor of apps”). 개별 hook에 deprecated 어노테이션이 붙어 있지 않더라도 Plugin 시스템 자체의 방향이 deprecated다. Saleor는 Plugin 시스템을 App/Webhook 시스템으로 전환 중이다.
3.2 내장 Plugin 목록
| 디렉토리 | 역할 |
|---|---|
avatax/ | Avalara AvaTax 세금 계산 |
openid_connect/ | OpenID Connect 인증 |
admin_email/ | 관리자 이메일 알림 |
user_email/ | 사용자 이메일 알림 |
sendgrid/ | SendGrid 이메일 |
webhook/ | App Webhook 디스패처 (핵심) |
3.3 Plugin Hook 메서드 카탈로그
세금 관련 (Tax Hooks)
| Hook | 설명 |
|---|---|
calculate_checkout_line_total | Checkout 라인 총액 계산 |
calculate_checkout_line_unit_price | Checkout 라인 단가 계산 |
calculate_checkout_shipping | Checkout 배송비 계산 |
calculate_checkout_total | Checkout 총액 계산 |
calculate_checkout_subtotal | Checkout 소계 계산 |
calculate_order_line_total | Order 라인 총액 계산 |
calculate_order_line_unit | Order 라인 단가 계산 |
calculate_order_shipping | Order 배송비 계산 |
calculate_order_total | Order 총액 계산 |
get_checkout_line_tax_rate | Checkout 라인 세율 조회 |
get_checkout_shipping_tax_rate | Checkout 배송 세율 조회 |
get_order_line_tax_rate | Order 라인 세율 조회 |
get_order_shipping_tax_rate | Order 배송 세율 조회 |
get_taxes_for_checkout | Checkout 전체 세금 데이터 [deprecated] |
get_tax_code_from_object_meta | 객체에서 세금 코드 추출 |
get_tax_rate_type_choices | 세금 유형 선택지 목록 |
결제 관련 (Payment Hooks)
| Hook | 설명 |
|---|---|
authorize_payment | 결제 승인 |
capture_payment | 결제 캡처 |
confirm_payment | 결제 확인 |
check_payment_balance | 잔액 확인 |
get_client_token | 클라이언트 토큰 |
get_payment_config | 결제 설정 |
get_supported_currencies | 지원 통화 목록 |
initialize_payment | 결제 초기화 |
list_payment_sources | 결제 수단 목록 |
list_stored_payment_methods | 저장된 결제 수단 [deprecated] |
stored_payment_method_request_delete | 저장 결제 수단 삭제 [deprecated] |
payment_gateway_initialize_tokenization | PG 토큰화 초기화 [deprecated] |
payment_method_initialize_tokenization | 결제 수단 토큰화 초기화 [deprecated] |
payment_method_process_tokenization | 결제 수단 토큰화 처리 [deprecated] |
엔티티 이벤트 훅 (모두 deprecated — App webhook으로 대체)
| Hook | 대상 |
|---|---|
account_confirmed, account_deleted, etc. | Account |
address_created, address_updated, address_deleted | Address |
app_installed, app_updated, app_deleted | App |
attribute_created/updated/deleted | Attribute |
attribute_value_created/updated/deleted | AttributeValue |
category_created/updated/deleted | Category |
channel_created/updated/deleted/status_changed/metadata_updated | Channel |
checkout_created/updated/fully_paid/fully_authorized/metadata_updated | Checkout |
collection_created/updated/deleted/metadata_updated | Collection |
customer_created/updated/deleted/metadata_updated | Customer |
draft_order_created/updated/deleted | Draft Order |
fulfillment_created/canceled/approved/metadata_updated | Fulfillment |
gift_card_created/updated/deleted/status_changed/metadata_updated/export_completed | Gift Card |
invoice_delete/request/sent | Invoice |
menu_created/updated/deleted | Menu |
menu_item_created/updated/deleted | MenuItem |
order_created/confirmed/cancelled/expired/fulfilled/paid/fully_paid/refunded/fully_refunded/updated/metadata_updated/bulk_created | Order |
page_created/updated/deleted | Page |
인증 관련
| Hook | 설명 |
|---|---|
authenticate_user | 사용자 인증 |
external_authentication_url | 외부 인증 URL |
external_logout | 외부 로그아웃 |
external_obtain_access_tokens | 외부 토큰 획득 |
external_refresh | 외부 토큰 갱신 |
external_verify | 외부 인증 검증 |
기타
| Hook | 설명 |
|---|---|
notify | 알림 전송 |
3.4 PluginsManager 동작 방식
class PluginsManager(PaymentInterface):
plugins_per_channel: dict[str, list[BasePlugin]]
global_plugins: list[BasePlugin]
all_plugins: list[BasePlugin]- 채널별로 독립된 플러그인 인스턴스 관리
- 각 hook 호출 시 체이닝: 이전 플러그인의 반환값이 다음 플러그인의
previous_value로 전달 CONFIGURATION_PER_CHANNEL = True이면 채널별 설정 가능
4. App/Webhook 시스템 분석
4.1 App 모델
class App(ModelWithMetadata):
uuid: UUID (유니크)
name: CharField(60)
type: "LOCAL" | "THIRDPARTY"
identifier: CharField(256) # 앱 고유 식별자
is_active: bool
permissions: M2M → Permission
manifest_url: URLField # 앱 매니페스트 URL
app_url: URLField # 앱 UI URL
# ... 기타 메타 정보AppType.LOCAL: Saleor 인스턴스 내부 앱AppType.THIRDPARTY: 외부 앱 (Saleor App Store 등)- Permission 기반 접근 제어 — 앱에 필요한 권한만 부여
4.2 Webhook 모델
class Webhook(models.Model):
app: FK → App
target_url: URLField (http, https, awssqs, gcpubsub)
is_active: bool
secret_key: 서명 검증용
subscription_query: [[📒 Saleor GraphQL|GraphQL]] subscription query
custom_headers: JSON
filterable_channel_slugs: ArrayField # 특정 채널만 필터
class WebhookEvent(models.Model):
webhook: FK → Webhook
event_type: CharField # WebhookEventAsyncType 또는 WebhookEventSyncType4.3 Webhook Event 타입 전체 목록
Async Events (비동기 — 이벤트 발생 후 알림)
| 카테고리 | 이벤트 | 필요 권한 |
|---|---|---|
| Account | account_confirmation_requested, account_email_changed, account_change_email_requested, account_set_password_requested, account_confirmed, account_delete_requested, account_deleted | MANAGE_USERS |
| Address | address_created, address_updated, address_deleted | MANAGE_USERS |
| App | app_installed, app_updated, app_deleted, app_status_changed | MANAGE_APPS |
| Attribute | attribute_created/updated/deleted, attribute_value_created/updated/deleted | None |
| Category | category_created/updated/deleted | MANAGE_PRODUCTS |
| Channel | channel_created/updated/deleted/status_changed/metadata_updated | MANAGE_CHANNELS |
| Checkout | checkout_created/updated/fully_authorized/fully_paid/metadata_updated | MANAGE_CHECKOUTS |
| Collection | collection_created/updated/deleted/metadata_updated | MANAGE_PRODUCTS |
| Customer | customer_created/updated/deleted/metadata_updated | MANAGE_USERS |
| Draft Order | draft_order_created/updated/deleted | MANAGE_ORDERS |
| Fulfillment | fulfillment_created/canceled/approved/metadata_updated/tracking_number_updated | MANAGE_ORDERS |
| Gift Card | gift_card_created/updated/deleted/sent/status_changed/metadata_updated/export_completed | MANAGE_GIFT_CARD |
| Invoice | invoice_requested/deleted/sent | MANAGE_ORDERS |
| Menu | menu_created/updated/deleted, menu_item_created/updated/deleted | MANAGE_MENUS |
| Order | order_created/confirmed/paid/fully_paid/refunded/fully_refunded/updated/cancelled/expired/fulfilled/metadata_updated/bulk_created | MANAGE_ORDERS |
| Page | page_created/updated/deleted | MANAGE_PAGES |
| Page Type | page_type_created/updated/deleted | MANAGE_PAGE_TYPES_AND_ATTRIBUTES |
| Permission Group | permission_group_created/updated/deleted | MANAGE_STAFF |
| Product | product_created/updated/deleted/metadata_updated/export_completed | MANAGE_PRODUCTS |
| Product Media | product_media_created/updated/deleted | MANAGE_PRODUCTS |
| Product Variant | product_variant_created/updated/deleted/metadata_updated/out_of_stock/back_in_stock/stock_updated | MANAGE_PRODUCTS |
| Promotion | promotion_created/updated/deleted/started/ended | MANAGE_DISCOUNTS |
| Promotion Rule | promotion_rule_created/updated/deleted | MANAGE_DISCOUNTS |
| Sale | sale_created/updated/deleted/toggle | MANAGE_DISCOUNTS |
| Shipping | shipping_price_created/updated/deleted, shipping_zone_created/updated/deleted/metadata_updated | MANAGE_SHIPPING |
| Staff | staff_created/updated/deleted/set_password_requested | MANAGE_STAFF |
| Transaction | transaction_item_metadata_updated | HANDLE_PAYMENTS |
| Translation | translation_created/updated | MANAGE_TRANSLATIONS |
| Voucher | voucher_created/updated/deleted/codes_created/codes_deleted/metadata_updated/code_export_completed | MANAGE_DISCOUNTS |
| Warehouse | warehouse_created/updated/deleted/metadata_updated | MANAGE_PRODUCTS |
| 기타 | notify_user [deprecated], observability, thumbnail_created, shop_metadata_updated | 각각 다름 |
Sync Events (동기 — 요청-응답 패턴)
| 이벤트 | 설명 | 필요 권한 |
|---|---|---|
payment_list_gateways | 결제 게이트웨이 목록 | HANDLE_PAYMENTS |
payment_authorize | 결제 승인 | HANDLE_PAYMENTS |
payment_capture | 결제 캡처 | HANDLE_PAYMENTS |
payment_refund | 환불 | HANDLE_PAYMENTS |
payment_void | 결제 취소 | HANDLE_PAYMENTS |
payment_confirm | 결제 확인 | HANDLE_PAYMENTS |
payment_process | 결제 처리 | HANDLE_PAYMENTS |
checkout_calculate_taxes | Checkout 세금 계산 | HANDLE_TAXES |
order_calculate_taxes | Order 세금 계산 | HANDLE_TAXES |
transaction_charge_requested | 거래 충전 요청 | HANDLE_PAYMENTS |
transaction_refund_requested | 거래 환불 요청 | HANDLE_PAYMENTS |
transaction_cancelation_requested | 거래 취소 요청 | HANDLE_PAYMENTS |
shipping_list_methods_for_checkout | 배송 방법 목록 | MANAGE_SHIPPING |
checkout_filter_shipping_methods | 배송 방법 필터 | MANAGE_CHECKOUTS |
order_filter_shipping_methods | 주문 배송 방법 필터 | MANAGE_ORDERS |
payment_gateway_initialize_session | PG 세션 초기화 | HANDLE_PAYMENTS |
transaction_initialize_session | 거래 세션 초기화 | HANDLE_PAYMENTS |
transaction_process_session | 거래 세션 처리 | HANDLE_PAYMENTS |
list_stored_payment_methods | 저장 결제 수단 목록 | HANDLE_PAYMENTS |
stored_payment_method_delete_requested | 저장 결제 수단 삭제 | HANDLE_PAYMENTS |
payment_gateway_initialize_tokenization_session | PG 토큰화 세션 | HANDLE_PAYMENTS |
payment_method_initialize_tokenization_session | 결제 수단 토큰화 세션 | HANDLE_PAYMENTS |
payment_method_process_tokenization_session | 결제 수단 토큰화 처리 | HANDLE_PAYMENTS |
4.4 Sync Webhook 디스패치 흐름
flowchart TD A[Checkout/Order 세금 계산 요청] --> B{tax_calculation_strategy?} B -->|TAX_APP| C[PluginsManager.get_taxes_for_checkout/order] C --> D[WebhookPlugin.get_taxes_for_checkout] D --> E[tax_app_id로 대상 App 결정] E --> F[sync webhook 전송 target_url로] F --> G[Tax App이 TaxData JSON 반환] G --> H[응답 파싱 → TaxData 객체] H --> I[라인별 net/gross/tax_rate 적용] B -->|FLAT_RATES| J[내장 Flat Rate 계산]
5. Plugin vs App: 비교 및 권장사항
5.1 핵심 차이 (Architecture)
| 항목 | Plugin (Legacy) | App (현재 권장) |
|---|---|---|
| 배포 | Saleor 코어에 포함 | 독립 서비스로 배포 |
| 코드 위치 | saleor/plugins/ 내부 | 외부 서비스 (어떤 언어든 가능) |
| 통신 | Python 함수 직접 호출 | HTTP Webhook (sync/async) |
| 상태 | 대부분 deprecated 표시 | 적극 개발 중 |
| 확장성 | 모놀리식 | 마이크로서비스 |
| 설정 | DB PluginConfiguration | App manifest + DB |
| 업그레이드 | Saleor 버전에 종속 | 독립적 버전 관리 |
5.2 한국 시장 개발 권장 방식
App(Webhook) 방식을 권장한다. 이유:
- Plugin 시스템은 deprecated 예정
- 독립 배포 가능 — Saleor 업그레이드에 영향 없음
- 한국 PG사/세금계산서/도로명주소 등 로컬 서비스 연동에 적합
- 필요한 sync webhook이 이미 모두 존재 (세금, 결제, 배송)
6. 한국 시장 로컬라이제이션 종합 권장사항
6.1 Tax App (세금계산서 + VAT)
flowchart TD subgraph "Korean Tax App" A[CHECKOUT_CALCULATE_TAXES webhook] --> B[10% VAT 적용] B --> C[면세/영세율 품목 체크] C --> D[TaxData 반환] E[ORDER_CONFIRMED webhook] --> F[사업자등록번호 확인] F --> G{세금계산서 필요?} G -->|Yes| H[국세청 전자세금계산서 API] G -->|No| I[현금영수증 발행] J[INVOICE_REQUESTED webhook] --> K[세금계산서 PDF 생성] end
6.2 개발 우선순위
| 순위 | 항목 | 구현 방식 | 예상 난이도 |
|---|---|---|---|
| 1 | 10% VAT 기본 세율 설정 | Flat Rate (TaxClassCountryRate KR=10) | 매우 낮음 |
| 2 | KRW 통화 설정 | Channel 설정 | 매우 낮음 |
| 3 | 한국 주소 포맷 | i18n_rules_override + 프론트엔드 | 낮음 |
| 4 | 도로명주소 API 연동 | Storefront 프론트엔드 | 중간 |
| 5 | 한국 PG 결제 App | Sync webhook App (Toss/NicePay 등) | 높음 |
| 6 | 전자세금계산서 발행 App | Async webhook App (국세청 API) | 높음 |
| 7 | 현금영수증 발행 | Payment App 확장 | 중간 |
| 8 | 면세/영세율 품목 관리 | TaxClass 추가 + Admin UI | 낮음 |
6.3 Flat Rate로 충분한 경우
대부분의 한국 B2C 커머스에서는 Flat Rate 전략으로 충분하다:
- 한국은 단일 VAT 10%
- TaxClass “면세”(rate=0), “표준”(rate=10) 두 가지면 대부분 커버
- Tax App은 세금계산서 발행이 필요한 B2B에서만 필요
별도 Tax App이 필요한 경우:
- B2B 세금계산서 발행
- 면세/과세 혼합 거래의 자동 분류
- 국세청 API 연동
관련 문서
핵심 개념
- 📒 Saleor Taxes — 세금 시스템 공식 문서
- 📒 Saleor Price Calculation — 가격 계산 로직
- 📒 Saleor Address — 주소 시스템
- 📒 Saleor Channels / 📒 Saleor Channels Detail — 채널 설정 (통화, 세금 전략)
- 📒 Saleor Checkout / 📒 Saleor Checkout Detail — Checkout 흐름
- 📒 Saleor Orders / 📒 Saleor Order Detail — 주문 처리
확장 시스템
- 📒 Saleor Extending Overview — 확장 방식 개요
- 📒 Saleor Apps / 📒 Saleor App Architecture — App 시스템
- 📒 Saleor Webhooks — Webhook 기본
- 📒 Saleor Async Events — 비동기 이벤트
- 📒 Saleor Sync Events Overview — 동기 이벤트 개요
- 📒 Saleor Sync Events Tax — 세금 계산 sync webhook
- 📒 Saleor Sync Events Payment — 결제 sync webhook
- 📒 Saleor Sync Events Shipping — 배송 sync webhook
결제 및 기타
- 📒 Saleor Payments / 📒 Saleor Payments Detail — 결제 시스템
- 📒 Saleor Payment App Development — 결제 App 개발
- 📒 Saleor Metadata — 메타데이터 활용
- 📒 Saleor Permissions — 권한 체계
- 📒 Saleor Authentication — 인증
- 📒 Saleor Dashboard Extensions — 대시보드 확장
- 📒 Saleor Storefront — 프론트엔드
- 📒 Saleor Architecture — 전체 아키텍처
- 📒 Saleor Core Fork Analysis — Core 포크 분석