diff --git a/config/web.php b/config/web.php
new file mode 100644
index 0000000..55cd983
--- /dev/null
+++ b/config/web.php
@@ -0,0 +1,49 @@
+ [
+ [
+ 'kicker' => 'PIN FOR YOU',
+ 'title' => '안전하고 빠른 상품권 거래',
+ 'desc' => '구글플레이·문화상품권·편의점 등 인기 상품을 할인 구매하세요.',
+ 'cta_label' => '상품 보러가기',
+ 'cta_url' => '/shop',
+ ],
+ [
+ 'kicker' => 'EVENT',
+ 'title' => '카드/휴대폰 결제 지원',
+ 'desc' => '원하는 결제수단으로 편하게, 발송은 빠르게.',
+ 'cta_label' => '결제 안내',
+ 'cta_url' => '/guide',
+ ],
+ [
+ 'kicker' => 'SUPPORT',
+ 'title' => '문제 생기면 1:1 문의',
+ 'desc' => '빠른 응답으로 도와드릴게요.',
+ 'cta_label' => '1:1 문의하기',
+ 'cta_url' => '/cs/qna',
+ ],
+ ],
+
+ 'cs_tabs' => [
+ ['label' => '공지사항', 'route' => 'web.cs.notice.index', 'key' => 'notice'],
+ ['label' => '자주 묻는 질문', 'route' => 'web.cs.faq.index', 'key' => 'faq'],
+ ['label' => '카카오톡상담', 'route' => 'web.cs.kakao.index', 'key' => 'kakao'],
+ ['label' => '1:1 문의', 'route' => 'web.cs.qna.index', 'key' => 'qna'],
+ ['label' => '이용안내', 'route' => 'web.cs.guide.index', 'key' => 'guide'],
+ ],
+
+ 'mypage_tabs' => [
+ ['label' => '나의정보', 'route' => 'web.mypage.info.index', 'key' => 'info'],
+ ['label' => '이용내역', 'route' => 'web.mypage.usage.index', 'key' => 'usage'],
+ ['label' => '교환내역', 'route' => 'web.mypage.exchange.index', 'key' => 'exchange'],
+ ['label' => '1:1문의내역', 'route' => 'web.mypage.qna.index', 'key' => 'qna'],
+ ],
+
+ 'policy_tabs' => [
+ ['label' => '개인정보처리방침', 'route' => 'web.policy.privacy.index', 'key' => 'privacy'],
+ ['label' => '이용약관', 'route' => 'web.policy.terms.index', 'key' => 'terms'],
+ ['label' => '이메일무단수집거부', 'route' => 'web.policy.email.index', 'key' => 'email'],
+ ],
+
+];
diff --git a/resources/css/web.css b/resources/css/web.css
index 8c778da..020ef59 100644
--- a/resources/css/web.css
+++ b/resources/css/web.css
@@ -1212,3 +1212,541 @@ h1, h2, h3, h4, h5, h6 {
.notice-link{ grid-template-columns: 44px 1fr; }
.notice-date{ display:none; }
}
+/* ===== Subpage Skeleton ===== */
+.subpage-wrap{ padding: 18px 0 26px; }
+
+.subpage-header{
+ display:flex;
+ align-items: baseline;
+ justify-content: space-between;
+ gap: 12px;
+ margin: 40px 0 16px;
+ padding-left:8px;
+}
+.subpage-title{
+ font-size: 20px;
+ font-weight: 900;
+ letter-spacing: -0.3px;
+ color:#0F172A;
+}
+.subpage-desc{
+ font-size: 13px;
+ color:#64748B;
+ white-space: nowrap;
+ overflow:hidden;
+ text-overflow: ellipsis;
+ max-width: 55%;
+}
+
+.breadcrumb{ margin-top: 6px; }
+.breadcrumb-list{
+ display:flex;
+ gap: 8px;
+ flex-wrap: wrap;
+ font-size: 12px;
+ color:#94A3B8;
+}
+.breadcrumb-item::after{
+ content:"/";
+ margin-left: 8px;
+ color:#CBD5E1;
+}
+.breadcrumb-item:last-child::after{ content:none; }
+.breadcrumb-link{ color:#64748B; }
+.breadcrumb-link:hover{ color:#2563EB; }
+.breadcrumb-current{ color:#475569; font-weight:700; }
+
+.subpage-grid{
+ display:grid;
+ grid-template-columns: 260px 1fr;
+ gap: 14px;
+ align-items: start;
+}
+
+.subpage-tabs{ display:none; }
+
+.subpage-side{ position: sticky; top: 90px; }
+
+.content-card{
+ background:#FFFFFF;
+ border: 1px solid #E5E7EB;
+ border-radius: 16px;
+ padding: 16px;
+ box-shadow: 0 1px 2px rgba(15,23,42,.04);
+}
+
+/* side nav */
+.subnav--side .subnav-list{
+ background:#FFFFFF;
+ border: 1px solid #E5E7EB;
+ border-radius: 16px;
+ padding: 10px;
+ display:grid;
+ gap: 6px;
+}
+.subnav-link{
+ display:flex;
+ align-items:center;
+ height: 40px;
+ padding: 0 12px;
+ border-radius: 12px;
+ font-size: 13px;
+ font-weight: 800;
+ color:#334155;
+}
+.subnav-link:hover{ background:#F8FAFC; }
+.subnav-link.is-active{
+ background:#EFF6FF;
+ border: 1px solid #BFDBFE;
+ color:#1D4ED8;
+}
+
+/* mobile tabs */
+.subnav--tabs{
+ display:flex;
+ gap: 8px;
+ overflow-x: auto;
+ scrollbar-width: none;
+ padding-bottom: 6px;
+}
+.subnav--tabs::-webkit-scrollbar{ display:none; }
+
+.subnav-tab{
+ flex: 0 0 auto;
+ height: 36px;
+ padding: 0 14px;
+ border-radius: 9999px;
+ border: 1px solid #E5E7EB;
+ background:#FFFFFF;
+ font-size: 12.5px;
+ font-weight: 900;
+ color:#334155;
+}
+.subnav-tab:hover{ background:#F8FAFC; }
+.subnav-tab.is-active{
+ background:#EFF6FF;
+ border-color:#BFDBFE;
+ color:#1D4ED8;
+}
+
+/* notice sample page */
+.list-head{ display:flex; align-items:center; justify-content:space-between; margin-bottom: 10px; }
+.list-title{ font-size: 14px; font-weight: 900; color:#0F172A; margin:0; }
+.list-desc{ font-size: 12.5px; color:#64748B; margin-top: 4px; }
+.list-head{
+ display:flex;
+ align-items: baseline;
+ justify-content: space-between;
+ gap: 12px;
+ margin-bottom: 10px;
+}
+
+.list-title{
+ margin: 0;
+}
+
+.list-desc{
+ margin: 0;
+ text-align: right;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 60%;
+ font-size: 12.5px; color:#64748B;
+}
+
+@media (max-width: 560px){
+ .list-desc{ display:none; } /* 모바일은 깔끔하게 */
+}
+
+
+.notice-list2{ display:grid; }
+.notice-list2 li + li{ border-top: 1px solid #EEF2F7; }
+.notice-list2 a{
+ display:grid;
+ grid-template-columns: 54px 1fr auto;
+ gap: 10px;
+ align-items:center;
+ padding: 12px 6px;
+ border-radius: 12px;
+}
+.notice-list2 a:hover{ background:#F8FAFC; }
+
+.n2-tag{
+ height: 20px;
+ display:inline-flex;
+ align-items:center;
+ justify-content:center;
+ padding: 0 10px;
+ border-radius: 9999px;
+ font-size: 11px;
+ font-weight: 900;
+ background:#EFF6FF;
+ border:1px solid #BFDBFE;
+ color:#1D4ED8;
+}
+.n2-tag--info{
+ background:#F1F5F9;
+ border-color:#E2E8F0;
+ color:#334155;
+}
+.n2-text{
+ font-size: 13px;
+ font-weight: 800;
+ color:#334155;
+ white-space: nowrap;
+ overflow:hidden;
+ text-overflow: ellipsis;
+}
+.n2-date{ font-size: 12px; color:#94A3B8; white-space: nowrap; }
+
+.n2s-text{
+ font-size: 13px;
+ font-weight: 600;
+ color: #2a3647;
+ white-space: nowrap;
+ overflow:hidden;
+ text-overflow: ellipsis;
+}
+
+@media (max-width: 1024px){
+ .subpage-grid{ grid-template-columns: 1fr; }
+ .subpage-side{ display:none; }
+ .subpage-tabs{ display:block; }
+ .subpage-desc{ max-width: 100%; }
+}
+@media (max-width: 560px){
+ .notice-list2 a{ grid-template-columns: 54px 1fr; }
+ .n2-date{ display:none; }
+}
+
+/* ===== Sub Hero (compact rolling banner) ===== */
+.subhero{
+ margin: 8px 0 10px;
+}
+.subhero-inner{
+ position: relative;
+ overflow: hidden;
+ border-radius: 16px;
+ border: 1px solid #E5E7EB;
+ background: #F8FAFC;
+ height: 160px; /* ✅ 메인보다 낮게 */
+}
+.subhero-track{
+ display:flex;
+ height: 100%;
+ transition: transform .45s cubic-bezier(.25,1,.5,1);
+}
+.subhero-slide{
+ min-width: 100%;
+ height: 100%;
+ background-image: var(--bg);
+ background-size: cover;
+ background-position: center;
+ position: relative;
+}
+.subhero-slide::after{
+ content:"";
+ position:absolute; inset:0;
+ background: rgba(255,255,255,.72); /* ✅ 과하지 않게 텍스트 가독 */
+}
+.subhero-content{
+ position: relative;
+ z-index: 1;
+ height: 100%;
+ padding: 18px 18px;
+ display:flex;
+ flex-direction: column;
+ justify-content: center;
+ max-width: 720px;
+}
+.subhero-kicker{
+ font-size: 11px;
+ font-weight: 900;
+ letter-spacing: .8px;
+ color: #2563EB;
+}
+.subhero-title{
+ margin-top: 6px;
+ font-size: 20px;
+ font-weight: 900;
+ color:#0F172A;
+ letter-spacing: -0.3px;
+}
+.subhero-desc{
+ margin-top: 6px;
+ font-size: 13px;
+ color:#64748B;
+}
+.subhero-cta{
+ margin-top: 10px;
+ display:inline-flex;
+ align-items:center;
+ height: 34px;
+ padding: 0 12px;
+ border-radius: 9999px;
+ border: 1px solid #BFDBFE;
+ background: #EFF6FF;
+ color:#1D4ED8;
+ font-size: 12.5px;
+ font-weight: 900;
+ width: fit-content;
+}
+.subhero-cta:hover{ background:#2563EB; border-color:#2563EB; color:#fff; }
+
+.subhero-arrow{
+ position:absolute; top:50%;
+ transform: translateY(-50%);
+ width: 34px; height: 34px;
+ border-radius: 9999px;
+ border: 1px solid #E5E7EB;
+ background: rgba(255,255,255,.9);
+ font-size: 20px;
+ font-weight: 900;
+ color:#0F172A;
+}
+.subhero-arrow.prev{ left: 10px; }
+.subhero-arrow.next{ right: 10px; }
+
+.subhero-dots{
+ position:absolute; bottom: 10px; left: 50%;
+ transform: translateX(-50%);
+ display:flex; gap: 6px;
+}
+.subhero-dot{
+ width: 7px; height: 7px;
+ border-radius: 9999px;
+ background: rgba(15,23,42,.18);
+}
+.subhero-dot.active{ background:#2563EB; transform: scale(1.2); }
+/* ===== Notice toolbar (no duplicate nav) ===== */
+.notice-toolbar{
+ display:flex;
+ align-items:flex-start;
+ justify-content:space-between;
+ gap: 12px;
+ margin: 6px 0 14px;
+ padding: 12px 12px;
+ border: 1px solid #E5E7EB;
+ border-radius: 16px;
+ background: #FFFFFF;
+ box-shadow: 0 1px 2px rgba(15,23,42,.04);
+}
+
+.nt-left{
+ min-width: 0;
+ display:flex;
+ flex-direction:column;
+ gap: 8px;
+}
+
+.nt-pill{
+ width: fit-content;
+ height: 22px;
+ padding: 0 10px;
+ border-radius: 9999px;
+ background: #EFF6FF;
+ border: 1px solid #BFDBFE;
+ color: #1D4ED8;
+ font-size: 11px;
+ font-weight: 900;
+}
+
+.nt-meta{
+ font-size: 12.5px;
+ color: #64748B;
+ line-height: 1.45;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 520px;
+}
+
+.nt-right{
+ display:flex;
+ flex-direction:column;
+ gap: 10px;
+ align-items:flex-end;
+}
+
+.nt-search{
+ display:flex;
+ align-items:center;
+ gap: 8px;
+}
+
+.nt-search input{
+ width: 280px;
+ height: 38px;
+ padding: 0 12px;
+ border-radius: 9999px;
+ border: 1px solid #E5E7EB;
+ background: #F3F4F6;
+ font-size: 13px;
+}
+.nt-search input:focus{
+ outline: none;
+ border-color: #2563EB;
+ background: #FFFFFF;
+ box-shadow: 0 0 0 2px #EFF6FF;
+}
+
+.nt-search button{
+ height: 38px;
+ padding: 0 12px;
+ border-radius: 9999px;
+ background: #2563EB;
+ color:#fff;
+ font-size: 13px;
+ font-weight: 900;
+ border: 1px solid #2563EB;
+}
+
+.nt-filters{
+ display:flex;
+ gap: 8px;
+ flex-wrap: wrap;
+ justify-content:flex-end;
+}
+
+.nt-chip{
+ height: 32px;
+ padding: 0 12px;
+ border-radius: 9999px;
+ border: 1px solid #E5E7EB;
+ background: #FFFFFF;
+ color: #334155;
+ font-size: 12.5px;
+ font-weight: 900;
+}
+.nt-chip:hover{ background:#F8FAFC; }
+
+.nt-chip.is-active{
+ background:#EFF6FF;
+ border-color:#BFDBFE;
+ color:#1D4ED8;
+}
+
+@media (max-width: 1024px){
+ .notice-toolbar{ flex-direction:column; align-items:stretch; }
+ .nt-meta{ max-width: 100%; white-space: normal; overflow: visible; text-overflow: clip; }
+ .nt-right{ align-items:stretch; }
+ .nt-search input{ width: 100%; }
+ .nt-filters{ justify-content:flex-start; }
+}
+
+/* ===== Hero variants ===== */
+.hero-slider{ position: relative; overflow: hidden; background: var(--color-bg-section); }
+.hero-slider--main{ height: 400px; }
+.hero-slider--compact{ height: 170px; border-radius: 16px; border: 1px solid #E5E7EB; margin: 14px 0 18px; }
+
+/* track/slide 동일 */
+.hero-track{ display:flex; height:100%; transition: transform 0.5s cubic-bezier(0.25,1,0.5,1); }
+.hero-slide{ min-width:100%; height:100%; display:flex; align-items:center; justify-content:center; padding: 0 24px; }
+
+.hero-content{ max-width: var(--container-width); width:100%; text-align:left; padding: 0 8px; }
+
+/* ✅ compact에서 타이포/여백만 줄이기 */
+.hero-slider--compact .hero-slide{ padding: 0 18px; }
+.hero-slider--compact .hero-title{ font-size: 22px; margin-bottom: 6px; }
+.hero-slider--compact .hero-desc{ font-size: 13px; margin-bottom: 10px; }
+.hero-slider--compact .btn.hero-cta{ padding: 8px 14px; font-size: 13px; }
+
+/* ✅ 왼쪽/오른쪽 화살표 버튼이 컨텐츠를 가리지 않게 여백 확보 */
+.slider-arrow{
+ position:absolute; top:50%; transform: translateY(-50%);
+ width: 34px; height: 34px;
+ border-radius: 9999px;
+ border: 1px solid #E5E7EB;
+ background: rgba(255,255,255,.9);
+ font-size: 20px; font-weight: 900;
+ display:flex; align-items:center; justify-content:center;
+ z-index: 5;
+}
+.slider-arrow.prev{ left: 10px; }
+.slider-arrow.next{ right: 10px; }
+
+/* ✅ 컨텐츠 좌우 패딩(화살표 영역만큼) */
+.hero-slider--compact .hero-content{ padding-left: 44px; padding-right: 44px; }
+
+/* dots */
+.dots-container{ position:absolute; bottom: 12px; left:50%; transform: translateX(-50%); display:flex; gap: 8px; z-index:5; }
+.dot{ width: 8px; height: 8px; border-radius: 50%; background: rgba(0,0,0,0.18); }
+.dot.active{ background: var(--color-accent-blue); transform: scale(1.15); }
+
+@media (max-width: 768px){
+ .hero-slider--compact{ height: 150px; }
+ .hero-slider--compact .hero-content{ padding-left: 14px; padding-right: 14px; } /* 모바일에선 화살표가 위에 떠도 괜찮게 */
+ .slider-arrow{ display:none; } /* 모바일은 스와이프/도트로만 */
+}
+.subpage-wrap .hero-slider--compact{
+ margin-top: 14px;
+ margin-bottom: 16px;
+}
+
+/* ===== List Head (section heading) ===== */
+.list-head{
+ display:flex;
+ align-items: baseline;
+ justify-content: space-between;
+ gap: 12px;
+ margin: 6px 0 12px;
+
+ /* 은은한 구획감: 라인 + 여백만 */
+ padding-bottom: 8px;
+ border-bottom: 1px solid #EEF2F7;
+}
+
+.list-title{
+ margin: 0;
+ font-size: 16px; /* 과하게 크지 않게 */
+ font-weight: 900;
+ letter-spacing: -0.2px;
+ color: #0F172A;
+ line-height: 1.2;
+}
+
+.list-desc{
+ margin: 0;
+ font-size: 13px;
+ color: #64748B;
+ line-height: 1.2;
+
+ /* 우측 정렬 + 길면 깔끔하게 처리 */
+ text-align: right;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 60%;
+}
+
+/* 모바일은 설명 숨기고 더 타이트하게 */
+@media (max-width: 560px){
+ .list-head{ padding-bottom: 6px; margin: 4px 0 10px; }
+ .list-title{ font-size: 15px; }
+ .list-desc{ display:none; }
+}
+
+/* ===== CS Tabs ===== */
+.cs-tabs{
+ display:flex;
+ gap: 8px;
+ flex-wrap: wrap;
+ margin: 10px 0 14px;
+}
+.cs-tab{
+ height: 34px;
+ padding: 0 14px;
+ border-radius: 9999px;
+ border: 1px solid #E5E7EB;
+ background:#fff;
+ font-size: 13px;
+ font-weight: 800;
+ color:#334155;
+}
+.cs-tab:hover{ background:#F8FAFC; }
+.cs-tab.is-active{
+ background:#EFF6FF;
+ border-color:#BFDBFE;
+ color:#1D4ED8;
+}
diff --git a/resources/js/web.js b/resources/js/web.js
index 36a21b2..f0b8ec4 100644
--- a/resources/js/web.js
+++ b/resources/js/web.js
@@ -125,4 +125,45 @@ document.addEventListener('DOMContentLoaded', () => {
alert('모바일 메뉴 드로어 열림 (구현 예정)');
});
}
+
+ // --- Sub Hero Carousel ---
+ (function initSubHero(){
+ const wrap = document.querySelector('.subhero-inner');
+ if(!wrap) return;
+
+ const track = wrap.querySelector('.subhero-track');
+ const slides = wrap.querySelectorAll('.subhero-slide');
+ const prev = wrap.querySelector('.subhero-arrow.prev');
+ const next = wrap.querySelector('.subhero-arrow.next');
+ const dots = wrap.querySelectorAll('.subhero-dot');
+
+ let idx = 0;
+ const total = slides.length;
+ if(total <= 1) return;
+
+ const render = () => {
+ track.style.transform = `translateX(-${idx * 100}%)`;
+ dots.forEach((d,i)=>d.classList.toggle('active', i===idx));
+ };
+
+ const goNext = () => { idx = (idx + 1) % total; render(); };
+ const goPrev = () => { idx = (idx - 1 + total) % total; render(); };
+
+ let t = setInterval(goNext, 6000);
+
+ const reset = () => { clearInterval(t); t = setInterval(goNext, 6000); };
+
+ next?.addEventListener('click', ()=>{ goNext(); reset(); });
+ prev?.addEventListener('click', ()=>{ goPrev(); reset(); });
+ dots.forEach(d => d.addEventListener('click', ()=>{
+ idx = Number(d.dataset.index || 0);
+ render(); reset();
+ }));
+
+ wrap.addEventListener('mouseenter', ()=>clearInterval(t));
+ wrap.addEventListener('mouseleave', ()=>{ t = setInterval(goNext, 6000); });
+
+ render();
+ })();
+
});
diff --git a/resources/views/web/company/header.blade.php b/resources/views/web/company/header.blade.php
index 6ce8850..f45fe69 100644
--- a/resources/views/web/company/header.blade.php
+++ b/resources/views/web/company/header.blade.php
@@ -13,8 +13,8 @@
HOME
SHOP
{{-- 상품권현금교환--}}
- 마이페이지
- 고객센터
+ 마이페이지
+ 고객센터
diff --git a/resources/views/web/cs/faq/index.blade.php b/resources/views/web/cs/faq/index.blade.php
new file mode 100644
index 0000000..b82083d
--- /dev/null
+++ b/resources/views/web/cs/faq/index.blade.php
@@ -0,0 +1,29 @@
+@php
+ $pageTitle = '자주 묻는 질문';
+ $pageDesc = '결제/발송/환불 등 자주 문의되는 내용을 빠르게 확인하세요.';
+
+ $breadcrumbs = [
+ ['label' => '홈', 'url' => url('/')],
+ ['label' => '고객센터', 'url' => url('/cs')],
+ ['label' => '자주 묻는 질문', 'url' => url()->current()],
+ ];
+
+ $csActive = 'faq';
+@endphp
+
+@extends('web.layouts.subpage')
+
+@section('title', '자주 묻는 질문(FAQ) | PIN FOR YOU')
+@section('meta_description', 'PIN FOR YOU FAQ입니다. 결제/발송/환불/이용 관련 자주 묻는 질문을 확인하세요.')
+@section('canonical', url('/cs/faq'))
+
+@section('subcontent')
+
+ @include('web.partials.content-head', [
+ 'title' => 'FAQ',
+ 'desc' => '원하시는 항목을 선택해 빠르게 해결해 보세요.'
+ ])
+
+ {{-- TODO: FAQ 내용(아코디언/카테고리/검색 등) --}}
+
+@endsection
diff --git a/resources/views/web/cs/guide/index.blade.php b/resources/views/web/cs/guide/index.blade.php
new file mode 100644
index 0000000..3290764
--- /dev/null
+++ b/resources/views/web/cs/guide/index.blade.php
@@ -0,0 +1,29 @@
+@php
+ $pageTitle = '이용안내';
+ $pageDesc = '구매부터 발송/환불까지 서비스 이용 방법을 한눈에 안내합니다.';
+
+ $breadcrumbs = [
+ ['label' => '홈', 'url' => url('/')],
+ ['label' => '고객센터', 'url' => url('/cs')],
+ ['label' => '이용안내', 'url' => url()->current()],
+ ];
+
+ $csActive = 'guide';
+@endphp
+
+@extends('web.layouts.subpage')
+
+@section('title', '이용안내 | PIN FOR YOU')
+@section('meta_description', 'PIN FOR YOU 이용안내입니다. 상품권 구매/발송/환불 등 이용 방법을 확인하세요.')
+@section('canonical', url('/cs/guide'))
+
+@section('subcontent')
+
+ @include('web.partials.content-head', [
+ 'title' => '서비스 이용 안내',
+ 'desc' => '주요 흐름(구매 → 결제 → 발송 → 환불)을 기준으로 안내합니다.'
+ ])
+
+ {{-- TODO: 이용안내 본문(단계별 가이드/주의사항/정책 링크 등) --}}
+
+@endsection
diff --git a/resources/views/web/cs/kakao/index.blade.php b/resources/views/web/cs/kakao/index.blade.php
new file mode 100644
index 0000000..20cc127
--- /dev/null
+++ b/resources/views/web/cs/kakao/index.blade.php
@@ -0,0 +1,29 @@
+@php
+ $pageTitle = '카카오톡 상담';
+ $pageDesc = '카카오톡으로 빠르고 편하게 문의하실 수 있어요.';
+
+ $breadcrumbs = [
+ ['label' => '홈', 'url' => url('/')],
+ ['label' => '고객센터', 'url' => url('/cs')],
+ ['label' => '카카오톡 상담', 'url' => url()->current()],
+ ];
+
+ $csActive = 'kakao';
+@endphp
+
+@extends('web.layouts.subpage')
+
+@section('title', '카카오톡 상담 | PIN FOR YOU')
+@section('meta_description', 'PIN FOR YOU 카카오톡 상담 안내입니다. 운영시간과 상담 절차를 확인하세요.')
+@section('canonical', url('/cs/kakao'))
+
+@section('subcontent')
+
+ @include('web.partials.content-head', [
+ 'title' => '카카오톡 상담 안내',
+ 'desc' => '운영시간과 안내사항을 확인하고 빠르게 문의해 주세요.'
+ ])
+
+ {{-- TODO: 카카오 채널 링크/QR/운영시간/주의사항 등 --}}
+
+@endsection
diff --git a/resources/views/web/cs/notice/index.blade.php b/resources/views/web/cs/notice/index.blade.php
new file mode 100644
index 0000000..50947f4
--- /dev/null
+++ b/resources/views/web/cs/notice/index.blade.php
@@ -0,0 +1,66 @@
+@php
+ $pageTitle = '공지사항';
+ $pageDesc = '서비스 운영 및 결제/발송 관련 안내를 확인하세요.';
+
+ $breadcrumbs = [
+ ['label' => '홈', 'url' => url('/')],
+ ['label' => '고객센터', 'url' => url('/cs')],
+ ['label' => '공지사항', 'url' => url()->current()],
+ ];
+
+ // ✅ 이것만 남기면 됨 (탭 목록은 config에서 자동)
+ $csActive = 'notice';
+@endphp
+
+@extends('web.layouts.subpage')
+
+@section('title', '공지사항 | PIN FOR YOU')
+@section('meta_description', 'PIN FOR YOU 공지사항입니다. 운영/결제/발송 관련 최신 안내를 확인하세요.')
+@section('canonical', url('/cs/notice'))
+
+@section('subcontent')
+
+ @include('web.partials.content-head', [
+ 'title' => '최신 공지',
+ 'desc' => '중요 안내를 빠르게 확인하세요.'
+ ])
+
+
+
+ {{-- Notice Toolbar (replace sub-quick) --}}
+
+
+@endsection
diff --git a/resources/views/web/cs/qna/index.blade.php b/resources/views/web/cs/qna/index.blade.php
new file mode 100644
index 0000000..2f31e67
--- /dev/null
+++ b/resources/views/web/cs/qna/index.blade.php
@@ -0,0 +1,29 @@
+@php
+ $pageTitle = '1:1 문의';
+ $pageDesc = '개인 문의는 1:1로 남겨주시면 순차적으로 답변드립니다.';
+
+ $breadcrumbs = [
+ ['label' => '홈', 'url' => url('/')],
+ ['label' => '고객센터', 'url' => url('/cs')],
+ ['label' => '1:1 문의', 'url' => url()->current()],
+ ];
+
+ $csActive = 'qna';
+@endphp
+
+@extends('web.layouts.subpage')
+
+@section('title', '1:1 문의 | PIN FOR YOU')
+@section('meta_description', 'PIN FOR YOU 1:1 문의 페이지입니다. 문의를 남겨주시면 순차적으로 답변드립니다.')
+@section('canonical', url('/cs/qna'))
+
+@section('subcontent')
+
+ @include('web.partials.content-head', [
+ 'title' => '문의하기',
+ 'desc' => '문의 내용을 남겨주시면 확인 후 빠르게 안내드리겠습니다.'
+ ])
+
+ {{-- TODO: 문의 폼 / 내 문의 내역 / 로그인 여부 처리 등 --}}
+
+@endsection
diff --git a/resources/views/web/home.blade.php b/resources/views/web/home.blade.php
index b9e26ba..b0414bd 100644
--- a/resources/views/web/home.blade.php
+++ b/resources/views/web/home.blade.php
@@ -3,7 +3,17 @@
@section('content')
{{-- Hero --}}
- @include('web.main.hero-carousel')
+ @php
+ $heroSlides = config('web.hero_slides', []);
+ @endphp
+
+ @if(!empty($heroSlides))
+ @include('web.partials.hero-slider', [
+ 'slides' => $heroSlides,
+ 'variant' => 'main',
+ 'id' => 'hero-main'
+ ])
+ @endif
{{-- Quick Categories --}}
@include('web.main.quick-categories')
diff --git a/resources/views/web/layouts/layout.blade.php b/resources/views/web/layouts/layout.blade.php
index cd90ee5..964e5f2 100644
--- a/resources/views/web/layouts/layout.blade.php
+++ b/resources/views/web/layouts/layout.blade.php
@@ -4,22 +4,54 @@
- Voucher Mall - 상품권 최저가 쇼핑
-
- {{-- SEO --}}
-
-
-
- {{-- CSRF (추후 폼/로그인 대비) --}}
+ {{-- CSRF --}}
- {{-- Pretendard Font --}}
-
-
+ {{-- Canonical/Title/Description (중복 금지) --}}
+ @php
+ $defaultTitle = 'PIN FOR YOU';
+ $defaultDesc = '상품권, 모바일 교환권, 구글플레이, 문화상품권 등 다양한 모바일 쿠폰을 안전하고 빠르게 할인 구매하세요.';
+ $canonicalUrl = trim($__env->yieldContent('canonical', url()->current()));
+ @endphp
- {{-- ✅ WEB 전용 번들 로딩 --}}
+ @yield('title', $defaultTitle)
+
+
+
+
+ {{-- Open Graph --}}
+
+
+
+
+
+
+ {{-- 대표 이미지 준비되면 사용 (없으면 생략 가능)
+
+ --}}
+
+ {{-- Twitter Card (선택이지만 권장) --}}
+
+
+
+ {{-- --}}
+
+ {{-- (선택) 기본 키워드는 큰 의미 없어서 생략 권장 --}}
+ {{-- --}}
+
+ {{-- Font --}}
+
+
+
+ {{-- Web Bundle --}}
@vite(['resources/css/web.css', 'resources/js/web.js'])
+
+ {{-- 페이지별 추가 head --}}
+ @yield('head')
+
{{-- Header --}}
diff --git a/resources/views/web/layouts/subpage.blade.php b/resources/views/web/layouts/subpage.blade.php
new file mode 100644
index 0000000..d029cde
--- /dev/null
+++ b/resources/views/web/layouts/subpage.blade.php
@@ -0,0 +1,143 @@
+@extends('web.layouts.layout')
+
+@section('content')
+
+
+
+ {{-- Breadcrumb (optional) --}}
+ @isset($breadcrumbs)
+ @include('web.partials.breadcrumb', ['items' => $breadcrumbs])
+ @endisset
+
+ @php
+ $heroSlides = config('web.hero_slides', []);
+
+ // ✅ 섹션 감지
+ $isCsPage = request()->is('cs') || request()->is('cs/*') || request()->routeIs('web.cs.*');
+ $isMypagePage = request()->is('mypage') || request()->is('mypage/*') || request()->routeIs('web.mypage.*');
+ $isPolicyPage = request()->is('policy') || request()->is('policy/*') || request()->routeIs('web.policy.*');
+
+ // ✅ CS subnav 자동 주입
+ if ($isCsPage && empty($subnavItems)) {
+ $subnavItems = collect(config('web.cs_tabs', []))
+ ->map(function ($t) {
+ $url = '#';
+ if (!empty($t['route']) && \Illuminate\Support\Facades\Route::has($t['route'])) {
+ $url = route($t['route']);
+ }
+ return [
+ 'label' => $t['label'] ?? '',
+ 'url' => $url,
+ 'key' => $t['key'] ?? null,
+ ];
+ })
+ ->values()
+ ->all();
+ }
+
+ // ✅ MYPAGE subnav 자동 주입
+ if ($isMypagePage && empty($subnavItems)) {
+ $subnavItems = collect(config('web.mypage_tabs', []))
+ ->map(function ($t) {
+ $url = '#';
+ if (!empty($t['route']) && \Illuminate\Support\Facades\Route::has($t['route'])) {
+ $url = route($t['route']);
+ }
+ return [
+ 'label' => $t['label'] ?? '',
+ 'url' => $url,
+ 'key' => $t['key'] ?? null,
+ ];
+ })
+ ->values()
+ ->all();
+ }
+
+ // ✅ PolicyPage subnav 자동 주입
+ if ($isPolicyPage && empty($subnavItems)) {
+ $subnavItems = collect(config('web.policy_tabs', []))
+ ->map(function ($t) {
+ $url = '#';
+ if (!empty($t['route']) && \Illuminate\Support\Facades\Route::has($t['route'])) {
+ $url = route($t['route']);
+ }
+ return [
+ 'label' => $t['label'] ?? '',
+ 'url' => $url,
+ 'key' => $t['key'] ?? null,
+ ];
+ })
+ ->values()
+ ->all();
+ }
+
+ // ✅ active key 우선순위: 각 섹션 전용 변수 -> 기존 subnavActive
+ $subnavActive = $csActive ?? $mypageActive ?? ($subnavActive ?? null);
+ @endphp
+
+ @if(!empty($heroSlides))
+ @include('web.partials.hero-slider', [
+ 'slides' => $heroSlides,
+ 'variant' => 'compact',
+ 'id' => 'hero-sub'
+ ])
+ @endif
+
+ {{-- Header --}}
+ @include('web.partials.subpage-header', [
+ 'title' => $pageTitle ?? '페이지 제목',
+ 'desc' => $pageDesc ?? null
+ ])
+
+ {{-- Body --}}
+
+
+ {{-- ✅ 고객센터면 cs-tabs --}}
+ @if($isCsPage)
+ @include('web.partials.cs-tabs', [
+ 'activeKey' => $subnavActive
+ ])
+
+ {{-- ✅ 마이페이지면 mypage-tabs --}}
+ @elseif($isMypagePage)
+ @include('web.partials.mypage-tabs', [
+ 'activeKey' => $subnavActive
+ ])
+
+ @elseif($isPolicyPage)
+ @include('web.partials.policy-tabs', [
+ 'activeKey' => $subnavActive
+ ])
+
+ {{-- 그 외 일반 서브페이지는 기존 방식 유지 --}}
+ @else
+ {{-- Mobile Tabs --}}
+
+ @include('web.partials.subpage-sidenav', [
+ 'items' => $subnavItems ?? [],
+ 'active' => $subnavActive ?? null,
+ 'mode' => 'tabs'
+ ])
+
+
+ {{-- Desktop Side --}}
+
+ @endif
+
+ {{-- Main --}}
+
+
+ @yield('subcontent')
+
+
+
+
+
+
+@endsection
diff --git a/resources/views/web/main/hero-carousel.blade.php b/resources/views/web/main/hero-carousel.blade.php
deleted file mode 100644
index 244ef55..0000000
--- a/resources/views/web/main/hero-carousel.blade.php
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
-
-
-
특별
- 프로모션
-
구글플레이 기프트카드
최대 12% 즉시 할인
-
인기 게임 아이템부터 영화까지, 더 저렴하게 즐기세요.
-
지금 구매하기
-
-
-
-
-
-
신규 입점
-
문화상품권 24시간
자동 발송 시스템 오픈
-
기다림 없이 결제 즉시 문자로 핀번호를 받아보세요.
-
상품 보러가기
-
-
-
-
-
-
한정 수량
-
편의점 모바일 금액권
5만원권 10% 핫딜
-
CU, GS25, 세븐일레븐 전국 어디서나 사용 가능
-
구매하기
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/resources/views/web/partials/breadcrumb.blade.php b/resources/views/web/partials/breadcrumb.blade.php
new file mode 100644
index 0000000..2b44edc
--- /dev/null
+++ b/resources/views/web/partials/breadcrumb.blade.php
@@ -0,0 +1,33 @@
+@props(['items' => []])
+
+
+
+{{-- SEO: Breadcrumb JSON-LD --}}
+@php
+ $ld = [
+ "@context" => "https://schema.org",
+ "@type" => "BreadcrumbList",
+ "itemListElement" => []
+ ];
+ foreach($items as $idx => $it){
+ $ld["itemListElement"][] = [
+ "@type" => "ListItem",
+ "position" => $idx+1,
+ "name" => $it["label"],
+ "item" => $it["url"] ?? url()->current()
+ ];
+ }
+@endphp
+
diff --git a/resources/views/web/partials/content-head.blade.php b/resources/views/web/partials/content-head.blade.php
new file mode 100644
index 0000000..e7c598a
--- /dev/null
+++ b/resources/views/web/partials/content-head.blade.php
@@ -0,0 +1,8 @@
+@props(['title' => '', 'desc' => null])
+
+
+
{{ $title }}
+ @if($desc)
+
{{ $desc }}
+ @endif
+
diff --git a/resources/views/web/partials/cs-tabs.blade.php b/resources/views/web/partials/cs-tabs.blade.php
new file mode 100644
index 0000000..1e16b54
--- /dev/null
+++ b/resources/views/web/partials/cs-tabs.blade.php
@@ -0,0 +1,44 @@
+@php
+ // config에서 CS 탭 가져와서, 기존 subpage-sidenav가 기대하는 형식(label,url,key)으로 변환
+ $items = collect(config('web.cs_tabs', []))
+ ->map(function ($t) {
+ return [
+ 'label' => $t['label'] ?? '',
+ 'url' => isset($t['route']) ? route($t['route']) : '#',
+ 'key' => $t['key'] ?? null,
+ ];
+ })
+ ->values()
+ ->all();
+
+ // activeKey는 페이지에서 넘기거나, 없으면 현재 route로 자동 판별도 가능
+ $activeKey = $activeKey ?? null;
+
+ if (!$activeKey) {
+ // route 기반 자동 active (routeIs가 동작하려면 routes에 name이 있어야 함)
+ foreach (config('web.cs_tabs', []) as $t) {
+ if (!empty($t['route']) && request()->routeIs($t['route'])) {
+ $activeKey = $t['key'] ?? null;
+ break;
+ }
+ }
+ }
+@endphp
+
+{{-- Mobile Tabs --}}
+
+ @include('web.partials.subpage-sidenav', [
+ 'items' => $items,
+ 'active' => $activeKey,
+ 'mode' => 'tabs'
+ ])
+
+
+{{-- Desktop Side --}}
+
diff --git a/resources/views/web/partials/hero-slider.blade.php b/resources/views/web/partials/hero-slider.blade.php
new file mode 100644
index 0000000..6b21f80
--- /dev/null
+++ b/resources/views/web/partials/hero-slider.blade.php
@@ -0,0 +1,43 @@
+@props([
+ 'slides' => [],
+ 'variant' => 'main', // 'main' | 'compact'
+ 'id' => 'hero'
+])
+@if(!empty($slides))
+
+
+ @foreach($slides as $s)
+
+
+ @if(!empty($s['kicker']))
+
{{ $s['kicker'] }}
+ @endif
+
+
{{ $s['title'] }}
+
+ @if(!empty($s['desc']))
+
{{ $s['desc'] }}
+ @endif
+
+ @if(!empty($s['cta_label']) && !empty($s['cta_url']))
+
+ {{ $s['cta_label'] }}
+
+ @endif
+
+
+ @endforeach
+
+
+ @if(count($slides) > 1)
+
+
+
+
+ @foreach($slides as $idx => $s)
+
+ @endforeach
+
+ @endif
+
+@endif
diff --git a/resources/views/web/partials/mypage-tabs.blade.php b/resources/views/web/partials/mypage-tabs.blade.php
new file mode 100644
index 0000000..85aa6f1
--- /dev/null
+++ b/resources/views/web/partials/mypage-tabs.blade.php
@@ -0,0 +1,45 @@
+@php
+ $rawTabs = config('web.mypage_tabs', []);
+
+ $items = collect($rawTabs)->map(function ($t) {
+ $url = '#';
+ if (!empty($t['route']) && \Illuminate\Support\Facades\Route::has($t['route'])) {
+ $url = route($t['route']);
+ }
+ return [
+ 'label' => $t['label'] ?? '',
+ 'url' => $url,
+ 'key' => $t['key'] ?? null,
+ ];
+ })->values()->all();
+
+ $activeKey = $activeKey ?? null;
+
+ // activeKey가 없으면 현재 라우트로 자동 판별
+ if (!$activeKey) {
+ foreach ($rawTabs as $t) {
+ if (!empty($t['route']) && request()->routeIs($t['route'])) {
+ $activeKey = $t['key'] ?? null;
+ break;
+ }
+ }
+ }
+@endphp
+
+{{-- Mobile Tabs --}}
+
+ @include('web.partials.subpage-sidenav', [
+ 'items' => $items,
+ 'active' => $activeKey,
+ 'mode' => 'tabs'
+ ])
+
+
+{{-- Desktop Side --}}
+
diff --git a/resources/views/web/partials/policy-tabs.blade.php b/resources/views/web/partials/policy-tabs.blade.php
new file mode 100644
index 0000000..893c68b
--- /dev/null
+++ b/resources/views/web/partials/policy-tabs.blade.php
@@ -0,0 +1,44 @@
+@php
+ $rawTabs = config('web.policy_tabs', []);
+
+ $items = collect($rawTabs)->map(function ($t) {
+ $url = '#';
+ if (!empty($t['route']) && \Illuminate\Support\Facades\Route::has($t['route'])) {
+ $url = route($t['route']);
+ }
+ return [
+ 'label' => $t['label'] ?? '',
+ 'url' => $url,
+ 'key' => $t['key'] ?? null,
+ ];
+ })->values()->all();
+
+ $activeKey = $activeKey ?? null;
+
+ if (!$activeKey) {
+ foreach ($rawTabs as $t) {
+ if (!empty($t['route']) && request()->routeIs($t['route'])) {
+ $activeKey = $t['key'] ?? null;
+ break;
+ }
+ }
+ }
+@endphp
+
+{{-- Mobile Tabs --}}
+
+ @include('web.partials.subpage-sidenav', [
+ 'items' => $items,
+ 'active' => $activeKey,
+ 'mode' => 'tabs'
+ ])
+
+
+{{-- Desktop Side --}}
+
diff --git a/resources/views/web/partials/subpage-header.blade.php b/resources/views/web/partials/subpage-header.blade.php
new file mode 100644
index 0000000..e7fc8e3
--- /dev/null
+++ b/resources/views/web/partials/subpage-header.blade.php
@@ -0,0 +1,4 @@
+
diff --git a/resources/views/web/partials/subpage-sidenav.blade.php b/resources/views/web/partials/subpage-sidenav.blade.php
new file mode 100644
index 0000000..305e4ec
--- /dev/null
+++ b/resources/views/web/partials/subpage-sidenav.blade.php
@@ -0,0 +1,29 @@
+@props(['items' => [], 'active' => null, 'mode' => 'side'])
+
+@if($mode === 'tabs')
+
+@else
+
+@endif
diff --git a/resources/views/web/policy/email/index.blade.php b/resources/views/web/policy/email/index.blade.php
new file mode 100644
index 0000000..4412e6a
--- /dev/null
+++ b/resources/views/web/policy/email/index.blade.php
@@ -0,0 +1,29 @@
+@php
+ $pageTitle = '이메일무단수집거부';
+ $pageDesc = '웹사이트 내 이메일 주소의 무단 수집을 거부합니다.';
+
+ $breadcrumbs = [
+ ['label' => '홈', 'url' => url('/')],
+ ['label' => '약관 및 정책', 'url' => url('/policy')],
+ ['label' => '이메일무단수집거부', 'url' => url()->current()],
+ ];
+
+ $policyActive = 'email';
+@endphp
+
+@extends('web.layouts.subpage')
+
+@section('title', '이메일무단수집거부 | PIN FOR YOU')
+@section('meta_description', 'PIN FOR YOU 이메일무단수집거부 안내입니다. 무단 수집 및 이용에 대한 조치를 안내합니다.')
+@section('canonical', url('/policy/email'))
+
+@section('subcontent')
+
+ @include('web.partials.content-head', [
+ 'title' => '무단 수집 금지 안내',
+ 'desc' => '자동 수집 프로그램 등을 통한 이메일 주소 수집을 금지합니다.'
+ ])
+
+ {{-- TODO: 이메일무단수집거부 본문 --}}
+
+@endsection
diff --git a/resources/views/web/policy/index.blade.php b/resources/views/web/policy/index.blade.php
new file mode 100644
index 0000000..8011a1b
--- /dev/null
+++ b/resources/views/web/policy/index.blade.php
@@ -0,0 +1,29 @@
+@php
+ $pageTitle = '이용약관';
+ $pageDesc = '서비스 이용 조건, 책임 범위, 분쟁 처리 기준 안내.';
+
+ $breadcrumbs = [
+ ['label' => '홈', 'url' => url('/')],
+ ['label' => '약관 및 정책', 'url' => url('/policy')],
+ ['label' => '이용약관', 'url' => url()->current()],
+ ];
+
+ $policyActive = 'terms';
+@endphp
+
+@extends('web.layouts.subpage')
+
+@section('title', '이용약관 | PIN FOR YOU')
+@section('meta_description', 'PIN FOR YOU 이용약관입니다. 서비스 이용 조건과 책임 범위, 분쟁 처리 기준을 안내합니다.')
+@section('canonical', url('/policy/terms'))
+
+@section('subcontent')
+
+ @include('web.partials.content-head', [
+ 'title' => '서비스 이용 규칙',
+ 'desc' => '회원 의무, 거래/결제, 환불, 제재 기준을 포함합니다.'
+ ])
+
+ {{-- TODO: 이용약관 본문 --}}
+
+@endsection
diff --git a/resources/views/web/policy/privacy/index.blade.php b/resources/views/web/policy/privacy/index.blade.php
new file mode 100644
index 0000000..278531e
--- /dev/null
+++ b/resources/views/web/policy/privacy/index.blade.php
@@ -0,0 +1,29 @@
+@php
+ $pageTitle = '개인정보처리방침';
+ $pageDesc = '개인정보 수집/이용/보관/파기 및 이용자 권리 안내.';
+
+ $breadcrumbs = [
+ ['label' => '홈', 'url' => url('/')],
+ ['label' => '약관 및 정책', 'url' => url('/policy')],
+ ['label' => '개인정보처리방침', 'url' => url()->current()],
+ ];
+
+ $policyActive = 'privacy';
+@endphp
+
+@extends('web.layouts.subpage')
+
+@section('title', '개인정보처리방침 | PIN FOR YOU')
+@section('meta_description', 'PIN FOR YOU 개인정보처리방침입니다. 개인정보 수집/이용/보관/파기 및 이용자 권리를 안내합니다.')
+@section('canonical', url('/policy/privacy'))
+
+@section('subcontent')
+
+ @include('web.partials.content-head', [
+ 'title' => '개인정보 처리 기준',
+ 'desc' => '수집 목적, 보관 기간, 제공/위탁, 이용자 권리 내용을 포함합니다.'
+ ])
+
+ {{-- TODO: 개인정보처리방침 본문 --}}
+
+@endsection
diff --git a/resources/views/web/policy/terms/index.blade.php b/resources/views/web/policy/terms/index.blade.php
new file mode 100644
index 0000000..278531e
--- /dev/null
+++ b/resources/views/web/policy/terms/index.blade.php
@@ -0,0 +1,29 @@
+@php
+ $pageTitle = '개인정보처리방침';
+ $pageDesc = '개인정보 수집/이용/보관/파기 및 이용자 권리 안내.';
+
+ $breadcrumbs = [
+ ['label' => '홈', 'url' => url('/')],
+ ['label' => '약관 및 정책', 'url' => url('/policy')],
+ ['label' => '개인정보처리방침', 'url' => url()->current()],
+ ];
+
+ $policyActive = 'privacy';
+@endphp
+
+@extends('web.layouts.subpage')
+
+@section('title', '개인정보처리방침 | PIN FOR YOU')
+@section('meta_description', 'PIN FOR YOU 개인정보처리방침입니다. 개인정보 수집/이용/보관/파기 및 이용자 권리를 안내합니다.')
+@section('canonical', url('/policy/privacy'))
+
+@section('subcontent')
+
+ @include('web.partials.content-head', [
+ 'title' => '개인정보 처리 기준',
+ 'desc' => '수집 목적, 보관 기간, 제공/위탁, 이용자 권리 내용을 포함합니다.'
+ ])
+
+ {{-- TODO: 개인정보처리방침 본문 --}}
+
+@endsection
diff --git a/routes/web.php b/routes/web.php
index 56b6833..ce54d58 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -7,4 +7,26 @@ Route::get('/', function () {
Route::view('/', 'web.home')->name('web.home');
+Route::prefix('cs')->name('web.cs.')->group(function () {
+ Route::view('/notice', 'web.cs.notice.index')->name('notice.index');
+ Route::view('/faq', 'web.cs.faq.index')->name('faq.index');
+ Route::view('/kakao', 'web.cs.kakao.index')->name('kakao.index');
+ Route::view('/qna', 'web.cs.qna.index')->name('qna.index');
+ Route::view('/guide', 'web.cs.guide.index')->name('guide.index');
+});
+
+Route::prefix('mypage')->name('web.mypage.')->group(function () {
+ Route::view('/info', 'web.mypage.info.index')->name('info.index');
+ Route::view('/usage', 'web.mypage.usage.index')->name('usage.index');
+ Route::view('/exchange', 'web.mypage.exchange.index')->name('exchange.index');
+ Route::view('/qna', 'web.mypage.qna.index')->name('qna.index');
+});
+
+Route::prefix('policy')->name('web.policy.')->group(function () {
+ Route::view('/', 'web.policy.index')->name('index');
+ Route::view('/privacy', 'web.policy.privacy.index')->name('privacy.index');
+ Route::view('/terms', 'web.policy.terms.index')->name('terms.index');
+ Route::view('/email', 'web.policy.email.index')->name('email.index');
+});
+
Route::fallback(fn () => abort(404));