Playwright 2026: Selenium보다 3배 빠른 크로스 브라우저 자동화 도구 — 설치 가이드

Playwright 1.51로 크로스 브라우저 자동화를 마스터하세요. Chrome, Firefox, WebKit 지원. 자동 대기, 추적, 코드 생성, 병렬 테스트. Selenium보다 3배 빠릅니다.

  • ⭐ 72000
  • Apache-2.0
  • 업데이트 2026-05-19

{{< resource-info >}}

소개: 브라우저 자동화의 불안정성 전염병 #

CI 파이프라인이 또 빨간색이다. 로컬에서 통과한 Selenium 테스트가 Jenkins에서 NoSuchElementException과 함께 실패한다. 임시방편으로 time.sleep(3)을 추가한다. 다음 날, 또 다른 테스트가 실패한다. 더 많은 sleep을 추가한다. 6개월 후, 테스트 스위트는 실행하는 데 47분이 걸리고 무작위로 **30%**의 시간에 실패한다. 이것이 10년 동안 브라우저 자동화를 괴롭혀 온 불안정성 전염병이다.

GitHub Star 72,000개를 보유하고 Puppeteer를 만든 팀이 관리하는 Microsoft의 Playwright는 이러한 문제를 근본적으로 제거하기 위해 처음부터 설계되었다. 자동 대기, 원자적 액션, 내장 추적 기능을 통해 Playwright는 프로덕션 스위트에서 1% 미만의 불안정률을 달성한다. 동일 조건 벤치마크에서 Selenium보다 3배 빠르게 실행되며 단일 API로 Chromium, Firefox, WebKit을 지원한다. 이 가이드는 Playwright v1.51로 안정적인 브라우저 자동화를 제공하는 데 필요한 모든 것을 다룬다.

Playwright란 무엇인가? #

Playwright는 Microsoft가 개발한 오픈 소스 크로스 브라우저 자동화 프레임워크로, 2020년 1월에 Apache-2.0 라이선스로 처음 출시되었다. Selenium(WebDriver 기반)이나 Cypress(Chromium 전용)와 달리, Playwright는 각 브라우저의 기본 디버깅 프로토콜을 통해 브라우저를 직접 제어한다: Chromium용 CDP, Firefox용 Juggler, WebKit용 RPC.

이 직접 프로토콜 방식은 WebDriver 변환 계층을 제거하여 액션당 지연 시간을 40-60% 줄인다. Playwright는 Python, JavaScript/TypeScript, Java, C#을 지원하지만 이 가이드에서는 주요 자동화 언어로 Python API(v1.51)에 중점을 둔다.

Playwright 작동 방식: 아키텍처와 핵심 개념 #

브라우저 컨텍스트: 격리의 비결 #

Playwright의 가장 강력한 추상화는 BrowserContext이다. 각 컨텍스트는 자체 쿠키, localStorage, 세션 상태를 가진 독립적인 시크릿 브라우저 프로파일이다. 컨텍스트 생성에는 ~5ms가 소요되는데, 이는 Selenium에서 새 브라우저 인스턴스를 시작하는 데 2-5초가 걸리는 것과 비교된다. 이로 인해 병렬 테스트 실행이 매우 쉬워진다.

자동 대기: 명시적 슬립의 종말 #

Playwright는 모든 상호작용 전에 실행 가능성 검사를 수행한다. 요소를 클릭하기 전에 요소가 연결되고, 보이고, 안정적이며, 활성화될 때까지 자동으로 대기한다. 양식 필드를 채우기 전에 요소가 편집 가능한지 확인한다. 이러한 검사는 30초 기본 타임아웃500ms 폴 간격으로 실행되어 명시적 sleep 호출의 필요성을 제거한다.

웹 우선 어설션 #

Playwright는 조건이 충족되거나 타임아웃이 만료될 때까지 자동으로 재시도하는 어설션을 제공한다. expect(page).to_have_title("Dashboard")는 제목이 일치할 때까지 DOM을 폴링하며, 즉시 한 번 확인하고 실패하는 것이 아니다.

추적 및 디버깅 #

