Files
Aislo/.agent/complete_and_old/plan_register_split.md
T
2026-07-08 19:59:25 +09:00

28 KiB

B01_Dashboard 설계 및 구현 계획

상태: 기본 설계 완료. 역할별 대시보드 구축 및 회사 연결 기능 미구현 참고: 완료된 항목은 .agent/complete_and_old/plan_register_split_COMPLETED.md 참조


1. B01_Dashboard 개편 사항

1.1 페이지명 변경

  • 이전: B01_AccountDetail (계정 상세 페이지)
  • 현재: B01_Dashboard (역할별 대시보드)
  • 목적: 로그인 후 메인 랜딩 페이지로, 역할에 따라 다양한 정보 표시

1.2 역할별 대시보드 구조

🟡 일반 사용자 (USER) 대시보드

┌─────────────────────────────────────────────────────┐
│ AISLO 대시보드                                        │
├─────────────────────────────────────────────────────┤
│                                                      │
│ 📊 [나의 프로젝트]                                   │
│   • 프로젝트 리스트 (테이블)                        │
│   • 프로젝트명 | 지역 | 진행도 [워크플로우] | 수정일 │
│   • 클릭 시 해당 단계로 이동                         │
│   • [+ 신규 프로젝트] 버튼                          │
│                                                      │
│ 🏢 [회사 정보]                                       │
│   • 현재 소속 회사명                                │
│   • 팀원 수, 진행 중인 프로젝트 수                  │
│                                                      │
│ 📞 [기본정보 & 보안] (섹션 병합)                     │
│   • 사용자명, 직급, 부서, 전화번호 수정             │
│   • 비밀번호 변경                                   │
│                                                      │
└─────────────────────────────────────────────────────┘

🟢 회사 관리자 (ADMIN) 대시보드

┌─────────────────────────────────────────────────────┐
│ AISLO 회사 관리자 대시보드                            │
├─────────────────────────────────────────────────────┤
│                                                      │
│ 🏢 [회사 정보]                                       │
│   회사명: 테스트회사 | 사업자: 123-45-67890         │
│   주소: 서울시 강남구 | 상태: 활동중                │
│                                                      │
│ 👥 [팀원 관리]                                      │
│   • 소속 사용자 리스트 (테이블)                     │
│   • 사용자명 | 직급 | 부서 | 역할 | 상태            │
│   • [+ 팀원 추가] (기가입 계정 검색/추가)          │
│   • [제거] 버튼                                    │
│                                                      │
│ 📋 [가입 요청]                                       │
│   • 이 회사에 가입을 신청한 사용자 리스트           │
│   • [승인] [거절] 버튼                              │
│                                                      │
│ 📊 [회사 프로젝트]                                   │
│   • 회사의 모든 프로젝트 리스트 (테이블)            │
│   • 프로젝트명 | 소유자 | 진행도 | 상태            │
│                                                      │
│ 📞 [기본정보 & 보안]                                 │
│   • 사용자 이름, 직급, 전화번호 수정               │
│   • 비밀번호 변경                                   │
│                                                      │
└─────────────────────────────────────────────────────┘

🔴 시스템 관리자 (SYSTEM_ADMIN) 대시보드

┌────────────────────────────────────────────────────┐
│ AISLO 시스템 관리자 대시보드                          │
├────────────────────────────────────────────────────┤
│                                                    │
│ 📊 [리소스 현황]                                    │
│   CPU: 45% | MEM: 62% | DISK: 78%                │
│   활성 사용자: 23 | 활성 프로젝트: 15              │
│                                                    │
│ 🏢 [회사 관리]                                     │
│   • 전체 회사 리스트 (테이블)                     │
│   • 회사명 | 사업자번호 | 상태 | 사용자 수         │
│   • [+ 회사 추가] 버튼                            │
│                                                    │
│ 👤 [사용자 관리]                                   │
│   • 전체 사용자 리스트 (테이블)                    │
│   • 이메일 | 이름 | 역할 | 회사 | 상태            │
│   • [역할 변경] [회사 할당] [비활성화] 버튼       │
│                                                    │
│ 📝 [가입 요청 관리]                                 │
│   • 회사 참여 대기 중인 요청 (테이블)              │
│   • 신청자 | 회사명 | 신청일 | 상태               │
│   • [승인] [거절] 버튼                             │
│                                                    │
│ 📊 [시스템 로그]                                    │
│   • 사용자 로그인/로그아웃 이력 (테이블)           │
│   • 계정 생성/수정/삭제 이력                       │
│   • 필터링: 기간, 사용자, 행동 유형               │
│                                                    │
│ 🖥️ [하드웨어 리소스 모니터링]                      │
│   • CPU 사용량 그래프 (시간대별)                   │
│   • 메모리 사용량 그래프                           │
│   • 디스크 사용량 그래프                           │
│   • 동시 접속자 수 추이                            │
│                                                    │
└────────────────────────────────────────────────────┘

