본문으로 건너뛰기

버그 제보

이상한 점을 알려 주시면 고칠게요. 지금 보고 있는 페이지와 브라우저 정보가 함께 담겨요.

페이지:

포트폴리오로 돌아가기

남광토건

AX팀 주임 · 풀스택 개발

엑셀과 종이로 돌던 건설사 업무를 AI 기반 사내 시스템으로 바꿨습니다. 콘크리트 품질, 경력 산정, 기술인력 배치, 회의록, 경비, 출결 시스템을 만들고 하나의 포털과 공통 조직 데이터 위에 올렸어요.

기간
2026.02 – 2026.09
근무 형태
서울 · 대면
회사
남광토건은 극동건설·금광기업과 함께 3개 건설사 그룹을 이루는 종합건설사입니다. AX팀은 2026년 초에 새로 생긴 팀으로, 현장이 커지고 신규 인력이 빠르게 늘어나는 가운데 업무 시스템이 부족한 문제를 풀기 위해 만들어졌습니다.
기술
Next.js, FastAPI, Supabase, PostgreSQL, Gemini, Roboflow, GitHub Actions, AWS Lightsail, Claude Code
포털에 올린 사내 서비스
11개
송장–타설 자동 매칭률
94%
지원자 1인 경력 산정 시간
30분→3분
DB화한 기술자 경력
1,488명
남광토건에서 만든 서비스 화면
목차10개 항목

팀은 12월에 현장과 본사를 인터뷰해서 개선할 업무 28건을 찾았습니다. 그중 효과가 가장 큰 것부터 "먼저 적용하고 나중에 다듬기" 원칙으로 13개월 안에 현장에 내보냈어요. 시판 솔루션 5종도 비교해 봤지만 한계가 분명했습니다. 전산화만 될 뿐 자동화가 아니었고, 솔루션끼리 데이터가 끊기고, 회사 양식과 맞지 않았고, 데이터가 솔루션에 묶이고, 확장하기 어려웠어요. 그래서 자체 개발로 결정했습니다.

팀은 3~4명이었고, 개발에는 Claude Code 같은 AI 코딩 도구를 적극적으로 썼습니다.

AXWORKS 포털 · 공통 조직 데이터(SSOT)

흩어진 사내 업무 앱 10여 개를 하나의 로그인(SSO)과 하나의 조직 데이터 위에 올린 사내 플랫폼

앱이 늘어날수록 사용자·부서·권한 데이터가 앱마다 따로 생기고 어긋나기 시작했습니다. 팀은 인증과 조직 정보를 한 곳으로 모으기로 했고, 저는 포털과 관리 콘솔을 만들어 운영하면서 각 앱을 이 공통 기반 위로 옮겼습니다. 그룹웨어 일회용 토큰 로그인과 ERP·그룹웨어 야간 동기화의 뼈대는 팀원들이 만들었어요.

  • 포털과 관리 콘솔: 서비스 카드에는 권한에 따라 사용 가능 / 권한 없음 / 보기 권한 배지가 붙습니다. 권한 신청(전 직원에게 개방), 제보·제안 게시판(답글, 공개 여부 전환, 첨부), 관리자 콘솔(서비스·권한 관리, 이용 통계)을 만들었습니다. 이용 통계는 SQL 집계로 다시 짜고 3년 보관 정책을 두었고, 운영자 본인의 활동은 집계에서 뺐습니다.
  • 앱 로그인을 포털 하나로: 앱 4개(기술인력 배치, 회의록, 경력 산정, 콘크리트)가 포털 SSO로만 들어오게 바꾸고, 세션이 만료되면 포털을 거쳐 원래 화면으로 돌아오게 했습니다.
  • 그룹웨어 임베드 배너: 그룹웨어 화면 안에 iframe으로 들어가는 배너(공지 캐러셀, 뉴스·발주 로테이터)를 만들었습니다. iframe 안에서도 로그인이 유지되도록 세션 쿠키를 SameSite=None으로 통일하고, 바로가기는 보는 사람 법인의 그룹웨어 OAuth를 한 번 거쳐 각 서비스로 보냅니다. 공지는 관리 화면에서 실물 미리보기, 드래그 정렬, 노출 토글로 관리합니다.
  • 공통 조직 데이터 정리: 명부를 공통 스키마로 옮겨 3층 이름 규칙에 맞추고, 통합 테이블에 빠져 있던 원천 필드 4개와 ERP 직위·직책 원본 코드를 보존했습니다. 그룹웨어를 뺀 실행이 매번 실패로 끝나던 문제와 중복 인덱스를 정리하고, 앱들이 이 공통 테이블만 읽도록 옮겼어요.
  • 건설 뉴스·입찰 피드: 500억 원 이상 입찰·발주 공고를 모으면서 국가철도공단·수자원공사·도로공사·한전 수집기를 더했고, 한전 엑셀이 메모리를 넘기던 문제는 스트리밍 파서로 풀었습니다. 누리장터 민간 입찰 탭에서는 공고 규격서 PDF를 워커 3개로 요약하고, Gemini로 사업명의 상투 문구를 걷어 "지역명 사업명"만 남깁니다.
  • 모바일 직원·현장 검색: 직원 사진·휴대폰·내선을 찾아 연락처(vCard)로 저장하고, 현장·사무실 주소를 T맵·카카오맵·네이버 지도로 바로 엽니다.
  • 데이터 구조: 팀은 Supabase 하나에 업무 도메인별 PostgreSQL 스키마 15개(테이블 약 300개)를 나누고, 테이블 대부분에 행 단위 보안 정책(RLS)을 걸어 앱별 접근 범위를 제한했습니다.
