01프로젝트 개요#
로펌 그룹웨어는 법무법인의 핵심 업무 — 사건 관리, 기일·불변기한, 의뢰인·당사자, 시간과금(TC/TM), 수납·정산, 전자결재, 사내 협업 — 을 하나의 시스템으로 묶는 종합 법률 ERP입니다. 시중 경쟁 제품을 교차분석해 국내 로펌 실무에 필요한 기능을 설계 근거로 삼았고, Microsoft 365를 이미 쓰는 조직이 "만들 것은 만들고, 빌릴 것은 빌린다"는 원칙으로 붙였습니다.
무엇을 직접 만드나
사건 원장, 담당자·권한, 기일/불변기한, TC/TM 정산 엔진, 수익 분배, 전자결재 원장 — M365로 대체 불가능한 법률 도메인 로직이 제품의 해자입니다.
무엇을 빌리나
문서(SharePoint), 메일·캘린더(Outlook), 화상회의(Teams), 설문(Forms), SSO(Entra ID). 이미 잘 하는 것은 M365를 원장으로 두고 링크·포인터만 소유합니다.
현재 단계
POC(개념검증)입니다. 화면·아키텍처·핵심 읽기 흐름이 실제 클라우드에서 동작하며, 쓰기(CRUD)·SSO·정산 엔진을 단계적으로 채우는 중입니다.
02기술 스택#
| 레이어 | 채택 | 비고 |
|---|---|---|
| 프레임워크 | Next.js (App Router) + TypeScript | 서버 컴포넌트 · 서버 액션 기반. 코드가 유일한 원본 |
| UI | Tailwind CSS + 디자인 토큰 | Pretendard 폰트, 사건유형·D-day 배지 등 도메인 토큰화 |
| 데이터베이스 | Azure SQL Database | Prisma ORM(provider = "sqlserver"), 서버리스 티어 |
| ORM | Prisma 7 (Query Compiler) | 드라이버 어댑터 @prisma/adapter-mssql 사용 |
| 인증 | Microsoft Entra ID | Auth.js + MSAL, 위임 권한(Authorization Code) 기반 |
| M365 연동 | Microsoft Graph API | @microsoft/microsoft-graph-client, 사용자 위임 토큰 |
| 배포 | Vercel | main push 시 자동 배포 · 함수 리전 서울(icn1) 고정 |
| DNS | Cloudflare | 커스텀 도메인 · CNAME(DNS only)로 Vercel 연결 |
03시스템 아키텍처#
브라우저 → Vercel(Next.js, 서울 리전) → Azure SQL(서울 리전) 이 핵심 경로이고, 여기에 사용자의 위임 토큰으로 Microsoft Graph를 호출해 M365 데이터를 실시간으로 끌어옵니다.
사용자 ─ Entra ID SSO(위임 권한)
│ HTTPS
▼
Vercel (Next.js) · icn1(Seoul) # 함수와 DB를 같은 서울 리전에
· 서버 컴포넌트 / 서버 액션
· Prisma 싱글턴
│ mssql │ Graph API(사용자 위임 토큰)
▼ ▼
Azure SQL (Korea Central) Microsoft 365
사건 원장 = 우리가 소유 Outlook · Teams · SharePoint · Forms · Entra ID
문서·일정·회의 = M365가 원장, 우리는 링크만 소유
04기능 모듈 소개#
상태 범례: 동작 실제 동작 · DB 연동 Azure SQL 읽기 · 개발중 CRUD 진행 · M365 외부 연동 · 화면 화면 우선
사건 관리
사건 홈 DB 연동
수임·수행·보조 담당자, 사건유형 4축(대분류/소분류/심급/자문), 계속기관 3단계(경찰→검찰→법원), 다음 기일 D-day를 한 화면에. 권한에 따라 보이는 사건이 쿼리 레벨에서 걸립니다.
신건 등록 · 사건메모 · 종결사건 화면
사건메모는 단순 로그가 아니라 파일노트(file note) — 징계·손배 방어 증거가 되므로 출처·최종수정자를 원장에 기록합니다.
기일 / 일정
기일관리 DB 연동
기일은 삭제하지 않습니다(소거·중간줄 2종 숨김). 출석인은 담당자와 별개 축이라 외부 변호사·복대리를 담습니다. 결과란은 수기/자동 2칸으로 분리해 파싱봇이 사람 입력을 덮지 않습니다.
불변기한 계산기 화면
민법 §155~161(초일불산입·공휴일 순연)을 적용한 기간 계산. 항소·상고 같은 불변기간은 놓치면 곧 사고이므로
알림에 mandatory 플래그가 처음부터 들어갑니다.
고객 · TC/TM · 수납/정산
고객/당사자 화면
Contact(마스터)/Party(사건 스냅샷) 2계층. 사건 시점의 당사자 정보가 보존되고, 상대방도 레코드라 이해충돌 검사가 성립합니다.
TC/TM 정산 화면
타임시트→정산서 라인은 값 복사 스냅샷. "표시 단가 × 시간 ≠ 청구액" 불일치가 구조적으로 불가능합니다.
수납/정산 · 수익분배 화면
분배 트리거는 청구가 아니라 입금. 실비는 매출이 아닌 통과자금이라 분배 모수에서 제외됩니다.
전자결재 · 그룹웨어
전자결재(결재함) 화면
지출품의·지급·수임리포트·휴가·세금계산서 결재선. 승인 흐름은 Power Automate 연계를 검토합니다.
구성원 디렉토리 DB 연동 CRUD 개발중
법인 구성원·연락처·담당 사건 수. 실제 사용자는 Entra ID와 연동해 채웁니다. 퇴사자는 hard delete가 아니라 soft delete.
업무공유 · 근태/부재 CRUD 개발중
사건 중심 업무 배분, 휴가·출장·재택 신청/승인. 스키마(Task · Absence)가 준비되어 쓰기 기능을 붙이는 중입니다.
게시판 · 차량운행일지 CRUD 개발중
사내 공지, 법인차량 운행 기록(사건 출장·실비 정산 근거). 전용 테이블을 추가해 실제 CRUD로 전환하는 중입니다.
문서함 · 설문/투표 · 화상원격 M365
SharePoint 문서, Microsoft Forms 설문, Teams 회의 — M365가 원장. 앱은 실시간 조회 런처 + 사건 결부 포인터만 소유합니다.
05Microsoft 365 연동#
이미 M365를 쓰는 로펌을 전제로, 잘 하는 것은 빌려 씁니다. 인증은 위임 권한(사용자 대신)이 기본이라 각 사용자는 본인이 볼 수 있는 것에만 접근합니다(앱 전체 권한 아님).
| 서비스 | 역할 | 연동 상태 |
|---|---|---|
| Entra ID | SSO 로그인 · 사용자 디렉토리 | 앱 등록 완료, 위임 권한 로그인 배선 중 |
| Outlook | 기일 → 캘린더 단방향 push, 메일 사건 결부 | Graph 캘린더 연동 구현 |
| Teams | 화상/원격 회의(온라인 미팅) | 실 로그인 시 /me/events로 실제 Teams 회의 표시 |
| SharePoint / OneDrive | 문서 원장 | 실 로그인 시 /me/drive 실시간 조회, 미로그인은 딥링크 런처 |
| Forms | 설문/투표 | Forms 바로가기 런처(자체 구현 안 함) |
06Graph API 활용#
Graph 호출은 사용자 위임 토큰으로만 합니다. 앱 권한(application permission)을 쓰지 않으므로, 화면에 보이는 M365 데이터는 언제나 "그 사용자가 원래 볼 수 있는 것"으로 제한됩니다.
| 화면 | Graph 엔드포인트 | 동작 |
|---|---|---|
| 문서함 | GET /me/drive/root/children | OneDrive/SharePoint 파일 실시간 목록, 실패 시 런처 폴백 |
| 화상/원격 | GET /me/events | 온라인 미팅(Teams) 이벤트만 필터, 참여 링크 제공 |
| 기일 → 캘린더 | POST/PATCH /me/events | 사건 기일을 Outlook 캘린더로 단방향 push |
Calendars.ReadWrite, Files.Read 등 사용자 위임 범위 내에서만 사용합니다.
데모 계정에는 Graph 토큰이 없으므로 M365 화면은 목업/런처로 폴백합니다 — 위임 권한은 진짜 로그인 사용자만 가집니다.07데이터베이스 — Azure 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개 화면의 행 단위 필터를 좌우합니다.
| 계정 예시(데모) | 사건 범위 | 금액 | 결재 |
|---|---|---|---|
| 대표변호사 | 전 사건 | 보임 | 있음 |
| 파트너 | 담당건만 | 본인 사건 보임 | 있음 |
| 어소시에이트 | 담당건만 | 가려짐 | 없음 |
| 회계담당 | 전 사건 | 보임 | 없음 |
09배포 · 인프라#
배포 파이프라인
- 호스팅
- Vercel (main push → 자동 배포)
- 함수 리전
- 서울(icn1) — DB와 같은 리전으로 왕복 지연 제거
- DNS
- Cloudflare (CNAME → Vercel, DNS only)
- DB
- Azure SQL (Korea Central, 서버리스)
겪고 해결한 함정
- 리전 불일치 — 함수(미국)↔DB(서울) 왕복 지연 → 함수 리전을 서울로 고정
- DB 방화벽 — "Azure 서비스 허용" 토글로는 Vercel(외부 클라우드)이 못 붙음 → 별도 규칙 필요
- 절전 타임아웃 — 무료 티어 auto-pause 첫 접속 실패 → "깨우는 중" 폴링 화면으로 흡수
- 테넌트 혼동 — SQL은 개인 테넌트, M365는 조직 테넌트
10작업 히스토리#
POC가 만들어진 순서. 각 단계는 배포까지 확인한 뒤 다음으로 넘어갔습니다.
프로토타입 → Next.js 전환
Claude Design 산출 HTML을 App Router + TypeScript로 이관. 좌측 사이드바 + 상단 멀티탭 구조 유지. 코드가 유일한 원본.
Prisma 스키마 v1 + Azure SQL
Matter-centric 40여 개 모델. 담당자 4축·사건유형 4축·스냅샷·이벤트 스트림 등 되돌릴 수 없는 결정을 v1에 확정.
사건·기일·구성원 화면을 DB로 전환
목업을 Azure SQL 읽기로 교체. 권한 스코프를 쿼리 레벨에서 적용. 시드 데이터로 권한별 화면 차이 검증.
그룹웨어 3종 + Teams/SharePoint 연동
전자결재·게시판·차량운행일지 화면 추가. 문서함·화상원격을 Graph 실연동으로 업그레이드.
운영 안정화 — 리전·방화벽·장애격리
함수 리전 서울 고정, DB 방화벽·절전 대응, DB 장애 시 안내 화면 대체. 커스텀 도메인 연결.
쓰기(CRUD) · SSO · 정산 엔진
그룹웨어 모듈에 생성/수정/삭제를 붙이고, Entra ID 위임 로그인과 TC/TM 정산 엔진을 채우는 단계.
11개발자 핸드오프#
다음 개발자가 맥락을 잃지 않고 이어받도록 하는 인수인계입니다. 이 프로젝트는 공용 PC를 포함해 여러 대를 오가므로 — 맥락은 로컬이 아니라 GitHub(문서 · Issues · git history)에만 남깁니다.
세션 시작 루틴
git pull— 다른 PC 작업 받기git log --oneline -10— 마지막 작업 확인- 열린 Issue 확인 = 할 일 목록
- 해당 Issue 본문에서 "왜 이렇게 했는지" 복원
환경 세팅 핵심
- 비밀값은 저장소에 넣지 않음 — Vercel 환경변수 / Key Vault
- 새 PC는 git 커밋 계정 설정 먼저(안 하면 배포 차단)
- 스키마 변경은
DATABASE_URL로prisma db push - 공용 PC였다면 종료 시 로그아웃 + 폴더 삭제
지금 이어서 할 일 (재개 지점)
| 우선 | 작업 | 메모 |
|---|---|---|
| P0 | 그룹웨어 CRUD 완성 | 업무공유·근태·게시판·차량·구성원. 게시판·차량은 신규 테이블 필요 |
| P0 | Entra ID 위임 로그인 배선 | 실 로그인 시 User 매칭 → PermissionSet 적용 |
| P1 | TC/TM 정산 엔진 | M365로 대체 불가 — 제품의 해자 |
| P1 | 전자결재 원장 | 스키마에 결재 원장 보강 |
| 보안 | 실데이터 전 개발용 임시설정 정리 | 데모 로그인 차단, DB 접근 범위 축소 등 — 상세는 비공개 문서 |
docs/09-개발자-핸드오프.md 및 GitHub Issues에만 기록되어 있습니다(공개 페이지엔 싣지 않습니다).docs/00-개발자-온보딩.md · docs/09-개발자-핸드오프.md와 GitHub Issues에서
전체 맥락(설계 근거·함정 로그·미해결 목록)을 복원합니다.