2. 핵심 기능 상세 설계

2.1 프로젝트 리스트 섹션 (USER, ADMIN 공통)

기능: 프로젝트 테이블을 통해 사용자의 모든 프로젝트를 한눈에 확인하고, 워크플로우 진행 단계별로 바로 이동할 수 있습니다.

테이블 구조:

│ 프로젝트명            │ 지역            │ 진행도        │ 워크플로우 단계                    │ 수정일      │
│ 2025년 산불진화임도 │ 울진군 금강송면 │ [●●●○○○] 60% │ [B03 완료]→[B04 진행중 ▶]→... │ 2025-07-08 │

워크플로우 단계 버튼:

[B03 완료] → [B04 진행중 ▶] → [B05 대기] → [B06 대기] → [B07 대기] → ...
  ↑ (클릭 시 B03 페이지로 이동)  ↑ (현재 단계)   (비활성화)

단계별 동작:

  • 완료된 단계 (B03, B04): 파란색, 클릭 가능 → 해당 페이지로 이동
  • 진행 중 단계 (B05): 주황색, 강조 표시, 현재 상태 유지
  • 미진행 단계 (B06~B09): 회색, 클릭 불가 (비활성화)

추가 기능:

  • [+ 신규 프로젝트] 버튼: B02_ProjRegister로 이동하여 새 프로젝트 생성

데이터 출처:

projects 테이블
├─ name → 프로젝트명
├─ region → 지역
├─ status → 워크플로우 단계 (NEW, FILE_UPLOADED, WF1_ANALYZING, WF1_COMPLETE, WF2_COMPLETE, ...)
├─ updated_at → 수정일
└─ 진행도 계산: (완료 단계 수 / 전체 단계 6) × 100%

2.2 회사 상태 섹션 (USER만 표시)

상태 표시:

회사 상태: 테스트회사 (활동중)
[회사 변경]  ← 다른 회사 검색 및 신청

동작:

  • status = 'NO_COMPANY': "회사 미연결" 표시 + [회사 생성] [회사 찾기] 버튼
  • status = 'PENDING': "가입 승인 대기 중 (OOO회사)" 표시
  • status = 'ACTIVE': "OOO회사 (ACTIVE)" 표시 + [회사 변경] 버튼

2.4 회사 프로젝트 섹션 (ADMIN용)

기능: 회사에 속한 모든 프로젝트를 관리자 관점에서 조회합니다.

표시 내용:

회사 프로젝트 목록:

│ 프로젝트명 │ 소유자 │ 지역 │ 진행도 │ 상태 │
│ 프로젝트A │ 김사용자 │ 울진군 │ 50% | 진행중 │
│ 프로젝트B │ 이사용자 │ 봉화군 │ 100% | 완료 │

기능:

  • 회사의 모든 프로젝트 리스트 조회 (본인이 생성하지 않은 프로젝트도 포함)
  • 프로젝트명, 소유자, 지역, 진행도, 상태 표시

2.5 팀원 관리 섹션 (ADMIN만 표시)

팀원 추가 동작:

  1. [+ 팀원 추가] 클릭 → 모달 팝업 노출
  2. 기가입 사용자 검색 (이메일 입력)
  3. 검색 결과 선택 → 회사에 추가
  4. 중복 확인 (이미 팀원인 경우 "이미 팀원입니다" 메시지)