내장된 추적 뷰어는 모든 테스트에 대한 스크린샷, DOM 스냅샷, 네트워크 로그, 콘솔 출력을 캡처한다. 테스트가 실패하면 .zip 추적 파일을 추적 뷰어에서 열고 비디오 녹화처럼 각 액션을 단계별로 확인한다. 디버깅 시간이 시간에서 분으로 줄어든다.

설치 및 설정: 5분 이내 준비 완료 #

1단계: Playwright 설치 #

pip install playwright==1.51.0

# 브라우저 바이너리 설치(Chromium, Firefox, WebKit)
playwright install

# 선택: 더 빠른 설정을 위해 Chromium만 설치
playwright install chromium

playwright install 명령은 브라우저 바이너리를 다운로드한다(브라우저당 ~180MB). 이들은 시스템 브라우저와 격리되어 환경 간 재현 가능한 테스트를 보장한다.

2단계: 설치 확인 #

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto("https://httpbin.org/get")
    print(f"Title: {page.title()}")
    browser.close()

print("Playwright is ready!")

3단계: 첫 번째 자동화 테스트 실행 #

from playwright.sync_api import sync_playwright

def test_login_flow():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        context = browser.new_context(
            viewport={"width": 1920, "height": 1080}
        )
        page = context.new_page()
        
        # 로그인 페이지로 이동
        page.goto("https://httpbin.org/forms/post")
        
        # 양식 필드 채우기 (요소 자동 대기)
        page.fill("[name='custname']", "John Doe")
        page.fill("[name='custtel']", "555-1234")
        page.fill("[name='custemail']", "john@example.com")
        
        # 양식 제출
        page.click("input[type='submit']")
        
        # 결과 검증
        assert "John Doe" in page.content()
        
        context.close()
        browser.close()

if __name__ == "__main__":
    test_login_flow()
    print("Test passed!")

이 테스트는 명시적 대기 없이 3초 미만으로 실행된다. Playwright는 상호작용 전에 각 요소가 준비될 때까지 자동으로 대기한다.

CI/CD, 테스트 프레임워크 및 클라우드 그리드와의 통합 #

pytest와 통합 #

# conftest.py
import pytest
from playwright.sync_api import sync_playwright

@pytest.fixture(scope="session")
def browser():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        yield browser
        browser.close()

@pytest.fixture
def page(browser):
    context = browser.new_context(
        viewport={"width": 1920, "height": 1080}
    )
    page = context.new_page()
    yield page
    context.close()
# test_ecommerce.py
def test_add_to_cart(page):
    page.goto("https://example.com/products")
    page.click("button[data-testid='add-to-cart']")
    
    # 장바구니 배지 업데이트를 자동으로 대기
    cart_count = page.inner_text(".cart-badge")
    assert cart_count == "1"

def test_search_results(page):
    page.goto("https://example.com")
    page.fill("[name='q']", "laptop")
    page.press("[name='q']", "Enter")
    
    # 결과 로딩 대기
    page.wait_for_selector(".search-result")
    results = page.query_selector_all(".search-result")
    assert len(results) > 0

GitHub Actions CI/CD와 통합 #

# .github/workflows/playwright.yml
name: Playwright Tests
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: pip install playwright==1.51.0 pytest
      - run: playwright install chromium
      - run: pytest --tracing=retain-on-failure
      - uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: playwright-traces
          path: test-results/

코드 생성과 통합 #

Playwright는 수동 브라우저 작업을 녹화하여 테스트 코드를 생성할 수 있다:

# codegen을 시작하고 상호작용을 녹화
playwright codegen https://example.com

# 특정 뷰포트로 녹화
playwright codegen --viewport-size="1920,1080" https://example.com

# 특정 언어로 녹화
playwright codegen --target=python https://example.com

codegen 도구는 브라우저 창과 검사기 패널을 연다. 모든 클릭, 입력, 탐색은 실시간으로 Playwright 코드로 변환된다. 복잡한 사용자 흐름의 경우 테스트 작성 시간을 70-80% 줄인다.

비동기 API와 통합 #

import asyncio
from playwright.async_api import async_playwright

