JinyPost ํจํค์ง๋ ๊ด๋ฆฌ์ ์ธํฐํ์ด์ค์ ์ผ๊ด์ฑ๊ณผ ๊ฐ๋ฐ ํจ์จ์ฑ์ ์ํด ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ Blade ์ปดํฌ๋ํธ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด ๋ฌธ์๋ Claude๋ ๋ค๋ฅธ AI ๋๊ตฌ๊ฐ Blade ํ๋ฉด์ ๊ตฌํํ ๋ ์ฐธ๊ณ ํ ์ ์๋๋ก ์์ฑ๋์์ต๋๋ค.
1. x-switch
ํ ๊ธ ์ค์์น ์ปดํฌ๋ํธ๋ก boolean ์ค์ ๊ฐ์ ์ ๋ ฅ๋ฐ์ ๋ ์ฌ์ฉํฉ๋๋ค.
<x-switch name="enable_feature" :checked="true">
<strong>๊ธฐ๋ฅ ํ์ฑํ</strong>
<div class="text-muted small">์ด ๊ธฐ๋ฅ์ ํ์ฑํํฉ๋๋ค.</div>
</x-switch>์ซ์ ์ ๋ ฅ์ ์ํ ์ปดํฌ๋ํธ๋ก ๋ผ๋ฒจ, ์ ๋ ฅ ํ๋, ์ค๋ช ์ ํตํฉํฉ๋๋ค.
<x-input-number name="max_items" :value="10" :min="1" :max="100">
<strong>์ต๋ ์์ดํ
์</strong>
<div class="text-muted small">์ค์ ํ ์ ์๋ ์ต๋ ์์ดํ
๊ฐ์์
๋๋ค.</div>
</x-input-number>3. x-btn-save
ํผ ์ ์ฅ์ ์ํ ์ผ๊ด๋ ๋ฒํผ ์ปดํฌ๋ํธ์ ๋๋ค.
<x-btn-save>์ค์ ์ ์ฅ</x-btn-save>โ ์ฌ์ฉํด์ผ ํ ๋:
- Boolean ๊ฐ (true/false, enabled/disabled) ์ค์
- ๊ธฐ๋ฅ ํ์ฑํ/๋นํ์ฑํ ํ ๊ธ
- ์ ์ฑ ๋๋ ๊ถํ ์ค์
- ์ฌ์ฉ์ ํ๊ฒฝ์ค์
โ ์ฌ์ฉํ์ง ๋ง์์ผ ํ ๋:
- ๋ค์ค ์ ํ ์ต์ (๋ผ๋์ค ๋ฒํผ ๋๋ ์ ๋ ํธ ๋ฐ์ค ์ฌ์ฉ)
- ์ซ์๋ ํ ์คํธ ์ ๋ ฅ (x-input-number ๋๋ ๊ธฐ๋ณธ input ์ฌ์ฉ)
- ํ์ผ ์ ๋ก๋
โ ์ฌ์ฉํด์ผ ํ ๋:
- ์ซ์ ๊ฐ ์ ๋ ฅ (๊ฐ์, ํฌ๊ธฐ, ๊ธธ์ด ๋ฑ)
- ๋ฒ์๊ฐ ์ ํด์ง ์ค์ ๊ฐ
- ์ต์/์ต๋ ์ ํ์ด ์๋ ์ ๋ ฅ
- ๋จ์๊ฐ ์๋ ์ซ์ (MB, ์ด, ๊ฐ ๋ฑ)
โ ์ฌ์ฉํ์ง ๋ง์์ผ ํ ๋:
- Boolean ๊ฐ (x-switch ์ฌ์ฉ)
- ํ ์คํธ ์ ๋ ฅ (๊ธฐ๋ณธ input ์ฌ์ฉ)
- ๋ ์ง/์๊ฐ ์ ๋ ฅ (date/time input ์ฌ์ฉ)
- ๋งค์ฐ ํฐ ๋ฒ์์ ์ซ์ (๊ฒ์, ID ๋ฑ)
โ ์ฌ์ฉํด์ผ ํ ๋:
- ํผ ๋ฐ์ดํฐ ์ ์ฅ
- ์ค์ ์ ์ฅ
- ๋ฐ์ดํฐ ์ ๋ฐ์ดํธ
- ์ ๋ณด ์ ์ถ
โ ์ฌ์ฉํ์ง ๋ง์์ผ ํ ๋:
- ํ์ด์ง ์ด๋ (๋งํฌ ์ฌ์ฉ)
- ๋ฐ์ดํฐ ์ญ์ (๋ค๋ฅธ ์คํ์ผ์ ๋ฒํผ ์ฌ์ฉ)
- ๋ชจ๋ฌ ์ด๊ธฐ/๋ซ๊ธฐ
vendor/jiny/post/resources/views/components/
โโโ switch.blade.php
โโโ input-number.blade.php
โโโ btn-save.blade.php
์ปดํฌ๋ํธ๋ JinyPostServiceProvider์์ ๋ฑ๋ก๋ฉ๋๋ค:
// vendor/jiny/post/src/Providers/JinyPostServiceProvider.php
protected function loadBladeComponents(): void
{
Blade::component('jiny-post::components.switch', 'switch');
Blade::component('jiny-post::components.input-number', 'input-number');
Blade::component('jiny-post::components.btn-save', 'btn-save');
}- Primary: Bootstrap์ primary ์์ (ํ๋์)
- ํ ์คํธ: ๊ธฐ๋ณธ ๋คํฌ ์์, ์ค๋ช ์ muted ์์
- ๋ฐฐ๊ฒฝ: ์ฃผ๋ก ํฐ์, ์นด๋๋ ์ฐํ ํ์ ํ ๋๋ฆฌ
- ์ปดํฌ๋ํธ ๊ฐ๊ฒฉ:
mb-3(ํ๋จ ๋ง์ง) - ๋ฒํผ ์์ญ:
mb-4(ํ๋จ ๋ง์ง) - ์์ด์ฝ ๊ฐ๊ฒฉ:
me-1(์ฐ์ธก ๋ง์ง)
- ๋ผ๋ฒจ:
<strong>ํ๊ทธ๋ก ๊ตต๊ฒ - ์ค๋ช
:
text-muted smallํด๋์ค
@extends($layout ?? 'jiny-site::layouts.admin.sidebar')
@section('title', '์ค์ ๊ด๋ฆฌ')
@section('content')
<div class="container-fluid">
<!-- ํค๋ฉ -->
<div class="d-flex justify-content-between align-items-center my-3">
<div>
<h3><i class="bi bi-gear me-2 text-primary"></i>์ค์ ๊ด๋ฆฌ</h3>
<p class="text-muted mb-0">์์คํ
์ค์ ์ ๊ด๋ฆฌํฉ๋๋ค.</p>
</div>
</div>
<hr>
<div class="row">
<div class="col-lg-8">
<form method="POST" action="{{ route('admin.config.save') }}">
@csrf
<!-- ์ ์ฑ
์ค์ -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0">
<i class="bi bi-shield-check me-2 text-primary"></i>
์ ์ฑ
์ค์
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<x-switch name="admin_write" :checked="$config['policies']['admin_write']['enabled']">
<strong>๊ด๋ฆฌ์ ์์ฑ ํ์ฉ</strong>
<div class="text-muted small">์์คํ
๊ด๋ฆฌ์๊ฐ ๊ธ์ ์์ฑํ ์ ์์ต๋๋ค.</div>
</x-switch>
<x-switch name="user_write" :checked="$config['policies']['user_write']['enabled']">
<strong>์ผ๋ฐ ์ฌ์ฉ์ ์์ฑ ํ์ฉ</strong>
<div class="text-muted small">๋ก๊ทธ์ธํ ์ผ๋ฐ ์ฌ์ฉ์๊ฐ ๊ธ์ ์์ฑํ ์ ์์ต๋๋ค.</div>
</x-switch>
</div>
<div class="col-md-6">
<x-switch name="user_approval" :checked="$config['policies']['user_approval']['enabled']">
<strong>์ฌ์ฉ์ ๊ธ ์น์ธ ํ์</strong>
<div class="text-muted small">์ผ๋ฐ ์ฌ์ฉ์์ ๊ธ์ ๊ด๋ฆฌ์ ์น์ธ ํ ๋ฐํ๋ฉ๋๋ค.</div>
</x-switch>
</div>
</div>
</div>
</div>
<!-- ๊ธฐ๋ณธ ์ค์ -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0">
<i class="bi bi-gear me-2 text-primary"></i>
๊ธฐ๋ณธ ์ค์
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<x-input-number
name="max_images"
:value="$config['settings']['max_images']"
:min="1"
:max="50"
>
<strong>์ต๋ ์ด๋ฏธ์ง ์</strong>
<div class="text-muted small">๊ธ๋น ์
๋ก๋ํ ์ ์๋ ์ต๋ ์ด๋ฏธ์ง ์์
๋๋ค.</div>
</x-input-number>
</div>
<div class="col-md-6">
<x-switch name="enable_comments" :checked="$config['settings']['enable_comments']">
<strong>๋๊ธ ๊ธฐ๋ฅ ํ์ฑํ</strong>
<div class="text-muted small">๊ธ์ ๋๊ธ ๊ธฐ๋ฅ์ ํ์ฑํํฉ๋๋ค.</div>
</x-switch>
</div>
</div>
</div>
</div>
<!-- ์ ์ฅ ๋ฒํผ -->
<x-btn-save>์ค์ ์ ์ฅ</x-btn-save>
</form>
</div>
<!-- ์ฌ์ด๋๋ฐ ์ ๋ณด -->
<div class="col-lg-4">
<div class="card border-0 shadow-sm">
<div class="card-header bg-light border-bottom">
<h6 class="mb-0">
<i class="bi bi-info-circle me-2 text-info"></i>
์ค์ ์ ๋ณด
</h6>
</div>
<div class="card-body">
<div class="mb-3">
<small class="text-muted">๋ง์ง๋ง ์
๋ฐ์ดํธ</small>
<div class="fw-medium">{{ $config['updated_at'] ?? 'N/A' }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection- ์ผ๊ด์ฑ: ๊ฐ์ ๊ธฐ๋ฅ์๋ ๊ฐ์ ์ปดํฌ๋ํธ ์ฌ์ฉ
- ๋จ์์ฑ: ๋ณต์กํ ๋ก์ง์ ์ปดํฌ๋ํธ ๋ด๋ถ๊ฐ ์๋ ์ปจํธ๋กค๋ฌ์์ ์ฒ๋ฆฌ
- ์ฌ์ฌ์ฉ์ฑ: ํ๋ก์ ํธ ์ ๋ฐ์์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ๋๋ก ์ค๊ณ
- ์ปดํฌ๋ํธ: kebab-case ์ฌ์ฉ (
x-switch,x-btn-save) - ์์ฑ: camelCase ์ฌ์ฉ (
name,checked,hiddenValue) - ์ฌ๋กฏ: ์๋งจํฑํ HTML ๊ตฌ์กฐ ์ ์ง
- ๋ผ๋ฒจ๊ณผ input ์ฐ๊ฒฐ
- ํค๋ณด๋ ๋ค๋น๊ฒ์ด์ ์ง์
- ์คํฌ๋ฆฐ ๋ฆฌ๋ ํธํ์ฑ
<form method="POST" action="{{ route('admin.save') }}">
@csrf
<!-- ์ค์ ๊ทธ๋ฃน -->
<div class="card mb-4">
<div class="card-header">
<h5>์ค์ ๊ทธ๋ฃน๋ช
</h5>
</div>
<div class="card-body">
<!-- ์ปดํฌ๋ํธ๋ค -->
</div>
</div>
<!-- ์ ์ฅ ๋ฒํผ -->
<x-btn-save>์ ์ฅ</x-btn-save>
</form>@if($errors->any())
<div class="alert alert-danger">
<!-- ์๋ฌ ๋ฉ์์ง -->
</div>
@endif
@if(session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif<div class="row">
<div class="col-lg-8">
<!-- ๋ฉ์ธ ํผ -->
</div>
<div class="col-lg-4">
<!-- ์ฌ์ด๋๋ฐ ์ ๋ณด -->
</div>
</div>์ด ๋ฌธ์๋ JinyPost ํจํค์ง์ UX ์ปดํฌ๋ํธ๋ฅผ ํจ์จ์ ์ผ๋ก ํ์ฉํ๊ธฐ ์ํ ๊ฐ์ด๋์ ๋๋ค. ์๋ก์ด ์ปดํฌ๋ํธ๊ฐ ์ถ๊ฐ๋๊ฑฐ๋ ๊ธฐ์กด ์ปดํฌ๋ํธ๊ฐ ์ ๋ฐ์ดํธ๋ ๋๋ง๋ค ์ด ๋ฌธ์๋ ํจ๊ป ์ ๋ฐ์ดํธ๋ฉ๋๋ค.