<?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%EA%B5%90%ED%99%98%EA%B8%B0/feed/" rel="self" type="application/rss+xml" />
	<link>https://myengnote.com</link>
	<description></description>
	<lastBuildDate>Wed, 08 Jul 2026 04:42:15 +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/heat-exchanger-lmtd-ntu-calculator/</link>
					<comments>https://myengnote.com/heat-exchanger-lmtd-ntu-calculator/#respond</comments>
		
		<dc:creator><![CDATA[동동]]></dc:creator>
		<pubDate>Mon, 22 Jun 2026 21:32:05 +0000</pubDate>
				<category><![CDATA[공학계산기]]></category>
		<category><![CDATA[LMTD]]></category>
		<category><![CDATA[NTU]]></category>
		<category><![CDATA[대향류]]></category>
		<category><![CDATA[열교환기]]></category>
		<category><![CDATA[평행류]]></category>
		<guid isPermaLink="false">https://myengnote.com/heat-exchanger-lmtd-ntu-calculator/</guid>

					<description><![CDATA[대향류와 평행류 배열에 따른 이중관 열교환기의 출구 온도, 전열량, 대수평균온도차(LMTD) 및 유용도(NTU)를 실시간 수치 해석하고 동적 온도 구배를 시각화하는 계산기입니다.]]></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 heatexchanger-calculator-wrapper */
        /* Modern Reset and Design Tokens */
        .heatexchanger-calculator-wrapper *, .heatexchanger-calculator-wrapper *::before, .heatexchanger-calculator-wrapper *::after {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        .heatexchanger-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);
        }
        .heatexchanger-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(2, 132, 199, 0.08) 0%, rgba(124, 58, 237, 0.03) 100%);
            border: 1px solid rgba(2, 132, 199, 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: #0284c7;
            letter-spacing: 1px;
            text-transform: uppercase;
        }
        .ratio-value {
    font-family: var(--font-heading);
    font-weight: 800;
    font-size: 26px;
    background: linear-gradient(90deg, var(--color-text-main), var(--color-cyan));
    -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(2, 132, 199, 0.2);
            background: rgba(2, 132, 199, 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: #0284c7;
            border-color: rgba(2, 132, 199, 0.3);
            background: rgba(2, 132, 199, 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 exchanger-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 exchanger-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열 컴팩트 대칭 레이아웃) ━━ */
.heatexchanger-calculator-wrapper .app-main-grid,
.heatexchanger-calculator-wrapper .main-grid,
.heatexchanger-calculator-wrapper .sim-grid {
    display: grid !important;
    grid-template-columns: 340px 1fr !important;
    gap: 24px !important;
    align-items: start !important;
}
/* 3열 레이아웃을 2열 레이아웃으로 변경하는 특화 스타일 */
.heatexchanger-calculator-wrapper .right-column {
    display: flex !important;
    flex-direction: column !important;
    gap: 24px !important;
    min-width: 0 !important;
    grid-column: 2 !important;
}
.heatexchanger-calculator-wrapper .simulation-panel,
.heatexchanger-calculator-wrapper .canvas-panel,
.heatexchanger-calculator-wrapper .sim-panel {
    grid-column: auto !important;
    order: 1 !important;
    align-self: stretch !important;
}
.heatexchanger-calculator-wrapper .control-panel {
    grid-column: 1 !important;
}
/* 2열 통합 결과 분석 영역 레이아웃 */
.heatexchanger-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 스타일 */
.heatexchanger-calculator-wrapper .simulation-results-section .ratio-readout-box,
.heatexchanger-calculator-wrapper .simulation-results-section .re-readout-box,
.heatexchanger-calculator-wrapper .simulation-results-section .status-readout-box,
.heatexchanger-calculator-wrapper .simulation-results-section .flow-readout-box,
.heatexchanger-calculator-wrapper .simulation-results-section [class*="readout-box"],
.heatexchanger-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;
}
.heatexchanger-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;
}
.heatexchanger-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;
}
.heatexchanger-calculator-wrapper .simulation-results-section .formula-card {
    grid-column: 1 !important;
    grid-row: 2 !important;
}
/* 모바일/반응형 (800px 이하) ── 항상 세로형(1열) 정렬 및 시뮬레이터 캔버스 최상단 배치 */
@media (max-width: 800px) {
    .heatexchanger-calculator-wrapper .app-main-grid,
    .heatexchanger-calculator-wrapper .main-grid,
    .heatexchanger-calculator-wrapper .sim-grid {
        grid-template-columns: 1fr !important;
        display: flex !important;
        flex-direction: column !important;
    }
    .heatexchanger-calculator-wrapper .control-panel {
        order: 2 !important;
        width: 100% !important;
    }
    .heatexchanger-calculator-wrapper .right-column {
        order: 1 !important;
        width: 100% !important;
        display: flex !important;
        flex-direction: column !important;
    }
    .heatexchanger-calculator-wrapper .simulation-panel,
    .heatexchanger-calculator-wrapper .canvas-panel,
    .heatexchanger-calculator-wrapper .sim-panel,
    .heatexchanger-calculator-wrapper .canvas-section {
        order: -1 !important;
    }
    .heatexchanger-calculator-wrapper .simulation-results-section {
        grid-template-columns: 1fr !important;
    }
    .heatexchanger-calculator-wrapper .simulation-results-section .ratio-readout-box,
    .heatexchanger-calculator-wrapper .simulation-results-section .re-readout-box,
    .heatexchanger-calculator-wrapper .simulation-results-section .status-readout-box,
    .heatexchanger-calculator-wrapper .simulation-results-section .flow-readout-box,
    .heatexchanger-calculator-wrapper .simulation-results-section [class*="readout-box"],
    .heatexchanger-calculator-wrapper .simulation-results-section .gauge-container {
        grid-column: 1 !important;
        grid-row: auto !important;
        height: auto !important;
    }
    .heatexchanger-calculator-wrapper .simulation-results-section .results-grid {
        grid-column: 1 !important;
        grid-row: auto !important;
    }
    .heatexchanger-calculator-wrapper .simulation-results-section .formula-card {
        grid-column: 1 !important;
        grid-row: auto !important;
    }
}
.heatexchanger-calculator-wrapper .app-container,
.heatexchanger-calculator-wrapper .main-container {
    max-width: 100% !important;
    padding: 12px !important;
}
/* Premium Advice/Formula Card & Typography Overrides */
.heatexchanger-calculator-wrapper .simulation-results-section .formula-card,
.heatexchanger-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;
}
.heatexchanger-calculator-wrapper .simulation-results-section .formula-card h4,
.heatexchanger-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;
}
.heatexchanger-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;
}
.heatexchanger-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="heatexchanger-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-arrows-spin"></i></div>
                <div>
                    <h1>HEAT EXCHANGER</h1>
                    <div class="subtitle">이중관 열교환기 설계 계산기 &#038; 실시간 LMTD/NTU 시뮬레이터</div>
                </div>
            </div>
            <div class="header-badge">
                <div class="pulse-dot"></div>
                <div class="badge-text">NTU 평형해석 작동중</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-shuffle text-cyan"></i> 흐름 유동 방식 (Flow Arrangement)</label>
                    </div>
                    <select id="select-flow" class="custom-select">
                        <option value="counter">대향류 (Counter Flow)</option>
                        <option value="parallel">평행류 (Parallel Flow)</option>
                    </select>
                </div>
                <!-- Hot Side Inputs -->
                <div class="input-group">
                    <div class="input-label-row">
                        <label><i class="fa-solid fa-temperature-arrow-up text-magenta"></i> 고온 입구 온도 (T_h,in)</label>
                        <span class="range-helper">Min: 80°C / Max: 250°C</span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-thin" class="custom-number-input" value="150" step="1" min="80" max="250">
                        <span class="unit-badge">°C</span>
                    </div>
                    <input type="range" id="slider-thin" class="custom-slider" value="150" min="80" max="250" step="1">
                </div>
                <div class="input-group">
                    <div class="input-label-row">
                        <label><i class="fa-solid fa-droplet text-magenta"></i> 고온 유체 질량유량 (m_h)</label>
                        <span class="range-helper">Min: 0.1 / Max: 3.0 kg/s</span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-mh" class="custom-number-input" value="1.0" step="0.1" min="0.1" max="3.0">
                        <span class="unit-badge">kg/s</span>
                    </div>
                    <input type="range" id="slider-mh" class="custom-slider" value="1.0" min="0.1" max="3.0" step="0.1">
                </div>
                <!-- Cold Side Inputs -->
                <div class="input-group">
                    <div class="input-label-row">
                        <label><i class="fa-solid fa-temperature-arrow-down text-cyan"></i> 저온 입구 온도 (T_c,in)</label>
                        <span class="range-helper">Min: 5°C / Max: 50°C</span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-tcin" class="custom-number-input" value="20" step="1" min="5" max="50">
                        <span class="unit-badge">°C</span>
                    </div>
                    <input type="range" id="slider-tcin" class="custom-slider" value="20" min="5" max="50" step="1">
                </div>
                <div class="input-group">
                    <div class="input-label-row">
                        <label><i class="fa-solid fa-droplet text-cyan"></i> 저온 유체 질량유량 (m_c)</label>
                        <span class="range-helper">Min: 0.1 / Max: 3.0 kg/s</span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-mc" class="custom-number-input" value="1.5" step="0.1" min="0.1" max="3.0">
                        <span class="unit-badge">kg/s</span>
                    </div>
                    <input type="range" id="slider-mc" class="custom-slider" value="1.5" min="0.1" max="3.0" step="0.1">
                </div>
                <!-- Geometry sizing -->
                <div class="input-group">
                    <div class="input-label-row">
                        <label><i class="fa-solid fa-expand text-cyan"></i> 전열 면적 (A)</label>
                        <span class="range-helper">Min: 0.5 / Max: 8.0 m<sup>2</sup></span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-area" class="custom-number-input" value="2.5" step="0.1" min="0.5" max="8.0">
                        <span class="unit-badge">m<sup>2</sup></span>
                    </div>
                    <input type="range" id="slider-area" class="custom-slider" value="2.5" min="0.5" max="8.0" step="0.1">
                </div>
                <div class="input-group">
                    <div class="input-label-row">
                        <label><i class="fa-solid fa-gauge-high text-cyan"></i> 총괄 열전달계수 (U)</label>
                        <span class="range-helper">Min: 100 / Max: 1200 W/m<sup>2</sup>K</span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-u" class="custom-number-input" value="600" step="50" min="100" max="1200">
                        <span class="unit-badge">W/m<sup>2</sup>K</span>
                    </div>
                    <input type="range" id="slider-u" class="custom-slider" value="600" min="100" max="1200" step="50">
                </div>
                <div class="presets-section">
                    <h3><i class="fa-solid fa-circle-nodes text-purple"></i> 대표 시험 동작 시나리오</h3>
                    <div class="presets-grid">
                        <button class="preset-btn" data-preset="water_counter">
                            <div class="preset-icon"><i class="fa-solid fa-circle-check"></i></div>
                            <div class="preset-details"><span class="preset-name">물-물 대향류 고효율</span><span class="preset-spec">Water-Water</span></div>
                        </button>
                        <button class="preset-btn" data-preset="oil_parallel">
                            <div class="preset-icon"><i class="fa-solid fa-triangle-exclamation"></i></div>
                            <div class="preset-details"><span class="preset-name">오일-물 평행류 저효율</span><span class="preset-spec">Oil-Water</span></div>
                        </button>
                        <button class="preset-btn" data-preset="compact_size">
                            <div class="preset-icon"><i class="fa-solid fa-compress"></i></div>
                            <div class="preset-details"><span class="preset-name">소형 콤팩트 고전열 열교환기</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-area text-cyan"></i>
                                        <h2>동적 대향류/평행류 이중관 시각화 &#038; 온도 거동 그래프</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">TOTAL HEAT TRANSFER RATE</span>
                                    <span id="txt-heat-rate" class="ratio-value">45.8 kW <span>(39,407 kcal/h)</span></span>
                                    <span class="ratio-sub-txt">LMTD-NTU 기하학적 총 전열량</span>
                                </div>
                                <div class="results-grid">
                                    <div class="result-card">
                                        <div class="card-icon"><i class="fa-solid fa-temperature-three-quarters text-magenta"></i></div>
                                        <div class="card-content">
                                            <div class="card-unit">고온 유체 출구 온도 (T_h,out)</div>
                                            <div id="txt-thout" class="card-value">139.1 °C</div>
                                        </div>
                                    </div>
                                    <div class="result-card">
                                        <div class="card-icon"><i class="fa-solid fa-temperature-quarter text-cyan"></i></div>
                                        <div class="card-content">
                                            <div class="card-unit">저온 유체 출구 온도 (T_c,out)</div>
                                            <div id="txt-tcout" class="card-value">27.3 °C</div>
                                        </div>
                                    </div>
                                    <div class="result-card">
                                        <div class="card-icon"><i class="fa-solid fa-gauge"></i></div>
                                        <div class="card-content">
                                            <div class="card-unit">열교환기 유용도 (Effectiveness &#8211; ε)</div>
                                            <div id="txt-effectiveness" class="card-value">55.2 %</div>
                                        </div>
                                    </div>
                                    <div class="result-card">
                                        <div class="card-icon"><i class="fa-solid fa-heading"></i></div>
                                        <div class="card-content">
                                            <div class="card-unit">대수평균온도차 (LMTD)</div>
                                            <div id="txt-lmtd" class="card-value">118.5 °C</div>
                                        </div>
                                    </div>
                                </div>
                                <div class="formula-card">
                                    <h4><i class="fa-solid fa-circle-info text-cyan"></i> NTU 해석 관계 방정식</h4>
                                    <div class="formula-equation">q = ε × C_min × (T_h,in &#8211; T_c,in)</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.__heatexchanger_initialized = true;
                // DOM variables
                const selectFlow = document.getElementById('select-flow');
                const sliderThin = document.getElementById('slider-thin');
                const inputThin = document.getElementById('input-thin');
                const sliderMh = document.getElementById('slider-mh');
                const inputMh = document.getElementById('input-mh');
                const sliderTcin = document.getElementById('slider-tcin');
                const inputTcin = document.getElementById('input-tcin');
                const sliderMc = document.getElementById('slider-mc');
                const inputMc = document.getElementById('input-mc');
                const sliderArea = document.getElementById('slider-area');
                const inputArea = document.getElementById('input-area');
                const sliderU = document.getElementById('slider-u');
                const inputU = document.getElementById('input-u');
                const presetBtns = document.querySelectorAll('.preset-btn');
                // Readout DOMs
                const txtHeatRate = document.getElementById('txt-heat-rate');
                const txtThout = document.getElementById('txt-thout');
                const txtTcout = document.getElementById('txt-tcout');
                const txtEffectiveness = document.getElementById('txt-effectiveness');
                const txtLmtd = document.getElementById('txt-lmtd');
                // Fluids configurations
                const fluids = {
                    hot: { cp: 4184 },  // standard Water cp [J/kgK]
                    cold: { cp: 4184 }
                };
                // State
                const state = {
                    flow: 'counter',
                    thin: 150.0,
                    mh: 1.0,
                    tcin: 20.0,
                    mc: 1.5,
                    area: 2.5,
                    u: 600.0,
                    cph: 4184, // J/kgK
                    cpc: 4184, // J/kgK
                    particles: []
                };
                // Smooth sync values with change-clamping only
                function syncThinFromSlider() {
                    state.thin = parseFloat(sliderThin.value);
                    inputThin.value = Math.round(state.thin);
                    clearPresets();
                    updateCalculations();
                }
                function syncThinFromInput() {
                    let val = parseFloat(inputThin.value);
                    if (isNaN(val)) {
                        val = 150;
                    }
                    if (val < 80) {
                        val = 80;
                    }
                    if (val > 250) {
                        val = 250;
                    }
                    inputThin.value = Math.round(val);
                    sliderThin.value = val;
                    state.thin = val;
                    clearPresets();
                    updateCalculations();
                }
                function syncMhFromSlider() {
                    state.mh = parseFloat(sliderMh.value);
                    inputMh.value = state.mh.toFixed(1);
                    clearPresets();
                    updateCalculations();
                }
                function syncMhFromInput() {
                    let val = parseFloat(inputMh.value);
                    if (isNaN(val)) {
                        val = 1.0;
                    }
                    if (val < 0.1) {
                        val = 0.1;
                    }
                    if (val > 3.0) {
                        val = 3.0;
                    }
                    inputMh.value = val.toFixed(1);
                    sliderMh.value = val;
                    state.mh = val;
                    clearPresets();
                    updateCalculations();
                }
                function syncTcinFromSlider() {
                    state.tcin = parseFloat(sliderTcin.value);
                    inputTcin.value = Math.round(state.tcin);
                    clearPresets();
                    updateCalculations();
                }
                function syncTcinFromInput() {
                    let val = parseFloat(inputTcin.value);
                    if (isNaN(val)) {
                        val = 20;
                    }
                    if (val < 5) {
                        val = 5;
                    }
                    if (val > 50) {
                        val = 50;
                    }
                    inputTcin.value = Math.round(val);
                    sliderTcin.value = val;
                    state.tcin = val;
                    clearPresets();
                    updateCalculations();
                }
                function syncMcFromSlider() {
                    state.mc = parseFloat(sliderMc.value);
                    inputMc.value = state.mc.toFixed(1);
                    clearPresets();
                    updateCalculations();
                }
                function syncMcFromInput() {
                    let val = parseFloat(inputMc.value);
                    if (isNaN(val)) {
                        val = 1.5;
                    }
                    if (val < 0.1) {
                        val = 0.1;
                    }
                    if (val > 3.0) {
                        val = 3.0;
                    }
                    inputMc.value = val.toFixed(1);
                    sliderMc.value = val;
                    state.mc = val;
                    clearPresets();
                    updateCalculations();
                }
                function syncAreaFromSlider() {
                    state.area = parseFloat(sliderArea.value);
                    inputArea.value = state.area.toFixed(1);
                    clearPresets();
                    updateCalculations();
                }
                function syncAreaFromInput() {
                    let val = parseFloat(inputArea.value);
                    if (isNaN(val)) {
                        val = 2.5;
                    }
                    if (val < 0.5) {
                        val = 0.5;
                    }
                    if (val > 8.0) {
                        val = 8.0;
                    }
                    inputArea.value = val.toFixed(1);
                    sliderArea.value = val;
                    state.area = val;
                    clearPresets();
                    updateCalculations();
                }
                function syncUFromSlider() {
                    state.u = parseFloat(sliderU.value);
                    inputU.value = Math.round(state.u);
                    clearPresets();
                    updateCalculations();
                }
                function syncUFromInput() {
                    let val = parseFloat(inputU.value);
                    if (isNaN(val)) {
                        val = 600;
                    }
                    if (val < 100) {
                        val = 100;
                    }
                    if (val > 1200) {
                        val = 1200;
                    }
                    inputU.value = Math.round(val);
                    sliderU.value = val;
                    state.u = val;
                    clearPresets();
                    updateCalculations();
                }
                function syncSelectFlow() {
                    state.flow = selectFlow.value;
                    clearPresets();
                    updateCalculations();
                }
                function loadPreset(key) {
                    clearPresets();
                    presetBtns.forEach(btn => {
                        if (btn.dataset.preset === key) {
                            btn.classList.add('active');
                        }
                    });
                    if (key === 'water_counter') {
                        state.flow = 'counter';
                        state.thin = 160;
                        state.mh = 1.2;
                        state.tcin = 15;
                        state.mc = 1.8;
                        state.area = 3.5;
                        state.u = 800;
                        state.cph = 4184; // Water
                        state.cpc = 4184;
                    }
                    if (key === 'oil_parallel') {
                        state.flow = 'parallel';
                        state.thin = 180;
                        state.mh = 0.8;
                        state.tcin = 25;
                        state.mc = 2.0;
                        state.area = 1.8;
                        state.u = 300;
                        state.cph = 2100; // Engine oil cp approx 2.1kJ/kgK
                        state.cpc = 4184;
                    }
                    if (key === 'compact_size') {
                        state.flow = 'counter';
                        state.thin = 140;
                        state.mh = 0.5;
                        state.tcin = 10;
                        state.mc = 0.6;
                        state.area = 1.2;
                        state.u = 1100; // High overall U
                        state.cph = 4184;
                        state.cpc = 4184;
                    }
                    selectFlow.value = state.flow;
                    sliderThin.value = state.thin;
                    inputThin.value = state.thin;
                    sliderMh.value = state.mh;
                    inputMh.value = state.mh.toFixed(1);
                    sliderTcin.value = state.tcin;
                    inputTcin.value = state.tcin;
                    sliderMc.value = state.mc;
                    inputMc.value = state.mc.toFixed(1);
                    sliderArea.value = state.area;
                    inputArea.value = state.area.toFixed(1);
                    sliderU.value = state.u;
                    inputU.value = state.u;
                    updateCalculations();
                }
                function clearPresets() {
                    presetBtns.forEach(btn => btn.classList.remove('active'));
                }
                // Math Results Nodal State
                const mathModel = {
                    thout: 0,
                    tcout: 0,
                    qRate: 0,
                    eff: 0,
                    lmtd: 0
                };
                function updateCalculations() {
                    const Ch = state.mh * state.cph;
                    const Cc = state.mc * state.cpc;
                    const Cmin = Math.min(Ch, Cc);
                    const Cmax = Math.max(Ch, Cc);
                    const Cr = Cmin / Cmax;
                    const NTU = (state.u * state.area) / Cmin;
                    // Effectiveness calculations
                    let eff = 0;
                    if (state.flow === 'parallel') {
                        eff = (1 - Math.exp(-NTU * (1 + Cr))) / (1 + Cr);
                    }
                    if (state.flow === 'counter') {
                        if (Cr < 0.999) {
                            const expTerm = Math.exp(-NTU * (1 - Cr));
                            eff = (1 - expTerm) / (1 - Cr * expTerm);
                        }
                        if (Cr >= 0.999) {
                            eff = NTU / (NTU + 1);
                        }
                    }
                    // Heat exchange rate limits
                    const qMax = Cmin * (state.thin - state.tcin);
                    const qActual = eff * qMax; // Watts
                    // Outlet temperatures
                    const thout = state.thin - (qActual / Ch);
                    const tcout = state.tcin + (qActual / Cc);
                    // LMTD calculation
                    let d1 = 0;
                    let d2 = 0;
                    if (state.flow === 'parallel') {
                        d1 = state.thin - state.tcin;
                        d2 = thout - tcout;
                    }
                    if (state.flow === 'counter') {
                        d1 = state.thin - tcout;
                        d2 = thout - state.tcin;
                    }
                    // Handle edge cases where d1 or d2 are extremely close to zero or equal
                    let lmtd = 0;
                    if (Math.abs(d1 - d2) < 0.01) {
                        lmtd = (d1 + d2) / 2;
                    }
                    if (Math.abs(d1 - d2) >= 0.01) {
                        if (d1 > 0) {
                            if (d2 > 0) {
                                lmtd = (d1 - d2) / Math.log(d1 / d2);
                            }
                        }
                    }
                    // Write variables
                    mathModel.qRate = qActual / 1000.0; // kW
                    mathModel.thout = thout;
                    mathModel.tcout = tcout;
                    mathModel.eff = eff * 100; // %
                    mathModel.lmtd = lmtd;
                    // Update UI elements
                    txtHeatRate.innerHTML = `${mathModel.qRate.toFixed(1)} kW <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;">(${(mathModel.qRate * 860.421).toLocaleString(undefined, {maximumFractionDigits: 0})} kcal/h)</span>`;
                    txtThout.innerText = `${thout.toFixed(1)} °C`;
                    txtTcout.innerText = `${tcout.toFixed(1)} °C`;
                    txtEffectiveness.innerText = `${mathModel.eff.toFixed(1)} %`;
                    txtLmtd.innerText = `${lmtd.toFixed(1)} °C`;
                }
                // Particle systems for fluids inside tubes
                class ExchangerFlowParticle {
                    constructor(streamType) {
                        this.stream = streamType; // 'hot' or 'cold'
                        this.size = Math.random() * 2.5 + 1.2;
                        this.reset();
                        this.x = Math.random() * (canvas.width - 120) + 60; // scattered start
                    }
                    reset() {
                        if (this.stream === 'hot') {
                            this.x = 60;
                            this.y = 80 + (Math.random() - 0.5) * 12; // center inner tube
                        }
                        if (this.stream === 'cold') {
                            if (state.flow === 'parallel') {
                                this.x = 60;
                            }
                            if (state.flow === 'counter') {
                                this.x = canvas.width - 60;
                            }
                            // Ring outer shell, randomized top and bottom
                            const ringOffset = Math.random() > 0.5 ? -18 : 18;
                            this.y = 80 + ringOffset + (Math.random() - 0.5) * 8;
                        }
                    }
                    update() {
                        const baseSpeed = 1.5;
                        if (this.stream === 'hot') {
                            const speedH = baseSpeed * Math.min(state.mh * 1.5, 3.0);
                            this.x += speedH;
                            if (this.x > canvas.width - 60) {
                                this.reset();
                            }
                        }
                        if (this.stream === 'cold') {
                            const speedC = baseSpeed * Math.min(state.mc * 1.5, 3.0);
                            if (state.flow === 'parallel') {
                                this.x += speedC;
                                if (this.x > canvas.width - 60) {
                                    this.reset();
                                }
                            }
                            if (state.flow === 'counter') {
                                this.x -= speedC;
                                if (this.x < 60) {
                                    this.reset();
                                }
                            }
                        }
                    }
                    draw(c) {
                        c.save();
                        // Dynamically shift color along length path
                        // x going from 60 (left) to canvas.width - 60 (right)
                        const L_total = canvas.width - 120;
                        const progress = (this.x - 60) / L_total; // 0 to 1
                        if (this.stream === 'hot') {
                            // cool down red (left) -> orange/yellow (right)
                            const r = Math.round(239 - progress * 40);
                            const g = Math.round(68 + progress * 90);
                            const b = Math.round(68 + progress * 10);
                            c.fillStyle = `rgb(${r},${g},${b})`;
                        }
                        if (this.stream === 'cold') {
                            if (state.flow === 'parallel') {
                                // warm up blue (left) -> purple/pink (right)
                                const r = Math.round(56 + progress * 150);
                                const g = Math.round(189 - progress * 130);
                                const b = Math.round(248 - progress * 80);
                                c.fillStyle = `rgb(${r},${g},${b})`;
                            }
                            if (state.flow === 'counter') {
                                // warm up blue (right) -> purple/pink (left)
                                // so progress = 0 is left (outlet, warm), progress = 1 is right (inlet, cold)
                                const r = Math.round(56 + (1 - progress) * 150);
                                const g = Math.round(189 - (1 - progress) * 130);
                                const b = Math.round(248 - (1 - progress) * 80);
                                c.fillStyle = `rgb(${r},${g},${b})`;
                            }
                        }
                        c.beginPath();
                        c.arc(this.x, this.y, this.size, 0, Math.PI * 2);
                        c.fill();
                        c.restore();
                    }
                }
                // Populate flow particles
                function setupParticles() {
                    state.particles = [];
                    for (let i = 0; i < 45; i++) {
                        state.particles.push(new ExchangerFlowParticle('hot'));
                    }
                    for (let i = 0; i < 45; i++) {
                        state.particles.push(new ExchangerFlowParticle('cold'));
                    }
                }
                // Main animation loop
                function animate(timestamp) {
                    requestAnimationFrame(animate);
                    const width = canvas.width;
                    const height = canvas.height;
                    if (state.particles.length === 0) {
                        setupParticles();
                    }
                    ctx.clearRect(0, 0, width, height);
                    // Blueprint grid
                    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();
                    // 1. Draw Concentric Tubes
                    const leftX = 60;
                    const rightX = width - 60;
                    const exLen = rightX - leftX;
                    const centerY = 80;
                    // Outer Tube (Shell)
                    ctx.save();
                    ctx.fillStyle = 'rgba(226, 232, 240, 0.6)';
                    ctx.fillRect(leftX, centerY - 28, exLen, 56);
                    ctx.strokeStyle = '#94a3b8';
                    ctx.lineWidth = 2.5;
                    ctx.strokeRect(leftX, centerY - 28, exLen, 56);
                    // Inner Tube (Center Pipe)
                    ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
                    ctx.fillRect(leftX - 15, centerY - 10, exLen + 30, 20);
                    ctx.strokeStyle = '#475569';
                    ctx.lineWidth = 2;
                    ctx.strokeRect(leftX - 15, centerY - 10, exLen + 30, 20);
                    ctx.restore();
                    // 2. Shell ports representation (concentric inlets/outlets)
                    ctx.save();
                    ctx.fillStyle = '#64748b';
                    // Left shell nozzle port
                    ctx.fillRect(leftX + 20, centerY - 42, 14, 15);
                    // Right shell nozzle port
                    ctx.fillRect(rightX - 34, centerY - 42, 14, 15);
                    ctx.restore();
                    // Update &#038; Render flow particles
                    state.particles.forEach(p => {
                        p.update();
                        p.draw(ctx);
                    });
                    // Inlet/Outlet labels on Exchanger
                    ctx.save();
                    ctx.fillStyle = '#0f172a';
                    ctx.font = 'bold 9px sans-serif';
                    ctx.textAlign = 'center';
                    // Hot stream
                    ctx.textAlign = 'left';
                    ctx.fillText(`T_hin (${Math.round(state.thin)}°C)`, 15, centerY + 30);
                    ctx.textAlign = 'right';
                    ctx.fillText(`T_hout (${Math.round(mathModel.thout)}°C)`, width - 15, centerY + 30);
                    // Cold stream nozzles mapping
                    ctx.textAlign = 'center';
                    if (state.flow === 'parallel') {
                        ctx.fillText(`T_cin (${Math.round(state.tcin)}°C)`, leftX + 27, centerY - 48);
                        ctx.fillText(`T_cout (${Math.round(mathModel.tcout)}°C)`, rightX - 27, centerY - 48);
                    }
                    if (state.flow === 'counter') {
                        ctx.fillText(`T_cout (${Math.round(mathModel.tcout)}°C)`, leftX + 27, centerY - 48);
                        ctx.fillText(`T_cin (${Math.round(state.tcin)}°C)`, rightX - 27, centerY - 48);
                    }
                    ctx.restore();
                    // 3. Draw Temperature Profile Curves Line Chart (x-axis at bottom)
                    const plotY = height - 120;
                    const plotH = 90;
                    const plotX = 70;
                    const plotW = width - 140;
                    // Plot Axis lines
                    ctx.save();
                    ctx.strokeStyle = '#cbd5e1';
                    ctx.lineWidth = 1.5;
                    ctx.beginPath();
                    ctx.moveTo(plotX, plotY);
                    ctx.lineTo(plotX + plotW, plotY);
                    ctx.lineTo(plotX + plotW, plotY - plotH);
                    ctx.stroke();
                    // Temperature axis helpers
                    const plotMax = Math.max(state.thin, 120);
                    const plotMin = Math.min(state.tcin, 40);
                    const plotSpan = plotMax - plotMin;
                    function mapChartTempToY(temp) {
                        const ratio = (temp - plotMin) / plotSpan;
                        return plotY - ratio * plotH;
                    }
                    // Compute curves profiles (Parallel vs Counter)
                    ctx.lineWidth = 3.5;
                    // 3a. Draw Hot Curve (decay left-to-right)
                    ctx.strokeStyle = '#ef4444';
                    ctx.beginPath();
                    for (let cx = 0; cx <= plotW; cx += 5) {
                        const px = plotX + cx;
                        const progress = cx / plotW;
                        // Exponential interpolation
                        const temp_x = state.thin + (mathModel.thout - state.thin) * (1 - Math.exp(-progress * 2.5)) / (1 - Math.exp(-2.5));
                        const py = mapChartTempToY(temp_x);
                        if (cx === 0) {
                            ctx.moveTo(px, py);
                        } else {
                            ctx.lineTo(px, py);
                        }
                    }
                    ctx.stroke();
                    // 3b. Draw Cold Curve
                    ctx.strokeStyle = '#38bdf8';
                    ctx.beginPath();
                    for (let cx = 0; cx <= plotW; cx += 5) {
                        const px = plotX + cx;
                        const progress = cx / plotW;
                        let temp_x = 0;
                        if (state.flow === 'parallel') {
                            temp_x = state.tcin + (mathModel.tcout - state.tcin) * (1 - Math.exp(-progress * 2.5)) / (1 - Math.exp(-2.5));
                        }
                        if (state.flow === 'counter') {
                            // starts cold at right side (progress = 1)
                            // heats up going left (progress = 0)
                            temp_x = mathModel.tcout + (state.tcin - mathModel.tcout) * (1 - Math.exp(-progress * 2.5)) / (1 - Math.exp(-2.5));
                        }
                        const py = mapChartTempToY(temp_x);
                        if (cx === 0) {
                            ctx.moveTo(px, py);
                        } else {
                            ctx.lineTo(px, py);
                        }
                    }
                    ctx.stroke();
                    ctx.restore();
                    // Node values print on graph
                    ctx.save();
                    ctx.fillStyle = '#0f172a';
                    ctx.font = '600 11px sans-serif';
                    // Labels mapping on graph
                    ctx.fillText(`고온 입구: ${Math.round(state.thin)}°C`, plotX, mapChartTempToY(state.thin) - 8);
                    ctx.fillText(`${Math.round(mathModel.thout)}°C`, plotX + plotW - 35, mapChartTempToY(mathModel.thout) - 8);
                    if (state.flow === 'parallel') {
                        ctx.fillText(`저온 입구: ${Math.round(state.tcin)}°C`, plotX, mapChartTempToY(state.tcin) + 12);
                        ctx.fillText(`${Math.round(mathModel.tcout)}°C`, plotX + plotW - 35, mapChartTempToY(mathModel.tcout) - 8);
                    }
                    if (state.flow === 'counter') {
                        ctx.fillText(`${Math.round(mathModel.tcout)}°C`, plotX, mapChartTempToY(mathModel.tcout) - 8);
                        ctx.fillText(`저온 입구: ${Math.round(state.tcin)}°C`, plotX + plotW - 75, mapChartTempToY(state.tcin) + 12);
                    }
                    ctx.fillStyle = '#475569';
                    ctx.font = '11px sans-serif';
                    ctx.fillText('열교환기 입출구 온도 전개 프로파일 선도', plotX, plotY + 36);
                    ctx.restore();
                }
                // Event Listeners Mapping
                sliderThin.addEventListener('input', syncThinFromSlider);
                inputThin.addEventListener('change', syncThinFromInput);
                sliderMh.addEventListener('input', syncMhFromSlider);
                inputMh.addEventListener('change', syncMhFromInput);
                sliderTcin.addEventListener('input', syncTcinFromSlider);
                inputTcin.addEventListener('change', syncTcinFromInput);
                sliderMc.addEventListener('input', syncMcFromSlider);
                inputMc.addEventListener('change', syncMcFromInput);
                sliderArea.addEventListener('input', syncAreaFromSlider);
                inputArea.addEventListener('change', syncAreaFromInput);
                sliderU.addEventListener('input', syncUFromSlider);
                inputU.addEventListener('change', syncUFromInput);
                selectFlow.addEventListener('change', syncSelectFlow);
                presetBtns.forEach(btn => {
                    btn.addEventListener('click', function() {
                        loadPreset(btn.dataset.preset);
                    });
                });
                // Run sequence
                loadPreset('water_counter');
                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.__heatexchanger_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>흐름 배열 선택: 평행류(Parallel Flow) 또는 대향류(Counter Flow) 유동 방식을 선택합니다.</strong></li>
<li style="margin-bottom: 6px;">고온 및 저온 유체 입구 온도 제어: 고온 유체 입구 온도(Th,in)와 저온 유체 입구 온도(Tc,in)를 입력합니다.</li>
<li style="margin-bottom: 6px;">유량 및 열용량 비율 조정: 두 유체의 질량 유량(m) 및 재질(물, 오일 등)을 설정하여 열용량율(C)을 결정합니다.</li>
<li style="margin-bottom: 6px;">열교환기 면적 및 총괄 전열계수 조절: 전열 면적(A)과 총괄 열전달 계수(U)를 증가시켜 열 성능 및 LMTD 변화를 관찰합니다.</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;" /> LMTD 및 ε-NTU 열교환기 계산 이론 해설 보기</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. 이중관 열교환기 (Double-pipe Heat Exchanger)의 작동 원리</h3>
<p>열교환기는 온도가 서로 다르고 고유한 유체가 직접 섞이지 않고 격벽을 사이에 두고 열에너지를 교환하도록 하는 장치입니다. 그 중 이중관 열교환기는 하나의 관 내부에 다른 관을 동심원으로 배치하여 내관 내부와 외관(環狀, Annulus) 공간으로 각각 유체를 흘려보내는 가장 단순하고 기본적인 형태입니다.</p><ul><li><strong>평행류 (Parallel Flow):</strong> 두 유체가 동일한 방향(좌측에서 우측)으로 흘러 들어가는 배치로, 아무리 면적을 키워도 고온 유체의 출구 온도가 저온 유체의 출구 온도보다 낮아질 수 없다는 한계가 있습니다.</li><li><strong>대향류 (Counter Flow):</strong> 두 유체가 서로 정반대 방향으로 마주 보며 주행하는 배치입니다. 평균 온도차를 일정하게 유지하여 전열 효율이 월등히 뛰어나며, 출구측 온도가 역전될 수 있는 독보적 이점을 지닙니다.</li></ul>
<h3>2. LMTD(대수평균온도차) 및 ε-NTU 해석 공식</h3>
<p>열교환기 설계 및 성능 예측에는 크게 **LMTD법**과 **유용도-NTU(ε-NTU)법**이 활용됩니다.</p><p><strong>① 총 전열량 공식:</strong></p><p style="text-align: center; font-weight: bold; background: #f3f4f6; padding: 12px; border-radius: 8px;">q = U × A × LMTD &nbsp;[W]</p><p>여기서 <code>U</code>는 총괄 열전달 계수(W/m²·K), <code>A</code>는 전열 면적(m²), <code>LMTD</code>는 다음식으로 정의되는 대수평균 온도차입니다.</p><p style="text-align: center; font-weight: bold; background: #f3f4f6; padding: 12px; border-radius: 8px;">LMTD = (ΔT1 - ΔT2) / ln(ΔT1 / ΔT2) &nbsp;[°C]</p><ul><li>대향류: ΔT1 = T_h,in - T_c,out , &nbsp; ΔT2 = T_h,out - T_c,in</li><li>평행류: ΔT1 = T_h,in - T_c,in , &nbsp; ΔT2 = T_h,out - T_c,out</li></ul><p><strong>② ε-NTU법 (출구 온도를 모를 때 유용):</strong></p><p>열용량율 <code>C_h = m_h × cp_h</code>, <code>C_c = m_c × cp_c</code> 중 작은 쪽을 <code>C_min</code>, 큰 쪽을 <code>C_max</code>라 합니다. 이때 최대 전달 가능한 열량 <code>q_max = C_min × (T_h,in - T_c,in)</code>이며, 실제 전달 열량은 유용도 <code>ε</code>을 곱해 구합니다 (<code>q = ε × q_max</code>).</p><p style="text-align: center; font-weight: bold; background: #e0f2fe; padding: 16px; border-radius: 8px; font-size: 1.05em; color: #0369a1;">NTU = U × A / C_min</p><p>유용도 <code>ε</code>은 흐름 형태와 <code>C_r = C_min / C_max</code> 비에 의존하는 함수식으로 완벽히 유도됩니다.</p>
<h3>3. 총괄 열전달 계수 (U-Value)의 공학적 의미</h3>
<p>총괄 열전달 계수 <code>U</code>는 튜브 벽면을 경계로 일어나는 내벽 대류, 벽체 전도, 외벽 대류 및 스케일 오염 저항(Fouling Factor)을 종합한 총괄적인 관통 열전달률입니다. 내외경 면적 변화가 미미한 이중관의 경우 저항의 직렬 합산으로 표기됩니다:</p><p style="text-align: center; font-weight: bold; background: #f3f4f6; padding: 12px; border-radius: 8px;">1/U ≈ 1/h_in + t/k_tube + 1/h_out</p><p>따라서 튜브 내부에 물과 같이 대류막 계수(h)가 높은 유체를 사용하더라도 외부가 가스나 오일과 같은 불량 전열 유체라면 총괄 U값은 병목 현상에 의해 최저 대류계수 수준으로 낮아지게 됩니다. 시뮬레이터를 통해 가스 및 오일 환경을 모방한 저효율 성능 시험도 수행할 수 있습니다.</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/heat-exchanger-lmtd-ntu-calculator/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>판형 및 쉘앤튜브 열교환기의 특징 비교 (Comparison of Plate and Shell &#038; Tube Heat Exchangers)</title>
		<link>https://myengnote.com/comparison-plate-vs-shell-tube-heat-exchangers/</link>
					<comments>https://myengnote.com/comparison-plate-vs-shell-tube-heat-exchangers/#respond</comments>
		
		<dc:creator><![CDATA[동동]]></dc:creator>
		<pubDate>Wed, 22 Apr 2026 21:08:13 +0000</pubDate>
				<category><![CDATA[배관/유공압]]></category>
		<category><![CDATA[Heat Exchanger]]></category>
		<category><![CDATA[Shell and Tube]]></category>
		<category><![CDATA[Thermal Efficiency]]></category>
		<category><![CDATA[쉘앤튜브]]></category>
		<category><![CDATA[열관리]]></category>
		<category><![CDATA[열교환기]]></category>
		<category><![CDATA[판형열교환기]]></category>
		<guid isPermaLink="false">https://myengnote.com/comparison-plate-vs-shell-tube-heat-exchangers/</guid>

					<description><![CDATA[산업용 열교환기의 두 축인 판형과 쉘앤튜브 방식의 구조적 특징과 열역학적 효율성을 심층 분석합니다. 현장 실무 경험을 바탕으로 한 유지보수 전략과 선정 기준을 제시합니다.... <a href="https://myengnote.com/comparison-plate-vs-shell-tube-heat-exchangers/" style="text-decoration:none; color:#0073aa; font-weight:bold;">[본문 전체보기 >]</a>]]></description>
										<content:encoded><![CDATA[<p>많은 산업 현장에서 열교환기 선정 오류로 인해 에너지를 낭비하거나 심지어 법적 감사를 통과하지 못하는 사례가 빈번하게 발생합니다. 특히 한국산업표준인 <strong>KS B 6281(판형 열교환기)</strong>이나 국제 규격인 <strong>ISO 15547</strong> 규정을 명확히 이해하지 못한 채, 단순히 초기 설치 비용만을 고려하여 장비를 선택했다가 나중에 유지보수 비용으로 수억 원을 지출하는 경우를 수없이 보아왔습니다. 열교환기는 단순히 뜨거운 유체와 차가운 유체를 섞이지 않게 교차시키는 장치가 아니라, 유체의 유동학적 특성과 열역학적 상변화, 그리고 소재의 열팽창 계수까지 정밀하게 계산되어야 하는 정밀 기계장치입니다.  </p>
<h2>실무 필드 로그 및 분석 (Field Log &#038; Analysis)</h2>
<p>최근 국내 한 자동차 부품 도장 라인의 냉각 시스템에서 열효율 저하 문제가 발생하여 정밀 진단을 수행했습니다. 해당 공정은 켈비온 브랜드의 판형 열교환기를 사용해 작동유의 온도를 제어하고 있었습니다. 현장 점검 당시, 작동유의 온도가 정상 범위인 45°C를 훨씬 상회하는 67°C까지 치솟아 <strong>유압 펌프의 캐비테이션</strong> 현상이 우려되는 상황이었습니다.</p>
<p>구체적인 관찰 결과, 열교환기 전후단의 압력 강하가 설계 수치인 0.4kg/cm²를 훨씬 초과한 1.3kg/cm²로 측정되었습니다. 장비를 분해하여 확인한 결과, 약 3.2mm 두께의 <strong>칼슘 카보네이트 스케일</strong>이 판 내부의 물결무늬 결을 따라 견고하게 흡착되어 있었습니다. 이는 냉각수 수질 관리 미흡으로 인해 판 사이의 좁은 유로가 폐쇄된 것이 근본 원인이었습니다. 판형 열교환기는 체적 대비 열전달 면적이 매우 넓어 효율적이지만, 이처럼 유로가 좁아 오염물질에 취약하다는 치명적인 단점이 있습니다. 만약 이 환경에서 안정적인 운영을 최우선으로 했다면, 쉘앤튜브 열교환기를 고려했어야 합니다. 이번 사고로 인해 라인이 8시간 동안 정지되었으며, 이는 약 1억 2천만 원의 생산 손실로 이어졌습니다.</p>
<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;">판형 열교환기의 가스켓은 유체의 화학적 성질에 따라 팽윤하거나 경화될 수 있습니다. 특히 오일을 취급할 때는 반드시 <strong>니트릴 고무(NBR)나 불소 고무(FKM)</strong> 재질의 적합성을 사전에 검토해야 하며, 세척 시 강력한 산성 용제를 사용하면 스테인리스판의 부동태 피막이 파괴되어 핀홀 부식이 발생할 수 있습니다.</div>
</p>
</div>
<h2>판형과 쉘앤튜브의 구조적 매커니즘 차이</h2>
<p><strong>쉘앤튜브(Shell &#038; Tube)</strong> 열교환기는 원통형 쉘 내부에 수많은 튜브를 배치한 형태로, 고압과 고온 환경에서 타의 추종을 불허하는 신뢰성을 보여줍니다. 튜브 내부와 쉘 쪽으로 흐르는 유체는 서로의 압력 차이를 견디기 위해 격판에 의해 지지되며, 이는 유체의 흐름을 지그재그로 유도하여 열전달 효율을 높입니다. 하지만 쉘앤튜브는 구조적으로 사각지대가 발생하기 쉽고, 판형에 비해 레이놀즈 수가 낮아 층류가 형성될 가능성이 큽니다. 이는 곧 열관류율의 저하로 이어져, 동일한 열량을 교환하기 위해 판형보다 3배에서 5배 이상의 거대한 설치 공간을 필요로 합니다.</p>
<p><strong>판형(Plate Type)</strong> 열교환기는 얇은 금속판을 겹쳐서 가스켓으로 밀봉한 구조입니다. 판에 새겨진 헤링본 패턴이나 물결무늬는 유체가 흐를 때 강한 와류를 발생시킵니다. 이 와류는 경계층의 두께를 최소화하여 열전달 계수를 극대화하는 물리적 원리를 충실히 따릅니다. 특히 접근 온도차를 1°C 내외로 좁힐 수 있다는 점은 에너지 회수 공정에서 판형이 압도적인 우위를 점하는 이유입니다. 하지만 가스켓 방식의 한계로 인해 대략 25kg/cm² 이상의 고압이나 200°C 이상의 고온에서는 누설 위험이 급격히 증가합니다.</p>
</p>
<h2>유지보수의 편의성과 경제성 논리</h2>
<p>현장 엔지니어들이 흔히 하는 착각 중 하나가 &#8220;판형은 청소하기 쉽다&#8221;는 것입니다. 물론 프레임의 볼트를 풀면 모든 판을 개별적으로 닦을 수 있다는 장점은 있지만, 수백 장에 달하는 판을 일일이 닦고 다시 가스켓을 정렬하여 조립하는 과정은 엄청난 노동력을 요구합니다. 조립 시 <strong>체결 토크</strong>가 일정하지 않으면 시운전 시 바로 누수가 발생하여 현장이 아수라장이 되기도 합니다. 이와 달리 쉘앤튜브는 튜브 내부에 스케일이 끼었을 때 고압 세척기나 전용 브러시를 이용해 비교적 단순하게 세척이 가능합니다.</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;">열교환기 성능이 떨어졌을 때 무조건 분해 청소부터 생각하지 마십시오. 유압 시스템에서 펌프의 흡입 양정이 불안정하면 유량이 부족해져 냉각 성능이 떨어지는 경우가 많습니다. 또한, 냉각수 계통에 공기가 차 있는 경우에도 열전달이 차단되므로, 반드시 <strong>상부 에어 벤트 밸브</strong>를 확인하는 습관을 들여야 합니다.</div>
</p>
</div>
<p>설비의 수명 주기 비용 측면에서 볼 때, 판형은 초기 투자비와 설치 공간 비용이 저렴하지만 가스켓 교체 비용과 세척 인건비가 지속적으로 발생합니다. 반면 쉘앤튜브는 초기 비용이 비싸고 무거워서 별도의 기초 공사가 필요하지만, 한 번 설치하면 20년 이상 큰 고장 없이 운영할 수 있는 내구성을 갖추고 있습니다. 따라서 공정의 연속성이 중요한 대규모 플랜트에서는 쉘앤튜브를, 공간 효율이 중요하고 주기적인 세척이 가능한 환경에서는 판형을 선택하는 것이 정석입니다.</p>
</p>
<h2>초보 엔지니어가 놓치기 쉬운 설계 포인트</h2>
<p>설계 단계에서 많은 주니어 엔지니어들이 <strong>파울링 계수(Fouling Factor)</strong>를 과소평가합니다. 새 제품일 때는 판형의 효율이 환상적이지만, 실제 가동 후 한 달만 지나도 유체 속의 이물질이 판 사이에 끼기 시작합니다. 이를 고려하여 설계 마진을 과도하게 잡으면 오히려 유속이 느려져 스케일 퇴적을 가속화하는 역효과를 낳기도 합니다. <strong>유속을 0.3m/s에서 0.5m/s 사이</strong>로 유지하여 자가 세정 효과를 유도하는 것이 설계의 핵심입니다.</p>
<p>또한, 수질이 좋지 않은 지하수를 냉각수로 사용할 경우 판형은 지옥이나 다름없습니다. 이런 경우에는 차라리 산업용 냉각기의 작동 원리를 응용한 밀폐형 냉각탑을 사용하거나, 튜브 직경이 커서 막힘에 강한 쉘앤튜브를 사용하는 것이 정신 건강에 이롭습니다. 배관 설계 시에도 열교환기의 진동이 배관으로 전달되지 않도록 <strong>플렉시블 조인트</strong>를 설치하는 것을 잊지 마십시오.</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;">
<div style="overflow-x: auto; 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: 600px; font-size: 15px; text-align: left; background-color: #ffffff;">
<thead>
<tr style="background-color: #1f2937; color: #ffffff;">
<th style="padding: 15px; border-bottom: 3px solid #3b82f6; font-weight: bold; text-transform: uppercase;">항목</th>
<th style="padding: 15px; border-bottom: 3px solid #10b981; font-weight: bold; text-transform: uppercase;">판형 열교환기</th>
<th style="padding: 15px; border-bottom: 3px solid #f59e0b; font-weight: bold; text-transform: uppercase;">쉘앤튜브 열교환기</th>
</tr>
</thead>
<tbody>
<tr>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; 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>
</tr>
<tr>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; 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>
</tr>
<tr>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; 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>
</tr>
<tr>
<td style="padding: 12px 15px; border-bottom: 1px solid #e5e7eb; 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>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<p> 결론적으로, 제가 만약 새로운 설비의 설계 책임자라면 다음과 같이 결정하겠습니다. 유체가 깨끗하고 온도 조절 정밀도가 최우선인 공정이라면 알파라발의 고효율 판형 열교환기를 배치하겠습니다. 하지만 부식성 유체를 다루거나 운전 중 예기치 못한 압력 서지가 발생하는 가혹한 현장이라면, 히사카나 켈비온의 튼튼한 쉘앤튜브 방식을 고집할 것입니다. 기술은 언제나 정답이 있는 것이 아니라, 상황에 맞는 &#8216;최선&#8217;의 선택이 있을 뿐입니다. 후배 엔지니어 여러분, 도면 속의 숫자만 믿지 마십시오. 현장의 냉각수 상태, 가스켓을 교체할 작업자의 숙련도, 그리고 유지보수를 위한 크레인 접근성까지 고려하는 것이 진정한 전문가의 자세입니다. </p>
<h2>0. 연관글</h2>
<p> <!-- START_SIMULATOR_LINK_CARD_heat_exchanger --><a href="https://myengnote.com/heat-exchanger-lmtd-ntu-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;">열교환기 LMTD 온도차 계산기 &#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_exchanger --><a href="https://myengnote.com/industrial-chiller-principles-and-cooling-types/" 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><br />
</a><a href="https://myengnote.com/importance-of-suction-head-hydraulic-pumps/" 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><br />
</a><a href="https://myengnote.com/rubber-seal-deformation-chemical-solvent-selection/" 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><br />
</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>
]]></content:encoded>
					
					<wfw:commentRss>https://myengnote.com/comparison-plate-vs-shell-tube-heat-exchangers/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