팀원 제거:

  • [제거] 버튼 클릭 → 확인 팝업 → 회사에서 제거

2.6 가입 요청 섹션 (ADMIN은 회사별, SYSTEM_ADMIN은 전체)

ADMIN 대시보드:

신청자 | 신청일 | 상태
김테스트 | 2025-07-08 | [승인] [거절]

SYSTEM_ADMIN 대시보드:

신청자 | 회사명 | 신청일 | 상태
김테스트 | 테스트회사 | 2025-07-08 | [승인] [거절]

동작:

  • [승인]: join_requests.status = 'APPROVED'users.status = 'ACTIVE'
  • [거절]: join_requests.status = 'REJECTED' → 이메일 발송

2.7 인증 갱신 로직

회원가입 시:

1. 회원가입 폼 입력
2. [가입하기] 클릭
3. 인증번호 입력 필드 노출 ← 가입 후에만 표시
4. 인증 완료 → users.auth_expires_at = NOW() + 3개월 설정

로그인 시:

1. 이메일/비밀번호 입력
2. DB 조회 후 auth_expires_at 확인
   - auth_expires_at > NOW() → 바로 대시보드 이동 ✅
   - auth_expires_at <= NOW() → 재인증 모달 표시 ⚠️
3. 로그인 성공 → last_login = NOW() 업데이트
4. 다음 로그인 시 auth_expires_at = NOW() + 3개월로 연장

인증 만료 기준:

  • 고정 기간 방식 (이전): 가입일로부터 3개월 후 만료 (자주 사용하면 3개월 후 갑자기 재인증)
  • 로그인 기반 갱신 (현재): 매 로그인 시 auth_expires_at 연장 (지속 사용 시 계속 유효)

3. DB 스키마 확장

3.1 users 테이블 추가 컬럼

ALTER TABLE users ADD COLUMN (
  role ENUM('SYSTEM_ADMIN', 'ADMIN', 'USER') DEFAULT 'USER',
  is_master BOOLEAN DEFAULT FALSE,
  status ENUM('PENDING_EMAIL', 'NO_COMPANY', 'PENDING', 'ACTIVE', 'INACTIVE', 'REJECTED') DEFAULT 'PENDING_EMAIL',
  last_login DATETIME DEFAULT NULL,
  auth_expires_at DATETIME DEFAULT NULL
);

3.2 신규 테이블: join_requests

CREATE TABLE join_requests (
  id INT PRIMARY KEY AUTO_INCREMENT,
  user_id INT NOT NULL,
  company_id INT NOT NULL,
  requested_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  status ENUM('PENDING', 'APPROVED', 'REJECTED') DEFAULT 'PENDING',
  reviewed_by INT DEFAULT NULL,
  reviewed_at TIMESTAMP DEFAULT NULL,
  FOREIGN KEY (user_id) REFERENCES users(id),
  FOREIGN KEY (company_id) REFERENCES companies(id),
  FOREIGN KEY (reviewed_by) REFERENCES users(id),
  UNIQUE KEY (user_id, company_id)  -- 중복 신청 방지
);

3.3 신규 테이블: system_audit_logs

CREATE TABLE system_audit_logs (
  id INT PRIMARY KEY AUTO_INCREMENT,
  user_id INT NOT NULL,
  action VARCHAR(50),  -- LOGIN, LOGOUT, USER_CREATE, USER_UPDATE, COMPANY_CREATE, etc
  resource_type VARCHAR(50),  -- user, company, project
  resource_id INT,
  timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  ip_address VARCHAR(50),
  user_agent TEXT,
  FOREIGN KEY (user_id) REFERENCES users(id),
  INDEX (timestamp),
  INDEX (action)
);

3.4 신규 테이블: system_resources

CREATE TABLE system_resources (
  id INT PRIMARY KEY AUTO_INCREMENT,
  timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  cpu_usage_percent FLOAT,
  memory_usage_percent FLOAT,
  disk_usage_percent FLOAT,
  active_user_count INT,
  active_project_count INT,
  total_storage_mb FLOAT,
  INDEX (timestamp)
);