포털 이용 통계: 90일 동안 순 방문자 932명, 서비스 클릭 3,484회
포털 이용 통계: 90일 동안 순 방문자 932명, 서비스 클릭 3,484회

공개 후 90일 동안 순 방문자 932명, 서비스 클릭 3,484회를 기록했고, 방문의 90%가 업무시간에 몰렸습니다. 사내 도구가 실제 업무 흐름 안에서 쓰이고 있다는 뜻으로 읽었어요.

콘크리트 품질 관리 시스템

시험 보드판 사진과 레미콘 송장 사진을 올리면 AI가 읽어서 품질 서류와 대시보드를 자동으로 만듭니다.

팀장이 이전 현장에서 GPT-4o로 검증해 본 프로토타입이 출발점이었고, 이를 남광 현장에 맞게 Roboflow + Gemini 구조로 새로 만들고 서류 자동 생성과 CSI 자동 업로드까지 넓혔습니다.

2024년 7월부터 콘크리트 시험 결과를 건설품질관리 사이트(CSI)에 올리는 것이 의무가 됐습니다. 현장에서는 타설할 때마다 사진 촬영, 보고서 작성, CSI 업로드를 손으로 반복했어요. 공시체 시험은 한 번 타설에 1·7·28일 세 차례씩 이어집니다. 인터뷰에서 "야근하는 직원 대부분이 이런 서류를 한다"는 말까지 들었습니다.

  • 사진 → 데이터: 모바일로 시험 사진을 올리면 Roboflow 객체 탐지 모델이 보드판 영역을 찾고, Gemini가 손글씨 수치(슬럼프, 공기량, 염화물, 온도, 단위수량, 압축강도)를 읽어 저장합니다. 사용자는 판정 기준과 비교해 보고 다시 찍거나 고칠 수 있습니다.
    • 인식률을 올리려고 모델만 바꾸지 않고 보드판 양식 자체를 표준화했습니다.
  • 송장 자동 매칭: 송장의 날짜·규격·업체 세 조건이 타설 기록과 맞으면 자동으로 연결합니다. 후보가 2건 이상이면 사람이 고르도록 했고, 송장은 첫차와 막차만 등록하게 설계해 입력량을 줄였습니다. 한 현장 기준 432세트 중 408건(94%)이 자동 매칭됐습니다.
  • 서류 자동 생성: 하나의 타설 데이터에서 품질시험대장 등 13종 엑셀 보고서를 템플릿 엔진으로 만들어 냅니다. 현장마다 다른 양식은 현장별 템플릿으로 관리합니다.
  • 품질 도메인 규칙의 코드화: 동절기·간절기 압축강도 보정, 염화물 계산, 규격별 배합 정보를 반영했고, 기상청 관측 데이터도 연동했습니다.
  • CSI 자동 업로드: CSI에는 결과를 올릴 API가 없어서, 브라우저를 대신 조작하는 Python 데스크톱 자동화(RPA) 프로그램을 만들었습니다.
    • 품질 서류의 작업 목록을 붙여 넣고 사진을 고른 뒤 시작을 누르면, 시험 등록, 슬럼프·공기량·염화물·단위수량 입력, 증빙 사진 첨부, 완료 화면 캡처 보관까지 사람 손 없이 진행됩니다.
    • 같은 건을 손으로 올리는 시연은 약 3분 47초, 자동화는 약 1분 40초가 걸렸고, 그중 사람이 하는 일은 처음 40초 남짓입니다. 시연용 샘플 기준이에요.
  • 현장 피드백을 쌓는 개발 방식: 석 달 동안 PR 170여 개를 머지하며 현장 요청을 반영했습니다. 6월에는 성능을 따로 손봐, 차례로 기다리던 요청을 병렬로 바꾸고 엑셀 생성 라이브러리(exceljs)를 클라이언트 번들에서 분리했고, Supabase의 1,000행 응답 제한 때문에 행이 빠지던 문제도 고쳤습니다.
