Skip to content
cfd-lab:~/ko/posts/2026-08-20-franklin-stov…online
NOTE #136DAY THU 유체역학DATE 2026.08.20READ 6 min read#Stack-Effect#Natural-Convection#Buoyancy#Historical#Flow-Phenomena

연기를 1 m 내려보냈더니 드래프트가 7 Pa 사라졌다 — 프랭클린 난로와 부력 예산

부력은 높이가 아니라 뜨거울 때의 높이로만 벌 수 있다. 같은 굴뚝이라도 하강 유로를 지나면 드래프트는 줄어든다.

1741년, 연기를 일부러 아래로 내려보낸 난로#

벤저민 프랭클린은 1741년에 벽난로를 다시 설계했다. 목적은 단순했다. 굴뚝으로 그냥 빠져나가는 열기를 방 안에서 한 번 더 붙잡는 것이다. 당시 유럽은 인구가 급증하며 땔감이 모자랐고, 난방 효율은 생존 문제에 가까웠다.

그가 쓴 방법은 유로를 접는 것이었다. 불에서 올라온 연기를 배플(baffle, 유로를 가로막아 흐름을 꺾는 판) 위로 넘긴 뒤, 주철 벽을 따라 아래로 내려보내고, 그다음에 굴뚝으로 올린다. 내려오는 동안 주철이 데워지고 그 열이 방으로 복사된다. 당대 기록은 이를 "사이펀 현상"이라 불렀다.

굴뚝 꼭대기 높이는 그대로다. 연기가 최종적으로 얻는 고도차도 그대로다. 그런데 이 난로는 연기가 방으로 새어 나오기로 악명이 높았다. 이 글은 그 손해가 정확히 어디서 얼마나 발생하는지를 부력 장부로 적어 본다. 답은 한 줄이다 — 부력은 높이가 아니라 뜨거울 때의 높이로만 벌 수 있다.

드래프트는 밀도차에 높이를 곱한 값이다#

굴뚝이 연기를 끌어올리는 힘을 드래프트(draft)라 부른다. 이것은 펌프가 아니라 정수압 차이다. 바깥 공기 기둥과 안쪽 연기 기둥의 무게가 다르기 때문에 생긴다.

높이 HH의 연도(flue)에 대해 드래프트는 이렇게 적힌다.

Δpdraft=0H(ρρ(z))gdz\Delta p_{\text{draft}} = \int_0^{H} \left( \rho_\infty - \rho(z) \right) g \, \mathrm{d}z

ρ\rho_\infty는 바깥 공기 밀도, ρ(z)\rho(z)는 높이 zz에서의 연기 밀도, gg는 중력가속도다. 연도 안팎의 절대압은 거의 같으므로 이상기체에서 ρ=p0/(RT)\rho = p_0 / (R T)가 성립하고, 연기 온도가 TgT_g로 균일하다면 적분이 곧바로 풀린다.

Δpdraft=ρgH(1TTg)\Delta p_{\text{draft}} = \rho_\infty g H \left( 1 - \frac{T_\infty}{T_g} \right)

10 °C의 바깥 공기(ρ=1.247\rho_\infty = 1.247 kg/m³), 연기 온도 500 K, 굴뚝 높이 7 m를 넣으면 37 Pa가 나온다. 실제 벽난로 드래프트가 10~30 Pa 수준이니 크기는 맞다.

여기서 중요한 것은 dz\mathrm{d}z가 적분 안에 있다는 점이다. 부력은 총 높이에 한 번 곱해지는 값이 아니라, 1 m마다 그때의 밀도로 사서 쌓는 값이다. 프랭클린이 지불한 값이 여기에 있다.

아래 시뮬레이션에서 직접 조작해보자.

The chimney top stays at 7 m however you drag down-leg, so the elevation gained never changes — but the red bar grows and the net draft falls, because the descent is paid for with the hottest, lightest gas. Now drag fire tempdown: the mouth gauge crosses the amber spill limit far earlier with a deep down-leg than with none.