4. 백엔드 API 설계

4.1 B01_Dashboard 라우터 (B01_Dashboard/B01_Dashboard_Router.py)

공통 API

# GET /api/dashboard/me — 현재 사용자 정보 조회
@router.get("/api/dashboard/me")
async def get_dashboard_me(session: dict = Depends(verify_session)):
    """
    현재 로그인한 사용자의 정보 반환
    응답: {
      id, email, name, position, department, phone, company_id, role, is_master, status,
      last_login, auth_expires_at
    }
    """

# PATCH /api/dashboard/me — 사용자 정보 수정
@router.patch("/api/dashboard/me")
async def patch_dashboard_me(
    request: UpdateUserRequest,
    session: dict = Depends(verify_session)
):
    """이름/직급/부서/전화번호 수정"""
    # 응답: 수정된 사용자 정보

USER 역할 API

# GET /api/dashboard/user/projects — 사용자의 프로젝트 리스트
@router.get("/api/dashboard/user/projects")
async def get_user_projects(session: dict = Depends(verify_session)):
    """
    사용자가 생성한 프로젝트 리스트
    응답: [{id, name, region, status, progress_percent, created_at, updated_at}, ...]
    """

# GET /api/dashboard/user/company — 사용자의 회사 정보
@router.get("/api/dashboard/user/company")
async def get_user_company(session: dict = Depends(verify_session)):
    """현재 소속 회사 정보"""
    # 응답: {id, name, status, user_count, project_count}

# GET /api/dashboard/user/companies?q= — 회사 검색
@router.get("/api/dashboard/user/companies")
async def search_companies_for_join(
    q: str = Query(...),
    session: dict = Depends(verify_session)
):
    """회사명 또는 사업자번호로 검색"""
    # 응답: [{id, name, business_number, status}, ...]

# POST /api/dashboard/user/company/create — 신규 회사 생성
@router.post("/api/dashboard/user/company/create")
async def create_company(
    request: CreateCompanyRequest,
    session: dict = Depends(verify_session)
):
    """
    신규 회사 생성 + 사용자를 ADMIN(is_master=TRUE)으로 자동 연결
    - companies 테이블에 INSERT
    - users.company_id = new_company_id
    - users.role = 'ADMIN'
    - users.is_master = TRUE
    - users.status = 'ACTIVE'
    """
    # 응답: {company_id, status='ACTIVE'}

# POST /api/dashboard/user/company/join — 회사 참여 신청
@router.post("/api/dashboard/user/company/join")
async def join_company(
    request: JoinCompanyRequest,
    session: dict = Depends(verify_session)
):
    """
    기존 회사에 참여 신청
    - join_requests 테이블에 INSERT (status='PENDING')
    - users.status = 'PENDING' (관리자 승인 대기)
    - 관리자에게 이메일 발송
    """
    # 응답: {join_request_id, status='PENDING'}

ADMIN 역할 API

# GET /api/dashboard/admin/members — 회사 팀원 리스트
@router.get("/api/dashboard/admin/members")
async def get_company_members(session: dict = Depends(verify_session)):
    """회사에 소속된 모든 팀원 조회"""
    # 응답: [{id, email, name, position, department, role, status}, ...]

# POST /api/dashboard/admin/members — 팀원 추가
@router.post("/api/dashboard/admin/members")
async def add_company_member(
    request: AddMemberRequest,
    session: dict = Depends(verify_session)
):
    """
    기가입 사용자를 회사에 추가
    - users.company_id = session.company_id
    - users.status = 'ACTIVE'
    - 중복 확인 필수
    """
    # 응답: {user_id, status='ACTIVE'}

# DELETE /api/dashboard/admin/members/{user_id} — 팀원 제거
@router.delete("/api/dashboard/admin/members/{user_id}")
async def remove_company_member(
    user_id: int,
    session: dict = Depends(verify_session)
):
    """팀원을 회사에서 제거 (soft delete)"""

