로펌 그룹웨어법무법인 종합 법률 ERP POC · 개발 진행중
Project Guide & Developer Handoff

사건 · 기일 · 정산 · 협업을 하나로

법무법인 전용 종합 법률 ERP 개념검증(POC) — 기능 소개 겸 개발자 핸드오프 자료입니다.

24화면 라우트
40+DB 테이블(Prisma)
5M365 서비스 연동
2Azure 테넌트 구성

01프로젝트 개요#

로펌 그룹웨어는 법무법인의 핵심 업무 — 사건 관리, 기일·불변기한, 의뢰인·당사자, 시간과금(TC/TM), 수납·정산, 전자결재, 사내 협업 — 을 하나의 시스템으로 묶는 종합 법률 ERP입니다. 국내외 시중 경쟁 제품을 교차분석해 로펌 실무에 필요한 기능을 설계 근거로 삼았고, Microsoft 365를 이미 쓰는 조직이 "만들 것은 만들고, 빌릴 것은 빌린다"는 원칙으로 붙였습니다.

무엇을 직접 만드나

사건 원장, 담당자·권한, 기일/불변기한, TC/TM 정산 엔진, 수익 분배, 전자결재 원장 — M365가 다루지 않는 법률 도메인 로직이 이 제품의 중심입니다.

무엇을 빌리나

문서(SharePoint), 메일·캘린더(Outlook), 화상회의(Teams), 설문(Forms), SSO(Entra ID). 이미 잘 하는 것은 M365를 원장으로 두고 링크·포인터만 소유합니다.

현재 단계

POC(개념검증)입니다. 화면·아키텍처·핵심 데이터 흐름이 실제 클라우드에서 동작하며, 그룹웨어 CRUD는 완료, SSO·정산 엔진을 이어서 채우는 중입니다.

특정 법무법인의 내부 업무 규정이나 실제 사건·고객 데이터를 반영하지 않았으며, 국내외 로펌에서 보편적으로 쓰이는 ERP 기능을 참고해 제작한 POC입니다. 자격증명·개인정보는 포함하지 않습니다.

02기술 스택#

레이어채택비고
프레임워크Next.js (App Router) + TypeScript서버 컴포넌트 · 서버 액션 기반. 코드가 기준 원본
UITailwind CSS + 디자인 토큰Pretendard 폰트, 사건유형·D-day 배지 등 도메인 토큰화
데이터베이스Azure MS-SQL DatabasePrisma ORM(provider = "sqlserver"), 서버리스 티어
ORMPrisma 7 (Query Compiler)드라이버 어댑터 @prisma/adapter-mssql 사용
인증Microsoft Entra IDAuth.js + MSAL, 위임 권한(Authorization Code) 기반
M365 연동Microsoft Graph API@microsoft/microsoft-graph-client, 사용자 위임 토큰
배포Azure 서버코드 반영 시 자동 배포 · MS Azure 서버 리전 서울 고정
DNS커스텀 도메인CNAME(DNS only)으로 애플리케이션 서버에 연결

03시스템 아키텍처#

브라우저 → 애플리케이션 서버(Next.js, 서울 리전) → Azure MS-SQL(서울 리전) 이 핵심 경로이고, 여기에 사용자의 위임 토큰으로 Microsoft Graph를 호출해 M365 데이터를 실시간으로 끌어옵니다.

          사용자  ─ Entra ID SSO(위임 권한)
            │ HTTPS
            ▼
   애플리케이션 서버 (Next.js) · 서울 리전   # 서버와 DB를 같은 리전에
       · 서버 컴포넌트 / 서버 액션
       · Prisma 싱글턴
        │  mssql                    │  Graph API(사용자 위임 토큰)
        ▼                           ▼
  Azure MS-SQL (Korea Central)    Microsoft 365
   사건 원장 = 우리가 소유       Outlook · Teams · SharePoint · Forms · Entra ID
                                문서·일정·회의 = M365가 원장, 우리는 링크만 소유