CSI 자동 업로드: 시험 결과 입력과 증빙 첨부가 끝난 화면을 캡처해 보관합니다
CSI 자동 업로드: 시험 결과 입력과 증빙 첨부가 끝난 화면을 캡처해 보관합니다
타설 대시보드: 한 달간 타설 45회, 약 12,700㎥, 물성시험 121건, 공시체시험 171건
타설 대시보드: 한 달간 타설 45회, 약 12,700㎥, 물성시험 121건, 공시체시험 171건

파일럿(2/27)부터 정식 오픈(3/19)까지 약 3주가 걸렸습니다. 현장 미팅 네 번과 단톡방 피드백을 반영하며 서류를 4종에서 9종으로, 다시 13종으로 늘렸고, 4월에는 남광·극동의 건축 현장 5곳에서 쓰였어요.

경력 산정 자동화 시스템

이력서와 건설기술인협회 경력증명서 PDF를 AI가 읽고, 회사 기준에 따라 인정 경력 연차를 자동으로 계산합니다.

경력직을 채용할 때 인사 담당자는 지원자의 이전 회사 규모(도급순위 100위 안인지), 직무 연관성, 고용형태를 하나하나 검색해서 추정했습니다. 한 명에 10~30분이 걸렸고, 기준도 관행적으로 해석되어 사람마다 달랐어요.

  • 추출과 병합은 AI, 계산은 코드: Gemini Vision으로 두 문서에서 경력을 뽑아 합칩니다. 합치다 생긴 충돌은 "미해소 항목"으로 따로 보여 주고 원본 문서를 기준으로 고칩니다.
    • 결과가 매번 같아야 하는 산정 규칙은 LLM에 맡기지 않고 함수 엔진으로 코드화했습니다. 회사 규모(도급순위)·업종·고용형태별 인정률, 겹치는 재직 기간 차감, 학력 차감, 법인만 바뀐 연속 근무 판정, "2019.03"처럼 월까지만 적힌 날짜의 정규화, 면접에서 확인할 항목 표시가 여기에 들어갑니다.
  • 일괄 분석: 이름_이력서.pdf, 이름_경력증명서.pdf 파일명으로 자동으로 짝을 짓고, asyncio로 동시에 분석합니다. 50명도 약 3분이면 끝납니다.
  • 도급순위 관리: 시공능력평가 명단(약 2,800개 회사)을 엑셀로 올리면 바로 반영되고, 사명 변경 때문에 생기는 회사명 불일치는 별칭 매핑으로 해결했습니다.
일괄 분석 화면: 업로드 → 자동 매칭 확인 → 동시 분석의 3단계
일괄 분석 화면: 업로드 → 자동 매칭 확인 → 동시 분석의 3단계

4월 중순 인사팀에 처음 배포한 뒤 그룹 3사 인사총무팀이 실제 채용에 썼고, 8월에는 설계 계열사 두 곳도 사용을 요청했습니다. 분석 이력은 9월 기준 200건을 넘었어요.

기준을 코드로 옮기다 보니 모호하거나 서로 충돌하던 기준이 드러났고, 인사팀이 경력 산정 기준을 다시 정의하는 논의로 이어졌어요.

기술인력 배치 시스템

입찰 때 발주처·공종별로 배치할 수 있는 기술자가 누구인지 자동으로 판정하고 순위를 매깁니다.

