Internal Platform · AI · Infrastructure

사내 서비스 통합 포탈

흩어진 업무 앱과 반복되는 IT 문의를 하나의 포탈로 통합했습니다. 로그인·권한·배포·감사 로그를 공통화하고, 자연어 질문이 각 업무 시스템의 API를 호출하도록 설계했습니다.

8종통합 업무 앱
27개LLM 연동 도구
11개검색 가능한 매뉴얼
59항목운영 체크리스트

비개발 부서에서 인프라 구축부터 개발·보안·배포·운영·조직 확산까지 단독으로 연결했습니다.

실제 데모 녹화 「지금 자산 몇 대야?」 한 줄 → 포탈이 자산관리 API를 호출 → 답과 함께 어떤 기능을 썼는지와 바로가기가 붙습니다. 화면의 숫자는 AI가 추정한 값이 아니라 그 앱이 돌려준 값입니다.

서비스가 늘어날수록 로그인, 권한, 배포, 문의 대응이 앱마다 반복되고 있었습니다.

01

분산된 접근 경로

업무 앱별 주소와 로그인 방식이 달라 사용자가 필요한 기능을 찾기 어려웠습니다.

02

반복되는 개발

각 앱이 인증·권한·감사 로그를 따로 구현해 기능 개발보다 공통 작업의 비중이 컸습니다.

03

사람에게 집중된 문의

자산 현황, 배치도, 매뉴얼 위치처럼 시스템이 답할 수 있는 질문도 IT 담당자에게 반복됐습니다.

포탈을 관문으로 두고 사용자 권한과 원본 업무 데이터를 끝까지 일치시키는 구조를 설계했습니다.

USER직원 · 관리자

하나의 계정으로 포탈과 허용된 업무 앱에 접근

GATEWAYnginx · auth_request

URL 진입 단계에서 부서·개인 권한을 검증

SERVICES독립 앱 · API

서비스별 컨테이너를 유지하면서 공통 인증 사용

AI LAYER도구 호출형 AI 챗

직접 계산하지 않고 권한 있는 원본 API의 답을 전달

권한 이중 검증

권한 없는 도구는 모델에 노출하지 않고, 실행 시점에도 사용자 권한을 다시 확인합니다.

화면과 AI의 숫자 일치

AI가 값을 추정하지 않고 화면과 동일한 API를 호출하므로 서로 다른 결과가 나오는 문제를 구조적으로 차단합니다.

포탈 자체를 포함해 9개 서비스가 로그인·권한을 공통으로 쓰며 각자 자기 일만 합니다.

하는 일눈여겨볼 곳
포탈로그인 · 권한 · 챗 · 이력 · AI 사용량접근 범위(부서/개인/제외) · 사용량 대시보드
IT 자산 관리자산 · 직원 · IP · 내선 · 자리 · 라이선스 · 렌탈퇴사자 미반납 · 라이선스 초과 배정 잡아내기
사업계획 예상손익엑셀 둘 → 채널·브랜드·월별 손익표틀렸을 때 숫자를 안 내보내는 것
연차 이상감지고립 연차 · 저사용 · 몰아쓰기 탐지요일 가중치 · 집단연차 제외
AI 이용 현황게이트웨이 원본 로그 → 대시보드브라우저 안에서 집계 (서버 부담 0)
매뉴얼 가져오기PPT → 웹 매뉴얼 자동 변환표를 절차로 펴기 · 작은 그림 버리기
IT 안내매뉴얼 · 운영 체크리스트 · 비용 · 프롬프트 생성기 · 사내앱 규칙 · AI 참고자료 · 자가진단정적 페이지 7장 · 챗이 그 안을 검색
온라인 교육 이수지정 영상 시청 진도 → 자동 이수 · 이수율스크롤바로 건너뛰면 이수 안 됨
앱 입고올린 앱 검사 → 검토 요청 → 담당자 승인·반려반려 사유를 붙여넣어 고칠 프롬프트로 바꿔 주는 것

"무엇을 만들었나" 보다 왜 그렇게 만들었는지가 이 프로젝트에서 가장 신경 쓴 부분입니다.

Anti-Cheat

진도는 '어디까지 갔나'가 아니라 '어디를 지났나'로 센다

온라인 교육의 유일한 자산은 수강 기록입니다. 처음에는 최대 재생 위치만 저장했는데, 그러면 스크롤바를 맨 뒤로 한 번 끄는 것만으로 이수가 끝나 버립니다. 그래서 영상을 10초 단위 칸으로 쪼개고, 화면이 5초마다 보내오는 위치로 지나간 칸만 채우도록 바꿨습니다.

