<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>열역학 &#8211; MyEngNote</title>
	<atom:link href="https://myengnote.com/tag/%ec%97%b4%ec%97%ad%ed%95%99/feed/" rel="self" type="application/rss+xml" />
	<link>https://myengnote.com</link>
	<description></description>
	<lastBuildDate>Wed, 08 Jul 2026 04:43:12 +0000</lastBuildDate>
	<language>ko-KR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1</generator>
	<item>
		<title>냉각사이클 계산기 &#038; 시뮬레이터</title>
		<link>https://myengnote.com/refrigeration-cooling-cycle-cop-calculator/</link>
					<comments>https://myengnote.com/refrigeration-cooling-cycle-cop-calculator/#respond</comments>
		
		<dc:creator><![CDATA[동동]]></dc:creator>
		<pubDate>Tue, 23 Jun 2026 22:27:07 +0000</pubDate>
				<category><![CDATA[공학계산기]]></category>
		<category><![CDATA[COP]]></category>
		<category><![CDATA[P-h선도]]></category>
		<category><![CDATA[냉동사이클]]></category>
		<category><![CDATA[압축기]]></category>
		<category><![CDATA[열역학]]></category>
		<guid isPermaLink="false">https://myengnote.com/refrigeration-cooling-cycle-cop-calculator/</guid>

					<description><![CDATA[압축기 효율, 증발 온도 및 응축 온도를 실시간 입력받아 냉동 사이클의 4대 작동 상태를 시뮬레이션하고, 압축기 일량, 냉동 능력 및 성적계수(COP)를 압력-엔탈피 선도와 함께 렌더링하는 명품 시뮬레이터입니다.]]></description>
										<content:encoded><![CDATA[
<h2 style="font-size: 1.6em; font-weight: 800; color: #0c0e25; border-bottom: 2px solid #00f2fe; padding-bottom: 8px; margin-bottom: 20px;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 냉각사이클 계산기 &#038; 시뮬레이터</h2>


<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&#038;family=Outfit:wght@400;500;600;700;800&#038;display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
/* Scoped & Isolated Styles for coolingcycle-calculator-wrapper */
        /* Modern Reset and Design Tokens */
        .coolingcycle-calculator-wrapper *, .coolingcycle-calculator-wrapper *::before, .coolingcycle-calculator-wrapper *::after {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        .coolingcycle-calculator-wrapper {
            --color-bg-dark: #f8f9fd;
            --color-bg-deep: #ffffff;
            --color-panel-bg: rgba(255, 255, 255, 0.85);
            --color-border: rgba(0, 0, 0, 0.06);
            --color-border-hover: rgba(0, 0, 0, 0.12);
            --color-text-main: #1e293b;
            --color-text-muted: #475569;
            --color-text-dark: #94a3b8;
            --color-cyan: #0284c7;
            --color-cyan-glow: rgba(2, 132, 199, 0.15);
            --color-magenta: #db2777;
            --color-magenta-glow: rgba(219, 39, 119, 0.15);
            --color-purple: #7c3aed;
            --color-purple-glow: rgba(124, 58, 237, 0.12);
            --color-success: #10b981;
            --gradient-primary: linear-gradient(135deg, var(--color-cyan) 0%, var(--color-purple) 100%);
            --gradient-accent: linear-gradient(135deg, var(--color-magenta) 0%, var(--color-purple) 100%);
            --gradient-panel: linear-gradient(180deg, rgba(255, 255, 255, 0.9) 0%, rgba(248, 250, 252, 0.95) 100%);
            --font-heading: 'Outfit', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            --font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
            --shadow-neon-cyan: 0 0 15px var(--color-cyan-glow);
            --shadow-neon-magenta: 0 0 15px var(--color-magenta-glow);
            --shadow-card: 0 8px 32px 0 rgba(15, 23, 42, 0.05);
            --blur-glass: blur(16px);
        }
        .coolingcycle-calculator-wrapper {
            background-color: var(--color-bg-dark);
            color: var(--color-text-main);
            font-family: var(--font-body);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            overflow-x: hidden;
            position: relative;
        }
        .app-background-glow {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: -1;
            overflow: hidden;
            pointer-events: none;
        }
        .app-background-glow::before, 
        .app-background-glow::after {
            content: '';
            position: absolute;
            width: 600px;
            height: 600px;
            border-radius: 50%;
            filter: blur(140px);
            opacity: 0.12;
        }
        .app-background-glow::before {
            background: var(--color-cyan);
            top: -10%;
            right: -5%;
            animation: pulse-slow 15s infinite alternate;
        }
        .app-background-glow::after {
            background: var(--color-purple);
            bottom: -10%;
            left: -5%;
            animation: pulse-slow 20s infinite alternate-reverse;
        }
        @keyframes pulse-slow {
            0% { transform: scale(1) translate(0, 0); opacity: 0.1; }
            100% { transform: scale(1.18) translate(40px, 40px); opacity: 0.18; }
        }
        .app-container {
            width: 100%;
            max-width: 1440px;
            padding: 24px;
            display: flex;
            flex-direction: column;
            gap: 24px;
        }
        .app-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 20px 24px;
            background: var(--color-panel-bg);
            backdrop-filter: var(--blur-glass);
            border: 1px solid var(--color-border);
            border-radius: 16px;
            box-shadow: var(--shadow-card);
        }
        .logo-area {
            display: flex;
            align-items: center;
            gap: 16px;
        }
        .logo-icon {
            font-size: 32px;
            background: linear-gradient(135deg, var(--color-cyan), var(--color-magenta));
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .logo-area h1 {
            font-family: var(--font-heading);
            font-weight: 800;
            font-size: 24px;
            letter-spacing: 1.5px;
            background: linear-gradient(90deg, var(--color-text-main), var(--color-text-muted));
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }
        .logo-area .subtitle {
            font-size: 12px;
            color: var(--color-text-muted);
            font-weight: 500;
            letter-spacing: 0.5px;
        }
        .header-badge {
            display: flex;
            align-items: center;
            gap: 10px;
            background: rgba(16, 185, 129, 0.1);
            border: 1px solid rgba(16, 185, 129, 0.2);
            padding: 6px 14px;
            border-radius: 20px;
        }
        .pulse-dot {
            width: 8px;
            height: 8px;
            background-color: var(--color-success);
            border-radius: 50%;
            box-shadow: 0 0 10px var(--color-success);
            animation: pulse-dot-anim 1.5s infinite;
        }
        @keyframes pulse-dot-anim {
            0% { transform: scale(0.9); opacity: 0.6; }
            50% { transform: scale(1.2); opacity: 1; }
            100% { transform: scale(0.9); opacity: 0.6; }
        }
        .badge-text {
            font-size: 11px;
            font-weight: 600;
            color: var(--color-success);
            letter-spacing: 0.5px;
        }
        .app-main-grid {
            display: grid;
            grid-template-columns: 340px 1fr 340px;
            gap: 24px;
            align-items: start;
        }
        .panel {
            background: var(--gradient-panel);
            backdrop-filter: var(--blur-glass);
            border: 1px solid var(--color-border);
            border-radius: 20px;
            padding: 24px;
            box-shadow: var(--shadow-card);
            display: flex;
            flex-direction: column;
            gap: 16px;
            transition: border-color 0.3s ease, box-shadow 0.3s ease;
        }
        .panel:hover {
            border-color: var(--color-border-hover);
        }
        .panel-header {
            display: flex;
            align-items: center;
            gap: 12px;
            border-bottom: 1px solid var(--color-border);
            padding-bottom: 14px;
        }
        .panel-header i {
            font-size: 18px;
        }
        .panel-header h2 {
            font-family: var(--font-heading);
            font-size: 18px;
            font-weight: 600;
            letter-spacing: 0.5px;
        }
        .text-cyan { color: #0284c7; }
        .text-magenta { color: #db2777; }
        .text-purple { color: var(--color-purple); }
        .control-panel {
            grid-column: 1;
        }
        .input-group {
            display: flex;
            flex-direction: column;
            gap: 6px;
        }
        .input-label-row {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .input-label-row label {
            font-size: 12px;
            font-weight: 600;
            color: var(--color-text-main);
            display: flex;
            align-items: center;
            gap: 6px;
        }
        .range-helper {
            font-size: 9px;
            color: var(--color-text-muted);
            font-weight: 500;
        }
                .number-input-wrapper {
            display: flex;
            position: relative;
            border-radius: 8px;
            overflow: hidden;
            border: 1px solid var(--color-border);
            background: #ffffff;
            transition: all 0.2s ease;
        }
        .number-input-wrapper:focus-within {
            border-color: var(--color-cyan);
            box-shadow: 0 0 10px var(--color-cyan-glow);
        }
        .number-input-wrapper:focus-within {
            border-color: #0284c7;
            box-shadow: 0 0 10px var(--color-cyan-glow);
        }
        .custom-select {
            width: 100%;
            background: #f8fafc;
            border: 1px solid var(--color-border);
            outline: none;
            color: #0f172a;
            padding: 8px 12px;
            font-family: var(--font-body);
            font-size: 13px;
            font-weight: 600;
            border-radius: 8px;
            cursor: pointer;
        }
                .custom-number-input {
            flex: 1;
            width: 0;
            min-width: 0;
            background: #f8fafc !important;
            border: none !important;
            outline: none !important;
            color: #0f172a !important;
            padding: 10px 14px !important;
            font-family: var(--font-body) !important;
            font-size: 15px !important;
            font-weight: 700 !important;
            text-align: right !important;
            box-shadow: none !important;
            -webkit-appearance: none !important;
            -moz-appearance: textfield !important;
        }
        .custom-number-input::-webkit-outer-spin-button,
        .custom-number-input::-webkit-inner-spin-button {
            -webkit-appearance: none;
            margin: 0;
        }
                .unit-badge {
            background: rgba(0, 0, 0, 0.03);
            color: var(--color-text-muted);
            font-size: 11px;
            font-weight: 700;
            padding: 0 14px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-left: 1px solid var(--color-border);
            pointer-events: none;
            flex-shrink: 0;
        }
        .custom-slider {
            -webkit-appearance: none;
            width: 100%;
            height: 6px;
            border-radius: 3px;
            background: rgba(0, 0, 0, 0.05);
            outline: none;
            margin: 6px 0;
        }
        .custom-slider::-webkit-slider-thumb {
            -webkit-appearance: none;
            appearance: none;
            width: 18px;
            height: 18px;
            border-radius: 50%;
            cursor: pointer;
            background: var(--color-cyan);
            box-shadow: 0 0 10px var(--color-cyan);
        }
        .presets-section {
            border-top: 1px solid var(--color-border);
            padding-top: 14px;
            display: flex;
            flex-direction: column;
            gap: 10px;
        }
        .presets-section h3 {
            font-size: 12px;
            font-weight: 700;
            color: var(--color-text-main);
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .presets-grid {
            display: grid;
            grid-template-columns: 1fr;
            gap: 6px;
        }
        .preset-btn {
            background: rgba(0, 0, 0, 0.015);
            border: 1px solid var(--color-border);
            border-radius: 10px;
            padding: 8px 12px;
            cursor: pointer;
            color: var(--color-text-main);
            display: flex;
            align-items: center;
            gap: 12px;
            text-align: left;
            transition: all 0.2s ease;
        }
        .preset-btn:hover {
            background: rgba(0, 0, 0, 0.05);
            transform: translateX(4px);
        }
        .preset-btn.active {
            background: linear-gradient(90deg, var(--color-cyan-glow), var(--color-magenta-glow));
            border-color: #0284c7;
            box-shadow: 0 0 10px var(--color-cyan-glow);
        }
        .preset-icon {
            width: 28px;
            height: 28px;
            background: rgba(0, 0, 0, 0.02);
            border-radius: 8px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 12px;
            color: #0284c7;
        }
        .preset-btn:hover .preset-icon, .preset-btn.active .preset-icon {
            background: var(--gradient-primary);
            color: #fff;
        }
        .preset-name {
            font-size: 11px;
            font-weight: 600;
        }
        .simulation-panel {
            grid-column: 2;
            align-self: start;
        }
        .simulation-panel .panel-header {
            justify-content: space-between;
        }
        .canvas-wrapper {
            position: relative;
            width: 100%;
            background: radial-gradient(circle at center, #ffffff 0%, #f1f5f9 100%);
            border: 1px solid rgba(0, 0, 0, 0.06);
            border-radius: 16px;
            overflow: hidden;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        #physics-canvas {
            display: block;
            width: 100%;
            height: auto;
            aspect-ratio: 16 / 11;
        }
        .results-panel {
            grid-column: 3;
        }
        .ratio-readout-box {
            background: linear-gradient(135deg, rgba(219, 39, 119, 0.08) 0%, rgba(124, 58, 237, 0.03) 100%);
            border: 1px solid rgba(219, 39, 119, 0.25);
            border-radius: 16px;
            padding: 16px;
            text-align: center;
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 4px;
        }
        .ratio-title {
            font-size: 10px;
            font-weight: 700;
            color: #db2777;
            letter-spacing: 1px;
            text-transform: uppercase;
        }
        .ratio-value {
    font-family: var(--font-heading);
    font-weight: 800;
    font-size: 28px;
    background: linear-gradient(90deg, var(--color-text-main), var(--color-magenta));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.ratio-sub-txt {
    font-size: 11px;
    font-weight: 600;
    color: var(--color-text-muted);
    margin-top: 2px;
}
        .results-grid {
            display: flex;
            flex-direction: column;
            gap: 10px;
        }
        .result-card {
            background: rgba(255, 255, 255, 0.85);
            border: 1px solid var(--color-border);
            border-radius: 12px;
            padding: 10px 14px;
            display: flex;
            align-items: center;
            gap: 14px;
            transition: all 0.2s ease;
        }
        .result-card:hover {
            transform: translateY(-2px);
            border-color: rgba(219, 39, 119, 0.2);
            background: rgba(219, 39, 119, 0.03);
        }
        .card-icon {
            width: 34px;
            height: 34px;
            background: rgba(0, 0, 0, 0.015);
            border: 1px solid var(--color-border);
            border-radius: 8px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 13px;
            color: var(--color-text-muted);
        }
        .result-card:hover .card-icon {
            color: #db2777;
            border-color: rgba(219, 39, 119, 0.3);
            background: rgba(219, 39, 119, 0.1);
        }
        .card-content {
            display: flex;
            flex-direction: column;
            gap: 1px;
        }
        .card-unit {
            font-size: 9px;
            font-weight: 600;
            color: var(--color-text-muted);
            text-transform: uppercase;
        }
        .card-value {
            font-family: var(--font-heading);
            font-weight: 700;
            font-size: 14px;
            color: var(--color-text-main);
        }
        .formula-card {
            background: rgba(0, 0, 0, 0.01);
            border: 1px solid var(--color-border);
            border-radius: 12px;
            padding: 14px;
            display: flex;
            flex-direction: column;
            gap: 6px;
            font-size: 11px;
        }
        .formula-card h4 {
            font-weight: 700;
            color: var(--color-text-main);
        }
        .formula-equation {
            font-family: monospace;
            color: #0284c7;
            font-size: 12px;
            background: #f8fafc;
            padding: 5px 8px;
            border-radius: 6px;
            border: 1px solid var(--color-border);
            text-align: center;
        }
        @container cooling-container (max-width: 1100px) {
            .app-main-grid {
                grid-template-columns: 1fr 1fr;
                gap: 20px;
            }
            .control-panel {
                grid-column: 1;
            }
            .simulation-panel {
                grid-column: 2;
                align-self: start;
            }
            .results-panel {
                grid-column: 1 / span 2;
                display: grid;
                grid-template-columns: 1fr 1.2fr;
                gap: 20px;
            }
            .results-panel .panel-header {
                grid-column: 1 / span 2;
            }
            .ratio-readout-box {
                grid-column: 1;
                grid-row: 2;
            }
            .formula-card {
                grid-column: 1;
                grid-row: 3;
            }
            .results-grid {
                grid-column: 2;
                grid-row: 2 / span 2;
            }
        }
        @container cooling-container (max-width: 768px) {
            .app-main-grid {
                grid-template-columns: 1fr;
            }
            .control-panel, .simulation-panel, .results-panel {
                grid-column: 1;
            }
            .results-panel {
                display: flex;
                flex-direction: column;
                gap: 16px;
            }
            .ratio-readout-box, .formula-card, .results-grid {
                grid-column: auto;
                grid-row: auto;
            }
            .panel-header h2 {
                white-space: normal !important;
                font-size: 15px !important;
            }
            .app-header {
                flex-direction: column;
                gap: 16px;
                text-align: center;
            }
            .logo-area {
                flex-direction: column;
                gap: 8px;
            }
        }
        .preset-details {
            display: flex;
            flex-direction: column;
            gap: 2px;
            align-items: flex-start;
            text-align: left;
        }
        .preset-spec {
            font-size: 11px;
            color: var(--color-text-muted);
            font-weight: 500;
        }
        .preset-name {
            font-size: 13px !important;
        }
/* ━━ WordPress 레이아웃 Override: 디자인 1 (2열 컴팩트 대칭 레이아웃) ━━ */
.coolingcycle-calculator-wrapper .app-main-grid,
.coolingcycle-calculator-wrapper .main-grid,
.coolingcycle-calculator-wrapper .sim-grid {
    display: grid !important;
    grid-template-columns: 340px 1fr !important;
    gap: 24px !important;
    align-items: start !important;
}
/* 3열 레이아웃을 2열 레이아웃으로 변경하는 특화 스타일 */
.coolingcycle-calculator-wrapper .right-column {
    display: flex !important;
    flex-direction: column !important;
    gap: 24px !important;
    min-width: 0 !important;
    grid-column: 2 !important;
}
.coolingcycle-calculator-wrapper .simulation-panel,
.coolingcycle-calculator-wrapper .canvas-panel,
.coolingcycle-calculator-wrapper .sim-panel {
    grid-column: auto !important;
    order: 1 !important;
    align-self: stretch !important;
}
.coolingcycle-calculator-wrapper .control-panel {
    grid-column: 1 !important;
}
/* 2열 통합 결과 분석 영역 레이아웃 */
.coolingcycle-calculator-wrapper .simulation-results-section {
    display: grid !important;
    grid-template-columns: 1.1fr 1.3fr !important;
    gap: 20px !important;
    border-top: 1px solid var(--color-border) !important;
    padding-top: 20px !important;
    margin-top: 10px !important;
    align-items: stretch !important;
}
/* Readout Box 스타일 */
.coolingcycle-calculator-wrapper .simulation-results-section .ratio-readout-box,
.coolingcycle-calculator-wrapper .simulation-results-section .re-readout-box,
.coolingcycle-calculator-wrapper .simulation-results-section .status-readout-box,
.coolingcycle-calculator-wrapper .simulation-results-section .flow-readout-box,
.coolingcycle-calculator-wrapper .simulation-results-section [class*="readout-box"],
.coolingcycle-calculator-wrapper .simulation-results-section .gauge-container {
    grid-column: 1 !important;
    grid-row: 1 !important;
    margin: 0 !important;
    height: auto !important;
    display: flex !important;
    flex-direction: column !important;
    justify-content: center !important;
}
.coolingcycle-calculator-wrapper .simulation-results-section .results-grid {
    grid-column: 2 !important;
    grid-row: 1 / span 2 !important;
    display: flex !important;
    flex-direction: column !important;
    gap: 12px !important;
    justify-content: flex-start !important;
}
.coolingcycle-calculator-wrapper .simulation-results-section .results-grid .result-card {
    flex: none !important;
    display: flex !important;
    align-items: center !important;
    min-height: 72px !important;
    height: auto !important;
    padding: 12px 16px !important;
}
.coolingcycle-calculator-wrapper .simulation-results-section .formula-card {
    grid-column: 1 !important;
    grid-row: 2 !important;
}
/* 모바일/반응형 (800px 이하) ── 항상 세로형(1열) 정렬 및 시뮬레이터 캔버스 최상단 배치 */
@media (max-width: 800px) {
    .coolingcycle-calculator-wrapper .app-main-grid,
    .coolingcycle-calculator-wrapper .main-grid,
    .coolingcycle-calculator-wrapper .sim-grid {
        grid-template-columns: 1fr !important;
        display: flex !important;
        flex-direction: column !important;
    }
    .coolingcycle-calculator-wrapper .control-panel {
        order: 2 !important;
        width: 100% !important;
    }
    .coolingcycle-calculator-wrapper .right-column {
        order: 1 !important;
        width: 100% !important;
        display: flex !important;
        flex-direction: column !important;
    }
    .coolingcycle-calculator-wrapper .simulation-panel,
    .coolingcycle-calculator-wrapper .canvas-panel,
    .coolingcycle-calculator-wrapper .sim-panel,
    .coolingcycle-calculator-wrapper .canvas-section {
        order: -1 !important;
    }
    .coolingcycle-calculator-wrapper .simulation-results-section {
        grid-template-columns: 1fr !important;
    }
    .coolingcycle-calculator-wrapper .simulation-results-section .ratio-readout-box,
    .coolingcycle-calculator-wrapper .simulation-results-section .re-readout-box,
    .coolingcycle-calculator-wrapper .simulation-results-section .status-readout-box,
    .coolingcycle-calculator-wrapper .simulation-results-section .flow-readout-box,
    .coolingcycle-calculator-wrapper .simulation-results-section [class*="readout-box"],
    .coolingcycle-calculator-wrapper .simulation-results-section .gauge-container {
        grid-column: 1 !important;
        grid-row: auto !important;
        height: auto !important;
    }
    .coolingcycle-calculator-wrapper .simulation-results-section .results-grid {
        grid-column: 1 !important;
        grid-row: auto !important;
    }
    .coolingcycle-calculator-wrapper .simulation-results-section .formula-card {
        grid-column: 1 !important;
        grid-row: auto !important;
    }
}
.coolingcycle-calculator-wrapper .app-container,
.coolingcycle-calculator-wrapper .main-container {
    max-width: 100% !important;
    padding: 12px !important;
}
/* Premium Advice/Formula Card & Typography Overrides */
.coolingcycle-calculator-wrapper .simulation-results-section .formula-card,
.coolingcycle-calculator-wrapper .results-panel .formula-card {
    background: #ffffff !important;
    border: 1px solid var(--color-border) !important;
    border-radius: 12px !important;
    padding: 16px !important;
    box-shadow: var(--shadow-card) !important;
    transition: all 0.2s ease !important;
    display: flex !important;
    flex-direction: column !important;
    justify-content: center !important;
    gap: 8px !important;
}
.coolingcycle-calculator-wrapper .simulation-results-section .formula-card h4,
.coolingcycle-calculator-wrapper .results-panel .formula-card h4 {
    font-size: 14px !important;
    font-weight: 700 !important;
    color: var(--color-text-main) !important;
    margin-top: 0 !important;
    margin-bottom: 4px !important;
    word-break: keep-all !important;
    line-height: 1.4 !important;
    display: flex !important;
    align-items: center !important;
    gap: 8px !important;
}
.coolingcycle-calculator-wrapper .formula-equation {
    font-family: 'Outfit', 'Cambria Math', 'Times New Roman', monospace !important;
    white-space: nowrap !important;
    overflow-x: auto !important;
    word-break: keep-all !important;
    text-align: center !important;
}
.coolingcycle-calculator-wrapper #text-judgment {
    font-size: 12px !important;
    font-weight: 500 !important;
    color: var(--color-text-muted) !important;
    line-height: 1.6 !important;
    word-break: keep-all !important;
}
</style>
<div class="coolingcycle-calculator-wrapper" style="position: relative; width: 100%; box-sizing: border-box; overflow: hidden; margin: 30px auto; border-radius: 20px;">
    <div class="app-background-glow" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1; pointer-events: none; overflow: hidden;"></div>
    <div style="position: relative; z-index: 2; width: 100%;">
    <div class="app-container">
        <!-- Header -->
        <header class="app-header">
            <div class="logo-area">
                <div class="logo-icon"><i class="fa-solid fa-snowflake"></i></div>
                <div>
                    <h1>COOLING CYCLE</h1>
                    <div class="subtitle">냉동 사이클 성적계수 계산기 &#038; 실시간 2D P-h 선도 시뮬레이터</div>
                </div>
            </div>
            <div class="header-badge">
                <div class="pulse-dot"></div>
                <div class="badge-text">R-134a 열역학 물성치 연산중</div>
            </div>
        </header>
        <div class="app-main-grid">
            <!-- Left Column: Controls -->
            <div class="panel control-panel">
                <div class="panel-header">
                    <i class="fa-solid fa-sliders text-cyan"></i>
                    <h2>사이클 상태 인자 제어</h2>
                </div>
                <div class="input-group">
                    <div class="input-label-row">
                        <label><i class="fa-solid fa-temperature-low text-cyan"></i> 증발 온도 (Low Temp &#8211; T_L)</label>
                        <span class="range-helper">Min: -25°C / Max: 10°C</span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-tl" class="custom-number-input" value="-5" step="1" min="-25" max="10">
                        <span class="unit-badge">°C</span>
                    </div>
                    <input type="range" id="slider-tl" class="custom-slider" value="-5" min="-25" max="10" step="1">
                </div>
                <div class="input-group">
                    <div class="input-label-row">
                        <label><i class="fa-solid fa-temperature-high text-magenta"></i> 응축 온도 (High Temp &#8211; T_H)</label>
                        <span class="range-helper">Min: 25°C / Max: 60°C</span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-th" class="custom-number-input" value="40" step="1" min="25" max="60">
                        <span class="unit-badge">°C</span>
                    </div>
                    <input type="range" id="slider-th" class="custom-slider" value="40" min="25" max="60" step="1">
                </div>
                <div class="input-group">
                    <div class="input-label-row">
                        <label><i class="fa-solid fa-bolt-lightning text-cyan"></i> 압축기 등엔트로피 효율 (η_isen)</label>
                        <span class="range-helper">Min: 50% / Max: 95%</span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-eff" class="custom-number-input" value="75" step="1" min="50" max="95">
                        <span class="unit-badge">%</span>
                    </div>
                    <input type="range" id="slider-eff" class="custom-slider" value="75" min="50" max="95" step="1">
                </div>
                <div class="input-group">
                    <div class="input-label-row">
                        <label><i class="fa-solid fa-gauge-simple-high text-cyan"></i> 냉매 질량 유량 (m)</label>
                        <span class="range-helper">Min: 0.01 / Max: 0.30 kg/s</span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-flow" class="custom-number-input" value="0.05" step="0.01" min="0.01" max="0.30">
                        <span class="unit-badge">kg/s</span>
                    </div>
                    <input type="range" id="slider-flow" class="custom-slider" value="0.05" min="0.01" max="0.30" step="0.01">
                </div>
                <div class="presets-section">
                    <h3><i class="fa-solid fa-gears text-purple"></i> 대표 표준 동작 프리셋</h3>
                    <div class="presets-grid">
                        <button class="preset-btn" data-preset="ac">
                            <div class="preset-icon"><i class="fa-solid fa-wind"></i></div>
                            <div class="preset-details"><span class="preset-name">가정용 에어컨 표준 냉방</span><span class="preset-spec">AC</span></div>
                        </button>
                        <button class="preset-btn" data-preset="warehouse">
                            <div class="preset-icon"><i class="fa-solid fa-box-open"></i></div>
                            <div class="preset-details"><span class="preset-name">저온 상업 냉동 창고</span><span class="preset-spec">-20°C급</span></div>
                        </button>
                        <button class="preset-btn" data-preset="winter">
                            <div class="preset-icon"><i class="fa-solid fa-cloud-sun"></i></div>
                            <div class="preset-details"><span class="preset-name">동절기 초고효율 세팅</span><span class="preset-spec">COP 최적화</span></div>
                        </button>
                    </div>
                </div>
            </div>
            <!-- Auto Injected Right Column wrapper for Design 1 -->
            <div class="right-column">
                <div class="panel simulation-panel">
                                <div class="panel-header">
                                    <div>
                                        <i class="fa-solid fa-circle-nodes text-cyan"></i>
                                        <h2>4대 장치 기계 장치 루프 &#038; 실시간 압력-엔탈피(P-h) 선도</h2>
                                    </div>
                                </div>
                                <div class="canvas-wrapper">
                                    <canvas id="physics-canvas" width="640" height="440"></canvas>
                                </div>
                            <div class="simulation-results-section">
                                <div class="ratio-readout-box">
                                    <span class="ratio-title">COEFFICIENT OF PERFORMANCE</span>
                                    <span id="txt-cop" class="ratio-value">4.12 <span>(14.1 EER)</span></span>
                                    <span class="ratio-sub-txt">냉동 성적계수 (COP) 성능 지표</span>
                                </div>
                                <div class="results-grid">
                                    <div class="result-card">
                                        <div class="card-icon"><i class="fa-solid fa-snowflake text-cyan"></i></div>
                                        <div class="card-content">
                                            <div class="card-unit">실제 냉동 성능 (Q_L)</div>
                                            <div id="txt-ql" class="card-value">7.20 kW</div>
                                        </div>
                                    </div>
                                    <div class="result-card">
                                        <div class="card-icon"><i class="fa-solid fa-bolt text-magenta"></i></div>
                                        <div class="card-content">
                                            <div class="card-unit">압축기 소요 전력 (W_c)</div>
                                            <div id="txt-wc" class="card-value">1.75 kW</div>
                                        </div>
                                    </div>
                                    <div class="result-card">
                                        <div class="card-icon"><i class="fa-solid fa-fire text-orange-500"></i></div>
                                        <div class="card-content">
                                            <div class="card-unit">응축기 방출 열량 (Q_H)</div>
                                            <div id="txt-qh" class="card-value">8.95 kW</div>
                                        </div>
                                    </div>
                                    <div class="result-card">
                                        <div class="card-icon"><i class="fa-solid fa-compress-arrows-alt text-purple"></i></div>
                                        <div class="card-content">
                                            <div class="card-unit">증발기/응축기 압력비 (P_ratio)</div>
                                            <div id="txt-pratio" class="card-value">3.45</div>
                                        </div>
                                    </div>
                                </div>
                                <div class="formula-card">
                                    <h4><i class="fa-solid fa-circle-info text-cyan"></i> 냉동 성적계수 공식</h4>
                                    <div class="formula-equation">COP_R = Q_L / W_c = (h1 &#8211; h3) / (h2 &#8211; h1)</div>
                                </div>
                            </div>
                </div>
            </div>
        </div>
        <!-- Disclaimer Footer -->
        <footer class="app-disclaimer" style="margin-top: 20px; padding: 12px 16px; background: rgba(0, 0, 0, 0.015); border: 1px solid var(--color-border); border-radius: 12px; font-size: 11px; color: var(--color-text-muted); line-height: 1.5; text-align: left; display: flex; gap: 10px; align-items: flex-start; clear: both;">
            <i class="fa-solid fa-circle-info" style="color: var(--color-cyan); font-size: 14px; margin-top: 2px; flex-shrink: 0;"></i>
            <span><strong>면책 조항 (Disclaimer):</strong> 본 시뮬레이터의 계산 결과는 교육 및 참고용으로만 제공되며, 실제 제품 설계나 제작 시에는 반드시 최신 공학 규격 및 공식 표준 설계 기준을 재확인하시기 바랍니다. 계산 값의 무결성을 보장하지 않으며, 이로 인해 발생하는 직접적/간접적 손해에 대해 제작자 및 본 블로그는 어떠한 책임을 지지 않습니다.</span>
        </footer>
</div>
    <!-- JavaScript Core Simulator Engine -->
    </div>
</div>
<script>
        (function() {
            let isInit = false;
            function initSimulator() {
                if (isInit) return;
                const canvas = document.getElementById('physics-canvas');
                if (!canvas) return;
                const ctx = canvas.getContext('2d');
                if (!ctx) return;
                isInit = true;
                window.__coolingcycle_initialized = true;
                // DOM components
                const sliderTl = document.getElementById('slider-tl');
                const inputTl = document.getElementById('input-tl');
                const sliderTh = document.getElementById('slider-th');
                const inputTh = document.getElementById('input-th');
                const sliderEff = document.getElementById('slider-eff');
                const inputEff = document.getElementById('input-eff');
                const sliderFlow = document.getElementById('slider-flow');
                const inputFlow = document.getElementById('input-flow');
                const presetBtns = document.querySelectorAll('.preset-btn');
                // Output metrics
                const txtCop = document.getElementById('txt-cop');
                const txtQl = document.getElementById('txt-ql');
                const txtWc = document.getElementById('txt-wc');
                const txtQh = document.getElementById('txt-qh');
                const txtPratio = document.getElementById('txt-pratio');
                // Thermodynamic parameters for R-134a
                const statePoints = {
                    h1: 0,
                    h2: 0,
                    h3: 0,
                    h4: 0,
                    pLow: 0,
                    pHigh: 0
                };
                const state = {
                    tl: -5.0,
                    th: 40.0,
                    eff: 75.0,
                    flow: 0.05,
                    particles: []
                };
                // Smooth sync values with change-clamping only
                function syncTlFromSlider() {
                    state.tl = parseFloat(sliderTl.value);
                    inputTl.value = Math.round(state.tl);
                    validateTemperatures();
                    clearPresets();
                    updateCalculations();
                }
                function syncTlFromInput() {
                    let val = parseFloat(inputTl.value);
                    if (isNaN(val)) {
                        val = -5;
                    }
                    if (val < -25) {
                        val = -25;
                    }
                    if (val > 10) {
                        val = 10;
                    }
                    inputTl.value = Math.round(val);
                    sliderTl.value = val;
                    state.tl = val;
                    validateTemperatures();
                    clearPresets();
                    updateCalculations();
                }
                function syncThFromSlider() {
                    state.th = parseFloat(sliderTh.value);
                    inputTh.value = Math.round(state.th);
                    validateTemperatures();
                    clearPresets();
                    updateCalculations();
                }
                function syncThFromInput() {
                    let val = parseFloat(inputTh.value);
                    if (isNaN(val)) {
                        val = 40;
                    }
                    if (val < 25) {
                        val = 25;
                    }
                    if (val > 60) {
                        val = 60;
                    }
                    inputTh.value = Math.round(val);
                    sliderTh.value = val;
                    state.th = val;
                    validateTemperatures();
                    clearPresets();
                    updateCalculations();
                }
                function syncEffFromSlider() {
                    state.eff = parseFloat(sliderEff.value);
                    inputEff.value = Math.round(state.eff);
                    clearPresets();
                    updateCalculations();
                }
                function syncEffFromInput() {
                    let val = parseFloat(inputEff.value);
                    if (isNaN(val)) {
                        val = 75;
                    }
                    if (val < 50) {
                        val = 50;
                    }
                    if (val > 95) {
                        val = 95;
                    }
                    inputEff.value = Math.round(val);
                    sliderEff.value = val;
                    state.eff = val;
                    clearPresets();
                    updateCalculations();
                }
                function syncFlowFromSlider() {
                    state.flow = parseFloat(sliderFlow.value);
                    inputFlow.value = state.flow.toFixed(2);
                    clearPresets();
                    updateCalculations();
                }
                function syncFlowFromInput() {
                    let val = parseFloat(inputFlow.value);
                    if (isNaN(val)) {
                        val = 0.05;
                    }
                    if (val < 0.01) {
                        val = 0.01;
                    }
                    if (val > 0.30) {
                        val = 0.30;
                    }
                    inputFlow.value = val.toFixed(2);
                    sliderFlow.value = val;
                    state.flow = val;
                    clearPresets();
                    updateCalculations();
                }
                // Prevent temperature overlaps (condenser must be hotter than evaporator)
                function validateTemperatures() {
                    const minGap = 15.0; // 15°C margin
                    if (state.th < state.tl + minGap) {
                        state.th = state.tl + minGap;
                        sliderTh.value = Math.round(state.th);
                        inputTh.value = Math.round(state.th);
                    }
                }
                function loadPreset(key) {
                    clearPresets();
                    presetBtns.forEach(btn => {
                        if (btn.dataset.preset === key) {
                            btn.classList.add('active');
                        }
                    });
                    if (key === 'ac') {
                        state.tl = 5;
                        state.th = 45;
                        state.eff = 80;
                        state.flow = 0.08;
                    }
                    if (key === 'warehouse') {
                        state.tl = -20;
                        state.th = 40;
                        state.eff = 70;
                        state.flow = 0.04;
                    }
                    if (key === 'winter') {
                        state.tl = 0;
                        state.th = 25; // cold ambient outside
                        state.eff = 85;
                        state.flow = 0.06;
                    }
                    sliderTl.value = state.tl;
                    inputTl.value = Math.round(state.tl);
                    sliderTh.value = state.th;
                    inputTh.value = Math.round(state.th);
                    sliderEff.value = state.eff;
                    inputEff.value = Math.round(state.eff);
                    sliderFlow.value = state.flow;
                    inputFlow.value = state.flow.toFixed(2);
                    updateCalculations();
                }
                function clearPresets() {
                    presetBtns.forEach(btn => btn.classList.remove('active'));
                }
                // Cycle Calculations
                function updateCalculations() {
                    const T_L = state.tl;
                    const T_H = state.th;
                    // Enthalpy approximations for R-134a [kJ/kg]
                    // Sat vapor at TL (State 1)
                    const h1 = 398.0 + 0.9 * T_L;
                    // Sat liquid at TH (State 3)
                    const h3 = 200.0 + 1.45 * T_H;
                    // Expansion isenthalpic (State 4)
                    const h4 = h3;
                    // Isentropic work model: wc_isen increases with pressure/temp difference
                    const tDiff = T_H - T_L;
                    const wc_isen = tDiff * (1.1 + 0.008 * tDiff);
                    const efficiency = state.eff / 100.0;
                    const wc_actual = wc_isen / efficiency;
                    // Superheated vapor exit compressor (State 2)
                    const h2 = h1 + wc_actual;
                    // Evaporator cooling load (refrigerating effect)
                    const q_L = h1 - h4; // kJ/kg
                    const Q_L = state.flow * q_L; // kW
                    // Compressor Power
                    const W_c = state.flow * wc_actual; // kW
                    const Q_H = state.flow * (h2 - h3); // kW
                    // COP
                    const COP = Q_L / W_c;
                    // Saturated pressures estimate for pressure ratio [bar]
                    const pLow = 1.0 * Math.exp(0.04 * T_L + 1.0);
                    const pHigh = 1.0 * Math.exp(0.04 * T_H + 1.0);
                    const pRatio = pHigh / pLow;
                    // Save state point calculations
                    statePoints.h1 = h1;
                    statePoints.h2 = h2;
                    statePoints.h3 = h3;
                    statePoints.h4 = h4;
                    statePoints.pLow = pLow;
                    statePoints.pHigh = pHigh;
                    // Update UI elements
                    txtCop.innerHTML = `${COP.toFixed(2)} <span style="display: block; font-size: 0.75em; opacity: 0.85; margin-top: 4px; -webkit-text-fill-color: var(--color-text-muted); color: var(--color-text-muted); background: none; -webkit-background-clip: initial;">(${(COP * 3.41214).toFixed(1)} EER)</span>`;
                    txtQl.innerText = `${Q_L.toFixed(2)} kW`;
                    txtWc.innerText = `${W_c.toFixed(2)} kW`;
                    txtQh.innerText = `${Q_H.toFixed(2)} kW`;
                    txtPratio.innerText = `${pRatio.toFixed(2)} : 1`;
                }
                // Loop Particle visual stream
                class CycleStreamParticle {
                    constructor() {
                        this.reset();
                        this.x = Math.random() * 200 + 40;
                    }
                    reset() {
                        // Four legs layout coords centered at top-left:
                        // Top Condenser: Y=20
                        // Bottom Evaporator: Y=180
                        // Left Expansion: X=50
                        // Right Compressor: X=210
                        this.segment = Math.floor(Math.random() * 4);
                        if (this.segment === 0) {
                            this.x = 50 + Math.random() * 160;
                            this.y = 180;
                        }
                        if (this.segment === 1) {
                            this.x = 210;
                            this.y = 20 + Math.random() * 160;
                        }
                        if (this.segment === 2) {
                            this.x = 50 + Math.random() * 160;
                            this.y = 20;
                        }
                        if (this.segment === 3) {
                            this.x = 50;
                            this.y = 20 + Math.random() * 160;
                        }
                        this.size = Math.random() * 2.5 + 1.2;
                    }
                    update() {
                        const speed = 1.6;
                        // Bottom Leg (Evaporator): left to right
                        if (this.segment === 0) {
                            this.x += speed * 0.8;
                            if (this.x >= 210) {
                                this.segment = 1;
                                this.x = 210;
                            }
                        }
                        // Right Leg (Compressor): bottom to top
                        if (this.segment === 1) {
                            this.y -= speed * 1.5; // moves faster (hot compressed gas)
                            if (this.y <= 20) {
                                this.segment = 2;
                                this.y = 20;
                            }
                        }
                        // Top Leg (Condenser): right to left
                        if (this.segment === 2) {
                            this.x -= speed * 1.0;
                            if (this.x <= 50) {
                                this.segment = 3;
                                this.x = 50;
                            }
                        }
                        // Left Leg (Expansion Valve): top to bottom
                        if (this.segment === 3) {
                            this.y += speed * 0.6;
                            if (this.y >= 180) {
                                this.segment = 0;
                                this.y = 180;
                            }
                        }
                    }
                    draw(c) {
                        c.save();
                        // Color styling based on thermodynamic states passing through physical components
                        if (this.segment === 0) {
                            // Evaporator leg: cold blue mixture
                            c.fillStyle = '#38bdf8';
                        }
                        else if (this.segment === 1) {
                            // Compressor leg: compression happens inside the compressor (Y = 140 to 60)
                            if (this.y > 140) {
                                c.fillStyle = '#38bdf8'; // Blue vapor inlet
                            } else if (this.y < 60) {
                                c.fillStyle = '#ef4444'; // Red hot gas outlet
                            } else {
                                const progress = (140 - this.y) / 80;
                                const r = Math.round(56 + progress * 180);
                                const g = Math.round(189 - progress * 130);
                                const b = Math.round(248 - progress * 180);
                                c.fillStyle = `rgb(${r},${g},${b})`;
                            }
                        }
                        else if (this.segment === 2) {
                            // Condenser leg: condensation happens inside the condenser (X = 170 to 90)
                            if (this.x > 170) {
                                c.fillStyle = '#ef4444'; // Red superheated vapor inlet
                            } else if (this.x < 90) {
                                c.fillStyle = '#f97316'; // Orange saturated liquid outlet
                            } else {
                                const progress = (170 - this.x) / 80;
                                const r = Math.round(239 - progress * 20);
                                const g = Math.round(68 + progress * 60);
                                const b = Math.round(68 + progress * 10);
                                c.fillStyle = `rgb(${r},${g},${b})`;
                            }
                        }
                        else if (this.segment === 3) {
                            // Expansion leg: flashing expansion happens at the center of the valve (Y = 100)
                            if (this.y < 100) {
                                c.fillStyle = '#f97316'; // Orange liquid inlet
                            } else {
                                c.fillStyle = '#38bdf8'; // Blue low-pressure wet mixture outlet
                            }
                        }
                        c.beginPath();
                        c.arc(this.x, this.y, this.size, 0, Math.PI * 2);
                        c.fill();
                        c.restore();
                    }
                }
                // Populate loop flow streams
                function setupStreams() {
                    state.particles = [];
                    for (let i = 0; i < 65; i++) {
                        state.particles.push(new CycleStreamParticle());
                    }
                }
                // Render main sequence loop
                function animate(timestamp) {
                    requestAnimationFrame(animate);
                    const width = canvas.width;
                    const height = canvas.height;
                    if (state.particles.length === 0) {
                        setupStreams();
                    }
                    ctx.clearRect(0, 0, width, height);
                    // Blueprint grid
                    ctx.save();
                    ctx.strokeStyle = 'rgba(2, 132, 199, 0.03)';
                    ctx.lineWidth = 1;
                    for (let x = 0; x < width; x += 20) {
                        ctx.beginPath();
                        ctx.moveTo(x, 0);
                        ctx.lineTo(x, height);
                        ctx.stroke();
                    }
                    for (let y = 0; y < height; y += 20) {
                        ctx.beginPath();
                        ctx.moveTo(0, y);
                        ctx.lineTo(width, y);
                        ctx.stroke();
                    }
                    ctx.restore();
                    // 1. Draw Loop Components Diagram (Left half of canvas, Y=20~180)
                    ctx.save();
                    ctx.strokeStyle = '#94a3b8';
                    ctx.lineWidth = 6;
                    ctx.lineJoin = 'round';
                    ctx.beginPath();
                    // Top pipe segments (Condenser is at X=80~180, Y=20)
                    ctx.moveTo(50, 20);
                    ctx.lineTo(80, 20);
                    ctx.moveTo(180, 20);
                    ctx.lineTo(210, 20);
                    // Bottom pipe segments (Evaporator is at X=80~180, Y=180)
                    ctx.moveTo(50, 180);
                    ctx.lineTo(80, 180);
                    ctx.moveTo(180, 180);
                    ctx.lineTo(210, 180);
                    // Left pipe segments (Expansion Valve is at X=50, Y=80~120)
                    ctx.moveTo(50, 20);
                    ctx.lineTo(50, 80);
                    ctx.moveTo(50, 120);
                    ctx.lineTo(50, 180);
                    // Right pipe segments (Compressor is at X=210, Y=60~140)
                    ctx.moveTo(210, 20);
                    ctx.lineTo(210, 60);
                    ctx.moveTo(210, 140);
                    ctx.lineTo(210, 180);
                    ctx.stroke();
                    ctx.restore();
                    // Render streams inside pipes
                    state.particles.forEach(p => {
                        p.update();
                        p.draw(ctx);
                    });
                    // Draw mechanical device boxes
                    // Condenser (Top side, centered at X=130, Y=20)
                    ctx.save();
                    ctx.fillStyle = '#fee2e2';
                    ctx.strokeStyle = '#ef4444';
                    ctx.lineWidth = 1.5;
                    ctx.fillRect(80, 5, 100, 30);
                    ctx.strokeRect(80, 5, 100, 30);
                    ctx.fillStyle = '#ef4444';
                    ctx.font = 'bold 9.5px sans-serif';
                    ctx.textAlign = 'center';
                    ctx.textBaseline = 'middle';
                    ctx.fillText('응축기 (Condenser)', 130, 20);
                    ctx.restore();
                    // Compressor (Right side, vertical box, centered at X=210, Y=100)
                    ctx.save();
                    ctx.fillStyle = '#f3e8ff';
                    ctx.strokeStyle = '#a855f7';
                    ctx.lineWidth = 1.5;
                    ctx.fillRect(196, 60, 28, 80);
                    ctx.strokeRect(196, 60, 28, 80);
                    ctx.fillStyle = '#a855f7';
                    ctx.font = 'bold 9.5px sans-serif';
                    ctx.textAlign = 'center';
                    ctx.textBaseline = 'middle';
                    ctx.translate(210, 100);
                    ctx.rotate(Math.PI / 2);
                    ctx.fillText('압축기 (Comp)', 0, 0);
                    ctx.restore();
                    // Evaporator (Bottom, centered at X=130, Y=180)
                    ctx.save();
                    ctx.fillStyle = 'rgba(255, 255, 255, 0.95)';
                    ctx.strokeStyle = '#38bdf8';
                    ctx.lineWidth = 1.5;
                    ctx.fillRect(80, 165, 100, 30);
                    ctx.strokeRect(80, 165, 100, 30);
                    ctx.fillStyle = '#0284c7';
                    ctx.font = 'bold 9.5px sans-serif';
                    ctx.textAlign = 'center';
                    ctx.textBaseline = 'middle';
                    ctx.fillText('증발기 (Evaporator)', 130, 180);
                    ctx.restore();
                    // Expansion Valve (Left, centered at X=50, Y=100)
                    ctx.save();
                    ctx.fillStyle = 'rgba(255, 255, 255, 0.95)';
                    ctx.strokeStyle = '#fb923c';
                    ctx.lineWidth = 1.5;
                    ctx.fillRect(32, 80, 36, 40);
                    ctx.strokeRect(32, 80, 36, 40);
                    ctx.fillStyle = '#ea580c';
                    ctx.font = 'bold 9px sans-serif';
                    ctx.textAlign = 'center';
                    ctx.textBaseline = 'middle';
                    ctx.fillText('팽창밸브', 50, 100);
                    ctx.restore();
                    // Draw Legend Box (Top Right, X=260~620, Y=20~170)
                    ctx.save();
                    ctx.fillStyle = 'rgba(255, 255, 255, 0.95)';
                    ctx.strokeStyle = '#cbd5e1';
                    ctx.lineWidth = 1;
                    ctx.strokeRect(260, 20, 360, 150);
                    ctx.fillRect(260, 20, 360, 150);
                    ctx.fillStyle = '#0f172a';
                    ctx.font = 'bold 13px sans-serif';
                    ctx.textAlign = 'left';
                    ctx.textBaseline = 'alphabetic';
                    ctx.fillText('상태 포인트 범례 (State Points)', 272, 38);
                    ctx.font = '11px sans-serif';
                    ctx.fillStyle = '#1e293b';
                    ctx.fillText('1 : 압축기 입구 (저압 포화기체) - 증발 완료 후 압축기 흡입 상태', 272, 60);
                    ctx.fillText('2 : 압축기 출구 (고압 과열증기) - 압축기 토출 후 온·압력 상승 상태', 272, 84);
                    ctx.fillText('3 : 응축기 출구 (고압 포화액체) - 응축 방열 후 상변화 완료 상태', 272, 108);
                    ctx.fillText('4 : 팽창 완료 (기액 혼합 상태) - 교축 팽창 후 저압 냉습증기 상태', 272, 132);
                    ctx.fillStyle = '#0284c7';
                    ctx.font = 'bold 10.5px sans-serif';
                    ctx.fillText('* 파란색: 저온 유체  |  빨간색: 고온 기체  |  주황색: 액체 냉매', 272, 156);
                    ctx.restore();
                    // 2. Draw Thermodynamic P-h Diagram (Bottom portion of canvas)
                    const pX = 80;
                    const pY = height - 60;
                    const pW = width - 140;
                    const pH = 140;
                    // Draw gridlines first so they sit behind the curves
                    ctx.save();
                    ctx.lineWidth = 0.8;
                    // Enthalpy gridlines
                    const xTicks = [200, 300, 400, 500, 600, 700];
                    xTicks.forEach(h => {
                        const x = mapHToChartX(h);
                        ctx.beginPath();
                        ctx.strokeStyle = 'rgba(226, 232, 240, 0.5)';
                        ctx.moveTo(x, pY);
                        ctx.lineTo(x, pY - pH);
                        ctx.stroke();
                    });
                    // Pressure gridlines (logarithmic spacing)
                    const yTicks = [1, 2, 5, 10, 20, 30];
                    yTicks.forEach(p => {
                        const y = mapPToChartY(p);
                        ctx.beginPath();
                        ctx.strokeStyle = 'rgba(226, 232, 240, 0.5)';
                        ctx.moveTo(pX, y);
                        ctx.lineTo(pX + pW, y);
                        ctx.stroke();
                    });
                    ctx.restore();
                    // Draw Main Axes
                    ctx.save();
                    ctx.strokeStyle = '#cbd5e1';
                    ctx.lineWidth = 1.5;
                    ctx.beginPath();
                    ctx.moveTo(pX, pY);
                    ctx.lineTo(pX + pW, pY);
                    ctx.moveTo(pX, pY);
                    ctx.lineTo(pX, pY - pH);
                    ctx.stroke();
                    // Draw ticks and labels
                    ctx.fillStyle = '#64748b';
                    ctx.font = '8.5px sans-serif';
                    xTicks.forEach(h => {
                        const x = mapHToChartX(h);
                        ctx.beginPath();
                        ctx.moveTo(x, pY);
                        ctx.lineTo(x, pY + 4);
                        ctx.strokeStyle = '#cbd5e1';
                        ctx.stroke();
                        ctx.textAlign = 'center';
                        ctx.fillText(h.toString(), x, pY + 14);
                    });
                    yTicks.forEach(p => {
                        const y = mapPToChartY(p);
                        ctx.beginPath();
                        ctx.moveTo(pX, y);
                        ctx.lineTo(pX - 4, y);
                        ctx.strokeStyle = '#cbd5e1';
                        ctx.stroke();
                        ctx.textAlign = 'right';
                        ctx.fillText(p.toString(), pX - 8, y + 3);
                    });
                    ctx.restore();
                    // Axis Title Labels
                    ctx.fillStyle = '#475569';
                    ctx.font = 'bold 9.5px Outfit';
                    ctx.fillText('엔탈피 (h, kJ/kg)', pX + pW - 100, pY + 28);
                    ctx.save();
                    ctx.translate(pX - 28, pY - pH + 30);
                    ctx.rotate(-Math.PI / 2);
                    ctx.fillText('압력 (P, bar)', 0, 0);
                    ctx.restore();
                    // Draw thermodynamic Saturation Bell Dome
                    ctx.strokeStyle = 'rgba(148, 163, 184, 0.5)';
                    ctx.lineWidth = 1.5;
                    ctx.beginPath();
                    // Saturation dome coordinate drawing scaled for hMax = 700 (aligned with R-134a h1 and h3 thermodynamic bounds)
                    const domeTopX = pX + pW * 0.22;
                    const domeTopY = pY - pH * 0.85;
                    ctx.moveTo(pX + pW * 0.08, pY);
                    // Bezier interpolation representing saturation dome boundary
                    ctx.bezierCurveTo(
                        pX + pW * 0.12, pY - pH * 0.72,
                        domeTopX - 15, domeTopY,
                        domeTopX, domeTopY
                    );
                    ctx.bezierCurveTo(
                        domeTopX + 15, domeTopY,
                        pX + pW * 0.38, pY - pH * 0.4,
                        pX + pW * 0.45, pY
                    );
                    ctx.stroke();
                    ctx.restore();
                    // Map refrigeration coordinates onto P-h Chart Space
                    // Low enthalpy scale around 150 to 500 kJ/kg
                    // Low pressure scale around 1 to 25 bar
                    function mapHToChartX(h) {
                        const hMin = 180;
                        const hMax = 700;
                        const ratio = (h - hMin) / (hMax - hMin);
                        return pX + ratio * pW;
                    }
                    function mapPToChartY(p) {
                        // Log scale plotting
                        const pMin = Math.log(0.8);
                        const pMax = Math.log(30);
                        const ratio = (Math.log(p) - pMin) / (pMax - pMin);
                        return pY - ratio * pH;
                    }
                    const pt1X = mapHToChartX(statePoints.h1);
                    const pt1Y = mapPToChartY(statePoints.pLow);
                    const pt2X = mapHToChartX(statePoints.h2);
                    const pt2Y = mapPToChartY(statePoints.pHigh);
                    const pt3X = mapHToChartX(statePoints.h3);
                    const pt3Y = mapPToChartY(statePoints.pHigh);
                    const pt4X = mapHToChartX(statePoints.h4);
                    const pt4Y = mapPToChartY(statePoints.pLow);
                    // Draw Closed Loop of Refrigeration Cycle
                    ctx.save();
                    ctx.strokeStyle = '#db2777';
                    ctx.lineWidth = 3;
                    ctx.lineJoin = 'round';
                    ctx.beginPath();
                    ctx.moveTo(pt1X, pt1Y);
                    ctx.lineTo(pt2X, pt2Y); // Compression (non-isentropic diagonal)
                    ctx.lineTo(pt3X, pt3Y); // Condenser isobaric cooling
                    ctx.lineTo(pt4X, pt4Y); // Throttling (vertical straight down)
                    ctx.closePath();        // Evaporator isobaric heating
                    ctx.stroke();
                    // Draw circles at state points
                    const pts = [
                        { x: pt1X, y: pt1Y, label: '1', col: '#0284c7' },
                        { x: pt2X, y: pt2Y, label: '2', col: '#ef4444' },
                        { x: pt3X, y: pt3Y, label: '3', col: '#f97316' },
                        { x: pt4X, y: pt4Y, label: '4', col: '#84cc16' }
                    ];
                    pts.forEach(pt => {
                        ctx.beginPath();
                        ctx.arc(pt.x, pt.y, 4, 0, Math.PI * 2);
                        ctx.fillStyle = '#ffffff';
                        ctx.fill();
                        ctx.strokeStyle = pt.col;
                        ctx.lineWidth = 2;
                        ctx.stroke();
                        ctx.fillStyle = '#0f172a';
                        ctx.font = 'bold 8.5px sans-serif';
                        ctx.fillText(pt.label, pt.x + 6, pt.y - 4);
                    });
                    ctx.restore();
                }
                // Event Listeners Mapping
                sliderTl.addEventListener('input', syncTlFromSlider);
                inputTl.addEventListener('change', syncTlFromInput);
                sliderTh.addEventListener('input', syncThFromSlider);
                inputTh.addEventListener('change', syncThFromInput);
                sliderEff.addEventListener('input', syncEffFromSlider);
                inputEff.addEventListener('change', syncEffFromInput);
                sliderFlow.addEventListener('input', syncFlowFromSlider);
                inputFlow.addEventListener('change', syncFlowFromInput);
                presetBtns.forEach(btn => {
                    btn.addEventListener('click', function() {
                        loadPreset(btn.dataset.preset);
                    });
                });
                // Load initial
                loadPreset('ac');
                requestAnimationFrame(animate);
                // Anti-copying protection
                document.addEventListener('contextmenu', function(e) {
                    e.preventDefault();
                    alert("이 시뮬레이터 프로그램의 지식재산권은 보호받고 있습니다.");
                    return false;
                }, { capture: true });
                document.addEventListener('selectstart', function(e) {
                    e.preventDefault();
                    return false;
                }, { capture: true });
            }
            // Retry loader sequence
            let loadAttempts = 0;
            function tryLoad() {
                loadAttempts++;
                initSimulator();
                if (!window.__coolingcycle_initialized) {
                    if (loadAttempts < 50) {
                        setTimeout(tryLoad, 100);
                    }
                }
            }
            if (document.readyState === 'complete' || document.readyState === 'interactive') {
                tryLoad();
            } else {
                document.addEventListener('DOMContentLoaded', tryLoad);
                window.addEventListener('load', tryLoad);
            }
        })();
</script>


<div style="background: linear-gradient(135deg, rgba(0,242,254,0.03), rgba(138,43,226,0.03)); border: 1px solid rgba(0,242,254,0.15); border-radius: 12px; padding: 18px 24px; margin: 25px auto 35px auto; font-size: 0.95em; color: #4b5563; line-height: 1.7; font-family: sans-serif;">
    <strong style="color: #1f2937; font-size: 1.05em; display: flex; align-items: center; gap: 8px;">
        <span style="font-size: 1.2em;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /></span> 간편 사용 설명서
    </strong>
    <ol style="margin: 10px 0 0 0; padding-left: 20px;">
        <li style="margin-bottom: 6px;"><strong>경계 온도 조건 제어: 증발 온(TL)과 응축 온(TH) 슬라이더를 조정하여 사이클의 온도 한계를 설정합니다.</strong></li>
<li style="margin-bottom: 6px;">장치 효율 및 냉매 유량 제어: 압축기의 등엔트로피 효율(η)과 냉매 순환 유량(m)을 조절하여 실제 전력 소비량과 냉동 용량을 확인합니다.</li>
<li style="margin-bottom: 6px;">P-h 선도 실시간 분석: 압력-엔탈피(P-h) 상태도 위에 그려진 4대 거점 사이클 선형 루프가 온도 변화에 따라 수축 팽창하는 과정을 관찰합니다.</li>
<li style="margin-bottom: 6px;">성적계수(COP) 및 전력 판독: 실시간 계측 모니터에서 총 소요 동력(kW)과 시스템 COP 변화를 모니터링하여 에너지 효율을 극대화하는 설계를 도출합니다.</li>
    </ol>
</div>


<details class="premium-seo-accordion" style="border: 1px solid rgba(0,0,0,0.08); border-radius: 12px; background: #fbfbfc; padding: 0; margin: 30px auto; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.01); font-family: sans-serif;">
    <summary style="display: flex; justify-content: space-between; align-items: center; padding: 20px 24px; font-size: 1.1em; font-weight: 700; color: #1f2937; cursor: pointer; user-select: none; outline: none; list-style: none;">
        <span><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4da.png" alt="📚" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 증기압축 냉동사이클 이론 및 COP 계산 해설 보기</span>
        <span class="accordion-arrow" style="font-size: 0.9em; color: #9ca3af; transition: transform 0.2s ease;">▼</span>
    </summary>
    <div style="padding: 0 24px 24px 24px; border-top: 1px solid rgba(0,0,0,0.04); background: #ffffff; border-radius: 0 0 12px 12px; font-size: 0.98em; color: #374151; line-height: 1.8;">
        <div style="margin-top: 20px;">
            <h3>1. 증기압축 냉동 사이클 (Vapor-compression Refrigeration Cycle)</h3>
<p>현대 에어컨과 냉장고의 핵심 기반이 되는 증기압축식 냉동 사이클은 저온의 열원으로부터 열을 흡수하여 고온의 열원으로 방출하는 열역학적 펌프 역할을 수행합니다. 사이클은 물리적으로 분리된 4개의 주요 장치로 구성됩니다.</p><ul><li><strong>압축기 (Compressor):</strong> 증발기를 거쳐 나온 저압 포화 증기 냉매를 흡입하여 고압 초임계 상태로 단열 압축합니다 (동력 투입).</li><li><strong>응축기 (Condenser):</strong> 고온 고압의 가스 냉매가 외부로 열을 방출하며 액체 상태로 포화 응축됩니다.</li><li><strong>팽창 밸브 (Expansion Valve):</strong> 교축 과정(Throttling, 등엔탈피 h1=h2)을 거치며 냉매의 압력과 온도를 급격히 하강시켜 습증기 상태로 만듭니다.</li><li><strong>증발기 (Evaporator):</strong> 저온 저압의 냉매가 피냉각 물체로부터 열을 흡수(냉각 작용)하여 증발 기화합니다.</li></ul>
<h3>2. 냉동기 성능 지수(COP) 및 사이클 엔탈피 계산 공식</h3>
<p>에어컨과 열펌프의 성능은 단순 열효율 대신 투입 전력 대비 얻은 냉동 능력을 뜻하는 **성적계수(COP, Coefficient of Performance)**로 정의합니다.</p><p><strong>① 냉동 사이클 상태별 에너지 해석:</strong></p><ul><li>압축기 소요 일량: <code>wc = h2 - h1</code> &nbsp;[kJ/kg]</li><li>증발기 흡수 열량 (단위 냉동 효과): <code>ql = h1 - h4 = h1 - h3</code> &nbsp;[kJ/kg]</li><li>응축기 방출 열량: <code>qh = h2 - h3</code> &nbsp;[kJ/kg]</li></ul><p><strong>② 냉동 능력 (Cooling Capacity, Ql) 및 소요 동력 (Wc):</strong></p><p style="text-align: center; font-weight: bold; background: #f3f4f6; padding: 12px; border-radius: 8px;">Ql = m × ql &nbsp;[kW], &nbsp; Wc = m × wc &nbsp;[kW]</p><p><strong>③ 냉동기 성적계수 (COP_R):</strong></p><p style="text-align: center; font-weight: bold; background: #e0f2fe; padding: 16px; border-radius: 8px; font-size: 1.05em; color: #0369a1;">COP_R = Ql / Wc = ql / wc = (h1 - h3) / (h2 - h1)</p><p>증발 온도가 높을수록, 응축 온도가 낮을수록 사이클 내부 면적(압축기 소요 전력)이 감소하여 COP가 획기적으로 상승합니다. 이는 고온 다습한 실외 환경이나 실내 극저온 셋팅 시 전기료가 급상승하는 물리적 배경을 설명합니다.</p>
<h3>3. 냉매(Refrigerant)와 P-h 선도의 시각적 이해</h3>
<p>압력-엔탈피(P-h) 선도는 종축에 압력(Log P), 횡축에 엔탈피(h)를 배치한 열역학 차트입니다. 한가운데 종 모양의 임계 돔(Saturation Dome)이 존재하며, 돔의 왼쪽 실선은 포화 액선, 오른쪽 실선은 포화 증기선입니다. 냉동 사이클은 이 돔의 하단과 상단을 종횡으로 누비며 열교환을 수행합니다. R-134a와 같은 친환경 대체 냉매는 높은 잠열량과 우수한 비체적 특징을 가집니다.</p>
        </div>
    </div>
</details>
<style>
details.premium-seo-accordion[open] summary .accordion-arrow { transform: rotate(180deg); color: #00f2fe; }
details.premium-seo-accordion summary::-webkit-details-marker { display: none; }
details.premium-seo-accordion:hover { border-color: rgba(0,242,254,0.3); }
</style>

]]></content:encoded>
					
					<wfw:commentRss>https://myengnote.com/refrigeration-cooling-cycle-cop-calculator/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>열팽창 계산기 &#038; 시뮬레이터</title>
		<link>https://myengnote.com/thermal-expansion-calculator-simulator/</link>
					<comments>https://myengnote.com/thermal-expansion-calculator-simulator/#respond</comments>
		
		<dc:creator><![CDATA[동동]]></dc:creator>
		<pubDate>Tue, 09 Jun 2026 19:52:51 +0000</pubDate>
				<category><![CDATA[공학계산기]]></category>
		<category><![CDATA[기계설계]]></category>
		<category><![CDATA[선팽창계수]]></category>
		<category><![CDATA[열역학]]></category>
		<category><![CDATA[열팽창]]></category>
		<category><![CDATA[재료역학]]></category>
		<guid isPermaLink="false">https://myengnote.com/thermal-expansion-calculator-simulator/</guid>

					<description><![CDATA[온도 변화에 따른 다양한 금속 봉의 길이 팽창을 실시간 시각화하고, 선팽창 공식과 마이크로 미터 단위의 변위를 물리 모델링과 아토믹 진동으로 보여주는 2D 시뮬레이터입니다.]]></description>
										<content:encoded><![CDATA[
<h2 style="font-size: 1.6em; font-weight: 800; color: #0c0e25; border-bottom: 2px solid #00f2fe; padding-bottom: 8px; margin-bottom: 20px;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 열팽창 계산기 &#038; 시뮬레이터</h2>


<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&#038;family=Outfit:wght@400;500;600;700;800&#038;display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
/* Scoped & Isolated Styles for thermalexpansion-calculator-wrapper */
        /* Modern Reset and Design Tokens */
        .thermalexpansion-calculator-wrapper *, .thermalexpansion-calculator-wrapper *::before, .thermalexpansion-calculator-wrapper *::after {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        .thermalexpansion-calculator-wrapper {
            --color-bg-dark: #f8f9fd;
            --color-bg-deep: #ffffff;
            --color-panel-bg: rgba(255, 255, 255, 0.85);
            --color-border: rgba(0, 0, 0, 0.06);
            --color-border-hover: rgba(0, 0, 0, 0.12);
            --color-text-main: #1e293b;
            --color-text-muted: #475569;
            --color-text-dark: #94a3b8;
            --color-cyan: #0284c7;
            --color-cyan-glow: rgba(2, 132, 199, 0.15);
            --color-magenta: #db2777;
            --color-magenta-glow: rgba(219, 39, 119, 0.15);
            --color-purple: #7c3aed;
            --color-purple-glow: rgba(124, 58, 237, 0.12);
            --color-success: #10b981;
            --gradient-primary: linear-gradient(135deg, var(--color-cyan) 0%, var(--color-purple) 100%);
            --gradient-accent: linear-gradient(135deg, var(--color-magenta) 0%, var(--color-purple) 100%);
            --gradient-panel: linear-gradient(180deg, rgba(255, 255, 255, 0.9) 0%, rgba(248, 250, 252, 0.95) 100%);
            --font-heading: 'Outfit', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            --font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
            --shadow-neon-cyan: 0 0 15px var(--color-cyan-glow);
            --shadow-neon-magenta: 0 0 15px var(--color-magenta-glow);
            --shadow-card: 0 8px 32px 0 rgba(15, 23, 42, 0.05);
            --blur-glass: blur(16px);
        }
        .thermalexpansion-calculator-wrapper {
            background-color: var(--color-bg-dark);
            color: var(--color-text-main);
            font-family: var(--font-body);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            overflow-x: hidden;
            position: relative;
        }
        .app-background-glow {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: -1;
            overflow: hidden;
            pointer-events: none;
        }
        .app-background-glow::before, 
        .app-background-glow::after {
            content: '';
            position: absolute;
            width: 600px;
            height: 600px;
            border-radius: 50%;
            filter: blur(140px);
            opacity: 0.12;
        }
        .app-background-glow::before {
            background: var(--color-cyan);
            top: -10%;
            right: -5%;
            animation: pulse-slow 15s infinite alternate;
        }
        .app-background-glow::after {
            background: var(--color-purple);
            bottom: -10%;
            left: -5%;
            animation: pulse-slow 20s infinite alternate-reverse;
        }
        @keyframes pulse-slow {
            0% { transform: scale(1) translate(0, 0); opacity: 0.1; }
            100% { transform: scale(1.18) translate(40px, 40px); opacity: 0.18; }
        }
        .app-container {
            width: 100%;
            max-width: 1440px;
            padding: 24px;
            display: flex;
            flex-direction: column;
            gap: 24px;
        }
        .app-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 20px 24px;
            background: var(--color-panel-bg);
            backdrop-filter: var(--blur-glass);
            border: 1px solid var(--color-border);
            border-radius: 16px;
            box-shadow: var(--shadow-card);
        }
        .logo-area {
            display: flex;
            align-items: center;
            gap: 16px;
        }
        .logo-icon {
            font-size: 32px;
            background: linear-gradient(135deg, var(--color-cyan), var(--color-magenta));
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .logo-area h1 {
            font-family: var(--font-heading);
            font-weight: 800;
            font-size: 24px;
            letter-spacing: 1.5px;
            background: linear-gradient(90deg, var(--color-text-main), var(--color-text-muted));
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }
        .logo-area .subtitle {
            font-size: 12px;
            color: var(--color-text-muted);
            font-weight: 500;
            letter-spacing: 0.5px;
        }
        .header-badge {
            display: flex;
            align-items: center;
            gap: 10px;
            background: rgba(16, 185, 129, 0.1);
            border: 1px solid rgba(16, 185, 129, 0.2);
            padding: 6px 14px;
            border-radius: 20px;
        }
        .pulse-dot {
            width: 8px;
            height: 8px;
            background-color: var(--color-success);
            border-radius: 50%;
            box-shadow: 0 0 10px var(--color-success);
            animation: pulse-dot-anim 1.5s infinite;
        }
        @keyframes pulse-dot-anim {
            0% { transform: scale(0.9); opacity: 0.6; }
            50% { transform: scale(1.2); opacity: 1; }
            100% { transform: scale(0.9); opacity: 0.6; }
        }
        .badge-text {
            font-size: 11px;
            font-weight: 600;
            color: var(--color-success);
            letter-spacing: 0.5px;
        }
        .app-main-grid {
            display: grid;
            grid-template-columns: 340px 1fr;
            gap: 24px;
            align-items: start;
        }
        .panel {
            background: var(--gradient-panel);
            backdrop-filter: var(--blur-glass);
            border: 1px solid var(--color-border);
            border-radius: 20px;
            padding: 24px;
            box-shadow: var(--shadow-card);
            display: flex;
            flex-direction: column;
            gap: 20px;
            transition: border-color 0.3s ease, box-shadow 0.3s ease;
        }
        .panel:hover {
            border-color: var(--color-border-hover);
        }
        .panel-header {
            display: flex;
            align-items: center;
            gap: 12px;
            border-bottom: 1px solid var(--color-border);
            padding-bottom: 14px;
        }
        .panel-header i {
            font-size: 18px;
        }
        .panel-header h2 {
            font-family: var(--font-heading);
            font-size: 18px;
            font-weight: 600;
            letter-spacing: 0.5px;
        }
        .text-cyan { color: #0284c7; }
        .text-magenta { color: #db2777; }
        .text-purple { color: var(--color-purple); }
        .control-panel {
            grid-column: 1;
        }
        .input-group {
            display: flex;
            flex-direction: column;
            gap: 8px;
        }
        .input-label-row {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .input-label-row label {
            font-size: 13px;
            font-weight: 600;
            color: var(--color-text-main);
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .range-helper {
            font-size: 10px;
            color: var(--color-text-muted);
            font-weight: 500;
        }
                .number-input-wrapper {
            display: flex;
            position: relative;
            border-radius: 8px;
            overflow: hidden;
            border: 1px solid var(--color-border);
            background: #ffffff;
            transition: all 0.2s ease;
        }
        .number-input-wrapper:focus-within {
            border-color: var(--color-cyan);
            box-shadow: 0 0 10px var(--color-cyan-glow);
        }
        .number-input-wrapper:focus-within {
            border-color: #0284c7;
            box-shadow: 0 0 10px var(--color-cyan-glow);
        }
        .custom-select {
            width: 100%;
            background: #f8fafc;
            border: 1px solid var(--color-border);
            outline: none;
            color: #0f172a;
            padding: 10px 14px;
            font-family: var(--font-body);
            font-size: 14px;
            font-weight: 600;
            border-radius: 8px;
            cursor: pointer;
            transition: all 0.2s ease;
        }
        .custom-select:focus {
            border-color: #0284c7;
            box-shadow: 0 0 10px var(--color-cyan-glow);
        }
                .custom-number-input {
            flex: 1;
            width: 0;
            min-width: 0;
            background: #f8fafc !important;
            border: none !important;
            outline: none !important;
            color: #0f172a !important;
            padding: 10px 14px !important;
            font-family: var(--font-body) !important;
            font-size: 15px !important;
            font-weight: 700 !important;
            text-align: right !important;
            box-shadow: none !important;
            -webkit-appearance: none !important;
            -moz-appearance: textfield !important;
        }
        .custom-number-input::-webkit-outer-spin-button,
        .custom-number-input::-webkit-inner-spin-button {
            -webkit-appearance: none;
            margin: 0;
        }
                .unit-badge {
            background: rgba(0, 0, 0, 0.03);
            color: var(--color-text-muted);
            font-size: 11px;
            font-weight: 700;
            padding: 0 14px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-left: 1px solid var(--color-border);
            pointer-events: none;
            flex-shrink: 0;
        }
        .custom-slider {
            -webkit-appearance: none;
            width: 100%;
            height: 6px;
            border-radius: 3px;
            background: rgba(0, 0, 0, 0.05);
            outline: none;
            margin: 6px 0;
        }
        .custom-slider::-webkit-slider-thumb {
            -webkit-appearance: none;
            appearance: none;
            width: 18px;
            height: 18px;
            border-radius: 50%;
            cursor: pointer;
            background: var(--color-cyan);
            box-shadow: 0 0 10px var(--color-cyan);
            transition: transform 0.1s ease;
        }
        .custom-slider::-webkit-slider-thumb:hover {
            transform: scale(1.2);
        }
        .presets-section {
            border-top: 1px solid var(--color-border);
            padding-top: 18px;
            display: flex;
            flex-direction: column;
            gap: 12px;
        }
        .presets-section h3 {
            font-size: 13px;
            font-weight: 700;
            color: var(--color-text-main);
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .presets-grid {
            display: grid;
            grid-template-columns: 1fr;
            gap: 8px;
        }
        .preset-btn {
            background: rgba(0, 0, 0, 0.015);
            border: 1px solid var(--color-border);
            border-radius: 10px;
            padding: 10px 14px;
            cursor: pointer;
            color: var(--color-text-main);
            display: flex;
            align-items: center;
            gap: 12px;
            text-align: left;
            transition: all 0.2s ease;
        }
        .preset-btn:hover {
            background: rgba(0, 0, 0, 0.05);
            transform: translateX(4px);
        }
        .preset-btn.active {
            background: linear-gradient(90deg, var(--color-cyan-glow), var(--color-magenta-glow));
            border-color: #0284c7;
            box-shadow: 0 0 10px var(--color-cyan-glow);
        }
        .preset-icon {
            width: 28px;
            height: 28px;
            background: rgba(0, 0, 0, 0.02);
            border-radius: 8px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 12px;
            color: #0284c7;
        }
        .preset-btn:hover .preset-icon, .preset-btn.active .preset-icon {
            background: var(--gradient-primary);
            color: #fff;
        }
        .preset-name {
            font-size: 12px;
            font-weight: 600;
        }
        .simulation-panel {
            grid-column: 2;
            align-self: start;
        }
        .simulation-panel .panel-header {
            justify-content: space-between;
        }
        .canvas-scale-indicator {
            font-size: 11px;
            color: var(--color-text-muted);
            background: rgba(0, 0, 0, 0.02);
            padding: 4px 10px;
            border-radius: 6px;
            border: 1px solid var(--color-border);
        }
        .canvas-wrapper {
            position: relative;
            width: 100%;
            background: radial-gradient(circle at center, #ffffff 0%, #f1f5f9 100%);
            border: 1px solid rgba(0, 0, 0, 0.06);
            border-radius: 16px;
            overflow: hidden;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        #physics-canvas {
            display: block;
            width: 100%;
            height: auto;
            aspect-ratio: 16 / 8;
        }
        .results-panel {
            grid-column: 3;
        }
        .ratio-readout-box {
            background: linear-gradient(135deg, rgba(219, 39, 119, 0.08) 0%, rgba(124, 58, 237, 0.03) 100%);
            border: 1px solid rgba(219, 39, 119, 0.25);
            border-radius: 16px;
            padding: 20px;
            text-align: center;
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 6px;
        }
        .ratio-title {
            font-size: 11px;
            font-weight: 700;
            color: #db2777;
            letter-spacing: 1px;
            text-transform: uppercase;
        }
        .ratio-value {
            font-family: var(--font-heading);
            font-weight: 800;
            font-size: 28px;
            background: linear-gradient(90deg, var(--color-text-main), var(--color-magenta));
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }
        .results-grid {
            display: flex;
            flex-direction: column;
            gap: 12px;
        }
        .result-card {
            background: rgba(255, 255, 255, 0.85);
            border: 1px solid var(--color-border);
            border-radius: 12px;
            padding: 12px 16px;
            display: flex;
            align-items: center;
            gap: 16px;
            transition: all 0.2s ease;
        }
        .result-card:hover {
            transform: translateY(-2px);
            border-color: rgba(219, 39, 119, 0.2);
            background: rgba(219, 39, 119, 0.03);
        }
        .card-icon {
            width: 38px;
            height: 38px;
            background: rgba(0, 0, 0, 0.015);
            border: 1px solid var(--color-border);
            border-radius: 10px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 14px;
            color: var(--color-text-muted);
        }
        .result-card:hover .card-icon {
            color: #db2777;
            border-color: rgba(219, 39, 119, 0.3);
            background: rgba(219, 39, 119, 0.1);
        }
        .card-content {
            display: flex;
            flex-direction: column;
            gap: 2px;
        }
        .card-unit {
            font-size: 10px;
            font-weight: 600;
            color: var(--color-text-muted);
            text-transform: uppercase;
        }
        .card-value {
            font-family: var(--font-heading);
            font-weight: 700;
            font-size: 16px;
            color: var(--color-text-main);
        }
        .formula-card {
            background: rgba(0, 0, 0, 0.01);
            border: 1px solid var(--color-border);
            border-radius: 12px;
            padding: 16px;
            display: flex;
            flex-direction: column;
            gap: 8px;
            font-size: 12px;
        }
        .formula-card h4 {
            font-weight: 700;
            color: var(--color-text-main);
        }
        .formula-equation {
            font-family: monospace;
            color: #0284c7;
            font-size: 13px;
            background: #f8fafc;
            padding: 6px 10px;
            border-radius: 6px;
            border: 1px solid var(--color-border);
            text-align: center;
        }
        @container expansion-container (max-width: 1100px) {
            .app-main-grid {
                grid-template-columns: 1fr 1.2fr;
                gap: 20px;
            }
        }
        @container expansion-container (max-width: 768px) {
            .app-main-grid {
                grid-template-columns: 1fr;
            }
            .control-panel, .simulation-panel, .results-panel {
                grid-column: 1;
            }
            .simulation-panel {
                order: -1;
            }
            .app-header {
                flex-direction: column;
                gap: 16px;
                text-align: center;
            }
            .logo-area {
                flex-direction: column;
                gap: 8px;
            }
        }
        .preset-details {
            display: flex;
            flex-direction: column;
            gap: 2px;
            align-items: flex-start;
            text-align: left;
        }
        .preset-spec {
            font-size: 11px;
            color: var(--color-text-muted);
            font-weight: 500;
        }
        .preset-name {
            font-size: 13px !important;
        }
/* ━━ WordPress 레이아웃 Override: 디자인 1 (2열 컴팩트 대칭 레이아웃) ━━ */
.thermalexpansion-calculator-wrapper .app-main-grid,
.thermalexpansion-calculator-wrapper .main-grid,
.thermalexpansion-calculator-wrapper .sim-grid {
    display: grid !important;
    grid-template-columns: 340px 1fr !important;
    gap: 24px !important;
    align-items: start !important;
}
/* 3열 레이아웃을 2열 레이아웃으로 변경하는 특화 스타일 */
.thermalexpansion-calculator-wrapper .right-column {
    display: flex !important;
    flex-direction: column !important;
    gap: 24px !important;
    min-width: 0 !important;
    grid-column: 2 !important;
}
.thermalexpansion-calculator-wrapper .simulation-panel,
.thermalexpansion-calculator-wrapper .canvas-panel,
.thermalexpansion-calculator-wrapper .sim-panel {
    grid-column: auto !important;
    order: 1 !important;
    align-self: stretch !important;
}
.thermalexpansion-calculator-wrapper .control-panel {
    grid-column: 1 !important;
}
/* 2열 통합 결과 분석 영역 레이아웃 */
.thermalexpansion-calculator-wrapper .simulation-results-section {
    display: grid !important;
    grid-template-columns: 1.1fr 1.3fr !important;
    gap: 20px !important;
    border-top: 1px solid var(--color-border) !important;
    padding-top: 20px !important;
    margin-top: 10px !important;
    align-items: stretch !important;
}
/* Readout Box 스타일 */
.thermalexpansion-calculator-wrapper .simulation-results-section .ratio-readout-box,
.thermalexpansion-calculator-wrapper .simulation-results-section .re-readout-box,
.thermalexpansion-calculator-wrapper .simulation-results-section .status-readout-box,
.thermalexpansion-calculator-wrapper .simulation-results-section .gauge-container {
    grid-column: 1 !important;
    grid-row: 1 !important;
    margin: 0 !important;
    height: auto !important;
    display: flex !important;
    flex-direction: column !important;
    justify-content: center !important;
}
.thermalexpansion-calculator-wrapper .simulation-results-section .results-grid {
    grid-column: 2 !important;
    grid-row: 1 / span 2 !important;
    display: flex !important;
    flex-direction: column !important;
    gap: 12px !important;
    justify-content: flex-start !important;
}
.thermalexpansion-calculator-wrapper .simulation-results-section .results-grid .result-card {
    flex: none !important;
    display: flex !important;
    align-items: center !important;
    min-height: 72px !important;
    height: auto !important;
    padding: 12px 16px !important;
}
.thermalexpansion-calculator-wrapper .simulation-results-section .formula-card {
    grid-column: 1 !important;
    grid-row: 2 !important;
}
/* 모바일/반응형 (800px 이하) ── 항상 세로형(1열) 정렬 및 시뮬레이터 캔버스 최상단 배치 */
@media (max-width: 800px) {
    .thermalexpansion-calculator-wrapper .app-main-grid,
    .thermalexpansion-calculator-wrapper .main-grid,
    .thermalexpansion-calculator-wrapper .sim-grid {
        grid-template-columns: 1fr !important;
        display: flex !important;
        flex-direction: column !important;
    }
    .thermalexpansion-calculator-wrapper .control-panel {
        order: 2 !important;
        width: 100% !important;
    }
    .thermalexpansion-calculator-wrapper .right-column {
        order: 1 !important;
        width: 100% !important;
        display: flex !important;
        flex-direction: column !important;
    }
    .thermalexpansion-calculator-wrapper .simulation-panel,
    .thermalexpansion-calculator-wrapper .canvas-panel,
    .thermalexpansion-calculator-wrapper .sim-panel,
    .thermalexpansion-calculator-wrapper .canvas-section {
        order: -1 !important;
    }
    .thermalexpansion-calculator-wrapper .simulation-results-section {
        grid-template-columns: 1fr !important;
    }
    .thermalexpansion-calculator-wrapper .simulation-results-section .ratio-readout-box,
    .thermalexpansion-calculator-wrapper .simulation-results-section .re-readout-box,
    .thermalexpansion-calculator-wrapper .simulation-results-section .status-readout-box,
    .thermalexpansion-calculator-wrapper .simulation-results-section .gauge-container {
        grid-column: 1 !important;
        grid-row: auto !important;
        height: auto !important;
    }
    .thermalexpansion-calculator-wrapper .simulation-results-section .results-grid {
        grid-column: 1 !important;
        grid-row: auto !important;
    }
    .thermalexpansion-calculator-wrapper .simulation-results-section .formula-card {
        grid-column: 1 !important;
        grid-row: auto !important;
    }
}
.thermalexpansion-calculator-wrapper .app-container,
.thermalexpansion-calculator-wrapper .main-container {
    max-width: 100% !important;
    padding: 12px !important;
}
/* Premium Advice/Formula Card & Typography Overrides */
.thermalexpansion-calculator-wrapper .simulation-results-section .formula-card,
.thermalexpansion-calculator-wrapper .results-panel .formula-card {
    background: #ffffff !important;
    border: 1px solid var(--color-border) !important;
    border-radius: 12px !important;
    padding: 16px !important;
    box-shadow: var(--shadow-card) !important;
    transition: all 0.2s ease !important;
    display: flex !important;
    flex-direction: column !important;
    gap: 8px !important;
}
.thermalexpansion-calculator-wrapper .simulation-results-section .formula-card h4,
.thermalexpansion-calculator-wrapper .results-panel .formula-card h4 {
    font-weight: 700 !important;
    color: var(--color-text-main) !important;
}
.thermalexpansion-calculator-wrapper #text-judgment {
    font-size: 12px !important;
    font-weight: 500 !important;
    color: var(--color-text-muted) !important;
    line-height: 1.6 !important;
    word-break: keep-all !important;
}
</style>
<div class="thermalexpansion-calculator-wrapper" style="position: relative; width: 100%; box-sizing: border-box; overflow: hidden; margin: 30px auto; border-radius: 20px;">
    <div class="app-background-glow" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1; pointer-events: none; overflow: hidden;"></div>
    <div style="position: relative; z-index: 2; width: 100%;">
    <div class="app-container">
        <!-- Header -->
        <header class="app-header">
            <div class="logo-area">
                <div class="logo-icon"><i class="fa-solid fa-temperature-three-quarters"></i></div>
                <div>
                    <h1>THERMAL EXPANSION</h1>
                    <div class="subtitle">금속 열팽창 계수 계산기 &#038; 실시간 2D 시뮬레이터</div>
                </div>
            </div>
            <div class="header-badge">
                <div class="pulse-dot"></div>
                <div class="badge-text">물리 연산 엔진 작동중</div>
            </div>
        </header>
        <div class="app-main-grid">
            <!-- Left Column: Controls -->
            <div class="panel control-panel">
                <div class="panel-header">
                    <i class="fa-solid fa-sliders text-cyan"></i>
                    <h2>시뮬레이션 제어</h2>
                </div>
                <div class="input-group">
                    <div class="input-label-row">
                        <label><i class="fa-solid fa-cubes text-cyan"></i> 대상 금속 재질</label>
                    </div>
                    <select id="select-material" class="custom-select">
                        <option value="steel">탄소강 (Steel)</option>
                        <option value="copper">구리 (Copper)</option>
                        <option value="aluminum">알루미늄 (Aluminum)</option>
                        <option value="brass">황동 (Brass)</option>
                    </select>
                </div>
                <div class="input-group">
                    <div class="input-label-row">
                        <label><i class="fa-solid fa-ruler-horizontal text-cyan"></i> 초기 길이 (L₀)</label>
                        <span class="range-helper">Min: 1.0m / Max: 10.0m</span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-l0" class="custom-number-input" value="5.0" step="0.1" min="1.0" max="10.0">
                        <span class="unit-badge">m</span>
                    </div>
                    <input type="range" id="slider-l0" class="custom-slider" value="5.0" min="1.0" max="10.0" step="0.1">
                </div>
                <div class="input-group">
                    <div class="input-label-row">
                        <label><i class="fa-solid fa-temperature-low text-cyan"></i> 초기 온도 (T₁)</label>
                        <span class="range-helper">Min: -50°C / Max: 100°C</span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-t1" class="custom-number-input" value="20" step="1" min="-50" max="100">
                        <span class="unit-badge">°C</span>
                    </div>
                    <input type="range" id="slider-t1" class="custom-slider" value="20" min="-50" max="100" step="1">
                </div>
                <div class="input-group">
                    <div class="input-label-row">
                        <label><i class="fa-solid fa-temperature-high text-magenta"></i> 최종 온도 (T₂)</label>
                        <span class="range-helper">Min: -50°C / Max: 500°C</span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-t2" class="custom-number-input" value="200" step="1" min="-50" max="500">
                        <span class="unit-badge">°C</span>
                    </div>
                    <input type="range" id="slider-t2" class="custom-slider" value="200" min="-50" max="500" step="1">
                </div>
                <div class="presets-section">
                    <h3><i class="fa-solid fa-fire-burner text-purple"></i> 급속 시나리오 프리셋</h3>
                    <div class="presets-grid">
                        <button class="preset-btn" data-preset="heat">
                            <div class="preset-icon"><i class="fa-solid fa-fire"></i></div>
                            <div class="preset-details"><span class="preset-name">고온 가열 시험</span><span class="preset-spec">500°C</span></div>
                        </button>
                        <button class="preset-btn" data-preset="normal">
                            <div class="preset-icon"><i class="fa-solid fa-leaf"></i></div>
                            <div class="preset-details"><span class="preset-name">표준 대기온 상태</span><span class="preset-spec">20°C</span></div>
                        </button>
                        <button class="preset-btn" data-preset="cold">
                            <div class="preset-icon"><i class="fa-solid fa-snowflake"></i></div>
                            <div class="preset-details"><span class="preset-name">극저온 빙결 시험</span><span class="preset-spec">-50°C</span></div>
                        </button>
                    </div>
                </div>
            </div>
            <!-- Auto Injected Right Column wrapper for Design 1 -->
            <div class="right-column">
                <div class="panel simulation-panel">
                                <div class="panel-header">
                                    <div>
                                        <i class="fa-solid fa-chart-line text-cyan"></i>
                                        <h2>실시간 거시/미시 변형 시뮬레이터</h2>
                                    </div>
                                    <span id="canvas-scale-indicator" class="canvas-scale-indicator">배율: 100배 과장</span>
                                </div>
                                <div class="canvas-wrapper">
                                    <canvas id="physics-canvas"></canvas>
                                </div>
                                <!-- Integrated Results Analysis Section -->
                            <div class="simulation-results-section">
                                <div class="ratio-readout-box">
                                            <div class="ratio-title">길이 변화량 (ΔL)</div>
                                            <div id="txt-delta-l" class="ratio-value">+15.30 mm</div>
                                        </div>
                                <div class="results-grid">
                                        <!-- Temperature Diff -->
                                        <div class="result-card">
                                            <div class="card-icon"><i class="fa-solid fa-temperature-half text-cyan"></i></div>
                                            <div class="card-content">
                                                <span class="card-unit">온도 변화폭 (ΔT)</span>
                                                <span id="txt-delta-t" class="card-value">180 °C</span>
                                            </div>
                                        </div>
                                        <!-- Final Length -->
                                        <div class="result-card">
                                            <div class="card-icon"><i class="fa-solid fa-ruler-horizontal text-purple"></i></div>
                                            <div class="card-content">
                                                <span class="card-unit">최종 전체 길이 (L)</span>
                                                <span id="txt-final-l" class="card-value">5.0153 m</span>
                                            </div>
                                        </div>
                                        <!-- Thermal Strain -->
                                        <div class="result-card">
                                            <div class="card-icon"><i class="fa-solid fa-percent text-magenta"></i></div>
                                            <div class="card-content">
                                                <span class="card-unit">열변형률 (Thermal Strain)</span>
                                                <span id="txt-strain" class="card-value">0.306 %</span>
                                            </div>
                                        </div>
                                        <!-- Thermal Stress -->
                                        <div class="result-card">
                                            <div class="card-icon"><i class="fa-solid fa-compress text-success"></i></div>
                                            <div class="card-content">
                                                <span class="card-unit">구속 시 온도응력 (Thermal Stress)</span>
                                                <span id="txt-stress" class="card-value">414.0 MPa</span>
                                            </div>
                                        </div>
                                    </div>
                                <div class="formula-card">
                                            <h4><i class="fa-solid fa-circle-info text-cyan"></i> 선팽창 계산 공식</h4>
                                            <div class="formula-equation">
                                                ΔL = α × L₀ × ΔT
                                            </div>
                                        </div>
                            </div>
                </div>
            </div>
        </div>
        <!-- Disclaimer Footer -->
        <footer class="app-disclaimer" style="margin-top: 20px; padding: 12px 16px; background: rgba(0, 0, 0, 0.015); border: 1px solid var(--color-border); border-radius: 12px; font-size: 11px; color: var(--color-text-muted); line-height: 1.5; text-align: left; display: flex; gap: 10px; align-items: flex-start; clear: both;">
            <i class="fa-solid fa-circle-info" style="color: var(--color-cyan); font-size: 14px; margin-top: 2px; flex-shrink: 0;"></i>
            <span><strong>면책 조항 (Disclaimer):</strong> 본 시뮬레이터의 계산 결과는 교육 및 참고용으로만 제공되며, 실제 제품 설계나 제작 시에는 반드시 최신 공학 규격 및 공식 표준 설계 기준을 재확인하시기 바랍니다. 계산 값의 무결성을 보장하지 않으며, 이로 인해 발생하는 직접적/간접적 손해에 대해 제작자 및 본 블로그는 어떠한 책임을 지지 않습니다.</span>
        </footer>
</div>
    <!-- JavaScript Core Simulator Engine -->
    </div>
</div>
<script>
        (function() {
            let isInit = false;
            function initSimulator() {
                if (isInit) return;
                const canvas = document.getElementById('physics-canvas');
                if (!canvas) return;
                const ctx = canvas.getContext('2d');
                if (!ctx) return;
                isInit = true;
                window.__thermalexpansion_initialized = true;
                // DOM elements
                const selectMaterial = document.getElementById('select-material');
                const sliderL0 = document.getElementById('slider-l0');
                const inputL0 = document.getElementById('input-l0');
                const sliderT1 = document.getElementById('slider-t1');
                const inputT1 = document.getElementById('input-t1');
                const sliderT2 = document.getElementById('slider-t2');
                const inputT2 = document.getElementById('input-t2');
                const presetBtns = document.querySelectorAll('.preset-btn');
                const txtDeltaL = document.getElementById('txt-delta-l');
                const txtDeltaT = document.getElementById('txt-delta-t');
                const txtFinalL = document.getElementById('txt-final-l');
                const txtStrain = document.getElementById('txt-strain');
                const txtStress = document.getElementById('txt-stress');
                // Simulation State
                const state = {
                    material: 'steel',
                    l0: 5.0,
                    t1: 20,
                    t2: 200,
                    alpha: 11.5e-6,
                    youngsModulus: 200e9, // Pa
                    density: 7850,
                    colorGradStart: '#94a3b8',
                    colorGradEnd: '#475569',
                    particles: []
                };
                const materialProperties = {
                    steel: {
                        alpha: 11.5e-6,
                        E: 200e9,
                        density: 7850,
                        c1: '#a1a1aa',
                        c2: '#52525b'
                    },
                    copper: {
                        alpha: 17.0e-6,
                        E: 110e9,
                        density: 8960,
                        c1: '#fb923c',
                        c2: '#c2410c'
                    },
                    aluminum: {
                        alpha: 23.0e-6,
                        E: 70e9,
                        density: 2700,
                        c1: '#cbd5e1',
                        c2: '#64748b'
                    },
                    brass: {
                        alpha: 19.0e-6,
                        E: 90e9,
                        density: 8500,
                        c1: '#fde047',
                        c2: '#ca8a04'
                    }
                };
                // Retina Display Canvas adaptation
                function resizeCanvas() {
                    const rect = canvas.getBoundingClientRect();
                    const dpr = window.devicePixelRatio || 1;
                    canvas.width = rect.width * dpr;
                    canvas.height = rect.height * dpr;
                    ctx.scale(dpr, dpr);
                }
                resizeCanvas();
                window.addEventListener('resize', resizeCanvas);
                setTimeout(resizeCanvas, 300);
                // Input sync handlers
                function syncL0FromSlider() {
                    const val = parseFloat(sliderL0.value);
                    inputL0.value = val.toFixed(1);
                    state.l0 = val;
                    clearPresets();
                    updateCalculations();
                }
                function syncL0FromInput() {
                    let val = parseFloat(inputL0.value);
                    if (isNaN(val)) {
                        val = 5.0;
                    }
                    if (val < 1.0) {
                        val = 1.0;
                    }
                    if (val > 10.0) {
                        val = 10.0;
                    }
                    sliderL0.value = val;
                    state.l0 = val;
                    clearPresets();
                    updateCalculations();
                }
                function syncT1FromSlider() {
                    const val = parseInt(sliderT1.value);
                    inputT1.value = val;
                    state.t1 = val;
                    clearPresets();
                    updateCalculations();
                }
                function syncT1FromInput() {
                    let val = parseInt(inputT1.value);
                    if (isNaN(val)) {
                        val = 20;
                    }
                    if (val < -50) {
                        val = -50;
                    }
                    if (val > 100) {
                        val = 100;
                    }
                    sliderT1.value = val;
                    state.t1 = val;
                    clearPresets();
                    updateCalculations();
                }
                function syncT2FromSlider() {
                    const val = parseInt(sliderT2.value);
                    inputT2.value = val;
                    state.t2 = val;
                    clearPresets();
                    updateCalculations();
                }
                function syncT2FromInput() {
                    let val = parseInt(inputT2.value);
                    if (isNaN(val)) {
                        val = 200;
                    }
                    if (val < -50) {
                        val = -50;
                    }
                    if (val > 500) {
                        val = 500;
                    }
                    sliderT2.value = val;
                    state.t2 = val;
                    clearPresets();
                    updateCalculations();
                }
                function handleMaterialChange() {
                    const selected = selectMaterial.value;
                    const props = materialProperties[selected];
                    if (props) {
                        state.material = selected;
                        state.alpha = props.alpha;
                        state.youngsModulus = props.E;
                        state.density = props.density;
                        state.colorGradStart = props.c1;
                        state.colorGradEnd = props.c2;
                    }
                    updateCalculations();
                }
                function loadPreset(presetKey) {
                    clearPresets();
                    presetBtns.forEach(btn => {
                        if (btn.dataset.preset === presetKey) {
                            btn.classList.add('active');
                        }
                    });
                    if (presetKey === 'heat') {
                        state.t1 = 20;
                        state.t2 = 500;
                    }
                    if (presetKey === 'normal') {
                        state.t1 = 20;
                        state.t2 = 20;
                    }
                    if (presetKey === 'cold') {
                        state.t1 = 20;
                        state.t2 = -50;
                    }
                    sliderT1.value = state.t1;
                    inputT1.value = state.t1;
                    sliderT2.value = state.t2;
                    inputT2.value = state.t2;
                    updateCalculations();
                }
                function clearPresets() {
                    presetBtns.forEach(btn => btn.classList.remove('active'));
                }
                // Math Model update
                function updateCalculations() {
                    const deltaT = state.t2 - state.t1;
                    const deltaL = state.alpha * state.l0 * deltaT * 1000; // mm
                    const finalL = state.l0 + (deltaL / 1000);
                    const strain = (state.alpha * deltaT) * 100; // %
                    const stress = state.youngsModulus * state.alpha * deltaT / 1e6; // MPa
                    txtDeltaT.innerText = `${deltaT} °C`;
                    if (deltaL >= 0) {
                        txtDeltaL.innerText = `+${deltaL.toFixed(3)} mm`;
                        txtDeltaL.style.color = '#db2777';
                    }
                    if (deltaL < 0) {
                        txtDeltaL.innerText = `${deltaL.toFixed(3)} mm`;
                        txtDeltaL.style.color = '#0284c7';
                    }
                    txtFinalL.innerText = `${finalL.toFixed(6)} m`;
                    txtStrain.innerText = `${strain.toFixed(4)} %`;
                    txtStress.innerText = `${stress.toFixed(1)} MPa`;
                }
                // Particle systems (Fire/Ice)
                class EffectParticle {
                    constructor(x, y, type) {
                        this.x = x;
                        this.y = y;
                        this.type = type; // 'fire' or 'cold'
                        this.size = Math.random() * 4 + 2;
                        this.vx = (Math.random() - 0.5) * 1.0;
                        if (type === 'fire') {
                            this.vy = -(Math.random() * 1.5 + 0.5);
                            this.life = Math.random() * 30 + 20;
                            const colors = ['#f97316', '#ef4444', '#f59e0b', '#ef4444'];
                            this.color = colors[Math.floor(Math.random() * colors.length)];
                        }
                        if (type === 'cold') {
                            this.vy = Math.random() * 1.2 + 0.3;
                            this.life = Math.random() * 40 + 30;
                            const colors = ['#38bdf8', '#0284c7', '#ffffff', '#e0f2fe'];
                            this.color = colors[Math.floor(Math.random() * colors.length)];
                        }
                        this.maxLife = this.life;
                    }
                    update() {
                        this.x += this.vx;
                        this.y += this.vy;
                        this.life--;
                    }
                    draw(c) {
                        const alpha = this.life / this.maxLife;
                        c.save();
                        c.globalAlpha = alpha;
                        c.fillStyle = this.color;
                        c.beginPath();
                        if (this.type === 'cold') {
                            c.arc(this.x, this.y, this.size, 0, Math.PI * 2);
                            c.fill();
                        }
                        if (this.type === 'fire') {
                            c.beginPath();
                            c.moveTo(this.x, this.y - this.size);
                            c.lineTo(this.x + this.size, this.y + this.size);
                            c.lineTo(this.x - this.size, this.y + this.size);
                            c.closePath();
                            c.fill();
                        }
                        c.restore();
                    }
                }
                // Helper to draw dimensional arrowheads
                function drawArrowhead(c, x, y, angle) {
                    c.save();
                    c.translate(x, y);
                    c.rotate(angle);
                    c.beginPath();
                    c.moveTo(0, 0);
                    c.lineTo(-6, -3.5);
                    c.lineTo(-6, 3.5);
                    c.closePath();
                    c.fillStyle = c.strokeStyle;
                    c.fill();
                    c.restore();
                }
                // Render main loop
                function animate(timestamp) {
                    requestAnimationFrame(animate);
                    // Check and auto-fit canvas resolution to layout changes (prevents vertical stretch &#038; empty gaps)
                    const dpr = window.devicePixelRatio || 1;
                    const rect = canvas.getBoundingClientRect();
                    if (Math.abs(canvas.width - rect.width * dpr) > 1.5 || Math.abs(canvas.height - rect.height * dpr) > 1.5) {
                        resizeCanvas();
                    }
                    const width = canvas.width / dpr;
                    const height = canvas.height / dpr;
                    ctx.clearRect(0, 0, width, height);
                    // Blueprint Grid Lines
                    ctx.save();
                    ctx.strokeStyle = 'rgba(2, 132, 199, 0.05)';
                    ctx.lineWidth = 1;
                    for (let x = 0; x < width; x += 24) {
                        ctx.beginPath();
                        ctx.moveTo(x, 0);
                        ctx.lineTo(x, height);
                        ctx.stroke();
                    }
                    for (let y = 0; y < height; y += 24) {
                        ctx.beginPath();
                        ctx.moveTo(0, y);
                        ctx.lineTo(width, y);
                        ctx.stroke();
                    }
                    ctx.restore();
                    // Physics Expansion calculations
                    const deltaT = state.t2 - state.t1;
                    const deltaL = state.alpha * state.l0 * deltaT * 1000; // in mm
                    const finalL = state.l0 + (deltaL / 1000);
                    // Layout positions - dynamic auto-zoom based on canvas size
                    const startX = 60;
                    // Leave 240px for dial gauge and magnifier to prevent boundary overflow
                    const availWidth = (width - startX - 240); 
                    // Map l0 (1.0m to 10.0m) to baseWidth (35% to 65% of availWidth)
                    const maxBaseWidth = availWidth * 0.65;
                    const minBaseWidth = availWidth * 0.35;
                    const baseWidth = minBaseWidth + (state.l0 - 1.0) / 9.0 * (maxBaseWidth - minBaseWidth);
                    // Dynamic visual expansion scale: max 15% of availWidth at 1.5% thermal strain
                    const maxExpansionWidth = availWidth * 0.15;
                    const strainPct = state.alpha * deltaT;
                    const visualExpansion = (strainPct / 0.015) * maxExpansionWidth; 
                    const rodHeight = Math.max(25, Math.min(45, height * 0.105));
                    // Golden Vertical Centering: mathematically centers the rod, dimension lines, and particle overlays
                    const totalDrawHeight = rodHeight + 84;
                    const rodY = (height - totalDrawHeight) / 2 + 10;
                    const currentRodWidth = baseWidth + visualExpansion;
                    // Draw Left Anchor Bracket
                    ctx.save();
                    ctx.fillStyle = '#64748b';
                    ctx.fillRect(startX - 20, rodY - 15, 20, rodHeight + 30);
                    ctx.strokeStyle = '#334155';
                    ctx.lineWidth = 2;
                    ctx.strokeRect(startX - 20, rodY - 15, 20, rodHeight + 30);
                    // Hatch pattern on anchor
                    ctx.strokeStyle = 'rgba(255,255,255,0.2)';
                    ctx.lineWidth = 1.5;
                    for (let h = rodY - 10; h < rodY + rodHeight + 15; h += 8) {
                        ctx.beginPath();
                        ctx.moveTo(startX - 18, h);
                        ctx.lineTo(startX - 2, h - 8);
                        ctx.stroke();
                    }
                    ctx.restore();
                    // Particles spawn (Flame underneath, or ice falling from top)
                    if (state.t2 > state.t1) {
                        // Spawn burner flame
                        const heatIntensity = Math.min((state.t2 - state.t1) / 300, 1.5);
                        if (Math.random() < 0.25 * heatIntensity) {
                            const px = startX + Math.random() * currentRodWidth;
                            state.particles.push(new EffectParticle(px, rodY + rodHeight + 15, 'fire'));
                        }
                    }
                    if (state.t2 < state.t1) {
                        // Spawn cold snowflake drop
                        const coldIntensity = Math.min((state.t1 - state.t2) / 100, 1.5);
                        if (Math.random() < 0.25 * coldIntensity) {
                            const px = startX + Math.random() * currentRodWidth;
                            state.particles.push(new EffectParticle(px, rodY - 20, 'cold'));
                        }
                    }
                    // Update &#038; Draw Particles
                    state.particles = state.particles.filter(p => p.life > 0);
                    state.particles.forEach(p => {
                        p.update();
                        p.draw(ctx);
                    });
                    // Draw heating element or cooling block visualizers
                    if (state.t2 > state.t1) {
                        ctx.fillStyle = 'rgba(239, 68, 68, 0.05)';
                        ctx.fillRect(startX, rodY + rodHeight + 2, currentRodWidth, 12);
                    }
                    if (state.t2 < state.t1) {
                        ctx.fillStyle = 'rgba(56, 189, 248, 0.05)';
                        ctx.fillRect(startX, rodY - 14, currentRodWidth, 12);
                    }
                    // Draw the Metal Rod itself
                    ctx.save();
                    // 1. Draw base initial length segment
                    const metalGrad = ctx.createLinearGradient(startX, rodY, startX, rodY + rodHeight);
                    metalGrad.addColorStop(0, state.colorGradStart);
                    metalGrad.addColorStop(0.3, '#ffffff');
                    metalGrad.addColorStop(1, state.colorGradEnd);
                    ctx.fillStyle = metalGrad;
                    // Draw base width (L0 portion)
                    if (visualExpansion >= 0) {
                        ctx.fillRect(startX, rodY, baseWidth, rodHeight);
                        // 2. Draw expanded segment (with pinkish/red overlay + stripes for clarity)
                        ctx.fillStyle = 'rgba(219, 39, 119, 0.2)';
                        ctx.fillRect(startX + baseWidth, rodY, visualExpansion, rodHeight);
                        ctx.strokeStyle = 'rgba(219, 39, 119, 0.4)';
                        ctx.lineWidth = 1.5;
                        for (let bx = startX + baseWidth; bx < startX + baseWidth + visualExpansion; bx += 8) {
                            ctx.beginPath();
                            ctx.moveTo(bx, rodY);
                            ctx.lineTo(bx + 6, rodY + rodHeight);
                            ctx.stroke();
                        }
                    } else {
                        // Rod has contracted (visualExpansion is negative)
                        ctx.fillRect(startX, rodY, currentRodWidth, rodHeight);
                        // Show contracted missing region as dotted translucent blue box
                        ctx.strokeStyle = 'rgba(2, 132, 199, 0.4)';
                        ctx.lineWidth = 1.5;
                        ctx.setLineDash([3, 3]);
                        ctx.strokeRect(startX + currentRodWidth, rodY, -visualExpansion, rodHeight);
                        ctx.setLineDash([]);
                        ctx.fillStyle = 'rgba(2, 132, 199, 0.08)';
                        ctx.fillRect(startX + currentRodWidth, rodY, -visualExpansion, rodHeight);
                    }
                    // External border for the actual physical rod
                    ctx.strokeStyle = state.colorGradEnd;
                    ctx.lineWidth = 2.5;
                    ctx.strokeRect(startX, rodY, currentRodWidth, rodHeight);
                    ctx.restore();
                    // Microscopic View Zoom Callout Circle
                    const zoomCx = width - 85;
                    const zoomCy = 75;
                    const zoomR = 45;
                    ctx.save();
                    // Draw outer border ring of magnifier
                    ctx.beginPath();
                    ctx.arc(zoomCx, zoomCy, zoomR, 0, Math.PI * 2);
                    ctx.fillStyle = '#ffffff';
                    ctx.fill();
                    ctx.strokeStyle = '#94a3b8';
                    ctx.lineWidth = 3;
                    ctx.stroke();
                    // Microscope glass reflection / grid lines
                    ctx.beginPath();
                    ctx.arc(zoomCx, zoomCy, zoomR, 0, Math.PI * 2);
                    ctx.clip();
                    ctx.fillStyle = '#f8fafc';
                    ctx.fill();
                    // Microscopic grid background
                    ctx.strokeStyle = 'rgba(0,0,0,0.02)';
                    ctx.lineWidth = 1;
                    for (let gx = zoomCx - zoomR; gx < zoomCx + zoomR; gx += 12) {
                        ctx.beginPath();
                        ctx.moveTo(gx, zoomCy - zoomR);
                        ctx.lineTo(gx, zoomCy + zoomR);
                        ctx.stroke();
                    }
                    for (let gy = zoomCy - zoomR; gy < zoomCy + zoomR; gy += 12) {
                        ctx.beginPath();
                        ctx.moveTo(zoomCx - zoomR, gy);
                        ctx.lineTo(zoomCx + zoomR, gy);
                        ctx.stroke();
                    }
                    // Atom lattice visualization inside zoom circle
                    const temperatureInfluence = Math.max((state.t2 + 100) / 100, 0.1);
                    const latticeSpacing = 16 + (deltaT * 0.005);
                    const vibrationAmp = temperatureInfluence * 0.45;
                    ctx.fillStyle = state.colorGradEnd;
                    ctx.strokeStyle = 'rgba(0,0,0,0.12)';
                    ctx.lineWidth = 1;
                    for (let lx = -3; lx <= 3; lx++) {
                        for (let ly = -3; ly <= 3; ly++) {
                            const vx = Math.sin(timestamp * 0.015 + lx) * vibrationAmp;
                            const vy = Math.cos(timestamp * 0.012 + ly) * vibrationAmp;
                            const atomX = zoomCx + lx * latticeSpacing + vx;
                            const atomY = zoomCy + ly * latticeSpacing + vy;
                            // Draw bond connections to right and bottom neighbors
                            if (lx < 3) {
                                const nextAtomX = zoomCx + (lx + 1) * latticeSpacing + Math.sin(timestamp * 0.015 + lx + 1) * vibrationAmp;
                                const nextAtomY = zoomCy + ly * latticeSpacing + Math.cos(timestamp * 0.012 + ly) * vibrationAmp;
                                ctx.beginPath();
                                ctx.moveTo(atomX, atomY);
                                ctx.lineTo(nextAtomX, nextAtomY);
                                ctx.stroke();
                            }
                            if (ly < 3) {
                                const nextAtomX = zoomCx + lx * latticeSpacing + Math.sin(timestamp * 0.015 + lx) * vibrationAmp;
                                const nextAtomY = zoomCy + (ly + 1) * latticeSpacing + Math.cos(timestamp * 0.012 + ly + 1) * vibrationAmp;
                                ctx.beginPath();
                                ctx.moveTo(atomX, atomY);
                                ctx.lineTo(nextAtomX, nextAtomY);
                                ctx.stroke();
                            }
                            // Draw atom node
                            ctx.beginPath();
                            ctx.arc(atomX, atomY, 3.5, 0, Math.PI * 2);
                            ctx.fill();
                        }
                    }
                    // Lens reflection overlay
                    const glassGrad = ctx.createLinearGradient(zoomCx - zoomR, zoomCy - zoomR, zoomCx + zoomR, zoomCy + zoomR);
                    glassGrad.addColorStop(0, 'rgba(255,255,255,0.4)');
                    glassGrad.addColorStop(0.5, 'rgba(255,255,255,0.05)');
                    glassGrad.addColorStop(1, 'rgba(2,132,199,0.05)');
                    ctx.fillStyle = glassGrad;
                    ctx.beginPath();
                    ctx.arc(zoomCx, zoomCy, zoomR, 0, Math.PI * 2);
                    ctx.fill();
                    ctx.restore();
                    // Magnifier link lines from rod end to callout
                    ctx.save();
                    ctx.strokeStyle = 'rgba(148, 163, 184, 0.4)';
                    ctx.lineWidth = 1;
                    ctx.setLineDash([4, 4]);
                    ctx.beginPath();
                    ctx.moveTo(startX + currentRodWidth, rodY);
                    ctx.lineTo(zoomCx - zoomR + 5, zoomCy - 20);
                    ctx.moveTo(startX + currentRodWidth, rodY + rodHeight);
                    ctx.lineTo(zoomCx - zoomR + 5, zoomCy + 20);
                    ctx.stroke();
                    ctx.restore();
                    // Microscope tag text
                    ctx.fillStyle = '#64748b';
                    ctx.font = 'bold 9px sans-serif';
                    ctx.textAlign = 'center';
                    ctx.fillText('미시 원자 격자 뷰', zoomCx, zoomCy + zoomR + 13);
                    // Micro Dial gauge representation below rod right end
                    const gaugeX = startX + currentRodWidth + 10;
                    const gaugeY = rodY + rodHeight / 2;
                    ctx.save();
                    // Draw contact plunger pin pressed against rod end
                    ctx.fillStyle = '#94a3b8';
                    ctx.fillRect(startX + currentRodWidth, gaugeY - 3, 22, 6);
                    ctx.strokeStyle = '#475569';
                    ctx.lineWidth = 1.5;
                    ctx.strokeRect(startX + currentRodWidth, gaugeY - 3, 22, 6);
                    // Dial body
                    const dialR = 24;
                    const dialCx = gaugeX + dialR + 10;
                    const dialCy = gaugeY;
                    ctx.beginPath();
                    ctx.arc(dialCx, dialCy, dialR, 0, Math.PI * 2);
                    ctx.fillStyle = '#ffffff';
                    ctx.fill();
                    ctx.strokeStyle = '#334155';
                    ctx.lineWidth = 2.5;
                    ctx.stroke();
                    // Dial grad ticks
                    ctx.strokeStyle = '#475569';
                    ctx.lineWidth = 1;
                    for (let ti = 0; ti < 12; ti++) {
                        const tickAng = (ti * Math.PI * 2) / 12;
                        ctx.beginPath();
                        ctx.moveTo(dialCx + dialR * Math.cos(tickAng), dialCy + dialR * Math.sin(tickAng));
                        ctx.lineTo(dialCx + (dialR - 4) * Math.cos(tickAng), dialCy + (dialR - 4) * Math.sin(tickAng));
                        ctx.stroke();
                    }
                    // Rotating indicator hand
                    // Rotates 360deg for every 10mm of expansion
                    const handAngle = (deltaL / 10.0) * Math.PI * 2;
                    ctx.strokeStyle = '#ef4444';
                    ctx.lineWidth = 2;
                    ctx.beginPath();
                    ctx.moveTo(dialCx, dialCy);
                    ctx.lineTo(dialCx + (dialR - 6) * Math.cos(handAngle), dialCy + (dialR - 6) * Math.sin(handAngle));
                    ctx.stroke();
                    // Dial hub pin
                    ctx.fillStyle = '#0f172a';
                    ctx.beginPath();
                    ctx.arc(dialCx, dialCy, 3, 0, Math.PI * 2);
                    ctx.fill();
                    ctx.restore();
                    ctx.fillStyle = '#64748b';
                    ctx.font = 'bold 9px sans-serif';
                    ctx.textAlign = 'center';
                    ctx.fillText('마이크로미터 변위계', dialCx, dialCy + dialR + 13);
                    // Visual Temperature Gradient Coloring bar (Repositioned to top-left corner)
                    ctx.save();
                    ctx.font = 'bold 11px Outfit';
                    ctx.fillStyle = '#64748b';
                    ctx.textAlign = 'left';
                    const tempBarX = 24;
                    const tempBarY = 40;
                    const tempBarW = 130;
                    const tempBarH = 6;
                    ctx.fillText(`현재 온도: ${state.t2}°C`, tempBarX, tempBarY - 10);
                    ctx.fillStyle = '#e2e8f0';
                    ctx.fillRect(tempBarX, tempBarY, tempBarW, tempBarH);
                    const barGrad = ctx.createLinearGradient(tempBarX, tempBarY, tempBarX + tempBarW, tempBarY);
                    barGrad.addColorStop(0, '#38bdf8');
                    barGrad.addColorStop(0.5, '#e2e8f0');
                    barGrad.addColorStop(1, '#ef4444');
                    ctx.fillStyle = barGrad;
                    ctx.fillRect(tempBarX, tempBarY, tempBarW, tempBarH);
                    // Draw marker pointer for current temperature T2
                    const normalizedT2 = (state.t2 - (-50)) / 550; // -50 to 500 scale
                    const markerX = tempBarX + Math.min(Math.max(normalizedT2, 0), 1.0) * tempBarW;
                    ctx.fillStyle = '#0f172a';
                    ctx.beginPath();
                    ctx.moveTo(markerX, tempBarY - 2);
                    ctx.lineTo(markerX - 4, tempBarY - 7);
                    ctx.lineTo(markerX + 4, tempBarY - 7);
                    ctx.closePath();
                    ctx.fill();
                    ctx.restore();
                    // Rod Dimensions scale line underneath (L0, Delta L, and Final L)
                    ctx.save();
                    // 1. Vertical guide lines (dashed)
                    ctx.strokeStyle = 'rgba(148, 163, 184, 0.35)';
                    ctx.lineWidth = 1;
                    ctx.setLineDash([3, 3]);
                    // Start guide line (startX)
                    ctx.beginPath();
                    ctx.moveTo(startX, rodY + rodHeight);
                    ctx.lineTo(startX, rodY + rodHeight + 63);
                    ctx.stroke();
                    // Initial length guide line (startX + baseWidth)
                    ctx.beginPath();
                    ctx.moveTo(startX + baseWidth, rodY);
                    ctx.lineTo(startX + baseWidth, rodY + rodHeight + 43);
                    ctx.stroke();
                    // Final end-point guide line (startX + currentRodWidth)
                    ctx.beginPath();
                    ctx.moveTo(startX + currentRodWidth, rodY);
                    ctx.lineTo(startX + currentRodWidth, rodY + rodHeight + 63);
                    ctx.stroke();
                    ctx.setLineDash([]);
                    // 2. Initial Length dimension line (L₀) - Level 1 (dimY1)
                    const dimY1 = rodY + rodHeight + 20;
                    ctx.strokeStyle = '#64748b';
                    ctx.lineWidth = 1;
                    ctx.beginPath();
                    ctx.moveTo(startX, dimY1);
                    ctx.lineTo(startX + baseWidth, dimY1);
                    ctx.stroke();
                    // Arrowheads
                    drawArrowhead(ctx, startX, dimY1, Math.PI);
                    drawArrowhead(ctx, startX + baseWidth, dimY1, 0);
                    // L₀ text label
                    ctx.fillStyle = '#475569';
                    ctx.font = '500 10px Inter';
                    ctx.textAlign = 'center';
                    ctx.fillText(`초기 L₀ = ${state.l0.toFixed(1)} m`, startX + baseWidth / 2, dimY1 - 4);
                    // 3. Changed/Increased Length dimension line (ΔL) - Level 2 (dimY2)
                    if (Math.abs(visualExpansion) > 3) {
                        const dimY2 = rodY + rodHeight + 40;
                        const isExpansion = deltaL >= 0;
                        ctx.strokeStyle = isExpansion ? '#db2777' : '#0284c7';
                        ctx.lineWidth = 1.2;
                        const expStartX = isExpansion ? startX + baseWidth : startX + currentRodWidth;
                        const expEndX = isExpansion ? startX + currentRodWidth : startX + baseWidth;
                        ctx.beginPath();
                        ctx.moveTo(expStartX, dimY2);
                        ctx.lineTo(expEndX, dimY2);
                        ctx.stroke();
                        drawArrowhead(ctx, expStartX, dimY2, Math.PI);
                        drawArrowhead(ctx, expEndX, dimY2, 0);
                        ctx.fillStyle = isExpansion ? '#db2777' : '#0284c7';
                        ctx.font = 'bold 10px Inter';
                        ctx.textAlign = 'center';
                        const sign = isExpansion ? '+' : '';
                        ctx.fillText(`ΔL = ${sign}${deltaL.toFixed(2)} mm`, expStartX + Math.abs(visualExpansion) / 2, dimY2 - 4);
                    }
                    // 4. Total Final Length dimension line (L) - Level 3 (dimY3)
                    const dimY3 = rodY + rodHeight + 60;
                    ctx.strokeStyle = '#334155';
                    ctx.lineWidth = 1.2;
                    ctx.beginPath();
                    ctx.moveTo(startX, dimY3);
                    ctx.lineTo(startX + currentRodWidth, dimY3);
                    ctx.stroke();
                    // vertical ticks
                    ctx.beginPath();
                    ctx.moveTo(startX, dimY3 - 4); ctx.lineTo(startX, dimY3 + 4);
                    ctx.moveTo(startX + currentRodWidth, dimY3 - 4); ctx.lineTo(startX + currentRodWidth, dimY3 + 4);
                    ctx.stroke();
                    // Final L text
                    ctx.fillStyle = '#0f172a';
                    ctx.font = 'bold 11px monospace';
                    ctx.textAlign = 'center';
                    ctx.fillText(`최종 L = ${finalL.toFixed(5)} m`, startX + currentRodWidth / 2, dimY3 + 14);
                    ctx.restore();
                }
                // Event Listeners mapping
                sliderL0.addEventListener('input', syncL0FromSlider);
                inputL0.addEventListener('change', syncL0FromInput);
                sliderT1.addEventListener('input', syncT1FromSlider);
                inputT1.addEventListener('change', syncT1FromInput);
                sliderT2.addEventListener('input', syncT2FromSlider);
                inputT2.addEventListener('change', syncT2FromInput);
                selectMaterial.addEventListener('change', handleMaterialChange);
                presetBtns.forEach(btn => {
                    btn.addEventListener('click', function() {
                        loadPreset(btn.dataset.preset);
                    });
                });
                // Initial run
                handleMaterialChange();
                requestAnimationFrame(animate);
                // Anti-copying / Context protection code
                document.addEventListener('contextmenu', function(e) {
                    e.preventDefault();
                    alert("이 시뮬레이터 프로그램의 지식재산권은 보호받고 있습니다.");
                    return false;
                }, { capture: true });
                document.addEventListener('selectstart', function(e) {
                    e.preventDefault();
                    return false;
                }, { capture: true });
                document.addEventListener('keydown', function(e) {
                    if (e.key === 'F12') {
                        e.preventDefault();
                        alert("이 시뮬레이터 프로그램의 지식재산권은 보호받고 있습니다.");
                        return false;
                    }
                    if (e.ctrlKey) {
                        if (e.key === 'u' || e.key === 'c' || e.key === 's' || e.key === 'U' || e.key === 'C' || e.key === 'S') {
                            e.preventDefault();
                            alert("이 시뮬레이터 프로그램의 지식재산권은 보호받고 있습니다.");
                            return false;
                        }
                    }
                }, { capture: true });
            }
            // Retry loader sequence
            let loadAttempts = 0;
            function tryLoad() {
                loadAttempts++;
                initSimulator();
                if (!window.__thermalexpansion_initialized) {
                    if (loadAttempts < 50) {
                        setTimeout(tryLoad, 100);
                    }
                }
            }
            if (document.readyState === 'complete' || document.readyState === 'interactive') {
                tryLoad();
            } else {
                document.addEventListener('DOMContentLoaded', tryLoad);
                window.addEventListener('load', tryLoad);
            }
        })();
</script>


<div style="background: linear-gradient(135deg, rgba(0,242,254,0.03), rgba(138,43,226,0.03)); border: 1px solid rgba(0,242,254,0.15); border-radius: 12px; padding: 18px 24px; margin: 25px auto 35px auto; font-size: 0.95em; color: #4b5563; line-height: 1.7; font-family: sans-serif;">
    <strong style="color: #1f2937; font-size: 1.05em; display: flex; align-items: center; gap: 8px;">
        <span style="font-size: 1.2em;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /></span> 간편 사용 설명서
    </strong>
    <ol style="margin: 10px 0 0 0; padding-left: 20px;">
        <li style="margin-bottom: 6px;"><strong>재질 선택: 강철, 구리, 알루미늄, 황동 등 분석할 금속을 선택하여 고유 선팽창계수(α)를 적용합니다.</strong></li>
<li style="margin-bottom: 6px;">초기 조건 설정: 봉의 초기 길이(L₀)와 초기 온도(T₁)를 슬라이더 또는 텍스트 입력으로 설정합니다.</li>
<li style="margin-bottom: 6px;">대상 온도 제어: 가열 또는 냉각할 최종 온도(T₂)를 조절하면 봉 아래에 가스 버너 불꽃이나 얼음 결정이 렌더링됩니다.</li>
<li style="margin-bottom: 6px;">실시간 팽창 변위 측정: 정밀 다이얼 게이지와 현미경 뷰를 통해 마이크로미터 및 밀리미터 단위로 미세하게 늘어나고 줄어드는 봉의 길이를 확인합니다.</li>
    </ol>
</div>


<details class="premium-seo-accordion" style="border: 1px solid rgba(0,0,0,0.08); border-radius: 12px; background: #fbfbfc; padding: 0; margin: 30px auto; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.01); font-family: sans-serif;">
    <summary style="display: flex; justify-content: space-between; align-items: center; padding: 20px 24px; font-size: 1.1em; font-weight: 700; color: #1f2937; cursor: pointer; user-select: none; outline: none; list-style: none;">
        <span><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4da.png" alt="📚" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 선팽창계수 공식 및 재료별 열팽창 특성 해설 보기</span>
        <span class="accordion-arrow" style="font-size: 0.9em; color: #9ca3af; transition: transform 0.2s ease;">▼</span>
    </summary>
    <div style="padding: 0 24px 24px 24px; border-top: 1px solid rgba(0,0,0,0.04); background: #ffffff; border-radius: 0 0 12px 12px; font-size: 0.98em; color: #374151; line-height: 1.8;">
        <div style="margin-top: 20px;">
            <h3>1. 고체 열팽창(Thermal Expansion)의 물리적 근원</h3>
<p>모든 고체 물질은 온도가 상승함에 따라 부피가 팽창하는 성질을 가집니다. 이는 미시적 관점에서 격자 진동(Lattice Vibration)으로 설명됩니다. 고체 내부의 원자들은 원자 간 결합력에 의해 평형 상태의 에너지를 유지하며 진동하고 있습니다. 에너지가 가해져 온도가 올라가면 원자들의 진동 진폭이 커지게 되는데, 원자 간 비선형 포텐셜 에너지 곡선의 비대칭성 때문에 진동 중심 사이의 평균 거리가 멀어지게 됩니다. 이것이 거시적으로 열팽창으로 관찰되는 물리적 원리입니다.</p><ul><li><strong>선팽창 (Linear Expansion):</strong> 막대나 봉과 같이 길이 방향 차원이 지배적인 물체에서 일어나는 팽창입니다.</li><li><strong>체적팽창 (Volume Expansion):</strong> 3차원 입체 형상 전체의 부피가 팽창하는 것으로, 등방성 고체의 경우 체적팽창계수는 선팽창계수의 약 3배(β ≈ 3α)입니다.</li></ul>
<h3>2. 열팽창 설계 방정식과 변위 유도</h3>
<p>고체의 선팽창 관계식은 온도 변화폭이 아주 크지 않은 경우 다음과 같이 선형 근사로 고도로 정밀하게 예측할 수 있습니다.</p><p><strong>① 선팽창 기본 공식:</strong></p><p style="text-align: center; font-weight: bold; background: #f3f4f6; padding: 12px; border-radius: 8px;">ΔL = α × L₀ × ΔT &nbsp;[mm]</p><p>여기서 <code>α</code>는 선팽창계수(Coefficient of Linear Expansion, K⁻¹ 또는 °C⁻¹), <code>L₀</code>는 초기 온도에서의 길이(m), <code>ΔT</code>는 온도 변화량(T₂ - T₁, °C)입니다.</p><p><strong>② 최종 길이 계산:</strong></p><p style="text-align: center; font-weight: bold; background: #f3f4f6; padding: 12px; border-radius: 8px;">L = L₀ + ΔL = L₀ × (1 + α × ΔT) &nbsp;[m]</p><p><strong>③ 온도 응력 (Thermal Stress):</strong> 만약 양단이 강체 벽으로 구속되어 팽창이 불가능한 상태에서 가열된다면, 팽창하려는 변위만큼 압축 변형률(Strain)이 발생하여 매우 강력한 내력이 발생합니다. 양단 구속 시 발생하는 열응력 공식은 다음과 같습니다:</p><p style="text-align: center; font-weight: bold; background: #e0f2fe; padding: 16px; border-radius: 8px; font-size: 1.05em; color: #0369a1;">σ_t = E × α × ΔT &nbsp;[MPa]</p><p>여기서 <code>E</code>는 금속의 세로탄성계수(Young's Modulus)입니다. 기계 부품 설계 시 이러한 열응력으로 인한 파손을 방지하기 위해 팽창 여유 갭(Thermal Gap)이나 신축 이음(Expansion Joint) 설치가 필수적입니다.</p>
<h3>3. 주요 금속 재료별 열팽창 특성 및 설계 가이드</h3>
<p>다양한 공업용 금속들은 결정 구조와 결합력의 차이로 인해 상이한 선팽창계수를 가집니다. 설계 시 이종 금속 접합 구조물이 온도 변화를 겪을 때 휠 가능성(바이메탈 효과)을 신중히 고려해야 합니다.</p><ul><li><strong>알루미늄 (Aluminum):</strong> 약 23.0 × 10⁻⁶ /°C 로 열팽창이 매우 크며, 경량화 설계 시 갭 설계가 중요합니다.</li><li><strong>황동 (Brass):</strong> 약 19.0 × 10⁻⁶ /°C 로 동합금 특유의 높은 팽창률을 가집니다.</li><li><strong>구리 (Copper):</strong> 약 17.0 × 10⁻⁶ /°C 로 전선 설계 및 배관 매설 시 길이 방향 수축팽창을 고려해야 합니다.</li><li><strong>탄소강 (Steel):</strong> 약 11.5 × 10⁻⁶ /°C 로 상대적으로 낮고 안정적이며 콘크리트의 팽창계수와 유사하여 철근콘크리트 구조가 성립되는 기반이 됩니다.</li></ul>
        </div>
    </div>
</details>
<style>
details.premium-seo-accordion[open] summary .accordion-arrow { transform: rotate(180deg); color: #00f2fe; }
details.premium-seo-accordion summary::-webkit-details-marker { display: none; }
details.premium-seo-accordion:hover { border-color: rgba(0,242,254,0.3); }
</style>

]]></content:encoded>
					
					<wfw:commentRss>https://myengnote.com/thermal-expansion-calculator-simulator/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>열역학 기초: 전도, 대류, 복사의 원리 쉽게 설명</title>
		<link>https://myengnote.com/heat-transfer-conduction-convection-radiation-principles-2/</link>
					<comments>https://myengnote.com/heat-transfer-conduction-convection-radiation-principles-2/#respond</comments>
		
		<dc:creator><![CDATA[동동]]></dc:creator>
		<pubDate>Thu, 29 Jan 2026 21:22:45 +0000</pubDate>
				<category><![CDATA[재료/후처리]]></category>
		<category><![CDATA[Conduction]]></category>
		<category><![CDATA[Convection]]></category>
		<category><![CDATA[Heat Transfer]]></category>
		<category><![CDATA[Radiation]]></category>
		<category><![CDATA[Thermodynamics]]></category>
		<category><![CDATA[대류]]></category>
		<category><![CDATA[복사]]></category>
		<category><![CDATA[열역학]]></category>
		<category><![CDATA[열전달]]></category>
		<category><![CDATA[전도]]></category>
		<guid isPermaLink="false">https://myengnote.com/heat-transfer-conduction-convection-radiation-principles-2/</guid>

					<description><![CDATA[뜨거운 물체의 열이 전달되는 세 가지 방법, 전도, 대류, 복사를 쉽게 설명합니다. 설비 설계 및 효율 개선을 위한 열역학 기초 원리를 실무적으로 파헤쳐 봅니다.... <a href="https://myengnote.com/heat-transfer-conduction-convection-radiation-principles-2/" style="text-decoration:none; color:#0073aa; font-weight:bold;">[본문 전체보기 >]</a>]]></description>
										<content:encoded><![CDATA[<p>제가 15년 전 조선소 근무 당시, 핵심 고온 반응기 RX-400이 갑작스러운 과열로 멈춰 수억 원의 생산 손실을 경험한 적이 있습니다. 설계대로라면 외벽 온도가 50°C를 넘지 않아야 했지만, 실제로는 120°C까지 치솟았죠. 이 문제의 원인은 복잡한 제어 시스템 오류가 아닌, 가장 기초적인 열역학 원리, 즉 &#8216;대류&#8217;에 대한 오해석 때문이었습니다. 엔지니어링에서 열역학의 기초를 이해하는 것은 단순한 이론 학습을 넘어, 장비의 수명과 공정 효율을 결정짓는 핵심 요소입니다. 특히 열전달의 세 가지 기본 방식인 전도, 대류, 복사의 원리를 정확히 구분해야만 효과적인 냉각 및 단열 설계를 할 수 있습니다.</p>
<h2>열전달 3대 요소 비교표</h2>
<p>장비 설계를 담당하거나 유지보수를 수행하는 실무자라면, 이 세 가지 열전달 메커니즘이 어떻게 작동하고 서로 어떻게 상호작용하는지 반드시 파악해야 합니다. 특히 고온 환경 장비의 열관리 계획을 세울 때 이 표는 기본적인 판단 기준을 제공합니다.</p>
<div style="overflow-x: auto; white-space: nowrap;">
<div style="overflow-x: auto; white-space: nowrap; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); margin: 20px 0; border: 1px solid #e5e7eb;">
<table style="border-collapse: collapse; width: 100%; min-width: 700px; font-size: 15px; text-align: left; background-color: #ffffff;" border="1" width="100%" cellpadding="10" cellspacing="0">
<thead>
<tr style="background-color: #1f2937;">
<th style="padding: 15px; border-bottom: 3px solid #3b82f6; background-color: #1f2937; color: #ffffff; font-weight: bold; text-transform: uppercase; letter-spacing: 0.05em;">구분</th>
<th style="padding: 15px; border-bottom: 3px solid #10b981; background-color: #1f2937; color: #ffffff; font-weight: bold; text-transform: uppercase; letter-spacing: 0.05em;">전도</th>
<th style="padding: 15px; border-bottom: 3px solid #f59e0b; background-color: #1f2937; color: #ffffff; font-weight: bold; text-transform: uppercase; letter-spacing: 0.05em;">대류</th>
<th style="padding: 15px; border-bottom: 3px solid #8b5cf6; background-color: #1f2937; color: #ffffff; font-weight: bold; text-transform: uppercase; letter-spacing: 0.05em;">복사</th>
</tr>
</thead>
<tbody>
<tr>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563; background-color: #f9fafb; font-weight: bold; color: #374151;">정의</td>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563;">매질 내 분자 또는 원자의 진동과 충돌을 통해 열이 이동 (고체 지배적)</td>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563;">유체(액체, 기체)의 실제 흐름(이동)을 통해 열이 전달</td>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563;">매질 없이 전자기파 형태로 열 에너지가 방출 및 흡수</td>
</tr>
<tr>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563; background-color: #f9fafb; font-weight: bold; color: #374151;">매질의 역할</td>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563;">필수 (고정된 매질)</td>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563;">필수 (움직이는 유체)</td>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563;">불필요 (진공에서도 전달 가능)</td>
</tr>
<tr>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563; background-color: #f9fafb; font-weight: bold; color: #374151;">핵심 원리</td>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563;">푸리에의 법칙 (열전도율, 온도 기울기)</td>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563;">뉴턴의 냉각 법칙 (유체 속도, 열전달 계수)</td>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563;">슈테판-볼츠만 법칙 (절대 온도 4제곱)</td>
</tr>
<tr>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563; background-color: #f9fafb; font-weight: bold; color: #374151;">실제 예시</td>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563;">쇠 막대기 한쪽 끝을 가열하면 다른 쪽이 뜨거워짐</td>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563;">주전자에 물을 끓이거나, 선풍기로 모터를 식히는 행위</td>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563;">햇빛, 난로 앞의 따뜻함, 고온 용광로의 열 방출</td>
</tr>
<tr>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563; background-color: #f9fafb; font-weight: bold; color: #374151;">설계 적용</td>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563;">단열재 선정 (낮은 열전도율 재료 사용)</td>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563;">냉각 핀, 팬, 펌프 설계 (유체 흐름 극대화)</td>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; color: #4b5563;">표면 색상 및 재질 코팅 (방사율 제어)</td>
</tr>
</tbody>
</table>
</div>
</div>
<h2>열전달 원리의 물리학적 이해</h2>
<p>이 세 가지 방식은 근본적으로 에너지가 어떻게 전달되는가에 대한 분자 수준의 차이를 보여줍니다. 이 차이를 명확히 이해해야만 비로소 &#8216;왜 이 장비에는 팬이 필요한지&#8217; 또는 &#8216;왜 이 재료를 써야 하는지&#8217;에 대한 설득력 있는 답을 찾을 수 있습니다.</p>
<h3>전도</h3>
<p>고체 내부의 미세 진동 전도는 매질이 움직이지 않고 에너지만 전달되는 방식입니다. 금속 같은 고체에서 열이 잘 전달되는 이유는 자유 전자가 에너지를 빠르게 운반하거나, 원자들이 강하게 결합되어 있어 진동 에너지를 효율적으로 이웃에게 전달하기 때문입니다.</p>
<div style="border-left: 5px solid #f59e0b; background-color: #fffbeb; padding: 15px; margin: 30px 0; border-radius: 10px; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);">
<div style="display: flex; align-items: center; margin-bottom: 12px;"><span style="font-size: 30px; margin-right: 15px;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /></span><span style="font-weight: bold; color: #92400e; font-size: 1.2em;">현장 전문가의 팁</span></div>
<div style="color: #444; line-height: 1.8; font-size: 1.05em;">장비의 볼트 체결 부위나 접촉면은 열 전달의 주요 경로(전도)가 됩니다. 따라서 열 민감 부품을 체결할 때는 열전도율이 낮은 와셔나 개스킷을 사용하여 열 전달 경로를 차단하는 것이 중요합니다. 미세한 접촉 저항을 관리하는 것이 큰 열 손실을 막는 핵심입니다.</div>
</p>
</div>
<h3>대류</h3>
<p>유체의 질량 이동 대류는 열이 유체의 움직임 그 자체에 의해 운반되는 현상입니다. 뜨거워진 유체는 밀도가 낮아져 상승하고, 차가운 유체는 밀도가 높아져 하강하면서 순환이 발생합니다. 이것을 자연 대류라고 하며, 냉각 팬이나 펌프를 사용하여 강제로 유체를 이동시키는 것을 강제 대류라고 합니다. 산업 현장에서는 대부분 냉각수 펌프(강제 대류)나 공기 순환 팬(강제/자연 대류 복합)을 이용해 장비의 열을 외부로 방출합니다. 유체의 흐름 속도(유속)와 접촉 면적을 극대화하는 것이 대류 냉각 효율을 높이는 핵심입니다.</p>
<h3>복사</h3>
<p>절대 온도의 4제곱 법칙 복사는 매질이 없어도 열이 전달되는 유일한 방식입니다. 모든 물체는 절대 온도 0K(켈빈) 이상이면 전자기파를 방출하며, 온도가 높을수록 방출하는 에너지의 양이 기하급수적으로 증가합니다 (T<sup>4</sup>). 고온 공정에서는 전도나 대류보다 복사가 주요한 열전달 방식으로 작용합니다. 용광로나 보일러 근처에서 작업할 때 느껴지는 뜨거운 열기가 바로 복사열입니다. 복사열을 제어하기 위해서는 물체의 표면 상태(색상, 방사율)를 조절해야 합니다. 광택이 있는 흰색 표면은 복사열을 잘 반사하고, 어둡고 무광인 표면은 복사열을 잘 흡수하고 방출합니다.</p>
<div style="border-left: 5px solid #3b82f6; background-color: #eff6ff; padding: 15px; margin: 30px 0; border-radius: 10px; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);">
<div style="display: flex; align-items: center; margin-bottom: 12px;"><span style="font-size: 30px; margin-right: 15px;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4d8.png" alt="📘" class="wp-smiley" style="height: 1em; max-height: 1em;" /></span><span style="font-weight: bold; color: #1e40af; font-size: 1.2em;">핵심 요약</span></div>
<div style="color: #444; line-height: 1.8; font-size: 1.05em;">전도는 &#8216;접촉&#8217;과 &#8216;재료&#8217;에 의존하고, 대류는 &#8216;흐름&#8217;과 &#8216;유속&#8217;에 의존하며, 복사는 &#8216;온도&#8217;와 &#8216;표면 특성&#8217;에 의해 결정됩니다. 열 관리 설계 시 이 세 요소를 동시에 고려해야 합니다.</div>
</p>
</div>
<h2>현장 문제 해결</h2>
<p>RX-400 반응기 과열 분석 앞서 언급했던 고온 반응기 RX-400 과열 사례를 열전달 원리에 비추어 분석해 보겠습니다. 이 반응기는 내부 온도가 높아 전도와 복사열이 외벽으로 전달되는 것을 막기 위해 두꺼운 단열재가 사용되었습니다. 하지만 이 단열재 외부에는 자연 대류를 이용한 공랭식 냉각 핀이 설치되어 있었습니다.</p>
<p><img loading="lazy" decoding="async" width="1024" height="613" src="https://myengnote.com/wp-content/uploads/2026/01/Gemini_Generated_Image_rbjq7orbjq7orbjq-1024x613.jpg" alt="열전달방식 이미지" class="wp-image-1179" srcset="https://myengnote.com/wp-content/uploads/2026/01/Gemini_Generated_Image_rbjq7orbjq7orbjq-1024x613.jpg 1024w, https://myengnote.com/wp-content/uploads/2026/01/Gemini_Generated_Image_rbjq7orbjq7orbjq-300x180.jpg 300w, https://myengnote.com/wp-content/uploads/2026/01/Gemini_Generated_Image_rbjq7orbjq7orbjq-768x460.jpg 768w, https://myengnote.com/wp-content/uploads/2026/01/Gemini_Generated_Image_rbjq7orbjq7orbjq.jpg 1200w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<h3>대류 경로 막힘이 낳은 치명적 오류</h3>
<p>문제는 정기 유지보수 시 외벽 단열 덮개를 교체하는 과정에서 발생했습니다. 신규 설치된 덮개가 규격보다 두꺼웠거나 잘못 장착되어 냉각 핀과 덮개 사이의 간격(에어 갭)이 좁아지게 된 것입니다. 이 좁아진 간격은 공기가 아래에서 위로 자연스럽게 흐르며 열을 빼앗아가는 <strong>자연 대류의 경로</strong>를 심각하게 방해했습니다.</p>
<ul>
<li><strong>정상 상태:</strong> 공기가 충분한 속도로 흐르면서 냉각 핀의 열(전도된 열)을 외부로 효과적으로 전달.</li>
<li><strong>고장 상태:</strong> 덮개에 막혀 공기 흐름이 정체되면서 핀 근처의 공기가 뜨거워진 채 머무름. 이는 핀과 공기 사이의 온도 차를 줄여 대류 효율을 90% 이상 급감시킴.</li>
</ul>
<div style="border-left: 5px solid #ef4444; background-color: #fef2f2; padding: 15px; margin: 30px 0; border-radius: 10px; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);">
<div style="display: flex; align-items: center; margin-bottom: 12px;"><span style="font-size: 30px; margin-right: 15px;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /></span><span style="font-weight: bold; color: #991b1b; font-size: 1.2em;">주의사항</span></div>
<div style="color: #444; line-height: 1.8; font-size: 1.05em;">냉각 설계 시, 대류를 위해 확보한 에어 갭을 임의로 줄이거나 막으면 안 됩니다. 특히 자연 대류는 유체의 밀도 변화에 의존하므로, 공기 흡입구와 배출구의 압력 차이와 경로 확보가 생명입니다. 유지보수 시 원 설계 도면에 명시된 최소 간격(mm 단위)을 철저히 준수해야 합니다.</div>
</p>
</div>
<p>결국, 내부 단열재는 제 역할을 했지만, 외벽의 열을 외부로 방출시키는 핵심 매커니즘인 &#8216;대류&#8217;가 차단되면서 전체 장비의 열 균형이 무너진 것입니다. 열역학 기초 원리에 입각하여 냉각 경로를 다시 확보해 준 후에야 반응기는 정상 온도를 회복할 수 있었습니다.</p>
<h2>마치며</h2>
<p>저는 엔지니어링 경력 20년 동안, 복잡하고 값비싼 부품보다 기본 원리를 간과하여 발생하는 단순한 오류들이 훨씬 큰 손실을 초래하는 것을 수없이 보았습니다. 열전달 원리, 즉 전도, 대류, 복사는 장비의 열적 안정성을 확보하는 알파이자 오메가입니다. 특히, 고온 장비의 안정성을 판단할 때는 세 가지 요소를 독립적으로 보지 말고, <strong>장비의 어떤 부분이 전도, 대류, 복사의 어느 영역에서 지배적인가</strong>를 정확히 분석하여 설계해야 합니다. 전도를 막기 위해 단열재를 보강했다면, 그 단열재가 복사열을 효율적으로 방출할 수 있는 표면 특성을 가졌는지 점검하고, 필요한 경우 대류 경로가 확보되었는지 확인해야 합니다. 이러한 통합적 접근이 현장 문제를 해결하는 진정한 기술력입니다.</p>
<hr/>
<p><a href="https://myengnote.com/first-law-of-thermodynamics-energy-conservation-guide/" style="text-decoration: none; background-color: #ffffff; border: 1px solid #e5e7eb; border-radius: 8px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); padding: 15px; margin: 10px 0; transition: box-shadow 0.2s; display: table; width: 100%; box-sizing: border-box;"><span style="display: table-cell; vertical-align: middle;"><span style="font-size: 30px; margin-right: 15px; float: left;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f517.png" alt="🔗" class="wp-smiley" style="height: 1em; max-height: 1em;" /></span><span style="display: block; overflow: hidden;"><span style="display: block; font-size: 0.9em; color: #6b7280; margin-bottom: 4px;">함께 보면 좋은 글</span><span style="display: block; font-size: 1.1em; font-weight: bold; color: #111827;">열역학 제1법칙: 에너지 보존 원리</span></span></span><span style="display: table-cell; vertical-align: middle; width: 40px; text-align: right; color: #3b82f6; font-size: 24px; font-weight: bold;">→</span></a><a href="https://myengnote.com/lubricant-viscosity-selection-failure-fatal-impacts/" style="text-decoration: none; background-color: #ffffff; border: 1px solid #e5e7eb; border-radius: 8px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); padding: 15px; margin: 10px 0; transition: box-shadow 0.2s; display: table; width: 100%; box-sizing: border-box;"><span style="display: table-cell; vertical-align: middle;"><span style="font-size: 30px; margin-right: 15px; float: left;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f517.png" alt="🔗" class="wp-smiley" style="height: 1em; max-height: 1em;" /></span><span style="display: block; overflow: hidden;"><span style="display: block; font-size: 0.9em; color: #6b7280; margin-bottom: 4px;">함께 보면 좋은 글</span><span style="display: block; font-size: 1.1em; font-weight: bold; color: #111827;">윤활유 점도 선택 실패의 치명적 영향 3가지</span></span></span><span style="display: table-cell; vertical-align: middle; width: 40px; text-align: right; color: #3b82f6; font-size: 24px; font-weight: bold;">→</span></a></p>
<h2>연관글</h2>
<p><a href="https://myengnote.com/safety-factor-mechanical-design-guide/" style="text-decoration: none; background-color: #ffffff; border: 1px solid #e5e7eb; border-radius: 8px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); padding: 15px; margin: 10px 0; transition: box-shadow 0.2s; display: table; width: 100%; box-sizing: border-box;"><span style="display: table-cell; vertical-align: middle;"><span style="font-size: 30px; margin-right: 15px; float: left;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f517.png" alt="🔗" class="wp-smiley" style="height: 1em; max-height: 1em;" /></span><span style="display: block; overflow: hidden;"><span style="display: block; font-size: 0.9em; color: #6b7280; margin-bottom: 4px;">함께 보면 좋은 글</span><span style="display: block; font-size: 1.1em; font-weight: bold; color: #111827;">안전율: 설계자를 위한 실무 해설</span></span></span><span style="display: table-cell; vertical-align: middle; width: 40px; text-align: right; color: #3b82f6; font-size: 24px; font-weight: bold;">→</span></a></p>
<hr style="border: 0; border-top: 1px solid #eee; margin: 40px 0 20px 0;">
<p style="text-align: center; font-size: 0.85em; color: #888; margin-bottom: 20px;">
    본 콘텐츠는 저작권법의 보호를 받으며, 무단 전재 및 재배포를 금지합니다.<br />
    Copyright 2026. 동동 All rights reserved.
</p>
<p><!-- Protection Scripts --></p>
<div id="protection-script" style="display:none;">
<script>
document.addEventListener('contextmenu', function(e) {
    e.preventDefault();
    alert('이 콘텐츠는 저작권법의 보호를 받습니다. 무단 복제 및 우클릭을 금지합니다.');
});
document.addEventListener('keydown', function(e) {
    if (e.ctrlKey && (e.key === 'c' || e.key === 'u' || e.key === 'a')) {
        e.preventDefault();
        alert('무단 복제를 금지합니다.');
    }
});
</script></p>
<style>
.entry-content {
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
</style>
</div>
<p><!-- START_SIMULATOR_LINK_CARD_heat_transfer --><a href="https://myengnote.com/heat-transfer-conduction-calculator/" target="_blank" rel="noopener noreferrer" class="eng-simulator-card" style="text-decoration: none; background-color: #ffffff; border: 1px solid #e5e7eb; border-radius: 8px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); padding: 15px; margin: 10px 0; transition: box-shadow 0.2s; display: table; width: 100%; box-sizing: border-box;"><span style="display: table-cell; vertical-align: middle;"><span style="font-size: 30px; margin-right: 15px; float: left;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9ee.png" alt="🧮" class="wp-smiley" style="height: 1em; max-height: 1em;" /></span><span style="display: block; overflow: hidden;"><span style="display: block; font-size: 0.9em; color: #10b981; font-weight: bold; margin-bottom: 4px;">실시간 공학 시뮬레이터 추천</span><span style="display: block; font-size: 1.1em; font-weight: bold; color: #111827;">열관류 및 벽체 열전달 계산기 &#038; 실시간 온도 구배 시뮬레이터</span></span></span><span style="display: table-cell; vertical-align: middle; width: 40px; text-align: right; color: #10b981; font-size: 24px; font-weight: bold;">→</span></a><!-- END_SIMULATOR_LINK_CARD_heat_transfer --></p>
]]></content:encoded>
					
					<wfw:commentRss>https://myengnote.com/heat-transfer-conduction-convection-radiation-principles-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