# GET /api/dashboard/admin/join-requests — 가입 신청 리스트
@router.get("/api/dashboard/admin/join-requests")
async def get_company_join_requests(session: dict = Depends(verify_session)):
    """이 회사에 가입을 신청한 사용자 리스트"""
    # 응답: [{id, user_id, user_email, user_name, requested_at, status}, ...]

# PATCH /api/dashboard/admin/join-requests/{request_id} — 가입 신청 처리
@router.patch("/api/dashboard/admin/join-requests/{request_id}")
async def process_join_request(
    request_id: int,
    request: ProcessJoinRequest,  # {action: 'APPROVE' | 'REJECT'}
    session: dict = Depends(verify_session)
):
    """
    가입 신청 승인/거절
    - APPROVE: join_requests.status='APPROVED', users.status='ACTIVE'
    - REJECT: join_requests.status='REJECTED'
    - 사용자에게 이메일 발송
    """

# GET /api/dashboard/admin/projects — 회사 프로젝트 리스트
@router.get("/api/dashboard/admin/projects")
async def get_company_projects(session: dict = Depends(verify_session)):
    """회사에 속한 모든 프로젝트 조회"""
    # 응답: [{id, name, owner, status, progress_percent}, ...]

SYSTEM_ADMIN 역할 API

# GET /api/dashboard/admin/companies — 전체 회사 리스트
@router.get("/api/dashboard/admin/companies")
async def get_all_companies(session: dict = Depends(verify_session)):
    """시스템 관리자용: 전체 회사 조회"""
    # 응답: [{id, name, status, user_count, project_count, created_at}, ...]

# GET /api/dashboard/admin/users — 전체 사용자 리스트
@router.get("/api/dashboard/admin/users")
async def get_all_users(session: dict = Depends(verify_session)):
    """시스템 관리자용: 전체 사용자 조회"""
    # 응답: [{id, email, name, role, company_id, status, last_login}, ...]

# PATCH /api/dashboard/admin/users/{user_id}/role — 사용자 역할 변경
@router.patch("/api/dashboard/admin/users/{user_id}/role")
async def change_user_role(
    user_id: int,
    request: ChangeUserRoleRequest,
    session: dict = Depends(verify_session)
):
    """사용자 역할 변경 (USER ↔ ADMIN ↔ SYSTEM_ADMIN)"""

# PATCH /api/dashboard/admin/users/{user_id}/company — 사용자 회사 할당
@router.patch("/api/dashboard/admin/users/{user_id}/company")
async def assign_user_to_company(
    user_id: int,
    request: AssignCompanyRequest,
    session: dict = Depends(verify_session)
):
    """사용자를 다른 회사에 할당"""

# GET /api/dashboard/admin/join-requests-all — 전체 가입 신청
@router.get("/api/dashboard/admin/join-requests-all")
async def get_all_join_requests(session: dict = Depends(verify_session)):
    """시스템 관리자용: 전체 가입 신청 조회"""

# PATCH /api/dashboard/admin/join-requests/{request_id}/approve — 시스템 레벨 승인
@router.patch("/api/dashboard/admin/join-requests/{request_id}/approve")
async def system_approve_join_request(
    request_id: int,
    session: dict = Depends(verify_session)
):
    """시스템 관리자가 가입 신청 승인"""

# GET /api/dashboard/admin/audit-logs — 시스템 로그
@router.get("/api/dashboard/admin/audit-logs")
async def get_system_audit_logs(
    page: int = Query(1),
    limit: int = Query(50),
    start_date: str = Query(None),
    end_date: str = Query(None),
    user_id: int = Query(None),
    action: str = Query(None),
    session: dict = Depends(verify_session)
):
    """
    시스템 감시 로그 조회 (필터링 지원)
    응답: {total, items: [{id, user_id, action, resource_type, timestamp}]}
    """

# GET /api/dashboard/admin/resources — 하드웨어 리소스 현황
@router.get("/api/dashboard/admin/resources")
async def get_system_resources(
    period: str = Query('1h'),  # 1h, 6h, 24h, 7d
    session: dict = Depends(verify_session)
):
    """
    시스템 리소스 사용량 조회 (그래프용)
    응답: {
      current: {cpu_usage_percent, memory_usage_percent, disk_usage_percent},
      history: [{timestamp, cpu_usage_percent, memory_usage_percent, ...}],
      stats: {active_user_count, active_project_count, total_storage_mb}
    }
    """