직전 위치와의 차이가 30초 이내면 이어 본 것으로 인정해 1.5배·2배속 시청은 정상적으로 기록되고, 차이가 크면 건너뛴 것으로 보고 지금 칸 하나만 채웁니다 - 맨 뒤로 끌어도 중간이 비어 이수 처리되지 않습니다. 영상은 유튜브가 재생하고 이 앱은 위치만 받아 적기 때문에 서버 부하도 거의 없습니다.

온라인 교육 직원 화면 - 1.5배속으로 봐도 진도는 정상 기록됩니다 안내 문구
Feedback Loop

반려 사유를 적어 보내지 않고, 고칠 프롬프트를 만들어 준다

앱을 만들어 보내는 쪽이 대부분 비개발 부서입니다. 그래서 검사에서 걸렸을 때 "규칙 14 위반 - 바깥 포트 금지"라고 적어 보내면 거기서 멈춥니다. 받는 사람이 모르는 건 무엇이 틀렸는지가 아니라, 쓰던 AI 에 무엇을 말해야 하는지입니다. 사유만 적어 보내면 결국 담당자에게 다시 물어보게 되고, 셀프서비스로 만든 의미가 없어집니다.

그래서 검사 문구 27가지마다 왜 막는지 · 어디를 고치는지 · 붙여넣을 코드를 붙여 두고, 걸린 항목만 모아 한 덩어리 글로 만들어 줍니다. 그대로 복사해 쓰던 AI 에 붙여넣으면 됩니다. 도커 설정처럼 큰 항목이 걸리면 그 아래 딸린 작은 항목들은 접습니다 - 같은 파일을 두 번 고치라고 하면 사람이 헷갈립니다.

검사에서 걸린 앱 화면 - 요청 버튼은 열리지 않고, 그 자리에 붙여넣을 수정 프롬프트가 만들어져 있다
Extensibility

포탈이 세지 않고, 앱에게 물어본다

첫 화면 앱 카드에 "결재 3건" 같은 숫자를 띄우려면 포탈이 그 앱의 일을 알아야 합니다. 그 방식은 앱이 하나 늘 때마다 포탈을 한 번 더 고치게 만듭니다 - 앱이 계속 추가되는 것이 이 플랫폼의 전제인데, 추가할 때마다 관문을 건드려야 한다면 구조가 잘못된 것입니다.

그래서 포탈은 개수를 세지 않고 앱마다 GET api/badge 를 한 번씩 물어봅니다. 앱은 {"count": 2, "label": "검토 요청 2건"} 만 내놓으면 되고, 만들지 않은 앱은 404 가 돌아와 조용히 넘어갑니다. 덕분에 기존 앱을 한 줄도 고치지 않고 붙었고, 앞으로 만들 앱은 규칙 문서의 한 문단만 보면 됩니다.

포탈 첫 화면 - 앱 입고 카드에만 빨간 3 이 붙어 있고 나머지 앱 카드에는 아무것도 없다
Auth

권한은 토큰이 아니라 DB를 본다

JWT 안의 값만 믿으면 관리자 권한을 회수해도 토큰이 만료되는 시간 동안 예전 권한이 그대로 살아 있습니다 - 화면에서 메뉴가 안 사라지는 정도가 아니라 관리자 API가 계속 열려 있다는 뜻입니다. 그래서 요청마다 DB를 한 번 다시 조회하도록 했습니다. SQLite 조회 하나라 이 규모에서는 체감되는 지연이 없습니다.

Deployment Safety

흔한 컨테이너 이름을 쓰지 않는다 (실제로 사고가 날 뻔했다)

컨테이너 이름이 portal · proxy · it-asset처럼 흔했습니다. docker compose는 이름을 안 적으면 폴더 이름으로 프로젝트를 정하기 때문에, 받는 쪽 PC에 같은 이름의 폴더가 있으면 남의 컨테이너를 이 프로젝트 것으로 착각해 명령을 그 안에서 실행할 수 있습니다. 실제로 그런 일이 있었고, 그 앱에 해당 파일이 없어서 실패로 끝났을 뿐 있었다면 남의 데이터가 덮였을 상황이었습니다.

이후 모든 컨테이너·네트워크 이름을 프로젝트 전용 접두사로 못 박고, 자료를 넣는 명령도 이름 하나만 정확히 지정하는 방식으로 바꿔 같은 사고가 구조적으로 재발하지 않도록 했습니다.

공개 데모는 로그인을 열어 둔 이상 아무나 계정을 지우거나 비밀번호를 바꿀 수 있는 곳입니다. "전부 읽기 전용"으로 막으면 안전하지만 볼 게 없어져서, 기준을 하나로 잡았습니다 - 남는 것만 막는다.