경력 산정 시스템을 본 토목공사팀의 요청으로 시작한 후속 과제입니다. 조달청, 지자체, 한국도로공사, 국가철도공단, LH 등 발주처마다 현장대리인·시공책임자 요건이 달라서 담당자도 헷갈리는 경우가 많았습니다. 기술자 경력증명서는 엑셀에 손으로 옮겨 관리했고, 인력이 자주 들고 나서 정리 부담이 컸습니다.

  • 구조화 OCR: Gemini의 구조화 출력으로 경력증명서에서 기술경력, 건설사업관리경력, 자격, 교육, 학력을 뽑아 DB에 저장합니다.
    • 수백 페이지짜리 문서에서는 응답이 중간에 잘렸습니다. 페이지를 재귀적으로 나눠 병렬로 다시 추출하고, 잘린 JSON은 스택 기반 파서로 복구하는 방식으로 해결했습니다.
  • 규정을 데이터로: 조달청 종합심사 세부기준 같은 발주처별 규정을 읽고 공종별 요건을 규정 테이블로 옮겨, 후보자마다 적격 여부를 평가해 순위를 매깁니다.
    • 토목공사팀·공공영업팀과 회의하며 규칙을 다듬었습니다. 현장대리인은 특급 등급이 하나 이상 있어야 하고, "시공" 경력을 셀 때는 안전·품질 경력을 빼고, 고속도로·철도 경력은 공종 칸뿐 아니라 공사명에 해당 단어가 있어도 인정하는 식이에요.
    • 후보자 증명서는 최대 10개씩 병렬로 처리하고, 판정 결과와 근거 조건을 엑셀로 내려받을 수 있습니다.
  • 폐업 추정 표시: 경력증명서 속 회사가 지금도 영업 중인지 웹 검색과 국세청 사업자 상태 조회로 확인해 표시합니다.
  • 데이터 품질 도구: 동명이인 병합 후보, 퇴사자 정리, ERP 인사정보와 대조한 경력증명서 미등록자 표시를 만들었습니다. 이 명단으로 각 사 인사총무팀이 미제출자에게 업로드를 요청하면서 전 임직원 경력 DB가 채워졌어요.
  • 판정 속도: 기술자 목록은 materialized view로, "한 눈에 보기"는 미리 계산한 집계 테이블을 증분 갱신하는 방식으로 바꿨고, 일괄 판정의 N+1 조회를 없애고 TTL 캐시를 붙였습니다.
한 눈에 보기: 발주처·공종별 배치 가능 인원
한 눈에 보기: 발주처·공종별 배치 가능 인원
적용 규정: 발주처별 현장대리인 요건을 데이터로 관리
적용 규정: 발주처별 현장대리인 요건을 데이터로 관리

기술자 1,488명의 경력을 DB로 만들었고, 포털에서 두 번째로 많이 쓰인 서비스가 됐습니다.

회의록 관리 시스템

회의 녹음을 올리면 회의록 초안을 만들고, 확정하면 참석자에게 업무를 배정하고 추적합니다.

  • 오디오 파이프라인: 긴 녹음은 오디오를 잘라 → 클립별로 병렬 추출하고 → 병합하는 Gemini 파이프라인으로 구조화 요약을 만듭니다.
  • 맥락 주입: ERP 인사정보(부서·직위), 지난 회차의 미완료 업무, 회의 시리즈별 도메인 지식, 첨부 자료를 프롬프트에 자동으로 넣어 요약 정확도를 높였습니다. 첨부 자료가 너무 크면 용량 가드가 걸러 냅니다.
  • 업무 추적: 회의록을 확정하면 참석자별 할 일이 만들어지고, 상태 변경 이력과 알림이 남아 다음 회차에 이어서 확인합니다. 사용자가 고친 요약도 이력으로 남깁니다.

6월에 완성해 사내에 배포했습니다.

경비 처리 시스템

영수증 사진을 올리면 AI가 읽고 분류해, 결재와 회계 전표 입력까지 이어 줍니다.

  • 영수증 인식: Gemini Vision이 영수증을 읽고 계정을 분류합니다. 간이영수증처럼 형식이 제각각인 영수증 6종도 따로 처리하도록 넓혔습니다.
  • 출장비 계산: 카카오모빌리티 경로 API로 출장 거리, 유류비, 통행료를 계산합니다.
  • 결재와 중복 방지: 영수증 단위로 결재선을 태우고, 같은 파일을 두 번 올리면 파일 해시로 걸러 냅니다.
  • 회계 전표: 거래처와 사번을 실제 ERP 데이터와 맞춰 전표 입력까지 이어지게 했습니다. 영수증 파일은 비공개 저장소에 두고 서명된 URL로만 엽니다.