4.2 Schema 정의 (B01_Dashboard/B01_Dashboard_Schema.py)

from pydantic import BaseModel

# 공통
class UpdateUserRequest(BaseModel):
    name: str
    position: str | None
    department: str | None
    phone: str | None

# USER 역할
class CreateCompanyRequest(BaseModel):
    name: str
    business_registration_number: str
    business_address: str
    business_owner: str

class JoinCompanyRequest(BaseModel):
    company_id: int

class AddMemberRequest(BaseModel):
    email: str  # 기가입 사용자의 이메일

class ProcessJoinRequest(BaseModel):
    action: str  # 'APPROVE' | 'REJECT'
    reason: str | None = None

# SYSTEM_ADMIN 역할
class ChangeUserRoleRequest(BaseModel):
    role: str  # 'USER' | 'ADMIN' | 'SYSTEM_ADMIN'

class AssignCompanyRequest(BaseModel):
    company_id: int | None = None  # None이면 회사 미연결

4.3 Repository (B01_Dashboard/B01_Dashboard_Repository.py)

Raw SQL을 이용한 데이터 조회/수정 함수들을 구현


5. 프론트엔드 구현 필요

5.1 B01_Dashboard_UI_Page.ts 전체 재설계

구조:

function DashboardPage() {
  const user = useAuth();  // role, status, company_id 포함

  return (
    <div class="dashboard">
      {/* USER/ADMIN 공통: 프로젝트 리스트 */}
      {(user.role === 'USER' || user.role === 'ADMIN') && (
        <ProjectListSection />
      )}

      {/* USER만: 회사 정보 */}
      {user.role === 'USER' && (
        <CompanyInfoSection />
      )}

      {/* ADMIN만: 팀원 관리 */}
      {user.role === 'ADMIN' && (
        <>
          <CompanyInfoSection />
          <TeamMembersSection />
          <JoinRequestsSection />
        </>
      )}

      {/* SYSTEM_ADMIN만: 시스템 관리 */}
      {user.role === 'SYSTEM_ADMIN' && (
        <>
          <ResourceStatusSection />
          <CompanyManagementSection />
          <UserManagementSection />
          <JoinRequestsManagementSection />
          <SystemAuditLogsSection />
          <SystemResourcesGraphSection />
        </>
      )}

      {/* 모든 역할: 기본정보 & 보안 */}
      <ProfileSection />
    </div>
  );
}

5.2 B01_Dashboard_Api_Fetch.ts 신규

// 공통
export async function fetchDashboardMe(): Promise<DashboardUser>;
export async function updateUserProfile(request: UpdateUserRequest): Promise<void>;

// USER 역할
export async function fetchUserProjects(): Promise<ProjectItem[]>;
export async function fetchUserCompany(): Promise<CompanyInfo>;
export async function searchCompanies(query: string): Promise<Company[]>;
export async function createCompany(request: CreateCompanyRequest): Promise<CompanyCreateResponse>;
export async function joinCompany(companyId: number): Promise<JoinCompanyResponse>;

// ADMIN 역할
export async function fetchCompanyMembers(): Promise<Member[]>;
export async function addCompanyMember(email: string): Promise<Member>;
export async function removeCompanyMember(userId: number): Promise<void>;
export async function fetchCompanyJoinRequests(): Promise<JoinRequest[]>;
export async function processJoinRequest(requestId: number, action: 'APPROVE' | 'REJECT'): Promise<void>;
export async function fetchCompanyProjects(): Promise<ProjectItem[]>;