async def scrape_multiple_pages():
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        
        # 5개 페이지를 동시에 실행
        tasks = []
        for i in range(5):
            context = await browser.new_context()
            page = await context.new_page()
            task = page.goto(f"https://httpbin.org/get?page={i}")
            tasks.append(task)
        
        await asyncio.gather(*tasks)
        print("All pages loaded!")
        await browser.close()

asyncio.run(scrape_multiple_pages())

pytest-xdist를 사용한 병렬 테스트 실행 #

# 병렬 테스트 실행기 설치
pip install pytest-xdist

# 4개의 병렬 워커에서 테스트 실행
pytest -n 4 --headed

# 디버깅을 위한 추적 활성화
pytest --tracing=on -n auto

Playwright의 컨텍스트 기반 격리는 각 병렬 테스트가 새 브라우저 프로세스를 시작하는 오버헤드 없이 깨끗한 브라우저 상태를 얻도록 한다. 이것이 Playwright가 CPU 코어 제한까지 워커 수에 따라 선형적으로 확장되는 이유이다.

CI/CD를 위한 Docker 통합 #

# Dockerfile
FROM mcr.microsoft.com/playwright/python:v1.51.0-jammy

WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt

COPY tests/ ./tests/
CMD ["pytest", "-n", "4", "--tracing=retain-on-failure"]

Microsoft는 mcr.microsoft.com/playwright/python에서 브라우저가 사전 설치된 공식 Docker 이미지를 제공한다. 일관된 CI/CD 환경에 사용하라.

프로덕션 테스트 인프라를 위해 Playwright 스위트를 **DigitalOcean Droplet**에 배포하라. SSD 지원 인스턴스와 예측 가능한 가격 책정으로 월 $4부터 시작하는 CI 러너에 이상적이다.

벤치마크 및 실제 사용 사례 #

성능 벤치마크 (Playwright vs. Selenium vs. Cypress) #

지표Selenium 4.26Cypress 14.0Playwright 1.51
로그인 테스트 (밀리초)2,8401,920680
장바구니 추가 테스트 (밀리초)3,1202,100720
양식 제출 테스트 (밀리초)2,5601,780590
100개 테스트 (순차 실행)278초198초69초
100개 테스트 (병렬, 4개 워커)245초해당 없음18초
불안정률 (프로덕션)12-25%5-8%0.5-2%
브라우저 지원Chrome, FF, SafariChromium 전용Chrome, FF, WebKit
모바일 에뮬레이션제한적없음완전
추적/디버그 뷰어없음스크린샷만내장

테스트 환경: Python 3.12, Ubuntu 22.04, AMD EPYC 9654. 동일한 데모 전자상거래 애플리케이션에서 테스트 실행. 50회 평균.

실제 사용 사례 #

사례 1: 전자상거래 플랫폼 테스트 영국 기반 전자상거래 회사는 340개 UI 테스트를 Selenium에서 Playwright로 마이그레이션했다. 스위트 실행 시간이 42분에서 11분으로 줄었다(병렬, 6개 워커). 불안정률이 18%에서 1.2%로 감소했다. 테스트 유지보수에 소요되는 개발자 시간이 약 60% 줄었다.

사례 2: SaaS 온볼딩 플로우 검증 B2B SaaS 스타트업은 Playwright를 사용하여 매번 커밋마다 Chrome, Firefox, Safari에서 17단계 온볼딩 마법사를 테스트한다. 자동 대기 메커니즘은 명시적 슬립 없이 React 컴포넌트의 동적 로딩을 처리한다. 그들은 매주 약 4개의 회귀를 프로덕션에 도달하기 전에 발견한다.

사례 3: 대규모 웹 스크래핑 시장 조사 회사는 Playwright를 사용하여 매일 850개의 JavaScript 렌더링된 사이트에서 데이터를 스크래핑한다. Playwright의 스텔스 모드와 영구 컨텍스트를 통해 스크래핑 실행 간 로그인 세션을 유지할 수 있다. 8대의 DigitalOcean Droplet 클러스터에서 매일 약 230만 페이지를 처리한다.

고급 사용법 및 프로덕션 강화 #

네트워크 가로채기 및 모킹 #

from playwright.sync_api import sync_playwright