down-leg 슬라이더를 끝까지 밀어도 굴뚝 꼭대기는 7 m에 고정되어 있다. 그런데 오른쪽 장부의 빨간 막대가 자라고 순 드래프트는 줄어든다. 이어서 fire temp를 내리면 아궁이 게이지가 주황색 역류 한계선을 넘는데, 하강 유로가 깊을수록 그 순간이 훨씬 빨리 온다.

부력은 뜨거울 때의 높이로만 벌 수 있다#

경로를 세 구간으로 자르자. 배플까지 상승(+0.8+0.8 m), 하강 유로(hd-h_d), 굴뚝(+6.2+hd+6.2 + h_d m). 세 구간의 고도 변화를 더하면 hdh_d와 무관하게 항상 7 m다. 그런데 각 구간의 부력 기여는 그 구간을 지날 때의 연기 밀도로 계산된다.

연기는 벽으로 열을 잃으며 식는다. 경로 좌표 ss를 따라가면 1차 ODE 하나가 된다.

dTds=UPm˙cp(TT)\frac{\mathrm{d}T}{\mathrm{d}s} = -\frac{U P}{\dot{m} c_p} \left( T - T_\infty \right)

UU는 총괄 열전달계수, PP는 연도 둘레, m˙\dot{m}은 질량유량, cpc_p는 정압비열이다. 해는 지수 감쇠이고, 감쇠 길이가 m˙cp/(UP)\dot{m} c_p / (U P)라는 사실이 뒤에서 중요해진다.

이제 손해가 보인다. 하강 유로는 경로에서 두 번째로 뜨거운 구간이다. 밀도가 가장 낮으니 (ρρ)(\rho_\infty - \rho)가 가장 크고, 그것에 음의 dz\mathrm{d}z가 곱해진다. 반대로 그 1 m를 되찾는 굴뚝 구간의 연기는 이미 주철 벽에 열을 내주고 식은 상태다. 비싸게 팔고 싸게 사는 것이 아니라, 비싸게 사고 싸게 파는 셈이다.

게다가 프랭클린 난로에서 하강 유로는 방 안에 있다. 즉 열을 가장 열심히 뺏기는 구간이기도 하다. 난방 효율을 위해 설계한 바로 그 특성이 굴뚝이 쓸 부력 예산을 먼저 소비한다.

루프 하나로 닫는 운동량 균형#

유량 m˙\dot{m}은 부력이 손실과 같아지는 곳에서 정해진다. 연도를 한 바퀴 도는 운동량 균형이다.

iLi(ρρ)gdz=0LfDm˙22ρA2ds+Km˙22ρeA2\sum_{i} \int_{L_i} (\rho_\infty - \rho) g \, \mathrm{d}z = \int_0^{L} \frac{f}{D} \frac{\dot{m}^2}{2 \rho A^2} \, \mathrm{d}s + K \frac{\dot{m}^2}{2 \rho_e A^2}

왼쪽이 부력 수두, 오른쪽이 마찰 손실과 부차 손실(굽힘·출구)이다. ff는 Darcy 마찰계수, DD는 연도 직경, AA는 단면적, KK는 부차 손실계수, ρe\rho_e는 출구 밀도다. 관 마찰 항의 형태는 발달 길이와 Hagen–Poiseuille에서 다룬 것과 같다.

이 식은 겉보기와 달리 선형이 아니다. m˙\dot{m}이 커지면 오른쪽은 m˙2\dot{m}^2으로 커지지만, 왼쪽도 함께 커진다. 유량이 많을수록 냉각 시간이 짧아져 연기가 뜨거운 채로 굴뚝을 지나기 때문이다. 이 되먹임 때문에 잔차 ΔpΔploss\Delta p - \Delta p_{\text{loss}}m˙\dot{m}에 대해 위로 볼록한 곡선이 되고, 근이 둘 생긴다. 아래쪽 근은 불안정하고, 실제 운전점은 위쪽 근이다.