설계 원칙 — "우리가 소유하는 것은 파일이나 메시지가 아니라 링크와 타임라인이다." 문서 실체는 SharePoint, 회의는 Teams, 메일은 Outlook이 원장입니다. 우리 DB는 사건(Matter)을 중심으로 그 링크와 사건 결부 메타데이터를 소유합니다. 이 연결이 없으면 M365를 붙이더라도 문서 저장소와 메일함 수준에 머무르기 쉽습니다.

04기능 모듈 소개#

상태 범례: 동작 생성·수정·삭제까지 동작 · DB 연동 Azure MS-SQL 읽기 · M365 외부 연동 · 화면 화면 우선

각 목록 화면은 항목을 클릭하면 상세 뷰페이지로 이어집니다. 아직 데이터가 없는 목록은 샘플 데이터로 채워 화면 흐름을 바로 확인할 수 있고, 실제로 등록하면 그때부터 실데이터로 바뀝니다.

사건 관리

사건 홈 DB 연동

수임·수행·보조 담당자, 사건유형 4축(대분류/소분류/심급/자문), 계속기관 3단계(경찰→검찰→법원), 다음 기일 D-day를 한 화면에. 권한에 따라 보이는 사건이 쿼리 레벨에서 걸립니다.

신건 등록 · 사건메모 · 종결사건 화면

사건메모는 단순 로그가 아니라 파일노트(file note) — 징계·손배 방어 증거가 되므로 출처·최종수정자를 원장에 기록합니다.

기일 / 일정

기일관리 DB 연동

기일은 삭제하지 않습니다(소거·중간줄 2종 숨김). 출석인은 담당자와 별개 축이라 외부 변호사·복대리를 담습니다. 결과란은 수기/자동 2칸으로 분리해 파싱봇이 사람 입력을 덮지 않습니다.

불변기한 계산기 화면

민법 §155~161(초일불산입·공휴일 순연)을 적용한 기간 계산. 항소·상고 같은 불변기간은 놓쳤을 때 영향이 커서 알림에 mandatory 플래그가 처음부터 들어갑니다.

고객 · TC/TM · 수납/정산

고객/당사자 화면

Contact(마스터)/Party(사건 스냅샷) 2계층. 사건 시점의 당사자 정보가 보존되고, 상대방도 레코드라 이해충돌 검사가 성립합니다.

TC/TM 정산 화면

타임시트→정산서 라인은 값 복사 스냅샷. "표시 단가 × 시간 ≠ 청구액" 불일치가 생기지 않도록 설계했습니다.

수납/정산 · 수익분배 화면

분배 트리거는 청구가 아니라 입금. 실비는 매출이 아닌 통과자금이라 분배 모수에서 제외됩니다.

전자결재 · 그룹웨어

전자결재(결재함) 화면

지출품의·지급·수임리포트·휴가·세금계산서 결재선. 승인 흐름은 Power Automate 연계를 검토합니다.

구성원 디렉토리 CRUD 동작

법인 구성원·연락처·담당 사건 수. 추가·수정·삭제가 동작하며, 퇴사자는 기록 보존을 위해 완전 삭제가 아닌 비활성 처리됩니다. 실제 사용자는 Entra ID와 연동해 채웁니다.

근태 / 부재 CRUD 동작

휴가·출장·재택 신청/수정/삭제 + 승인·반려. 승인은 결재 권한자만 가능하고, 남의 부재를 대신 등록할 수 있도록 신청자와 등록자를 구분해 저장합니다.

업무공유 CRUD 동작

사건 중심 업무 배분. 담당자·연결사건·기한·우선순위를 등록하고, 목록에서 상태를 바로 변경할 수 있습니다.

게시판 · 차량운행일지 CRUD 동작

사내 공지(분류·상단고정)와 법인차량 운행 기록(사건 출장·실비 정산 근거). 전용 테이블로 실제 저장됩니다.

문서함 · 설문/투표 · 화상원격 M365

SharePoint 문서, Microsoft Forms 설문, Teams 회의 — M365가 원장. 앱은 실시간 조회 런처 + 사건 결부 포인터만 소유합니다.

05Microsoft 365 연동#

이미 M365를 쓰는 로펌을 전제로, 잘 하는 것은 빌려 씁니다. 인증은 위임 권한(사용자 대신)이 기본이라 각 사용자는 본인이 볼 수 있는 것에만 접근합니다(앱 전체 권한 아님).