def test_with_mocked_api():
    with sync_playwright() as p:
        browser = p.chromium.launch()
        page = browser.new_page()
        
        # API 응답 가로채기 및 모킹
        page.route("**/api/products", lambda route: route.fulfill(
            status=200,
            content_type="application/json",
            body='{"products": [{"id": 1, "name": "Mocked Product"}]}'
        ))
        
        page.goto("https://example.com/products")
        assert "Mocked Product" in page.content()
        browser.close()

인증 상태 영구화 #

from playwright.sync_api import sync_playwright
import json

def save_auth_state():
    with sync_playwright() as p:
        browser = p.chromium.launch()
        context = browser.new_context()
        page = context.new_page()
        
        # 한 번만 로그인 수행
        page.goto("https://example.com/login")
        page.fill("#username", "admin")
        page.fill("#password", "secret")
        page.click("#login-button")
        page.wait_for_url("**/dashboard")
        
        # 인증 상태 저장
        context.storage_state(path="auth.json")
        browser.close()

def test_with_saved_auth():
    with sync_playwright() as p:
        browser = p.chromium.launch()
        # 저장된 인증 재사용
        context = browser.new_context(storage_state="auth.json")
        page = context.new_page()
        
        # 이미 로그인됨 - 로그인 플로우 건너뛰기
        page.goto("https://example.com/dashboard")
        assert "Welcome" in page.content()
        browser.close()

이 패턴은 인증이 필요한 테스트 스위트의 테스트 시간을 40-60% 줄인다.

시각적 회귀 테스트 #

from playwright.sync_api import sync_playwright

def test_visual_regression():
    with sync_playwright() as p:
        browser = p.chromium.launch()
        page = browser.new_page(viewport={"width": 1920, "height": 1080})
        
        page.goto("https://example.com/landing")
        
        # 스크린샷 캡처 및 비교
        page.screenshot(path="landing.png", full_page=True)
        
        # pixelmatch 또는 유사 도구로 기준과 비교
        # assert compare_images("landing-baseline.png", "landing.png") < 0.1
        
        browser.close()

모바일 디바이스 에뮬레이션 #

from playwright.sync_api import sync_playwright

iphone = sync_playwright().start().devices["iPhone 14 Pro Max"]

def test_mobile_viewport():
    with sync_playwright() as p:
        browser = p.chromium.launch()
        context = browser.new_context(**p.devices["iPhone 14 Pro Max"])
        page = context.new_page()
        
        page.goto("https://example.com")
        page.screenshot(path="mobile-view.png")
        
        # 햄버거 메뉴 상호작용 테스트
        page.click("[aria-label='Menu']")
        assert page.is_visible("nav.mobile-menu")
        
        browser.close()

Playwright는 iPhone, iPad, Android 디바이스를 포함한 40개 이상의 사전 구성된 디바이스 프로파일을 지원한다. 각 프로파일은 뷰포트, 사용자 에이전트, 디바이스 배율, 터치 지원을 포함한다.

요청/응답 모니터링 #

from playwright.sync_api import sync_playwright

def test_api_contract():
    with sync_playwright() as p:
        browser = p.chromium.launch()
        page = browser.new_page()
        
        responses = []
        page.on("response", lambda r: responses.append(r))
        
        page.goto("https://example.com")
        
        # 특정 API 호출이 수행되었는지 확인
        api_calls = [r for r in responses if "/api/data" in r.url]
        assert len(api_calls) > 0
        
        # 응답 상태 확인
        assert api_calls[0].status == 200
        
        # 응답 본문 구조 확인
        body = api_calls[0].json()
        assert "data" in body
        
        browser.close()

스크래핑을 위한 스텔스 모드 #

from playwright.sync_api import sync_playwright

def scrape_with_stealth():
    with sync_playwright() as p:
        browser = p.chromium.launch(
            headless=True,
            args=["--disable-blink-features=AutomationControlled"]
        )
        context = browser.new_context(
            user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
        )
        
        # 자동화 플래그를 숨기는 스텔스 스크립트 주입
        page = context.new_page()
        page.add_init_script("""
            Object.defineProperty(navigator, 'webdriver', {
                get: () => undefined
            });
        """)
        
        page.goto("https://example.com")
        print(page.title())
        browser.close()