Python으로 적어본 부력 장부#

경로를 잘게 잘라 온도를 행진시키고, 구간별 부력 수두를 따로 모은 뒤, 위쪽 근을 이분법으로 찾는다. 하강 높이를 0에서 1.2 m까지 쓸어 본다.

import math
 
G, R_AIR, CP = 9.81, 287.0, 1100.0
T_AMB, P_ATM = 283.0, 101325.0
D_FLUE = 0.15
A_FLUE = math.pi * D_FLUE ** 2 / 4.0
PERIM = math.pi * D_FLUE
F_DARCY, K_MINOR = 0.030, 3.0
U_ROOM, U_STACK = 40.0, 5.0        # 실내 주철 채널 / 굴뚝 조적 [W/m2K]
Z_TOP, Z_BAFFLE = 7.0, 0.80        # 굴뚝 출구 / 배플 상단 [m]
A_MOUTH, V_SPILL = 0.12, 0.25      # 아궁이 개구 면적 [m2] / 역류 한계 면속도 [m/s]
 
 
def gas_density(T):
    return P_ATM / (R_AIR * T)
 
 
def march_flue(mdot, h_down, T_fire, n=120):
    # 상승 / 하강 / 굴뚝 세 구간을 따라가며 구간별 부력 수두와 총 손실을 모은다
    legs = [(Z_BAFFLE, +1.0, U_ROOM),
            (h_down, -1.0, U_ROOM),
            (Z_TOP - Z_BAFFLE + h_down, +1.0, U_STACK)]
    T, loss, heads = T_fire, 0.0, []
    rho_a = gas_density(T_AMB)
    for L, sgn, U in legs:
        head = 0.0
        if L > 0.0:
            ds = L / n
            for _ in range(n):
                T_new = T_AMB + (T - T_AMB) * math.exp(-U * PERIM * ds / (mdot * CP))
                rho = gas_density(0.5 * (T + T_new))
                head += (rho_a - rho) * G * sgn * ds
                loss += F_DARCY / D_FLUE * 0.5 * mdot ** 2 / (rho * A_FLUE ** 2) * ds
                T = T_new
        heads.append(head)
    loss += K_MINOR * 0.5 * mdot ** 2 / (gas_density(T) * A_FLUE ** 2)
    return heads, loss, T
 
 
def solve_mdot(h_down, T_fire, lo=1e-3, hi=0.4, n=100):
    # 부력 = 손실의 위쪽(안정) 근. 해가 없으면 0.0
    grid = [lo * (hi / lo) ** (i / (n - 1.0)) for i in range(n)]
    res = []
    for m in grid:
        heads, loss, _ = march_flue(m, h_down, T_fire)
        res.append(sum(heads) - loss)
    k = max(range(n), key=lambda i: res[i])
    if res[k] <= 0.0:
        return 0.0
    a, b = grid[k], grid[-1]
    for _ in range(40):
        m = 0.5 * (a + b)
        heads, loss, _ = march_flue(m, h_down, T_fire)
        a, b = (m, b) if sum(heads) - loss > 0.0 else (a, m)
    return 0.5 * (a + b)
 
 
print("h_down[m]  mdot[kg/s]  V_exit[m/s]  draft[Pa]  T_exit[K]")
for i in range(0, 7):
    h = 0.2 * i
    m = solve_mdot(h, 700.0)
    heads, loss, T_e = march_flue(m, h, 700.0)
    print(f"  {h:4.2f}     {m:8.4f}     {m / (gas_density(T_e) * A_FLUE):6.2f}"
          f"     {sum(heads):7.2f}    {T_e:7.1f}")
 
