first commit 2

This commit is contained in:
hmw1001
2026-06-11 18:47:38 +09:00
parent c768729ce6
commit 6f534e33a6
11095 changed files with 1595758 additions and 0 deletions
+580
View File
@@ -0,0 +1,580 @@
<?php
/**
* install_journal_theme.php
* - GNUBOARD5 테마( journal ) + 공용 게시판 스킨 생성
* - ZIP까지 생성
*
* 사용 후 반드시 삭제하세요.
*/
error_reporting(E_ALL);
ini_set('display_errors', 1);
function ensure_dir($dir) {
if (!is_dir($dir)) {
if (!mkdir($dir, 0755, true)) {
throw new Exception("mkdir 실패: {$dir}");
}
}
}
function put_file($path, $content) {
$dir = dirname($path);
ensure_dir($dir);
if (file_put_contents($path, $content) === false) {
throw new Exception("file_put_contents 실패: {$path}");
}
}
function zip_dir($sourceDir, $zipPath) {
if (!extension_loaded('zip')) {
throw new Exception("PHP zip 확장(ZipArchive)이 없습니다.");
}
$sourceDir = rtrim($sourceDir, '/\\');
$zip = new ZipArchive();
if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
throw new Exception("ZIP 생성 실패: {$zipPath}");
}
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($sourceDir, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $file) {
$filePath = $file->getPathname();
$localPath = substr($filePath, strlen($sourceDir) + 1);
if ($file->isDir()) {
$zip->addEmptyDir($localPath);
} else {
$zip->addFile($filePath, $localPath);
}
}
$zip->close();
}
try {
$root = __DIR__;
$themeRoot = $root . '/theme/journal';
// ---------------------------
// 1) 테마 기본 파일
// ---------------------------
put_file($themeRoot.'/theme.config.php', <<<'PHP'
<?php
if (!defined('_GNUBOARD_')) exit;
$theme_config = array();
$theme_config['name'] = 'journal';
$theme_config['version'] = '1.0.0';
PHP
);
put_file($themeRoot.'/head.php', <<<'PHP'
<?php
if (!defined('_GNUBOARD_')) exit;
add_stylesheet('<link rel="stylesheet" href="'.G5_THEME_URL.'/assets/css/journal.base.css?v=1">', 0);
add_stylesheet('<link rel="stylesheet" href="'.G5_THEME_URL.'/assets/css/journal.layout.css?v=1">', 1);
add_javascript('<script src="'.G5_THEME_URL.'/assets/js/journal.base.js?v=1"></script>', 0);
include_once(G5_THEME_PATH.'/parts/header/header.php');
PHP
);
put_file($themeRoot.'/tail.php', <<<'PHP'
<?php
if (!defined('_GNUBOARD_')) exit;
include_once(G5_THEME_PATH.'/parts/footer/footer.php');
PHP
);
put_file($themeRoot.'/index.php', <<<'PHP'
<?php
define('_INDEX_', true);
include_once('./_common.php');
include_once(G5_THEME_PATH.'/head.php');
include_once(G5_THEME_PATH.'/parts/main/main.php');
include_once(G5_THEME_PATH.'/tail.php');
PHP
);
// ---------------------------
// 2) parts: header/main/footer
// ---------------------------
put_file($themeRoot.'/parts/header/header.php', <<<'PHP'
<?php
if (!defined('_GNUBOARD_')) exit;
?>
<header class="jrnl" id="jrnl-header">
<div class="jrnl__topbar">
<div class="jrnl__container">
<nav class="jrnl__utility">
<?php if ($is_member) { ?>
<a href="<?php echo G5_BBS_URL ?>/logout.php">로그아웃</a>
<?php } else { ?>
<a href="<?php echo G5_BBS_URL ?>/login.php">로그인</a>
<a href="<?php echo G5_BBS_URL ?>/register.php">회원가입</a>
<?php } ?>
<a href="<?php echo G5_BBS_URL ?>/faq.php">고객센터</a>
</nav>
</div>
</div>
<div class="jrnl__gnb">
<div class="jrnl__container jrnl__gnbRow">
<a class="jrnl__logo" href="<?php echo G5_URL ?>/">
<img src="<?php echo G5_THEME_URL ?>/assets/img/logo.svg" alt="LaserWorld">
</a>
<button class="jrnl__menuBtn" type="button" data-jrnl="menu-toggle">메뉴</button>
<nav class="jrnl__nav" data-jrnl="nav">
<a href="#">기업소개</a>
<a href="#">레이저 뉴스</a>
<a href="#">신기술&신제품</a>
<a href="#">커뮤니티</a>
<a href="#">과월호</a>
</nav>
<div class="jrnl__search">
<form action="<?php echo G5_BBS_URL ?>/search.php" method="get">
<input type="text" name="stx" placeholder="검색" />
<button type="submit">검색</button>
</form>
</div>
</div>
</div>
</header>
PHP
);
put_file($themeRoot.'/parts/main/main.php', <<<'PHP'
<?php
if (!defined('_GNUBOARD_')) exit;
?>
<main class="jrnl" id="jrnl-main">
<!-- HERO + LATEST -->
<section class="jrnl__hero">
<div class="jrnl__container jrnl__heroGrid">
<article class="jrnl__heroCard" data-slot="hero">
<div class="jrnl__heroThumb">
<img src="<?php echo G5_THEME_URL ?>/assets/img/hero-laser.svg" alt="Hero" />
</div>
<div class="jrnl__heroBody">
<p class="jrnl__kicker">HEADLINE</p>
<h1 class="jrnl__heroTitle">메인 헤드라인 영역(연동 전)</h1>
<p class="jrnl__heroLead">이 영역은 ‘가장 최신/중요 기사 1건’을 연결하세요.</p>
<div class="jrnl__meta">
<span>YYYY-MM-DD</span>
<span>Category</span>
</div>
<a class="jrnl__btn" href="#">전체 기사 보기</a>
</div>
</article>
<aside class="jrnl__latest" data-slot="latest">
<div class="jrnl__sectionHead">
<h2>Latest News</h2>
<a href="#">더보기</a>
</div>
<ul class="jrnl__latestList">
<?php for($i=0;$i<8;$i++){ ?>
<li class="jrnl__latestItem">
<a href="#">
<span class="jrnl__latestTitle">최신 기사 제목 자리 <?php echo $i+1; ?></span>
<span class="jrnl__latestDate">YYYY-MM-DD</span>
</a>
</li>
<?php } ?>
</ul>
</aside>
</div>
</section>
<!-- THIS ISSUE -->
<section class="jrnl__issue">
<div class="jrnl__container">
<div class="jrnl__sectionHead">
<h2>VOL. 384 | Monthly Laser Technology</h2>
<a href="#">과월호 보기</a>
</div>
<div class="jrnl__cardGrid" data-slot="issue-picks">
<?php for($i=0;$i<6;$i++){ ?>
<article class="jrnl__card">
<div class="jrnl__thumb">
<img src="<?php echo G5_THEME_URL ?>/assets/img/card-placeholder.svg" alt="thumb" />
</div>
<div class="jrnl__body">
<p class="jrnl__tag">Editors Pick</p>
<h3 class="jrnl__title">이번 호 추천 기사 <?php echo $i+1; ?></h3>
<p class="jrnl__excerpt">요약문 자리(2~3줄)</p>
<div class="jrnl__meta"><span>YYYY-MM-DD</span><span>Category</span></div>
</div>
</article>
<?php } ?>
</div>
</div>
</section>
<!-- SECTIONS -->
<section class="jrnl__sections">
<div class="jrnl__container">
<?php
$sections = array(
array('id'=>'focus', 'title'=>'포커스', 'sub'=>'Industry Focus'),
array('id'=>'interview', 'title'=>'인터뷰', 'sub'=>'Interviews'),
array('id'=>'market', 'title'=>'레이저시장', 'sub'=>'Laser Market'),
array('id'=>'trend', 'title'=>'관련산업동향', 'sub'=>'Industry Trend'),
array('id'=>'photo', 'title'=>'포토이슈', 'sub'=>'Photo Issue'),
array('id'=>'tech', 'title'=>'신기술', 'sub'=>'New Technology'),
array('id'=>'product', 'title'=>'신제품', 'sub'=>'New Products'),
);
?>
<?php foreach($sections as $sec){ ?>
<div class="jrnl__block" data-slot="section-<?php echo $sec['id']; ?>">
<div class="jrnl__sectionHead">
<div>
<h2><?php echo $sec['title']; ?></h2>
<p class="jrnl__sectionSub"><?php echo $sec['sub']; ?></p>
</div>
<a href="#">더보기</a>
</div>
<div class="jrnl__cardGrid jrnl__cardGrid--3">
<?php for($i=0;$i<3;$i++){ ?>
<article class="jrnl__card">
<div class="jrnl__thumb">
<img src="<?php echo G5_THEME_URL ?>/assets/img/card-placeholder.svg" alt="thumb" />
</div>
<div class="jrnl__body">
<p class="jrnl__tag"><?php echo $sec['title']; ?></p>
<h3 class="jrnl__title"><?php echo $sec['title']; ?> 기사 <?php echo $i+1; ?></h3>
<p class="jrnl__excerpt">요약문 자리(2~3줄)</p>
<div class="jrnl__meta"><span>YYYY-MM-DD</span><span><?php echo $sec['sub']; ?></span></div>
</div>
</article>
<?php } ?>
</div>
</div>
<?php } ?>
</div>
</section>
</main>
PHP
);
put_file($themeRoot.'/parts/footer/footer.php', <<<'PHP'
<?php
if (!defined('_GNUBOARD_')) exit;
?>
<footer class="jrnl" id="jrnl-footer">
<div class="jrnl__container">
<section class="jrnl__cta">
<h3>정기 구독 신청 & 광고 게재 문의</h3>
<p>월간 레이저 기술 / 레이저 뉴스 / 신기술&신제품</p>
<a class="jrnl__btn" href="#">문의하기</a>
</section>
<div class="jrnl__footerMeta">
<a href="<?php echo G5_BBS_URL ?>/content.php?co_id=privacy">개인정보처리방침</a>
<a href="<?php echo G5_BBS_URL ?>/content.php?co_id=provision">이용약관</a>
<p class="jrnl__copy">© <?php echo date('Y'); ?> LaserWorld</p>
</div>
</div>
</footer>
PHP
);
// ---------------------------
// 3) assets: css/js/img(svg)
// ---------------------------
put_file($themeRoot.'/assets/css/journal.base.css', <<<'CSS'
.jrnl { color:#111; font-family: system-ui, -apple-system, Segoe UI, Roboto, "Noto Sans KR", sans-serif; }
.jrnl * { box-sizing: border-box; }
.jrnl a { color: inherit; text-decoration: none; }
.jrnl img { max-width:100%; display:block; }
.jrnl__container { width: min(1200px, calc(100% - 32px)); margin:0 auto; }
.jrnl__btn { display:inline-block; padding:10px 14px; border:1px solid #111; background:#111; color:#fff; border-radius:10px; }
CSS
);
put_file($themeRoot.'/assets/css/journal.layout.css', <<<'CSS'
#jrnl-header .jrnl__topbar { background:#f6f6f6; font-size:14px; }
#jrnl-header .jrnl__utility { display:flex; gap:12px; justify-content:flex-end; padding:8px 0; }
#jrnl-header .jrnl__gnb { border-bottom:1px solid #eee; background:#fff; }
#jrnl-header .jrnl__gnbRow { display:flex; align-items:center; gap:16px; padding:14px 0; }
#jrnl-header .jrnl__nav { display:flex; gap:14px; margin-left:auto; }
#jrnl-header .jrnl__menuBtn { display:none; margin-left:auto; }
#jrnl-main .jrnl__hero { padding:22px 0; background:#0b0f17; border-bottom:1px solid #111; }
#jrnl-main .jrnl__heroGrid { display:grid; grid-template-columns: 1.6fr 1fr; gap:18px; }
#jrnl-main .jrnl__heroCard { background:#101827; border:1px solid rgba(255,255,255,.08); border-radius:12px; overflow:hidden; color:#fff; }
#jrnl-main .jrnl__heroThumb { background:#05070c; }
#jrnl-main .jrnl__heroBody { padding:16px; }
#jrnl-main .jrnl__kicker { margin:0 0 6px; font-size:12px; letter-spacing:.08em; color:rgba(255,255,255,.7); }
#jrnl-main .jrnl__heroTitle { margin:0 0 8px; font-size:28px; line-height:1.2; }
#jrnl-main .jrnl__heroLead { margin:0 0 10px; color:rgba(255,255,255,.85); }
#jrnl-main .jrnl__meta { display:flex; gap:10px; font-size:12px; color:rgba(255,255,255,.7); }
#jrnl-main .jrnl__btn { background:#fff; color:#111; border-color:#fff; }
#jrnl-main .jrnl__latest { background:#0f172a; border:1px solid rgba(255,255,255,.08); border-radius:12px; padding:16px; color:#fff; }
#jrnl-main .jrnl__latestList { list-style:none; padding:0; margin:0; display:flex; flex-direction:column; gap:10px; }
#jrnl-main .jrnl__latestItem a { display:flex; justify-content:space-between; gap:12px; color:#fff; }
#jrnl-main .jrnl__latestTitle { color:rgba(255,255,255,.9); }
#jrnl-main .jrnl__latestDate { color:rgba(255,255,255,.6); font-size:12px; }
#jrnl-main .jrnl__issue { padding:28px 0; background:#fff; }
#jrnl-main .jrnl__sections { padding:10px 0 40px; background:#fff; }
#jrnl-main .jrnl__block { padding:22px 0; border-top:1px solid #eee; }
#jrnl-main .jrnl__sectionHead { display:flex; align-items:flex-end; justify-content:space-between; gap:12px; margin-bottom:12px; }
#jrnl-main .jrnl__sectionSub { margin:0; color:#666; font-size:13px; }
#jrnl-main .jrnl__cardGrid { display:grid; grid-template-columns: repeat(3, 1fr); gap:16px; }
#jrnl-main .jrnl__card { border:1px solid #eee; border-radius:12px; overflow:hidden; background:#fff; }
#jrnl-main .jrnl__thumb { background:#f2f2f2; }
#jrnl-main .jrnl__body { padding:14px; }
#jrnl-main .jrnl__tag { margin:0 0 6px; font-size:12px; color:#666; }
#jrnl-main .jrnl__title { margin:0 0 8px; font-size:18px; line-height:1.3; }
#jrnl-main .jrnl__excerpt { margin:0 0 10px; color:#444; font-size:14px; line-height:1.5; }
#jrnl-main .jrnl__meta { display:flex; gap:10px; font-size:12px; color:#777; }
#jrnl-footer { border-top:1px solid #eee; background:#fff; padding:26px 0; }
#jrnl-footer .jrnl__cta { border:1px solid #eee; border-radius:12px; padding:16px; background:#fafafa; margin-bottom:14px; }
#jrnl-footer .jrnl__footerMeta { display:flex; flex-wrap:wrap; gap:12px; align-items:center; justify-content:space-between; }
#jrnl-footer .jrnl__copy { margin:0; color:#666; font-size:13px; }
@media (max-width: 1024px) {
#jrnl-main .jrnl__heroGrid { grid-template-columns: 1fr; }
#jrnl-main .jrnl__cardGrid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
#jrnl-header .jrnl__nav { display:none; }
#jrnl-header .jrnl__menuBtn { display:inline-block; }
#jrnl-main .jrnl__cardGrid { grid-template-columns: 1fr; }
}
CSS
);
put_file($themeRoot.'/assets/js/journal.base.js', <<<'JS'
(function () {
const btn = document.querySelector('[data-jrnl="menu-toggle"]');
const nav = document.querySelector('[data-jrnl="nav"]');
if (!btn || !nav) return;
btn.addEventListener('click', () => {
const isOpen = nav.style.display === 'flex';
nav.style.display = isOpen ? 'none' : 'flex';
nav.style.flexDirection = 'column';
nav.style.gap = '10px';
});
})();
JS
);
// 로고 SVG
put_file($themeRoot.'/assets/img/logo.svg', <<<'SVG'
<svg xmlns="http://www.w3.org/2000/svg" width="160" height="32" viewBox="0 0 160 32">
<rect width="160" height="32" rx="8" fill="#111"/>
<text x="12" y="21" fill="#fff" font-size="16" font-family="Arial">LaserWorld</text>
</svg>
SVG
);
// 메인 히어로 이미지 (SVG)
put_file($themeRoot.'/assets/img/hero-laser.svg', <<<'SVG'
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="675" viewBox="0 0 1200 675">
<defs>
<linearGradient id="g1" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#0b0f17"/>
<stop offset="1" stop-color="#111c33"/>
</linearGradient>
<radialGradient id="g2" cx="70%" cy="35%" r="60%">
<stop offset="0" stop-color="#66e3ff" stop-opacity="0.55"/>
<stop offset="0.55" stop-color="#2b5cff" stop-opacity="0.18"/>
<stop offset="1" stop-color="#0b0f17" stop-opacity="0"/>
</radialGradient>
<filter id="glow" x="-30%" y="-30%" width="160%" height="160%">
<feGaussianBlur stdDeviation="6" result="b"/>
<feMerge>
<feMergeNode in="b"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<rect width="1200" height="675" fill="url(#g1)"/>
<rect width="1200" height="675" fill="url(#g2)"/>
<!-- grid -->
<g opacity="0.22">
<path d="M0 560 H1200" stroke="#2a3b5f"/>
<path d="M0 470 H1200" stroke="#2a3b5f"/>
<path d="M0 380 H1200" stroke="#2a3b5f"/>
<path d="M0 290 H1200" stroke="#2a3b5f"/>
<path d="M0 200 H1200" stroke="#2a3b5f"/>
<path d="M150 0 V675" stroke="#2a3b5f"/>
<path d="M330 0 V675" stroke="#2a3b5f"/>
<path d="M510 0 V675" stroke="#2a3b5f"/>
<path d="M690 0 V675" stroke="#2a3b5f"/>
<path d="M870 0 V675" stroke="#2a3b5f"/>
<path d="M1050 0 V675" stroke="#2a3b5f"/>
</g>
<!-- laser line -->
<g filter="url(#glow)">
<path d="M120 470 C 380 300, 540 420, 760 270 C 900 175, 1030 190, 1120 140"
stroke="#7bf4ff" stroke-width="6" fill="none" opacity="0.95"/>
<path d="M120 470 C 380 300, 540 420, 760 270 C 900 175, 1030 190, 1120 140"
stroke="#2b5cff" stroke-width="2" fill="none" opacity="0.8"/>
</g>
<!-- sparks -->
<g opacity="0.9">
<circle cx="760" cy="270" r="4" fill="#7bf4ff"/>
<circle cx="770" cy="280" r="2" fill="#7bf4ff"/>
<circle cx="748" cy="262" r="2" fill="#7bf4ff"/>
</g>
<text x="70" y="90" fill="rgba(255,255,255,0.92)" font-size="34" font-family="Arial" font-weight="700">
Laser Industry Journal
</text>
<text x="70" y="132" fill="rgba(255,255,255,0.7)" font-size="18" font-family="Arial">
Latest news + in-depth features, optimized for responsive layouts.
</text>
</svg>
SVG
);
// 카드용 플레이스홀더 이미지 (SVG)
put_file($themeRoot.'/assets/img/card-placeholder.svg', <<<'SVG'
<svg xmlns="http://www.w3.org/2000/svg" width="960" height="540" viewBox="0 0 960 540">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#f3f4f6"/>
<stop offset="1" stop-color="#e5e7eb"/>
</linearGradient>
</defs>
<rect width="960" height="540" fill="url(#bg)"/>
<path d="M0 420 L260 260 L420 370 L630 180 L960 420 V540 H0 Z" fill="#d1d5db"/>
<circle cx="720" cy="160" r="48" fill="#cbd5e1"/>
<text x="40" y="70" fill="#6b7280" font-size="28" font-family="Arial" font-weight="700">Thumbnail</text>
<text x="40" y="110" fill="#6b7280" font-size="16" font-family="Arial">16:9 placeholder</text>
</svg>
SVG
);
// ---------------------------
// 4) 게시판 공용 스킨
// ---------------------------
$skinRoot = $themeRoot.'/skin/board/journal_board';
put_file($skinRoot.'/style.css', <<<'CSS'
.jrnl-board .jrnl-board__head { display:flex; justify-content:space-between; align-items:flex-end; gap:12px; margin:18px 0; }
.jrnl-board .jrnl-board__title { margin:0; font-size:26px; }
.jrnl-board .jrnl-board__list { display:grid; grid-template-columns:repeat(3, 1fr); gap:16px; }
.jrnl-board .jrnl-board__item { border:1px solid #eee; border-radius:12px; overflow:hidden; background:#fff; }
.jrnl-board .jrnl-board__thumb { aspect-ratio:16/9; background:#ddd; overflow:hidden; }
.jrnl-board .jrnl-board__thumb img { width:100%; height:100%; object-fit:cover; }
.jrnl-board .jrnl-board__body { padding:14px; }
.jrnl-board .jrnl-board__meta { font-size:12px; color:#777; display:flex; gap:10px; margin-bottom:8px; }
.jrnl-board .jrnl-board__subject { margin:0 0 8px; font-size:18px; line-height:1.3; }
.jrnl-board .jrnl-board__excerpt { margin:0; color:#444; font-size:14px; line-height:1.5; }
@media (max-width:1024px){
.jrnl-board .jrnl-board__list { grid-template-columns:repeat(2, 1fr); }
}
@media (max-width:640px){
.jrnl-board .jrnl-board__list { grid-template-columns:1fr; }
}
CSS
);
put_file($skinRoot.'/list.skin.php', <<<'PHP'
<?php
if (!defined('_GNUBOARD_')) exit;
add_stylesheet('<link rel="stylesheet" href="'.$board_skin_url.'/style.css?v=1">', 50);
?>
<div class="jrnl jrnl-board" id="jrnl-board-<?php echo $bo_table; ?>">
<div class="jrnl__container">
<div class="jrnl-board__head">
<div>
<h1 class="jrnl-board__title"><?php echo $board['bo_subject']; ?></h1>
</div>
<div class="jrnl-board__actions">
<?php if ($write_href) { ?>
<a class="jrnl__btn" href="<?php echo $write_href; ?>">글쓰기</a>
<?php } ?>
</div>
</div>
<div class="jrnl-board__list">
<?php for ($i=0; $i<count($list); $i++) {
$excerpt = strip_tags($list[$i]['wr_content']);
$excerpt = preg_replace('/\s+/', ' ', $excerpt);
$excerpt = mb_substr($excerpt, 0, 120);
if (mb_strlen($excerpt) >= 120) $excerpt .= '...';
// 썸네일은 연동 시 get_list_thumbnail()로 교체 권장
$fallback = G5_THEME_URL.'/assets/img/card-placeholder.svg';
?>
<article class="jrnl-board__item">
<a href="<?php echo $list[$i]['href']; ?>">
<div class="jrnl-board__thumb">
<img src="<?php echo $fallback; ?>" alt="thumb" />
</div>
<div class="jrnl-board__body">
<div class="jrnl-board__meta">
<span><?php echo date('Y-m-d', strtotime($list[$i]['wr_datetime'])); ?></span>
<span><?php echo $list[$i]['name']; ?></span>
</div>
<h2 class="jrnl-board__subject"><?php echo $list[$i]['subject']; ?></h2>
<p class="jrnl-board__excerpt"><?php echo $excerpt; ?></p>
</div>
</a>
</article>
<?php } ?>
</div>
<div style="margin:18px 0;">
<?php echo $write_pages; ?>
</div>
</div>
</div>
PHP
);
// ---------------------------
// 5) ZIP 생성
// ---------------------------
zip_dir($themeRoot, $root.'/theme-journal.zip');
zip_dir($skinRoot, $root.'/skin-journal_board.zip');
header('Content-Type: text/plain; charset=utf-8');
echo "완료!\n";
echo "- 생성: theme/journal\n";
echo "- 생성: theme-journal.zip\n";
echo "- 생성: skin-journal_board.zip\n";
echo "\n주의: install_journal_theme.php 파일은 실행 후 삭제하세요.\n";
} catch (Exception $e) {
header('Content-Type: text/plain; charset=utf-8');
echo "오류: ".$e->getMessage()."\n";
}