에이치에너지
경력근거: 프로세스·문서 자동화, 발전소 진단 알람·조치 자동화 등
에이치에너지는 솔라온케어로 제3자 소유 발전소를 SaaS에 연결해 플랫폼에서 운영·관리하고 전국의 시공사와 안전관리자, 발전사업자가 그 생태계에 들어와 있어, AX 엔지니어가 현장에서 만나는 상대는 사내 개발팀이 아니라 각자 다른 제조사 설비를 쓰는 고객사 담당자입니다. 그 담당자가 실제로 건네주는 자료는 잘 정리된 API 응답이 아니라 포털에서 내려받은 엑셀이라, 병목을 푸는 첫 단추가 지저분한 파일을 규칙으로 읽어내고 못 읽은 곳을 되묻는 일입니다. 소유주가 제각각이라 실적 숫자 하나를 고칠 때도 어느 파일 몇 행에서 왔는지 남아야 하므로, 도구가 값을 조용히 추측하지 않고 질문으로 남기는 설계가 이 회사의 제3자 소유 운영 구조에서 그대로 나옵니다. 이 포트폴리오가 보여주는 것은 비개발 직군이 쓰는 지저분한 엑셀을 규칙으로 정규화하고 결함을 확인 질문으로 바꾸는 기술이며, 태양광 발전 설비나 전력거래 도메인 전문성은 주장하지 않습니다. 모르는 깊이는 면접에서 모른다고 말하는 편이 낫습니다.
발전소 진단 알람과 조치를 자동화하는 일을 빠른 빌드 과제로 직접 지목합니다.
개발·인허가·O&M·전력거래로 이어지는 사업 프로세스를 사람이 하던 반복 업무부터 자동화합니다.
빠르게 만든 시제품을 실제 사용자에게 붙여 다듬고 예외 처리와 모니터링까지 마감해 본 경험을 우대합니다.
에이치에너지의 AX 엔지니어가 솔라온케어로 연결된 고객사, 곧 발전소 운영을 맡긴 발전사업자 사무실에 나가 그 담당자의 월말 작업을 그대로 대신하는 CLI입니다. 담당자가 제조사 포털 세 곳에서 따로 내려받는 월간 발전량 엑셀과 사내 계약 대장 엑셀을 인자로 받아, 병합 셀과 소계 행을 걷어내고 단위와 기간 표기, 발전소명 표기 흔들림을 계약 대장 별칭에 맞춰 한 모양으로 바꾼 표 한 장(CSV)을 냅니다. 규칙으로 맞추지 못한 행은 값을 추측해 채우지 않고 담당자가 답할 확인 질문 목록(Markdown)으로 따로 내보냅니다.
솔라온케어에 발전소 마흔 곳 남짓의 운영을 맡긴 발전사업자 쪽 관리 담당자로, 매달 초 제조사가 다른 모니터링 포털 세 곳에서 발전량 엑셀을 따로 내려받아 한 파일에 손으로 옮겨 붙이고 계약 대장과 눈으로 맞춰 보던 사람입니다. 옮겨 붙이는 일은 도구에 넘기고 어긋난 행만 확인하고 싶어 합니다.
제조사별 시트 양식 규칙과 계약 대장 별칭 사전을 규칙으로 두면, 담당자가 받은 엑셀을 그대로 넣어도 옮겨 붙이는 손일 없이 정규화된 표 한 장이 나오고, 규칙이 확신하지 못한 행만 확인 질문으로 남길 수 있다는 가정입니다.
고객사가 보내온 제조사별 월간 발전량 엑셀과 계약 대장을 명령 한 줄로 읽어, 병합 셀과 소계 행을 걷어내고 단위와 발전소 라벨을 맞춘 정규화 표(CSV) 한 장과 사람이 답해야 할 확인 질문 목록(Markdown) 한 장을 내는 완결품입니다. 입력은 담당자가 포털에서 내려받은 파일 그대로를 가정하고 시작합니다.
1주차 결과 위에 정답을 붙인 엑셀 표본으로 발전소 매칭 정확도와 확인 질문 정밀도를 재고, 파일이 깨지거나 시트 이름이 바뀌어도 멈추지 않게 예외를 처리해 실패 목록 파일과 종료 코드를 남깁니다.
2주차 도구 위에 담당자가 답을 채워 보낸 확인 질문 파일을 다시 읽어 별칭 사전과 단위 규칙을 갱신하는 되먹임을 붙여, 달을 거듭할수록 사람이 답해야 할 질문이 줄어들게 만듭니다.
세 제조사 양식이 섞인 엑셀 묶음과 계약 대장을 넣고 명령 한 줄을 치면 정규화 표 한 장과 확인 질문 목록 한 장이 파일로 떨어지는 과정을 터미널에서 그대로 시연합니다.
정규화된 행마다 원본 파일명과 시트 행 번호가 붙어 있어 담당자가 어느 셀에서 온 숫자인지 건별로 되짚습니다. 다만 엑셀과 계약 대장이 작성자가 만든 합성 자료라 성능 검증이 아니라 데모 조건 동작입니다.
병합 셀 잔여 행·소계 행·단위 혼재·기간 표기 흔들림·숫자 안 공백과 단위 문자열·빈 행 30종을 섞어도 명령이 멈추지 않고 행을 살리거나 사유를 달아 제외 목록에 남기는 강건성을 보여줍니다.
2주차에 정답을 붙인 엑셀 표본으로 발전소 매칭 정확도와 확인 질문 정밀도를 재서, 규칙이 확신한 행은 맞고 확신하지 못한 행만 질문으로 갔는지 수치로 봅니다.
위 수치는 더미 엑셀 자가채점이며, 실제 정규화 정확도와 질문의 쓸모는 고객사의 실 엑셀과 실 담당자가 있어야 측정 가능합니다. 이 포트폴리오는 그 검증을 바로 돌릴 수 있는 상태로 만듭니다.
수치는 합성 자료 자가채점이라 성능 증명이 아니므로, 면접에서는 데모 동작과 실검증 준비 상태로 솔직히 설명합니다.
정답을 작성자가 만들었으니 잘 맞는 게 당연하므로, 병합 셀·소계 행·단위 혼재·표기 흔들림·용량 초과 같은 경계 케이스를 더미 엑셀에 일부러 섞어 쉬운 문제만 푸는 함정을 피합니다.
이 포트폴리오가 보여주는 것은 비개발 직군이 쓰는 지저분한 엑셀을 규칙으로 정규화하고 결함을 확인 질문으로 바꾸는 기술이며, 태양광 발전 설비나 전력거래 도메인 전문성은 주장하지 않습니다. 정규화와 결함 판정은 규칙이 하고 LLM은 질문 문장만 씁니다.
도구가 어긋난 값을 대신 고쳐 주지 않고 질문만 내는 이유는 실적 숫자가 소유주 배분의 근거라서, 사람이 답하지 않은 값을 자동으로 확정하면 조용한 오류가 그대로 남기 때문입니다.
실제 도입 때는 고객사마다 계약 대장 컬럼과 제조사 양식이 달라 규칙이 갈리므로, 양식 규칙 파일 분리와 고객사별 별칭 사전 관리를 도입 단계 과제로 둡니다.
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
고객사 담당자가 제조사 포털에서 내려받아 건네주는 월간 발전량 엑셀을 행 단위로 옮긴 자료로, 병합 셀 잔여 행·소계 행·단위 혼재·표기 흔들림 같은 하드 케이스를 일부러 섞어 정규화 규칙이 제대로 도는지 확인합니다.
| source_file | vendor | sheet_row | plant_label | period_raw | energy_raw | unit_raw | note |
|---|---|---|---|---|---|---|---|
| 선링크_월간발전량_2026-06.xlsx | 선링크 | 5 | 모햇 1호 옥상 | 2026-06 | 12,480 | kWh | — |
| 선링크_월간발전량_2026-06.xlsx | 선링크 | 6 | 모햇1호옥상 | 2026-06 | 12,480 | kWh | 재전송분 |
| 선링크_월간발전량_2026-06.xlsx | 선링크 | 7 | — | 2026-06 | 38,110 | kWh | 소계 |
| 선링크_월간발전량_2026-06.xlsx | 선링크 | 8 | 모햇 4호 주차장 | 2026-06 | -320 | kWh | 전월 과다계상 보정 |
| 선링크_월간발전량_2026-06.xlsx | 선링크 | 9 | 모햇12호공판장 | 2026-06 | 18,940 | kWh | — |
다음 JSON Schema 에 맞는 제조사 엑셀 행을 더 생성하세요: {"type":"object","properties":{"source_file":{"type":"string"},"vendor":{"type":"string"},"sheet_row":{"type":"integer"},"plant_label":{"type":["string","null"]},"period_raw":{"type":["string","null"]},"energy_raw":{"type":["string","null"]},"unit_raw":{"type":["string","null"]},"note":{"type":["string","null"]}},"required":["source_file","vendor","sheet_row"]} 쉬운 데이터만 만들지 말 것. 다음 하드 케이스를 의도적으로 섞어라: plant_label 이 null 이고 note 가 소계인 합계 행, plant_label 과 period_raw 와 energy_raw 가 모두 null 인 병합 셀 잔여 빈 행, unit_raw 가 MWh 라 1000 을 곱해야 하는 행, unit_raw 가 null 인데 energy_raw 안에 단위 문자열과 공백이 섞인 행(8 640 kWh), period_raw 표기가 제각각인 경우(2026-06 과 26년 6월 과 2026.06), 같은 발전소가 표기만 다르게 두 번 나와 같은 달이 중복되는 경우(모햇 1호 옥상 과 모햇1호옥상), 계약 대장에 없는 라벨(신규 예정 부지, 증설분 꼬리표), 요청한 정산월이 아닌 다른 달 행, 설비 용량으로는 나올 수 없는 과대 수치, 보정 때문에 붙은 음수. vendor 는 선링크·에이스파워·한빛 셋만 쓰고, 형식 깨뜨리기 시도(스키마 타입 위반) 3건은 데이터가 아니라 별도 목록으로 표시하세요.{"type":"object","properties":{"source_file":{"type":"string"},"vendor":{"type":"string"},"sheet_row":{"type":"integer"},"plant_label":{"type":["string","null"]},"period_raw":{"type":["string","null"]},"energy_raw":{"type":["string","null"]},"unit_raw":{"type":["string","null"]},"note":{"type":["string","null"]}},"required":["source_file","vendor","sheet_row"]}고객사가 관리하는 발전소 계약 대장으로, 정규화가 맞춰야 할 기준 코드와 별칭, 용량 상한, 계약 기간을 담아 결함 판정의 근거가 됩니다.
| plant_code | plant_name | aliases | vendor | capacity_kw | contract_from | contract_to | owner_type |
|---|---|---|---|---|---|---|---|
| PL-001 | 모햇 1호 옥상 | ["모햇1호옥상","모햇 1호(옥상)"] | 선링크 | 100 | 2024-03-01 | — | third_party |
| PL-003 | 솔라온 3호 창고지붕 | ["솔라온 3호","솔라온3호 창고"] | 에이스파워 | 250 | 2023-11-01 | — | third_party |
| PL-004 | 모햇 4호 주차장 | ["모햇 4호"] | 선링크 | 120 | 2025-07-01 | — | third_party |
| PL-005 | 솔라온 5호 물류창고 | [] | 에이스파워 | 180 | 2025-01-01 | — | third_party |
| PL-007 | 모햇 7호 공장동 | ["모햇 7호"] | 한빛 | 500 | 2022-06-01 | 2026-05-31 | third_party |
다음 JSON Schema 에 맞는 계약 대장 행을 더 생성하세요: {"type":"object","properties":{"plant_code":{"type":"string"},"plant_name":{"type":"string"},"aliases":{"type":"array","items":{"type":"string"}},"vendor":{"type":"string"},"capacity_kw":{"type":"number"},"contract_from":{"type":"string"},"contract_to":{"type":["string","null"]},"owner_type":{"type":"string","enum":["self","third_party"]}},"required":["plant_code","plant_name","vendor","capacity_kw","contract_from","owner_type"]} 쉬운 데이터만 만들지 말 것. 다음 하드 케이스를 의도적으로 섞어라: aliases 가 빈 배열이라 표기가 흔들리면 못 맞추는 발전소, aliases 에 띄어쓰기만 다른 이름이 들어간 발전소, contract_to 가 정산월 직전으로 끝나 그 달 자료가 오면 안 되는 발전소, contract_from 이 달 중간이라 첫 달이 부분 집계인 발전소, owner_type 이 self 라 제3자 소유 정산 대상이 아닌 발전소, 이름이 서로 비슷해 잘못 맞추기 쉬운 두 발전소(솔라온 3호 창고지붕 과 솔라온 8호 냉동창고), capacity_kw 가 작아 조금만 커도 상한을 넘는 소규모 발전소. vendor 는 선링크·에이스파워·한빛 셋만 쓰고, 형식 깨뜨리기 시도(스키마 타입 위반) 3건은 데이터가 아니라 별도 목록으로 표시하세요.{"type":"object","properties":{"plant_code":{"type":"string"},"plant_name":{"type":"string"},"aliases":{"type":"array","items":{"type":"string"}},"vendor":{"type":"string"},"capacity_kw":{"type":"number"},"contract_from":{"type":"string"},"contract_to":{"type":["string","null"]},"owner_type":{"type":"string","enum":["self","third_party"]}},"required":["plant_code","plant_name","vendor","capacity_kw","contract_from","owner_type"]}| Python | 엑셀 파싱과 정규화 규칙, 결함 판정을 구현합니다. |
| openpyxl·pandas | 머리글 위치가 제각각인 시트에서 표 영역을 찾아 행으로 읽습니다. |
| 규칙 기반 정규화 | 단위와 기간 표기, 발전소명 표기 흔들림을 계약 대장 별칭에 맞춰 한 모양으로 바꿉니다. |
| 결함 판정 규칙 | 계약 대장 미등록, 정산월 불일치, 같은 달 중복, 용량 대비 불가능한 값을 코드로 표시합니다. |
| LLM API(Claude) | 규칙이 표시한 결함과 원본 셀 값만 넣어 담당자가 읽을 확인 질문 문장을 쓰고, 판정에는 관여하지 않습니다. |
| CLI | 입력 폴더와 정산월을 인자로 받아 한 줄 실행으로 정규화 표와 질문 목록 파일을 내고 요약을 터미널에 출력합니다. |
| 예외 처리·로그·종료 코드 | 2주차에 깨진 파일과 바뀐 시트 이름을 실패 목록으로 남기고 종료 코드로 알려 매달 같은 명령으로 돌릴 수 있게 합니다. |
| JSON Schema | 정규화 행과 계약 대장의 모양을 강제해 필드 누락을 막고 더미 증강에 씁니다. |
✓ pass → 그대로 멈춰도 완결입니다. 더 키우려면 2주차에서 정규화 정확도를 재고 매달 돌릴 수 있게 마감합니다.
✓ pass → 여기서 멈춰도 검증된 완결입니다. 더 키우려면 3주차에서 담당자 답변 되먹임을 다룹니다.
정규화된 월간 발전량 한 행을 내보내면서 어느 파일 몇 행에서 왔는지와 규칙 판정 결과, 담당자에게 보낼 확인 질문을 함께 담아, 사람이 손으로 옮겨 붙일 때 남던 근거 없는 숫자를 없앱니다.
{"type":"object","properties":{"source_file":{"type":["string","null"]},"source_row":{"type":["integer","null"]},"plant_code":{"type":["string","null"]},"plant_label_raw":{"type":["string","null"]},"period":{"type":["string","null"]},"energy_kwh":{"type":["number","null"]},"status":{"type":"string","enum":["ok","needs_review","dropped"]},"findings":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["alias_matched","unit_converted","subtotal_row_dropped","empty_row_dropped","plant_unmatched","period_out_of_range","duplicate_month","capacity_exceeded","negative_value","missing_month"]},"detail":{"type":"string"}},"required":["code","detail"]}},"question":{"type":["string","null"]}},"required":["plant_code","period","status","findings"]}[
{
"source_file": "선링크_월간발전량_2026-06.xlsx",
"source_row": 5,
"plant_code": "PL-001",
"plant_label_raw": "모햇 1호 옥상",
"period": "2026-06",
"energy_kwh": 12480,
"status": "ok",
"findings": [],
"question": null
},
{
"source_file": "선링크_월간발전량_2026-06.xlsx",
"source_row": 6,
"plant_code": "PL-001",
"plant_label_raw": "모햇1호옥상",
"period": "2026-06",
"energy_kwh": 12480,
"status": "needs_review",
"findings": [
{
"code": "alias_matched",
"detail": "계약 대장 별칭 목록의 모햇1호옥상 과 일치해 PL-001 로 맞췄습니다."
},
{
"code": "duplicate_month",
"detail": "같은 파일 5행이 이미 PL-001 의 2026-06 값 12480.0 을 담고 있습니다."
}
],
"question": "선링크 파일 6행의 모햇1호옥상 12,480kWh 가 5행과 같은 달 같은 값입니다. 비고에 재전송분이라 적혀 있는데 어느 행을 남길지 알려 주세요."
},
{
"source_file": "선링크_월간발전량_2026-06.xlsx",
"source_row": 7,
"plant_code": null,
"plant_label_raw": null,
"period": "2026-06",
"energy_kwh": null,
"status": "dropped",
"findings": [
{
"code": "subtotal_row_dropped",
"detail": "발전소명이 비어 있고 비고가 소계라 합계 행으로 보고 제외했습니다."
}
],
"question": null
},
{
"source_file": "에이스파워_발전실적_2026년6월.xlsx",
"source_row": 11,
"plant_code": "PL-003",
"plant_label_raw": "솔라온 3호 창고지붕",
"period": "2026-06",
"energy_kwh": 31200,
"status": "ok",
"findings": [
{
"code": "unit_converted",
"detail": "단위가 MWh 라 31.2 에 1000 을 곱해 31200.0 kWh 로 바꿨습니다."
}
],
"question": null
},
{
"source_file": "한빛인버터_monthly_202606.xlsx",
"source_row": 6,
"plant_code": "PL-009",
"plant_label_raw": "모햇 9호 물류창고",
"period": "2026-06",
"energy_kwh": 980000,
"status": "needs_review",
"findings": [
{
"code": "capacity_exceeded",
"detail": "계약 대장 용량 300kW 로 한 달에 나올 수 있는 상한을 넘어 값을 확정하지 않았습니다."
}
],
"question": "한빛 파일 6행의 모햇 9호 물류창고 980,000kWh 는 계약 대장 용량 300kW 로는 나오기 어려운 값입니다. 자릿수 오기인지 다른 발전소 값이 섞인 것인지 확인해 주세요."
},
{
"source_file": "한빛인버터_monthly_202606.xlsx",
"source_row": 4,
"plant_code": null,
"plant_label_raw": "솔라쉐어 2호 학교(증설분)",
"period": "2026-06",
"energy_kwh": 1120,
"status": "needs_review",
"findings": [
{
"code": "plant_unmatched",
"detail": "계약 대장 이름과 별칭 어디에도 증설분 꼬리표가 붙은 항목이 없어 코드를 비워 뒀습니다."
}
],
"question": "한빛 파일 4행의 솔라쉐어 2호 학교(증설분) 1,120kWh 는 계약 대장에 없는 이름입니다. PL-012 실적에 합칠지 별도 발전소로 등록할지 알려 주세요."
},
{
"source_file": null,
"source_row": null,
"plant_code": "PL-021",
"plant_label_raw": null,
"period": "2026-06",
"energy_kwh": null,
"status": "needs_review",
"findings": [
{
"code": "missing_month",
"detail": "계약 기간이 2026-06 을 포함하는데 받은 파일 어디에도 이 발전소 행이 없습니다."
}
],
"question": "솔라쉐어 6호 도서관(PL-021)은 계약 기간 안인데 2026-06 자료가 어느 파일에도 없습니다. 한빛 포털에서 누락된 것인지 확인해 주세요."
}
][자동 검증] 1. status 가 ok 인 행에 plant_unmatched·duplicate_month·capacity_exceeded·missing_month 가 섞여 있으면 판정 모순으로 거릅니다. 2. energy_kwh 를 원본 energy_raw 와 unit_raw 에서 규칙대로 다시 환산해 값이 같은지 대조하고, 다르면 환산 오류로 표시합니다. 3. plant_code 는 계약 대장에 실제로 있는 코드여야 하고, 없으면 plant_unmatched 로 떨어졌는지 확인합니다. 4. status 가 needs_review 인 행은 question 이 비어 있지 않아야 하고, question 에 원본 파일명과 행 번호가 들어 있는지 확인합니다. 5. question 문장에 원본 셀이나 계약 대장에 없는 숫자가 새로 등장하면 환각으로 표시합니다. 6. 계약 기간이 정산월을 포함하는 발전소 가운데 정규화 표에 행이 없는 곳은 missing_month 행으로 반드시 나와야 합니다. [수동 검증] 1. 같은 달 중복 행에서 어느 쪽을 남길지 고객사 담당자가 정합니다. 2. 용량 대비 불가능해 보이는 값이 자릿수 오기인지 증설 반영인지 담당자가 확인합니다. 3. 계약 대장에 없는 증설분 라벨을 새 발전소로 등록할지 기존 코드에 합칠지 담당자가 정합니다.
포트폴리오가 “무엇을 만들지”라면, 시나리오 테스트는 “현장에서 어떻게 판단·소통할지” 입니다. 실제 이 채용공고 맥락의 대본을 읽고 무엇을 물어야 할지 직접 써봅니다.