웹페이지에 JavaScript/TypeScript 스크립트를 저장하고, 이를 Playwright로 동적으로 실행하는 아키텍처와 개발 방법에 대해 단계별로 설명드리겠습니다.
1.목표
> 웹사이트에 JS/TS 스크립트를 저장 → Playwright가 해당 스크립트를 불러와 실행 → 동작 자동화
이 구조는 다음과 같은 시나리오에 유용합니다:
- 스크립트 기반 자동화 플랫폼 개발
- 사용자 정의 테스트 케이스 저장 및 실행
- 로우코드 테스트 도구 구현
---
2. 전체 아키텍처 구성
+------------------+ +---------------------+
| 웹 프론트엔드 |<----->| 백엔드 (API 서버) |
| (스크립트 저장) | | (스크립트 DB 저장) |
+------------------+ +----------+----------+
|
v
+-----------+-----------+
| 데이터베이스 (MongoDB, PostgreSQL 등) |
| - 스크립트 코드 저장 |
+------------------------+
|
v
+----------------------------------+
| Playwright 실행 엔진 (Node.js) |
| - DB에서 스크립트 읽어와 실행 |
+----------------------------------+
3. 주요 구성 요소
| 구성 요소 | 역할 |
|---------|------|
| 프론트엔드 (Web UI) | 사용자가 JS/TS 스크립트를 작성, 저장, 편집 |
| 백엔드 API 서버 | 스크립트 저장/수정/삭제, Playwright 실행 요청 |
| DB | 사용자 스크립트 저장 (예: `scriptId`, `code`, `name`, `createdAt`) |
| Playwright Worker | 저장된 스크립트를 동적으로 실행하는 Node.js 프로세스 |
예시: 데이터베이스 스키마 (PostgreSQL 기준)
CREATE TABLE scripts (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
code TEXT NOT NULL, -- 사용자가 작성한 JS/TS 코드
language VARCHAR(10) DEFAULT 'javascript', -- 'javascript' or 'typescript'
created_at TIMESTAMP DEFAULT NOW()
);
예시 데이터:
json
{
"id": 1,
"name": "Login Test",
"code": "await page.goto('https://example.com'); await page.screenshot({ path: 'login.png' });",
"language": "javascript"
}
## 개발 방법 단계별 설명
---
### 1. ? 프론트엔드: 스크립트 저장 UI 만들기
- 도구: React, Vue, Angular 등
- 기능:
- 코드 에디터 (예: [Monaco Editor](https://microsoft.github.io/monaco-editor/) ? VS Code 엔진)
- 저장/실행 버튼
- 스크립트 목록 표시
tsx
// 예: React + Monaco Editor
import Editor from '@monaco-editor/react';
function ScriptEditor() {
const [code, setCode] = useState(`await page.goto('https://example.com');`);
const handleSave = () => {
fetch('/api/scripts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Test', code, language: 'javascript' })
});
};
return (
<div>
<Editor
height="500px"
defaultLanguage="javascript"
defaultValue={code}
onChange={setCode}
/>
<button onClick={handleSave}>저장</button>
<button onClick={() => runScript(code)}>실행 (Playwright)</button>
</div>
);
}
---
### 2. 백엔드: API 서버 (Node.js + Express)
javascript
// server.js
const express = require('express');
const { Pool } = require('pg');
const { execScript } = require('./playwright-runner');
const app = express();
app.use(express.json());
const pool = new Pool({ connectionString: 'your-db-url' });
// 스크립트 저장
app.post('/api/scripts', async (req, res) => {
const { name, code, language } = req.body;
const result = await pool.query(
'INSERT INTO scripts (name, code, language) VALUES ($1, $2, $3) RETURNING id',
[name, code, language]
);
res.json({ id: result.rows[0].id });
});
// 스크립트 실행 요청
app.post('/api/scripts/run/:id', async (req, res) => {
const { id } = req.params;
const result = await pool.query('SELECT code FROM scripts WHERE id = $1', [id]);
if (!result.rows[0]) return res.status(404).send('Script not found');
try {
const output = await execScript(result.rows[0].code); // Playwright 실행
res.json({ success: true, output });
} catch (error) {
res.json({ success: false, error: error.message });
}
});
app.listen(3001, () => console.log('Server running on 3001'));
---
### 3. Playwright 실행기 (`playwright-runner.js`)
이 파일은 저장된 코드를 안전하게 실행합니다.
javascript
// playwright-runner.js
const { chromium } = require('playwright');
let browser;
// 브라우저 재사용 (성능 향상)
async function getBrowser() {
if (!browser) {
browser = await chromium.launch({ headless: true });
}
return browser;
}
// 외부 코드 실행 함수
async function execScript(code) {
const browser = await getBrowser();
const context = await browser.newContext();
const page = await context.newPage();
let result;
// 주의: eval()은 보안 위험! 하지만 여기서는 제한된 환경에서만 사용
// 보안을 강화하려면 코드 샌드박스화 (예: vm2) 필요
try {
// page 객체를 주입하여 사용자가 page를 사용할 수 있도록 함
const func = new Function('page', code); // 주의: 보안 취약점 존재
result = await func(page);
await context.close();
return { result };
} catch (error) {
await context.close();
throw error;
}
}
module.exports = { execScript, getBrowser };
> 보안 주의: `new Function()` 또는 `eval()`은 XSS 및 코드 주입 위험이 있음.
> 프로덕션에서는 [vm2](https://github.com/patriksimek/vm2) 같은 샌드박스 도구를 사용하세요.
4. 보안 강화 (선택 사항)
#### 샌드박스 예시 (vm2 사용)
bash
npm install vm2
javascript
const { NodeVM } = require('vm2');
async function execScriptSecure(code) {
const browser = await getBrowser();
const context = await browser.newContext();
const page = await context.newPage();
const vm = new NodeVM({
sandbox: { page }, // page 객체만 허용
require: {
external: false, // 외부 모듈 차단
builtin: [] // 허용된 내장 모듈 제한
}
});
try {
await vm.run(`
(async () => {
${code}
})();
`, __filename);
await context.close();
return { success: true };
} catch (error) {
await context.close();
throw error;
}
}
---
## 실행 흐름 요약
1. 사용자가 웹 UI에서 JS 코드 작성 → 저장
2. 백엔드가 DB에 코드 저장
3. 사용자가 "실행" 버튼 클릭
4. 백엔드가 DB에서 코드 가져와 Playwright 실행기 호출
5. Playwright가 브라우저 열고, 코드 실행
6. 결과 (성공/스크린샷/에러) 반환 → 프론트엔드 표시
---
## 폴더 구조 예시
/project-root
│
├── frontend/ # React 프론트엔드
├── backend/
│ ├── server.js # Express API
│ ├── playwright-runner.js
│ └── db.js
├── database/
│ └── schema.sql
└── package.json
---
## ? 활용 사례
- 자동화 테스트 플랫폼 (사용자 정의 스크립트 저장/실행)
- 로우코드 웹 자동화 도구 (코드 기반 + UI 기반 혼합)
- 스크래핑 규칙 저장소
- 교육용 플랫폼 (학생이 Playwright 코드 작성 후 실행)
---
## 주의사항
| 항목 | 설명 |
|------|------|
| 보안 | 사용자 입력 코드 실행은 매우 위험. 반드시 샌드박스 적용 |
| 격리 | 각 스크립트는 독립된 `context`에서 실행 (쿠키/세션 격리) |
| ? 타임아웃 | 무한 루프 방지를 위해 `Promise.race` + 타임아웃 설정 |
| 로깅 | 실행 로그, 스크린샷, 에러 기록 필수 |
---
## ? 보너스: TypeScript 지원
- 백엔드를 TypeScript로 만들면 더 안정적
- 사용자가 저장한 `.ts` 코드는 실행 전 컴파일 필요 없음 (Playwright는 JS만 실행)
- 따라서 저장 시 TS → JS 변환 필요:
bash
npm install typescript
javascript
const ts = require('typescript');
function transpile(tsCode) {
return ts.transpile(tsCode, {
target: ts.ScriptTarget.ES2020,
module: ts.ModuleKind.CommonJS
});
}
---
## 결론
> ? 웹에 저장된 JS/TS 스크립트를 Playwright로 실행하는 시스템은
> 자동화 플랫폼, 테스트 관리 도구, 로우코드 솔루션에 매우 유용합니다.
### 추천 스택 조합
- 프론트엔드: React + Monaco Editor
- 백엔드: Node.js + Express
- DB: PostgreSQL or MongoDB
- 실행: Playwright + vm2 (보안 샌드박스)
---
'AI' 카테고리의 다른 글
Windows 11에서 Playwright 실행 엔진 개발하기 (0) | 2025.08.25 |
---|---|
개발자가 로컬에서 Playwright 기반 스크립트 실행 엔진을 구축 (1) | 2025.08.25 |
playwright (1) | 2025.08.25 |
2025년 8월 유용한 AI 관련 소식 (1) | 2025.08.21 |
개발자들이 AI를 효과적으로 활용하기 위한 50가지 팁 (0) | 2025.08.21 |