서비스역할연동 상태
Entra IDSSO 로그인 · 사용자 디렉토리앱 등록 완료, 위임 권한 로그인 배선 중
Outlook기일 → 캘린더 단방향 push, 메일 사건 결부Graph 캘린더 연동 구현
Teams화상/원격 회의(온라인 미팅)실 로그인 시 /me/events로 실제 Teams 회의 표시
SharePoint / OneDrive문서 원장실 로그인 시 /me/drive 실시간 조회, 미로그인은 딥링크 런처
Forms설문/투표Forms 바로가기 런처(자체 구현 안 함)
테넌트가 2개인 구조입니다. 구독·Azure MS-SQL은 개인 Azure 테넌트에, M365(Business Basic)와 Entra 앱 등록은 조직 테넌트에 있습니다. 포털 작업 시 어느 테넌트에 로그인했는지를 항상 먼저 확인해야 합니다.

06Graph API 활용#

Graph 호출은 사용자 위임 토큰으로만 합니다. 앱 권한(application permission)을 쓰지 않으므로, 화면에 보이는 M365 데이터는 언제나 "그 사용자가 원래 볼 수 있는 것"으로 제한됩니다.

화면Graph 엔드포인트동작
문서함GET /me/drive/root/childrenOneDrive/SharePoint 파일 실시간 목록, 실패 시 런처 폴백
화상/원격GET /me/events온라인 미팅(Teams) 이벤트만 필터, 참여 링크 제공
기일 → 캘린더POST/PATCH /me/events사건 기일을 Outlook 캘린더로 단방향 push
승인 스코프Calendars.ReadWrite, Files.Read 등 사용자 위임 범위 내에서만 사용합니다. 데모 계정에는 Graph 토큰이 없으므로 M365 화면은 샘플/런처로 폴백합니다 — 위임 권한은 실제 로그인 사용자만 가집니다.

07데이터베이스 — Azure MS-SQL + Prisma#

Matter-centric 설계: 모든 테이블이 사건(Matter)을 중심으로 연결됩니다. 스키마는 40여 개 모델로, 나중에 바꾸기 어려운 설계 결정(스냅샷·값 복사·이력)을 v1에 미리 넣었습니다.

핵심 설계 결정

  • 담당자 4축 — 수임/수행/보조 + 기일 출석인(별개 축)
  • 사건유형 4축 — 대분류·소분류·심급·자문 플래그
  • 스냅샷/값 복사 — 정산 라인·업무보고서는 조인이 아니라 발행 시점 값 복사
  • hard delete 금지 — 사건·기일·구성원은 소프트 삭제/숨김
  • 이벤트 스트림 — MatterActivity로 사건 타임라인을 소유

서버리스 대응

  • Prisma 싱글턴 + 커넥션 풀 상한으로 서버리스 커넥션 고갈 방지
  • 지연 생성 — 빌드가 DB 자격증명을 요구하지 않도록 런타임에만 클라이언트 생성
  • auto-pause 대응 — 무료 티어 DB가 절전에서 깨어나는 30~60초 동안 "깨우는 중" 화면 후 자동 복구
  • 장애 격리 — DB 실패 시 통짜 500 대신 안내 화면으로 대체(사이드바 유지)

SQL Server 제약(Prisma enum 미지원 → String+상수, 인덱스 키 900바이트 상한, 다중 캐스케이드 경로 금지)을 스키마 전체의 작성 규칙으로 삼았습니다.

08권한 모델#

RBAC도 ACL도 아닙니다. 권한의 1차 축은 직급이 아니라 "이 사건의 담당자인가"입니다. 담당(수임·수행·보조 중 하나) 여부가 약 20개 화면의 행 단위 필터를 좌우합니다.

역할 예시사건 범위금액결재
대표변호사전 사건보임있음
파트너담당건만본인 사건 보임있음
어소시에이트담당건만가려짐없음
회계담당전 사건보임없음
필터를 화면마다 걸면 누락이 생기기 쉽습니다. 그래서 Prisma 쿼리 레벨의 공통 스코프 헬퍼로 강제하고, 금액은 화면에서 가리는 게 아니라 서버에서 값 자체를 넘기지 않습니다. 쓰기 권한은 별도 가드로 관리합니다.