for h in (0.0, 1.0):
    m = solve_mdot(h, 700.0)
    heads, loss, T_e = march_flue(m, h, 700.0)
    print(f"\nbuoyancy ledger  h_down = {h:.1f} m, mdot = {m:.4f} kg/s")
    for name, val in zip(["rise to baffle", "descent      ", "chimney      "], heads):
        print(f"  {name}  {val:+7.2f} Pa")
    print(f"  net             {sum(heads):+7.2f} Pa   (loss {loss:.2f} Pa)")
 
mdot_spill = gas_density(T_AMB) * A_MOUTH * V_SPILL
print(f"\nspillage threshold: mdot < {mdot_spill:.4f} kg/s")
for h in (0.0, 1.0):
    lo, hi = 290.0, 700.0
    for _ in range(30):
        mid = 0.5 * (lo + hi)
        lo, hi = (mid, hi) if solve_mdot(h, mid) < mdot_spill else (lo, mid)
    print(f"  h_down = {h:.1f} m -> spills below T_fire = {0.5 * (lo + hi):6.1f} K")
h_down[m]  mdot[kg/s]  V_exit[m/s]  draft[Pa]  T_exit[K]
  0.00       0.0629       5.59       44.72      554.5
  0.20       0.0623       5.37       43.48      537.2
  0.40       0.0617       5.15       42.16      520.6
  0.60       0.0610       4.93       40.76      504.6
  0.80       0.0602       4.72       39.29      489.2
  1.00       0.0593       4.51       37.72      474.2
  1.20       0.0583       4.30       36.05      459.6
 
buoyancy ledger  h_down = 0.0 m, mdot = 0.0629 kg/s
  rise to baffle    +5.57 Pa
  descent          +0.00 Pa
  chimney         +39.15 Pa
  net              +44.72 Pa   (loss 44.72 Pa)
 
buoyancy ledger  h_down = 1.0 m, mdot = 0.0593 kg/s
  rise to baffle    +5.56 Pa
  descent          -6.16 Pa
  chimney         +38.32 Pa
  net              +37.72 Pa   (loss 37.72 Pa)
 
spillage threshold: mdot < 0.0374 kg/s
  h_down = 0.0 m -> spills below T_fire =  335.2 K
  h_down = 1.0 m -> spills below T_fire =  377.0 K

장부를 두 줄만 비교하면 된다. 하강 유로 1 m는 직접 6.16-6.16 Pa를 가져간다. 그리고 굴뚝은 1 m 더 길어졌는데도 기여가 +39.15+39.15에서 +38.32+38.32 Pa로 줄었다. 늘어난 1 m를 통과하는 연기가 이미 더 식었기 때문이다. 두 손해를 합치면 6.99 Pa, 순 드래프트 감소분 7.00 Pa와 정확히 맞는다.

아궁이가 먼저 항복한다 — 42 K가 사라졌다#

드래프트가 44.7에서 37.7 Pa로 준다고 해서 곧바로 연기가 방으로 나오지는 않는다. 실제 한계는 아궁이 개구에서 온다. 불구멍을 지나는 면속도가 대략 0.25 m/s 아래로 떨어지면 뜨거운 연기가 개구 위쪽으로 새어 나오기 시작한다. 이 기준을 유량으로 바꾸면 0.0374 kg/s다.

출력의 마지막 두 줄이 그 문턱을 온도로 환산한 것이다. 하강 유로가 없으면 연기 온도가 335 K 아래로 떨어질 때까지 버틴다. 하강 유로가 1 m 있으면 377 K에서 이미 항복한다. 42 K의 여유가 사라진 것이다.

불이 활활 타는 동안에는 둘 다 잘 뽑힌다. 문제는 불을 붙이는 순간과 잦아드는 순간이다. 프랭클린 난로가 "연기 나는 난로"로 기억된 이유가 여기 있다. 결국 1780년대에 데이비드 리튼하우스가 하강 유로를 걷어내고 연도를 곧장 굴뚝으로 올리는 L자 구조로 고쳤고, 그 형태가 이후 표준이 되었다.