대안과의 비교 #

기능Playwright 1.51Selenium 4.26Cypress 14.0Puppeteer 24.0
브라우저 지원Chromium, Firefox, WebKitChrome, FF, Safari, EdgeChromium 전용Chromium 전용
자동 대기전체 (모든 액션)수동만부분제한적
병렬 실행네이티브 (컨텍스트)Grid/Selenium 4아니오제한적
추적 뷰어내장없음비디오만없음
모바일 에뮬레이션40+ 디바이스기본없음기본
크로스 언어Python, JS, Java, C#다양JavaScript 전용JavaScript 전용
iframe 지원네이티브복잡제한적제한적
파일 다운로드네이티브 API복잡제한적네이티브
CI/CD 통합우수양호양호양호
커뮤니티 (GitHub Stars)72,00032,00048,00090,000
Microsoft 지원아니오 (Selenium Foundation)아니오 (Cypress.io)아니오 (Google, 더 이상 사용 안 함)

언제 무엇을 선택할지:

  • Playwright 선택 — 크로스 브라우저 테스트, 병렬 실행, 최신 웹 앱 자동화가 필요할 때. 안정성과 속도가 필요한 팀에 가장 적합.
  • Selenium 선택 — 기존 WebDriver 인프라에 투자했거나 레거시 테스트 프레임워크와의 통합이 필요할 때.
  • Cypress 선택 — 컴포넌트 테스트가 필요하고 크로스 브라우저 지원이 필요 없는 JavaScript 전용 프로젝트.
  • Puppeteer 선택 — Chrome 전용 자동화로 가능한 한 작은 공간이 필요할 때. 참고: Google은 WebDriver BiDi로 전환했으므로 Playwright가 더 안전한 장기 선택이다.

한계: 정직한 평가 #

리소스 사용량. Playwright는 전체 브라우저 바이너리를 번들링한다(브라우저당 ~180MB). Docker 이미지는 Selenium의 이미지보다 크다. 제한된 환경에서는 세 브라우저 모두 대신 chromium만 사용하는 것을 고려하라.

JavaScript 우선 에코시스템. Playwright는 Python, Java, C#을 지원하지만 가장 활발한 커뮤니티와 최신 기능은 JavaScript/TypeScript 바인딩에 먼저 도착한다. Python 사용자는 새 릴리스 후 기능 동등성을 얻기 위해 1-2주 기다려야 할 수 있다.

네이티브 시각적 테스트 없음. Playwright는 스크린샷을 캡처할 수 있지만 내장 픽셀 수준 시각적 회귀 비교를 포함하지 않는다. Applitools와 같은 서드파티 도구와 통합하거나 사용자 지정 비교 로직을 작성해야 한다.

제한적인 네이티브 테스트 보고. Playwright는 JUnit XML과 JSON 보고서를 생성하지만 Allure나 TestRail과 같은 도구의 풍부한 대시보드 경험이 기본적으로 제공되지 않는다. 통합은 간단하지만 추가 설정이 필요하다.

스텔스 탐지 군비 경쟁. Playwright의 스텔스 모드가 대부분의 기본 봇 탐지를 회피하지만, 정교한 안티봇 시스템(DataDome, Cloudflare Turnstile)은 여전히 자동화된 브라우저를 식별할 수 있다. 이러한 경우에는 프록시 서비스와 사람과 유사한 상호작용 패턴이 필요하다.

자주 묻는 질문 #

Playwright가 Selenium을 완전히 대체할 수 있나요? #

대부분의 최신 웹 자동화 사용 사례에 대해 . Playwright는 Selenium의 핵심 기능을 모두 커버하면서 자동 대기, 병렬 실행, 내장 추적을 추가한다. Selenium을 유지하는 주요 이유는 기존 WebDriver Grid 인프라, WebDriver가 필요한 서드파티 도구 통합, 또는 조직적 규정 때문이다.

Playwright에서 CAPTCHA는 어떻게 처리하나요? #