// SYSTEM_ADMIN 역할
export async function fetchAllCompanies(): Promise<Company[]>;
export async function fetchAllUsers(filters?: UserFilters): Promise<User[]>;
export async function changeUserRole(userId: number, role: string): Promise<void>;
export async function assignUserToCompany(userId: number, companyId: number | null): Promise<void>;
export async function fetchAllJoinRequests(): Promise<JoinRequest[]>;
export async function systemApproveJoinRequest(requestId: number): Promise<void>;
export async function fetchAuditLogs(filters?: AuditLogFilters): Promise<AuditLog[]>;
export async function fetchSystemResources(period: string): Promise<ResourceData>;

5.3 B01_Dashboard_UI_Style.css 확장

  • 역할별 섹션 레이아웃
  • 프로젝트 리스트 테이블 스타일
  • 워크플로우 진행도 시각화
  • 팝업 모달 스타일
  • 그래프/차트 영역 스타일

5.4 섹션별 컴포넌트

ProjectListSection

  • 프로젝트 테이블 (프로젝트명, 지역, 진행도, 워크플로우, 수정일)
  • [+ 신규 프로젝트] 버튼
  • 워크플로우 단계 클릭 이벤트 처리

CompanyInfoSection (USER용)

회사 상태: 테스트회사 (ACTIVE) | [회사 변경]

상태별 표시:
- NO_COMPANY: "회사 미연결" + [회사 생성] [회사 찾기]
- PENDING: "가입 승인 대기 중 (OOO회사)"
- ACTIVE: "OOO회사 (ACTIVE)" + [회사 변경]

TeamMembersSection (ADMIN용)

  • 팀원 리스트 테이블 (이메일, 이름, 직급, 부서, 역할, 상태)
  • [+ 팀원 추가] 버튼 → 모달 팝업
  • [제거] 버튼

JoinRequestsSection (ADMIN용)

  • 가입 신청 리스트 테이블 (신청자, 신청일, 상태)
  • [승인] [거절] 버튼

ResourceStatusSection (SYSTEM_ADMIN용)

CPU: 45% | MEM: 62% | DISK: 78%
활성 사용자: 23 | 활성 프로젝트: 15

SystemAuditLogsSection (SYSTEM_ADMIN용)

  • 시스템 로그 테이블 (사용자, 행동, 대상, 타임스탬프)
  • 필터링: 기간, 사용자, 행동 유형

SystemResourcesGraphSection (SYSTEM_ADMIN용)

  • CPU 사용량 그래프 (시간대별)
  • 메모리 사용량 그래프
  • 디스크 사용량 그래프
  • 동시 접속자 수 추이

6. 검증 방법 (다음 단계)

6.1 USER 역할 검증

  1. 새 계정으로 로그인 → B01_Dashboard 진입
  2. 프로젝트 리스트 표시 확인
  3. 회사 상태: "회사 미연결" 표시 + [회사 생성] [회사 찾기] 버튼 확인
  4. [회사 생성] → 모달 팝업 → 회사 정보 입력 → [생성]
  5. DB 확인:
    • users.company_id 세팅
    • users.role = 'ADMIN' (관리자 전환)
    • users.is_master = TRUE
    • users.status = 'ACTIVE'
  6. 페이지 새로고침 → 회사명 표시 확인

6.2 ADMIN 역할 검증

  1. 회사 생성자(관리자)로 로그인 → B01_Dashboard 진입
  2. 팀원 관리, 가입 요청, 회사 프로젝트 섹션 표시 확인
  3. [+ 팀원 추가] → 모달 → 기가입 사용자 이메일 입력 → 검색 → 선택 → [추가]
  4. DB 확인:
    • users.company_id 업데이트
    • 중복 확인 (이미 팀원인 경우 오류 메시지)
  5. 팀원 리스트에 새로운 팀원 표시 확인

6.3 SYSTEM_ADMIN 역할 검증

  1. 시스템 관리자 계정으로 로그인 → B01_Dashboard 진입
  2. 전체 회사 리스트, 사용자 리스트, 시스템 로그, 리소스 현황 섹션 표시 확인
  3. 리소스 현황 (CPU, MEM, DISK, 활성 사용자/프로젝트) 표시 확인
  4. 사용자 역할 변경: USER → ADMIN 전환 → DB 확인
  5. 시스템 로그 필터링 (기간, 사용자, 행동 유형) 동작 확인