중립면 — 방 하나에서 같은 계산이 반복된다#

같은 정수압 논리는 굴뚝이 없는 방에서도 그대로 작동한다. 안팎의 밀도가 다르면 두 정수압 직선의 기울기가 달라지고, 두 직선은 정확히 한 높이에서 만난다. 그 높이가 중립면(neutral plane) znz_n이다.

Δp(z)=poutpin=(ρρi)g(znz)\Delta p(z) = p_{\text{out}} - p_{\text{in}} = (\rho_\infty - \rho_i) g \left( z_n - z \right)

개구가 위아래로 두 개 있고 각각 면적이 A1,A2A_1, A_2, 높이가 z1,z2z_1, z_2라면, 두 개구의 질량유량이 같다는 조건에서 znz_n이 닫힌 형태로 나온다.

zn=ρA12z1+ρiA22z2ρA12+ρiA22z_n = \frac{\rho_\infty A_1^2 z_1 + \rho_i A_2^2 z_2}{\rho_\infty A_1^2 + \rho_i A_2^2}

중립면 아래에서는 바깥 공기가 들어오고 위에서는 실내 공기가 나간다. 아래 그림에서 개구 높이와 면적비, 실내 온도를 바꿔보자.

Enlarge the upper opening and the amber neutral plane climbs toward it — the big hole is the one that sits near zero pressure difference. Then drag inside T below 283 K: the blue line tips the other way, both arrows reverse, and the room that was drawing at the floor starts drawing at the ceiling.

위쪽 개구를 키우면 중립면이 그쪽으로 끌려간다. 큰 구멍은 작은 압력차로도 같은 유량을 통과시키기 때문이다. 그리고 실내 온도를 283 K 아래로 내리면 파란 직선이 반대로 기울고 두 화살표가 모두 뒤집힌다.

자연대류 해석에서 이 예산은 어디에 적히는가#

이 계산을 CFD로 옮길 때 걸리는 지점이 세 군데 있다.

첫째, 압력 경계조건의 기준 높이다. 개구에 totalPressure = 0을 그냥 얹으면 중립면을 경계면 자체에 고정해 버리는 것과 같다. 실제로는 ρgz\rho_\infty g z를 뺀 동수압으로 다뤄야 바깥 기둥의 정수압 기울기가 살아난다. 이걸 놓치면 해가 수렴은 하는데 유량이 몇 배씩 틀린다.

둘째, Boussinesq 근사의 유효 범위다. 위 계산의 온도차는 200 K를 넘는다. 밀도 변화가 50 %를 넘으니 ρρ0(1βΔT)\rho \approx \rho_0 (1 - \beta \Delta T)로 선형화하면 부력을 크게 잘못 센다. 이 경계가 어디인지는 Boussinesq가 30 K에서 거짓말하는 자리에서 정리했다. 굴뚝 문제는 저마하 압축성이나 가변밀도 정식화로 가야 한다.

셋째, 정상해가 하나가 아니라는 점이다. 루프 균형의 근이 둘이라는 사실은 반복 계산에서 그대로 나타난다. 초기 유량을 0에 가깝게 주면 솔버가 아래쪽 근으로 미끄러져 "드래프트 없음"으로 수렴한다. 자연대류 문제 전반의 이 다중해 성질은 자연대류와 Rayleigh 수에서 다룬 분기 구조와 같은 뿌리다. 초기값을 위쪽 근 근처에서 주거나, 유량을 강제한 상태에서 서서히 풀어주는 편이 안전하다.

프랭클린은 열을 방에 붙잡는 데 성공했다. 다만 그 열은 굴뚝이 쓰려던 예산이었다. 부력으로 움직이는 계에서 열교환기를 어디에 놓을지 정할 때, 장부의 어느 칸에서 돈을 빼 쓰는지 먼저 확인하는 편이 낫다.

도움이 됐다면 공유해주세요.