출결 관리 시스템

사내 교육 현장에서 태블릿과 QR로 출석을 받는 시스템. 행사 진행 중에 첫 버전을 만들어 바로 썼습니다.

  • 10회차 사내 강의에서 처음 203명, 4회차부터 235명의 출석을 받았습니다. 회차마다 "N회차부터" 명단이 바뀌는 경우를 처리하고, 모든 상태 변경을 이력으로 남깁니다.
  • 여러 기기 동시 사용: 접수 태블릿 여러 대가 Supabase Realtime으로 같은 화면을 보고, 소켓이 끊기면 5초 폴링으로 자동 전환합니다.
  • 현장 UX: 사번으로 하는 QR 셀프 체크인, 한글 초성 검색, 화면이 꺼지지 않게 하는 Wake Lock, 실수하기 쉬운 "출석 취소"에만 확인 창, 체크에 실패하면 다시 시도하는 토스트를 넣었습니다.

계약·기성 관리 시스템

그룹 ERP의 공사 계약 화면 5개를 3개로 줄이고, 기성 청구 흐름을 상태 기계로 옮겼습니다.

  • 기성 청구 워크플로: 작성 → 결재 → 청구 → 마감 순서로 진행하고, 청구를 확정하면 금액이 잠기고 청구서 엑셀이 만들어집니다. 일부만 수금된 건도 처리합니다.
  • 공동도급: 공동 계약에서 우리 회사 지분 금액을 다루고, 지분율은 금액에서 거꾸로 계산합니다.
  • ERP 이관: Oracle ERP의 기존 계약 데이터를 insert만 하는 재실행 가능한 스크립트로 옮겼고, 실제로 쓰기 전에 dry-run으로 결과를 먼저 확인합니다.

AI 개발 인프라와 팀 공통 품질

3~4명이 앱 10여 개를 만들고 고치기 위해, Claude Code 스킬과 공통 도구를 팀 단위로 맞췄습니다.

  • 팀 공용 Claude Code 스킬: 의존성 없는 npx 설치기를 만들어 list/add/check/update로 스킬을 배포했습니다. 설치한 스킬의 해시와 원본 커밋을 잠금 파일에 남겨 최신·뒤처짐·로컬 수정 상태를 구분하고, check --scan으로 여러 저장소를 한 번에 점검해 CI에서도 쓸 수 있게 했어요. 실제 장애에서 나온 Supabase 쿼리 규칙(1,000행 제한, ILIKE 와일드카드 이스케이프, 권한 점검)과 사용자용 한국어 오류 문구 스킬을 담아 앱 5개에 설치했습니다.
  • 수정 요청 자동 처리: 포털로 들어온 수정 요청을 Claude Code가 가져가 고치고, 머지·배포한 뒤 커밋 링크와 함께 결과를 회신하는 스킬을 만들어 여러 저장소에 배포했습니다.
  • 공통 도구: 4개 앱의 Node 버전, npm 스크립트, 커밋 훅(husky·commitlint·pre-push 검사), 린터(oxlint, ruff), 테스트(vitest), CI 구성을 하나로 맞췄습니다. 콘크리트 시스템에서만 경고 245개를 정리했어요.
  • 넘겨받은 시스템 안정화: 팀원이 만든 전사 현장 대시보드를 8월에 넘겨받아 데이터 기준을 그룹 ERP로 옮겼고, 네트워크·DB 없이 1.3초에 도는 백엔드 특성 테스트 157개를 더해 CI 검사를 되살렸습니다.

돌아보며

  • LLM과 코드의 경계를 나누는 것이 가장 중요했습니다. 문서를 읽고 분류하는 일은 LLM에 맡기고, 결과가 매번 같아야 하는 계산과 판정은 코드로 옮겼어요. 덕분에 결과를 설명할 수 있었고, 사람이 검수할 수 있었습니다.
  • 현장 사용자는 기다려 주지 않습니다. 3주 만에 파일럿을 내보내고 단톡방 피드백으로 고치는 방식이, 완벽한 기획서를 쓰는 것보다 빨리 신뢰를 얻었습니다.