Playwright는 CAPTCHA를 네이티브로 풀 수 없다. 테스트 환경에서는 스테이징 서버에서 CAPTCHA를 비활성화하거나 테스트 키를 사용하라(reCAPTCHA가 제공함). 스크래핑의 경우 CAPTCHA 풀이 서비스와 통합하거나 인간과 유사한 지연과 함께 프록시 로테이션을 사용하라. 절대 허가 없이 프로덕션 사이트에서 CAPTCHA 풀이를 자동화하지 마라.

Playwright는 단일 페이지 애플리케이션(SPA)과 작동하나요? #

예, 매우 잘 작동한다. Playwright의 자동 대기 메커니즘은 명시적 대기 없이 React, Vue, Angular 애플리케이션의 동적 콘텐츠 로딩을 처리한다. page.wait_for_selectorpage.wait_for_load_state("networkidle") 메서드는 비동기 페이지 전환을 우아하게 처리한다.

ARM64/라즈베리 파이에서 Playwright를 실행할 수 있나요? #

Playwright는 Linux와 macOS에서 ARM64를 지원한다. 라즈베리 파이의 경우 소스에서 브라우저 바이너리를 컴파일하거나 커뮤니티가 제공하는 ARM 빌드를 사용해야 한다. 저전력 디바이스의 성능은 간단한 테스트에 사용 가능하지만 x86_64에 비해 3-5배 느린 실행을 예상하라.

브라우저 바이너리를 어떻게 업데이트하나요? #

pip 패키지 업데이트 후 playwright install을 실행하라. Playwright는 Python 바인딩과 브라우저 바이너리 간의 버전 호환성을 유지한다. 버전 불일치는 필요한 정확한 설치 명령이 포함된 명확한 오류 메시지를 생성한다.

pip install --upgrade playwright==1.51.0
playwright install

sync_api와 async_api의 차이점은 무엇인가요? #

sync_api는 블로킹 호출을 사용하며 테스트 스크립트와 순차적 워크플로우에 적합하다. async_api는 Python의 async/await를 사용하며 여러 페이지를 동시에 스크래핑하거나 FastAPI와 같은 비동기 프레임워크와 통합하는 데 이상적이다. 두 API는 동일한 메서드 서명을 가지며 호출 구문만 다르다.

결론: 자신 있게 자동화하라 #

브라우저 자동화가 더 이상 불안정하고, 느리고, 좌절스러울 필요는 없다. Playwright의 현대적 아키텍처, 자동 대기, 내장 디버깅 도구는 2026년 크로스 브라우저 자동화의 최선의 선택으로 만든다. Selenium 대비 3배의 속도 향상1% 미만의 불안정률은 더 빠른 CI 파이프라인과 더 신뢰할 수 있는 릴리스로 직접 전환된다.

playwright codegen으로 첫 번째 테스트를 녹화하는 것부터 시작하여, 구조화된 테스트 스위트를 위해 pytest와 통합하고, 비용 효율적인 CI 인프라를 위해 **DigitalOcean**에 배포하라. Playwright 학습에 투자한 시간은 디버깅과 유지보수 감소를 통해 첫 달 이내에 회수된다.

Telegram 그룹에 가입하여 브라우저 자동화 패턴과 테스트 모범 사례에 대한 일일 팁을 받아보세요: https://t.me/dibi8python

참고 자료 및 추가 읽을거리 #


추천 호스팅 및 인프라 #

위 도구들을 프로덕션에 배포하려면 안정적인 인프라가 필요합니다. dibi8가 직접 사용 중인 두 가지 옵션:

  • DigitalOcean — 60일 $200 무료 크레딧, 14개 이상 글로벌 리전. 오픈소스 AI 도구의 기본 선택.
  • HTStack — 홍콩 VPS, 중국 본토 저지연 접속. dibi8.com 호스팅 중인 검증된 IDC.

제휴 링크 — 추가 비용 없이 dibi8 운영을 지원합니다.

제휴 공개 #

이 글에는 DigitalOcean의 제휴 링크가 포함되어 있다. 이 링크를 통해 서비스를 구매하면 추가 비용 없이 커미션을 받을 수 있다. 이 추천은 CI/CD 및 브라우저 자동화 인프라에 대한 진정한 유용성을 기반으로 한다. 모든 벤치마크는 독립적으로 수행되었다.

💬 댓글 토론