09배포 · 인프라#

배포 파이프라인

서버
Azure 서버 — 코드 반영 시 자동 배포
MS Azure 서버 리전
서울 — DB와 같은 리전으로 왕복 지연 제거
DNS
커스텀 도메인 (CNAME, DNS only)
DB
Azure MS-SQL (Korea Central, 서버리스)

겪고 해결한 함정

  • Azure 리전 불일치 — 서버(미국)↔DB(서울) 왕복 지연 → MS Azure 서버 리전을 서울로 고정
  • DB 방화벽 — "Azure 서비스 허용" 토글로는 외부 클라우드가 못 붙음 → 별도 규칙 필요
  • 절전 타임아웃 — 무료 티어 auto-pause 첫 접속 실패 → "깨우는 중" 폴링 화면으로 흡수
  • 테넌트 혼동 — SQL은 개인 테넌트, M365는 조직 테넌트

10작업 히스토리#

POC가 만들어진 순서. 각 단계는 배포까지 확인한 뒤 다음으로 넘어갔습니다.

STEP 1 · 완료

프로토타입 → Next.js 전환

초기 화면 프로토타입(HTML)을 App Router + TypeScript로 이관. 좌측 사이드바 + 상단 멀티탭 구조 유지. 코드가 기준 원본.

STEP 2 · 완료

Prisma 스키마 v1 + Azure MS-SQL

Matter-centric 40여 개 모델. 담당자 4축·사건유형 4축·스냅샷·이벤트 스트림 등 나중에 바꾸기 어려운 결정을 v1에 확정.

STEP 3 · 완료

사건·기일·구성원 화면을 DB로 전환

샘플 데이터를 Azure MS-SQL 읽기로 교체. 권한 스코프를 쿼리 레벨에서 적용해 권한별 화면 차이를 검증.

STEP 4 · 완료

그룹웨어 화면 + Teams/SharePoint 연동

전자결재·게시판·차량운행일지 화면 추가. 문서함·화상원격을 Graph 실연동으로 업그레이드.

STEP 5 · 완료

운영 안정화 — 리전·방화벽·장애격리

함수 리전 서울 고정, DB 방화벽·절전 대응, DB 장애 시 안내 화면 대체. 커스텀 도메인 연결.

STEP 6 · 완료

그룹웨어 CRUD 5종 — 쓰기 기능 도입

구성원·근태·업무공유·게시판·차량운행일지에 생성/수정/삭제(+승인·반려)를 붙이고, 신규 테이블 2종을 반영. 서버 액션·권한 가드·모달 폼으로 재사용 가능한 CRUD 패턴을 확립.

STEP 7 · 완료

전자결재 원장 · 상세 뷰페이지 · 데모 데이터 정비

전자결재를 우리 DB의 원장으로 두고 기안 → 결재선(동시·다수결) → 승인, 지급품의의 지출 전기까지 연결. 구성원·업무·근태·게시판·차량·고객·사건·수납·전자결재 등 목록 화면에 상세 뷰페이지를 붙이고, 비어 있는 목록은 샘플 데이터로 채워 실제 등록 시 실데이터로 전환되게 함. 프로필 아바타·문서 종류별 색상 아이콘·Microsoft 365 브랜드 아이콘·파비콘·머리글/바닥글 정리로 화면 완성도 향상.

STEP 8 · 완료

운영 편의 — DB 절전 자동 예열 · 배포 안정화

서버리스 DB가 유휴로 잠들어 첫 접속이 느려지는 것을 줄이기 위해 주기적으로 DB를 깨워두는 예열을 도입. 배포 파이프라인 점검으로 안정적으로 자동 배포되도록 정리.

STEP 9 · 진행중

SSO · 정산 엔진 · 나머지 화면 쓰기 기능

Entra ID 위임 로그인 배선, TC/TM 정산 엔진, 사건·기일·수납 등 나머지 화면에 같은 CRUD 패턴 적용.