허용 - 다음 사람에게 남지 않는 것

올리기 · 계산 · 챗 · 검색 · 내려받기

요청이 끝나면 사라지는 작업이라 자유롭게 열어 둡니다.

차단 - 다음 사람에게 남는 것

계정 · 자산 · 서비스 · 부서 · 비밀번호

nginx와 앱 미들웨어 두 겹으로 막습니다. 새 서비스를 추가해도 기본값이 차단이라 안전합니다.

챗은 별도로 세 겹의 사용량 제한을 둡니다.

IP당 하루 20회하루 전체 15만 토큰이번 달 전체 300만 토큰

막힌 상태는 설정을 눈으로 읽는 대신 실제로 바깥에서 요청을 보내 외부 스크립트로 검증합니다 - 상태 코드뿐 아니라 응답 본문이 정상적으로 읽히는지까지 확인합니다.

단순한 링크 모음이 아니라 서비스가 계속 추가될 수 있는 운영 플랫폼으로 만들었습니다.

8종

업무 앱 통합

자산관리, 배치도, 매뉴얼, 연차 이상 감지 등 업무 앱을 단일 포탈로 통합했습니다.

27개

AI 도구 연결

자연어 질문이 허용된 앱 API를 선택해 실제 업무 데이터를 조회하도록 구성했습니다.

9개 형식

첨부 문서 판독

PDF·DOCX·XLSX·PPTX 등을 추출하고 스캔 문서는 Vision으로 판독해 결과를 캐싱합니다.

2단계

CSV 계정 등록

검증 후 적용 구조로 오등록을 막고 명부에 있는 신규 부서도 함께 생성합니다.

자동

서비스 발견

nginx 설정을 스캔해 신규 서비스와 포트 충돌을 파악하고 등록 과정을 줄였습니다.

통합

감사 로그

사용자와 서비스 이벤트를 한곳에서 추적할 수 있도록 운영·보안 기준을 공통화했습니다.

개발뿐 아니라 실제로 배포하고 장애를 줄일 수 있는 운영 체계를 함께 구축했습니다.

외부 사용자 FortiGate 방화벽 정책 기반 접근 통제 GitHub 저장소 Git push 자동 배포 HYPER-V 물리 서버 Ubuntu Server VM Docker 컨테이너 nginx 리버스 프록시 auth_request 접근 통제 Let's Encrypt(TLS) 요청마다 세션을 DB로 재검증 FastAPI 앱 컨테이너 · 9종 포탈 · IT자산관리 · 사업계획손익 · 연차이상감지 AI이용현황 · 매뉴얼변환 · IT안내 · 온라인교육 · 앱입고 SQLite 앱별 데이터 OpenAI API Tool Calling

실제 서비스 배포에 쓰는 인프라 구성 - 물리 호스트부터 컨테이너 내부 구조까지

Hyper-VUbuntuDockernginxFastAPISQLiteOpenAI APIFortiGateGit 기반 배포통합 감사 로그

새로운 앱을 더 쉽게 배포하고, 사용자가 스스로 필요한 정보에 도달하는 구조를 만들었습니다.

공통 기능의 반복 제거

앱마다 로그인과 권한을 다시 만드는 대신 게이트웨이에서 공통 처리하도록 전환했습니다.

배포 안정성 개선

FTP 수동 반영을 Git 기반 배포로 바꿔 파일 일부만 반영되는 장애 가능성을 줄였습니다.

IT 문의의 셀프서비스화

반복 질문을 AI 챗과 검색 가능한 매뉴얼로 전환해 담당자 의존도를 낮췄습니다.

조직 확산 가능한 표준

비개발 직원도 서비스를 제안하고 검토·배포할 수 있도록 가이드와 온보딩 절차를 정리했습니다.

만든 것보다 넘길 수 있게 만든 것이 이 프로젝트에서 오래 남을 부분이라고 봤습니다.

운영과 인수인계에 쓰는 매뉴얼을 같은 저장소에서 함께 관리합니다. 1부는 직원용(로그인·챗·앱별 사용법), 2부는 담당자용(권한 판정 순서·배포·장애 대응·백업)이고, 화면 사진 37장은 전부 돌고 있는 데모에서 그대로 찍었습니다. 회사·사람·부서 이름은 지어낸 것이며 기준 값은 코드 한 곳에 모여 있습니다.

IT 포탈 매뉴얼 전문 보기 직원용 1부 · 담당자용 2부 · 화면 37장 · 새 창 코드 보기 (GitHub) · 체험판 demo / demo1234 실제 운영본을 가짜 데이터로 바꿔 공개 · 띄우는 법과 체험판 안전장치는 README에