Exergy Dashboard는 다양한 에너지 시스템의 엑서지(Exergy) 분석을 손쉽게 수행할 수 있도록 설계된 대시보드 애플리케이션입니다. 사용자는 다양한 시스템을 등록하고, 각 시스템의 파라미터를 입력하여 엑서지 분석 결과를 시각적으로 확인할 수 있습니다.
이 프로젝트의 목표는 다양한 시스템과 모드(냉방, 난방, 온수 등)에 대해 손쉽게 엑서지 분석을 수행할 수 있는 범용적이고 확장 가능한 대시보드를 개발하는 것입니다. 이를 통해 누구나 새로운 시스템과 평가/시각화 함수를 쉽게 추가할 수 있도록 설계되었습니다.
- 다양한 시스템 및 모드 지원: ASHP, GSHP 등 여러 시스템과 냉방, 난방, 온수 등 다양한 운전 모드를 지원합니다.
- 파라미터 관리: 시스템별 파라미터 입력 및 관리 기능을 제공합니다.
- 동적 평가 함수: 엑서지 평가 함수를 손쉽게 등록하고 실행할 수 있습니다.
- 시각적 분석: Altair 기반의 시각화 함수를 등록하여 대시보드에서 결과를 시각적으로 제공합니다.
- 웹 기반 UI: Streamlit 기반의 웹 대시보드를 통해 사용자 친화적인 인터페이스를 제공합니다.
- 높은 확장성: 사용자 정의 시스템, 평가, 시각화 함수를 쉽게 추가하고 확장할 수 있습니다.
- 언어: Python 3.11+
- 웹 프레임워크: Streamlit
- 데이터 시각화: Altair, Pandas
- 패키지 관리: uv
- 문서화: Markdown
이 섹션에서는 Exergy Dashboard의 내부 동작 방식과 데이터 흐름, 그리고 애플리케이션의 생명주기를 상세히 설명합니다.
다음 다이어그램은 사용자의 입력부터 시작하여 데이터가 각 모듈을 거쳐 최종적으로 시각화되는 전체 과정을 보여줍니다.
graph TD
subgraph User Interaction
A[Start App] --> B(Select Mode);
B --> C(Add/Remove System);
C --> D(Adjust Parameters);
end
subgraph App Lifecycle in app.py
F[Initialize Session State] --> G[Dynamic Import `systems/*.py`];
G --> H(Render Sidebar UI);
H --> I(Render Main Panel UI);
I -- Triggers --> J(Evaluate Parameters);
J -- Triggers --> K(Render Visualizations);
end
subgraph Core Modules
L[system.py<br/>SystemRegistry]
M[evaluation.py<br/>EvaluationRegistry]
N[visualization.py<br/>VisualizationRegistry]
end
subgraph "Session State (sss)"
sss_mode["mode"]
sss_systems["systems"]
sss_params["system:param values"]
sss_vars["system variables"]
end
A --> F;
B -- Updates --> sss_mode;
C -- Updates --> sss_systems;
D -- Updates --> sss_params;
G -- Populates --> L;
H -- Uses --> L;
I -- Reads --> sss_systems;
J -- Calls registered function in --> M;
M -- Returns results --> J;
J -- Updates --> sss_vars;
K -- Calls registered function in --> N;
N -- Reads --> sss_vars;
N -- Returns chart --> K;
app.py는 Streamlit 기반으로 실행되며, 다음과 같은 생명주기를 가집니다.
-
초기화 단계:
- 동적 모듈 임포트:
app.py가 실행되면 가장 먼저systems/디렉토리 내의 모든*_system.py파일을 동적으로 임포트합니다. 이 과정을 통해 각 파일에 정의된 시스템, 평가, 시각화 함수들이 각자의 레지스트리에 자동으로 등록됩니다. - 세션 상태(
sss) 초기화: Streamlit의session_state를sss라는 축약 변수로 사용합니다. 사용자의 현재 선택 모드(mode), 추가된 시스템 목록(systems), 각 시스템의 파라미터 개수(system_count) 등이 초기화됩니다. 이 상태는 사용자가 앱과 상호작용하는 동안 계속 유지됩니다.
- 동적 모듈 임포트:
-
UI 렌더링 및 상호작용:
- 사이드바 렌더링:
st.sidebar내부에 모드 선택(Segmented Control), 시스템 추가(Selectbox, Button), 비교할 시스템 선택(Radio) 위젯을 렌더링합니다. 각 위젯의 값은session_state와 양방향으로 바인딩됩니다. - 메인 패널 렌더링: 사용자가 사이드바에서 선택한 시스템의 파라미터 입력 위젯(
st.number_input)들을 렌더링합니다. 각 입력 위젯의key는{system_name}:{parameter_name}형식으로 지정되어session_state에 독립적으로 저장됩니다.
- 사이드바 렌더링:
-
상태 업데이트 및 자동 재실행:
- 콜백 함수: 'Add to List'나 'Remove system' 버튼 클릭 시,
on_click인자에 연결된 콜백 함수(add_system,remove_system)가 실행되어sss.systems딕셔너리를 직접 수정합니다. - 자동 평가: 파라미터가 변경될 때마다 Streamlit은 스크립트를 재실행합니다. 이때
evaluate_parameters(sss, system_name)함수가 자동으로 호출되어 변경된 파라미터 값으로 재계산을 수행하고, 결과를sss.systems[...]['variables']에 업데이트합니다. - 시각화 업데이트: 평가 결과가 업데이트되면,
VisualizationManager가 해당 모드에 등록된 시각화 함수들을 실행하여 차트를 다시 렌더링합니다.
- 콜백 함수: 'Add to List'나 'Remove system' 버튼 클릭 시,
pyproject.toml:uv를 위한 프로젝트 설정 파일입니다.[project]섹션에는 이름, 버전, 설명 등 메타데이터가,[project.dependencies]에는 실행에 필요한 Python 패키지 목록이 명시되어 있습니다.uv sync명령어는 이 파일을 읽어 의존성을 설치합니다.Dockerfile: 애플리케이션을 컨테이너화하기 위한 빌드 명세입니다.FROM python:3.11-slim: 가벼운 Python 3.11 이미지를 기반으로 합니다.COPY . .: 프로젝트 전체 파일을 컨테이너로 복사합니다.RUN pip install uv && uv sync:uv를 설치하고,pyproject.toml에 명시된 의존성을 설치합니다.CMD ["streamlit", "run", "app.py"]: 컨테이너가 시작될 때 실행할 기본 명령어입니다.
docker-compose.yml: 다중 컨테이너 Docker 애플리케이션을 정의하고 실행하기 위한 파일입니다.services.app:app이라는 서비스(컨테이너)를 정의합니다.build: .: 현재 디렉토리의Dockerfile을 사용하여 이미지를 빌드합니다.ports: - "8501:8501": 호스트의 8501 포트를 컨테이너의 8501 포트(Streamlit 기본 포트)로 매핑합니다.volumes: - .:/app: 호스트의 현재 디렉토리를 컨테이너의/app디렉토리와 동기화(마운트)하여, 코드 변경 시 컨테이너를 재빌드할 필요 없이 바로 적용되도록 합니다.
이 섹션에서는 Exergy Dashboard를 구성하는 핵심 함수와 클래스의 입출력(I/O)을 상세하게 설명합니다.
시스템의 등록과 관리를 담당하는 모듈입니다.
- 설명: 새로운 분석 시스템을 전역 레지스트리에 등록합니다.
- 입력 (Inputs):
mode(str): 시스템이 사용될 운전 모드. (예:'COOLING','HEATING')system_type(str): 시스템의 고유 타입. (예:'ASHP','MyCustomSystem')system_config(dict): 시스템의 상세 구성을 정의하는 딕셔너리.get_system_template()을 참조하여 작성합니다.
- 출력 (Output):
None
- 설명: 새로운 시스템을 정의할 때 사용할 수 있는 표준 템플릿 딕셔너리를 반환합니다.
- 입력 (Inputs): 없음
- 출력 (Output):
dict: 시스템 구성 템플릿. 필수 필드와 데이터 타입에 대한 가이드를 포함합니다.
{ 'display': { 'title': str, 'icon': str }, 'parameters': { 'param_name': { 'explanation': {'EN': str, 'KR': str}, 'latex': str, 'default': float, 'range': [float, float], 'unit': str, 'step': float, 'category': str (optional) } } }
- 설명: 현재 레지스트리에 등록된 모든 시스템의 정보를 깊은 복사(deep copy)하여 반환합니다.
- 입력 (Inputs): 없음
- 출력 (Output):
dict: 등록된 모든 시스템 정보.{mode: {system_type: config}}구조를 가집니다.
시스템의 성능 및 엑서지 계산을 담당하는 평가 함수를 관리하는 모듈입니다.
- 설명: 평가 함수를 레지스트리에 등록하는 데코레이터입니다.
- 입력 (Decorator Inputs):
mode(str): 평가 함수가 적용될 운전 모드.system_type(str): 평가 함수가 계산을 수행할 시스템 타입.
- 함수 시그니처 (Decorated Function Signature):
- 입력:
params(dict): 키는 파라미터 이름(str), 값은 해당 파라미터의 값(float). - 출력:
dict: 계산된 모든 변수(중간값 포함)를 담은 딕셔너리. 키와 값 모두str또는float입니다.
@registry.register('HEATING', 'ASHP') def evaluate_heating_ashp(params: dict) -> dict: T_0 = params['T_0'] # ... more calculations ... X_h = Q_h * (1 - T_0 / T_h) return locals() # 모든 지역 변수를 반환
- 입력:
- 설명: Streamlit 세션 상태(session state)와 연동하여 특정 시스템의 평가를 수행하는 통합 함수입니다.
- 입력 (Inputs):
sss(streamlit.delta_generator.DeltaGenerator): Streamlit의session_state객체.system_name(str): 평가를 수행할 대상 시스템의 이름.
- 출력 (Output):
dict: 평가 함수가 반환한 계산 결과 딕셔너리. 이 값은sss.systems[system_name]['variables']에 자동으로 저장됩니다.
계산 결과를 시각화하는 차트 함수를 관리하는 모듈입니다.
- 설명: 시각화 함수를 레지스트리에 등록하는 데코레이터입니다.
- 입력 (Decorator Inputs):
mode(str): 이 시각화가 표시될 운전 모드.name(str): 대시보드 탭에 표시될 시각화의 이름.
- 함수 시그니처 (Decorated Function Signature):
- 입력:
session_state(streamlit.delta_generator.DeltaGenerator): Streamlit의session_state객체.selected_systems(list[str]): 사용자가 UI에서 선택한 시스템들의 이름 리스트.
- 출력:
altair.Chart: Altair 라이브러리로 생성된 차트 객체.
@registry.register('COOLING', 'COP Distribution') def plot_cop_dist(session_state, selected_systems): # ... 데이터 처리 ... df = pd.DataFrame(...) chart = alt.Chart(df).mark_bar().encode(...) return chart
- 입력:
- 설명: 등록된 시각화 함수들을 관리하고, Streamlit UI에 탭 형태로 렌더링하는 역할을 담당합니다.
app.py에서 주로 사용됩니다. - 주요 메서드:
__init__(self, registry):VisualizationRegistry인스턴스를 받아 초기화합니다.render_tabs(self, session_state, selected_systems, mode): 현재 선택된 모드에 등록된 모든 시각화를 가져와 Streamlit 탭으로 구성하고 각 탭에 차트를 렌더링합니다. 오류 발생 시 UI에 에러 메시지를 표시합니다.
새로운 시스템을 추가하고 실행하는 전체 과정은 다음과 같습니다.
-
시스템 파일 생성:
systems/my_new_system.py파일을 생성합니다. -
코드 작성: 파일에 시스템, 평가, 시각화 함수를 정의하고 등록합니다.
# systems/my_new_system.py from exergy_dashboard.system import register_system from exergy_dashboard.evaluation import registry as eval_registry from exergy_dashboard.visualization import registry import altair as alt import pandas as pd # 1. 시스템 정의 및 등록 my_system = { ... } # 4.1. 구조 참조 register_system('MY_MODE', 'MY_SYSTEM', my_system) # 2. 평가 함수 등록 @eval_registry.register('MY_MODE', 'MY_SYSTEM') def evaluate_my_system(params): # ... 계산 로직 ... return {'my_result': 123} # 3. 시각화 함수 등록 @registry.register('MY_MODE', 'My Result Vis') def plot_my_vis(session_state, selected_systems): # ... 시각화 로직 ... return alt.Chart(...)
-
애플리케이션 실행:
app.py가 실행되면systems디렉토리의*_system.py파일을 자동으로 임포트하여 시스템을 로드합니다.uv sync streamlit run app.py
.
├── app.py # Streamlit 메인 애플리케이션
├── Dockerfile # Docker 이미지 빌드 설정
├── docker-compose.yml # Docker Compose 설정
├── docs/ # 프로젝트 문서
├── examples/ # 예제 코드
├── notebooks/ # 데이터 분석 및 테스트용 노트북
├── src/
│ └── exergy_dashboard/ # 메인 소스 코드
│ ├── system.py # 시스템 등록 및 관리
│ ├── evaluation.py # 평가 함수 레지스트리
│ └── visualization.py# 시각화 함수 레지스트리
└── systems/ # 사용자 정의 시스템 모듈
├── cooling_system.py
└── heating_system.py
이 절에서는 개발 경험이 없는 일반 사용자도 Exergy Dashboard를 빠르게 체험하고 활용할 수 있도록 단계별 안내를 제공합니다.
추가적인 파이썬 환경 설정 없이도 Docker만 설치되어 있으면 한 줄 명령어로 대시보드를 실행할 수 있습니다.
# 1) 프로젝트 루트에서 이미지 빌드 및 실행 (백그라운드)
docker compose up -d --build
# 2) 브라우저에서 대시보드 접속
# 기본적으로 http://localhost:8501 에서 실행됩니다.Tip: 이미 포트 8501을 사용 중인 경우, docker-compose.yml 파일의 ports 항목(8501:8501)에서 호스트 포트를 다른 값으로 바꾼 후 재실행하세요.
# 1) 의존성 설치 (uv 사용)
uv sync
# 2) 대시보드 실행
streamlit run app.py실행 후 터미널에 표시되는 URL(기본값: http://localhost:8501)을 브라우저에 입력하면 대시보드가 나타납니다.
- 사이드바
- 분석 모드 선택: 냉방, 난방, 온수 등.
- 시스템 추가/제거 버튼: 원하는 시스템을 체크박스로 선택합니다.
- 메인 패널
- 각 시스템 카드: 파라미터 슬라이더와 입력창이 자동으로 생성됩니다.
- Calculate 버튼: 모든 시스템의 파라미터 설정이 끝나면 클릭하여 결과를 계산합니다.
- 시각화 탭: 등록된 시각화 함수 목록이 탭으로 표시되며, 클릭 시 인터랙티브 차트가 나타납니다.
UI 배치는 버전에 따라 조금씩 달라질 수 있습니다. 기능 위치가 보이지 않는 경우 사이드바의
Refresh버튼(🔄)을 눌러보세요.
- 슬라이더 외에도 숫자를 더블 클릭하여 키보드로 정확한 값을 입력할 수 있습니다.
- 단위(°C, kg/s 등)는 우측 라벨로 표시되므로 헷갈리지 않도록 확인하세요.
- 동일 모드 내에서 여러 시스템을 동시에 비교할 수 있으므로, 비슷한 조건을 유지하며 파라미터만 변경해 성능을 비교해 보세요.
| 컬러 | 의미 |
|---|---|
| 파란색 막대 | 냉방 모드의 엑서지 손실 |
| 빨간색 막대 | 난방 모드의 엑서지 손실 |
| 회색 배경 | 기준(환경) 조건 |
시각화마다 범례가 제공되며, Legend 항목을 클릭하면 특정 시스템/변수를 숨기거나 강조할 수 있습니다.
| 질문 | 답변 |
|---|---|
| 대시보드 접속이 안 돼요. | 터미널에 나타난 URL이 방화벽으로 차단되었을 수 있습니다. 같은 PC에서 실행했다면 localhost 대신 127.0.0.1을 사용해 보세요. |
| 차트가 보이지 않아요. | 브라우저 캐시 문제일 수 있습니다. 새로고침(F5) 후에도 동일하다면 터미널에 오류 메시지가 있는지 확인하고, Altair 버전을 최신으로 유지하세요. |
| 포트 충돌 오류(Address already in use) | 이미 실행 중인 Streamlit 프로세스를 종료하거나, streamlit run app.py --server.port 8502처럼 다른 포트를 지정하세요. |
| 새 시스템을 추가했는데 UI에 안 보여요. | 파일 이름이 *_system.py 형태인지 확인하고, 앱을 재실행하거나 사이드바의 🔄 버튼으로 새로고침하세요. |
| 결과가 이상해 보여요. | 파라미터 범위가 합리적인지 확인 후, 평가 함수(evaluation.py)에 예외 처리(분모 0 등)를 추가하세요. |
추가적인 질문·버그 제보는 GitHub Issue로 남겨주세요. 재현 방법(파라미터 값, 캡처)과 로그를 함께 제공해 주시면 빠른 대응이 가능합니다.