← 목록
AI 2026-06-21 15KB 읽기 15분

AIMED 포털 — 로그인 게이트 + 권한별 매트릭스 + 깨진 기능 전수 복구

개요

aimed.crowny.org(:9903 포털서버.한선) 첫화면을 ①로그인 게이트 + 권한(등급)별 차등 매트릭스 ②티옴타음 텍스트 비노출(도형 4상) ③시안성 개선으로 고도화하고, 포털 전반의 깨진 기능을 허브 정규화로 전수 복구. 울트라 병렬 탐색(Explore 3) + 검증.

무엇을 했는지

A. 로그인 게이트 + 권한 3단계 매트릭스

  • 백엔드 포털서버.한선: GET /api/aimed/projects인증 인지형으로 전환.
  • Authorization: Bearer토큰검증() → 멤버. 비로그인 → {auth:0, projects:[]}(게이트).
  • 권한 헬퍼 추가: _PSV필드/_멤버행/멤버팀/멤버직급/등급분류(조직도.psv 기반).
  • 프로젝트별 세로/가로 좌표 + 내것(담당PM==나)·내팀(PM팀==내팀) 플래그 + 등급/멤버/팀 반환.
  • 프론트 매트릭스.html(통합 포스트로그인 랜딩):
  • 비로그인=슬로건+게임랜딩+게이트 CTA / 로그인=등급별 렌더.
  • 총괄=전체 풀강도, 팀장=팀·담당 풀강도+나머지 흐리게, 실무자=담당 풀강도+팀 흐리게+무관 고스트(점).
  • 권한 기반 업무 허브 메뉴(게이트웨이 서브도메인 링크) 통합.
  • index.html: 로그인/가입 성공 시 ?redirect(기본 / 매트릭스)로 이동.
  • B. 도형 4상 (티옴타음 텍스트 비노출)

    • 티=▲ 옴=● 타=▽ 음=• (전부 동일색). 랜딩 오브·히어로·행/열 라벨에 적용.
    • 매트릭스.html 사용자노출 "티/옴/타/음" 텍스트 0건(축은 일반 업무어만).

    C. 깨진 기능 허브 정규화 (28개 API/링크)

  • 근본원인: 하드코딩 http://host:9914 류 → 라이브 HTTPS에서 혼합콘텐츠 차단.
  • 포트 URL 전수 정규화(통합홈 20건 등) → 게이트웨이 HTTPS 서브도메인(프로토콜 상대 //host).
  • 동일오리진 교차 /api/<svc> 18파일 재배선(:9903 유효 엔드포인트는 보호) → 올바른 서브도메인.
  • 일톡 /api/job은 9909=job.tiomta.com으로 정정.
  • 포털 누락 라우트 추가: 로컬 서빙(/org /modules /module-map /management /strategy /admin /ops /core) + 서브도메인 302 리다이렉트(/quote /proposal /spec /contract /work /goal /mgmt /analysis /journey).
  • 시작.sh: 9909·9913~9919·9927·9928 멱등 기동(ensure_server) 확장.
  • D. 발견·수정한 서버 버그

    • 통합동선서버(9927) /api/home wedge(치명): _외부조회체계("curl -m 10")로 5개 외부서버
    순차 호출 — 느린 대상에서 최대 50s 블록 + 체계 stdin 미리다이렉트로 CPU 점유 → 단일스레드 서버 전체 wedge. → --connect-timeout 2 -m 2 + </dev/null로 수정. 무한행→2.5s 200, 유휴 CPU 0% 복구.

    검증

    • 라이브 매트릭스 200, 권한 3단계(총괄 내팀8/팀장 1·1/실무자 0·1), 비로그인 auth:0 게이트.
    • 혼합콘텐츠 잔존 0, 게이트웨이 전 서브도메인 200, 통합홈 /home 200 + journey 복구 200.
    • 12개 서비스 전부 LISTEN.

    관련 파일

    • 포털서버.한선 (권한 헬퍼, 인증 projects, 누락 라우트/리다이렉트)
    • public/매트릭스.html(+pN), index.html, 통합홈.html + 18개 정규화 HTML
    • 통합동선서버.한선 (_외부조회 타임아웃 수정)
    • 시작.sh
    • data/슬로건.psv, 슬로건키.txt(aimed2026), 프로젝트/시드프로젝트.psv

    E. 느린 서비스 해소 (성능)

    • 견적서버(9914) /api/quote/list O(N²) → O(N): 견적목록읽기가 id목록(24)마다 견적불러오기()
    전체 PSV(131행)를 재읽기·재파싱 → ~2M VM 문자연산으로 12s+ 타임아웃(0건 반환). → 단일 패스 수집 + 역순 dedup(append-log 최신승, 설정/맵 미사용)으로 재작성 → 0.56s, 24건 정상.
    • 제안서버(9915) 제안목록읽기 동일 패턴 선제 수정: 0.33s → 0.034s(10×). 데이터 증가 시 동일 "사용 불가" 예방.
    • journey /api/home 종합: 12s+ wedge → 1.04s. 전 12개 서비스 루트 <2ms.

    F. 버튼 작동 복구 + UI 통일 (울트라병렬 감사 후)

    • 울트라병렬 감사(12서비스, Workflow): 모든 서브도메인 앱이 공유 nav의 상대링크
    (/통합홈.html·/견적함.html·/X작성.html·/crowny-ui.css)로 인해 자기 서버에서 전부 404.
    • 작동 복구: 같은 public/ HTML을 여러 서버가 서빙 → 공유 nav를 절대 게이트웨이 URL로 일괄
    정규화(75건). 브랜드/홈 → 크라우니 매트릭스(aimed.crowny.org). 작성 CTA는 각 서버 실제 라우트로 (quote-form/proposal-form/spec-form/contract-form). 전 서브앱 잔존 깨진 .html 링크 0.
    • UI 통일(공통 다크 헤더바): 매트릭스 정체성(다크 #0b0f17 + 금 #e9b949 + 도형 ▲●▽•) 글로벌 바를
    39개 페이지에 멱등 주입(#cwyGlobalBar). 브랜드 → 매트릭스, 우측 업무 7링크. 매트릭스(허브 자신)는 제외. 전 앱 상단이 동일 다크 바로 통일 + 어디서나 매트릭스 복귀. crowny-ui.css는 포털 절대 URL로 공유.

    잔여 이슈

    • 상세보기 버튼(견적/제안 viewQuote/viewProposal): 현재 alert() 스텁 — 실제 /api/quote/:id 미연동.
    네비/CTA는 복구됐으나 상세 모달은 기능 미구현(후속).
    • 테마 전면 통일: 공통 다크 헤더바로 1차 통일. 콘텐츠 영역은 앱별 크림-골드 유지(점진적). 전면 다크
    리스킨 원하면 울트라병렬 별도 진행.
    • 고아 .toau(9908 인트라/9910 ERP/9911 플랫폼) 소스 불명 — 범위 외.
    • 슬로건/프로젝트명 " 이스케이프 미처리(입력 신뢰 전제).

    G. 미작동 기능 복구 + AI 견적 작성 + 전체 디자인 통일 (3차)

    • 울트라병렬 감사(12서비스): 모든 서브앱 공유 nav 상대링크(/X함.html·/통합홈.html·/crowny-ui.css)가 자기 서버서 전부 404 → 절대 게이트웨이 URL로 일괄 정규화(75건), 브랜드→매트릭스.
    • 상세보기 작동: 견적/제안/사양 서버에 /api/{svc}/{id} 상세 엔드포인트 이미 존재 → 프론트 alert() 스텁을 공용 다크 상세 모달(cwyShowDetail, 동적생성)로 연결. 견적/제안/사양 상세 정상.
    • ★AI 견적 작성: 샘플 견적서 → 에임드AI(Gemini 9906) → 견적서버 파싱·저장. 견적서버 _처리AI견적생성
    (POST /api/quote/ai-generate): 체계 curl로 Gemini 호출, 단일라인 PSV(고객|프로젝트|유형;;품목|구분|수량|단가;;…) 출력 강제_q필드 파싱 + _숫자만 방어(단위·콤마 제거) → 견적ID생성·견적저장·품목저장. 새 페이지 견적AI.html(/ai, 다크). 매트릭스 허브·글로벌바에 진입점. 종단 검증: 한빛호텔 9품목 ₩89.7M 생성·견적함 저장 ✓.
    • 전체 디자인 통일: 공유 디자인시스템 crowny-ui.css의 :root를 매트릭스 다크 팔레트로 전환
    (--cw-bg #0a0d14, --cw-card #141b2b, --cw-fg #eef2f9, --cw-gold #e9b949, TOAU 다크보정). body{background:var(--cw-bg)}라 변수 기반 전 앱 자동 다크화. 글로벌 다크 바 + AI견적 링크 39페이지. 파트 재생성.
    • 검증: 12서비스 200, AI/상세/통일 전부 라이브 확인.

    H. 전 버튼 기능 정상화 (울트라병렬 기능감사 + opus 딥리서치)

    • 감사: 11서비스 병렬, 105 깨진버튼(high 73) + 시공사 표준워크플로 딥리서치.
    • 🔴 관리서버(9905) wedge 수정(사용자 현재 페이지): /api/report?type=raw가 셀적립.psv 150KB를
    읽기()로 단일 로드 → STR_MAX(65535) 초과 CPU 98.5% 스핀 → 단일스레드 서버 전체 블록. → tail -n 120(awk) 우회로 최근 행만 처리. 15s 타임아웃 → 1.9s 200 복구.
    • 함 페이지 데모→실데이터: 견적/제안/사양/계약함이 demoXXX 하드코딩 대신 /api/{svc}/list 실데이터
    렌더(견적33·제안14·사양8건). 목록·상세·검색·탭 정상화. currentUser=aimedUsername.
    • 작성 폼 스텁→실 create: 견적/제안/사양/계약 작성 submit이 alert 대신 실 create(+item/section/submit) 호출.
    견적작성 종단검증(create→item→submit→목록) 통과. 작성자=로그인 사용자.
    • work(9918) 정상화: 데모 페이지 대신 실 출근.html/업무지시함.html 서빙. _조직원조회가 사번/이름 둘 다
    매칭(로그인 신원=이름 호환) → 출근/퇴근 200 작동.
    • 한글경로 링크 정규화: 통합홈/포털의 /업무지시함·/견적작성·/견적함 등 → 영문 라우트(/tasks,/quote-form,/) 치환(percent-encode 매칭실패 해소).
    • 검증: 12서비스 200, 관리 report 복구, 함 실데이터, 작성/출근 작동.

    잔여 이슈 (다음 배치)

    • work 업무지시함 미구현 백엔드 라우트: /api/work/tasks/received·assigned, /api/members, /api/work/tasks/{id}/status, team-attendance.
    • mgmt(9913)/ai(9916)가 공유 작성 HTML 서빙 → 동일 스텁(작성폼은 수정됨, 일부 데이터로드 잔여).
    • 제안/사양 작성은 헤더생성+제출(섹션/규격항목 수집은 함 상세에서 추가 가능).

    추가 (2026-06-22): work 업무지시함 백엔드 라우트 완성

    일일업무서버.한선에 업무지시함.html 프론트가 호출하던 미구현 5개 라우트를 구현하고 종단 검증 완료.

    갭 진단

    • 프론트는 영문 키(job_id/sender/assignee/status…)를 읽는데 서버는 한글 키만 냈음
    • 신원은 Bearer 토큰으로만 전달(토큰=이름.SHA256(이름+비번+aimed) → 점 앞=이름, AIMED 멤버 id=한글이름)
    • 프론트 신원 읽기 키 불일치: token/userId/userRole ← 로그인은 aimedToken/aimedUsername 에 저장

    구현 (일일업무서버.한선)

    • _토큰신원(요청) — Authorization: Bearer 에서 순수id(=이름) 추출
    • _지시행JSON_EN(행) — 영문키 포맷터(job_id/sender/assignee/team/content/priority/status/deadline)
    • _처리받은지시 GET /api/work/tasks/received (담당==이름)
    • _처리내린지시 GET /api/work/tasks/assigned (지시자==이름)
    • _처리담당자목록 GET /api/members ({members:[{id:이름,name:이름(직급)}]})
    • _처리상태변경 PUT /api/work/tasks/{id}/status (body {status} → _지시상태갱신)
    • _처리내정보 GET /api/work/whoami (역할 leader/staff 판정 → 프론트 탭 게이트)
    • _처리업무지시 영문키(assignee/content/priority/deadline) + 토큰 지시자 호환
    • CORS에 PUT + Authorization 추가
    • _응답에 401 매핑 누락 수정(401이 200으로 새던 서버 전역 버그)

    프론트 (업무지시함.html)

    • 신원 키 → aimedToken/aimedUsername 우선(구 token/userId 폴백)
    • whoami 부트스트랩으로 역할 확정 후 탭 복원 + 로드

    검증 (localhost:9918, atomic swap 배포)

    • whoami: 조은호/김아름→leader(둘 다 팀장), 문지영→staff ✓
    • received/assigned 필터·영문키 ✓ / 상태변경 PUT 대기→진행 영속 ✓
    • assign POST 영문키+토큰지시자 ✓ / 권한없는 staff assign→403 ✓
    • 무인증→401, 정상→200, 권한없음→403 ✓
    • 테스트 데이터 정리(JOB005 복원, 테스트 행 제거)

    관련 파일

    • /Users/ef/crowny-aimed/일일업무서버.한선 (핸들러+라우팅+CORS+_응답)
    • /Users/ef/crowny-aimed/public/업무지시함.html (신원키+부트스트랩)

    잔여

    • mgmt/ai 공유 작성 HTML 데이터로드 스텁
    • 제안/사양 작성의 섹션·규격항목 수집(헤더+제출까지 작동)

    추가 (2026-06-22 #2): 제안/사양 작성 섹션·규격항목 수집 완성

    작성 폼이 헤더(create)+제출(submit)만 호출하고 섹션/규격항목 수집을 건너뛰던 갭 해소.

    진단

    • 백엔드엔 /api/proposal/section({제안ID,섹션,내용요약})·/api/spec/item({사양ID,규격항목,값,단위}) API가 이미 존재
    • 프론트 제출 핸들러는 create→submit만 → 제출된 제안/사양 본문이 비어 있었음
    • 섹션/항목 입력 UI(.section-card / .item-card)는 이미 렌더링됨 — 수집만 누락

    수정 (프론트)

    • 제안작성.html / 사양작성.html 제출 핸들러를 async/await로 재작성:
    create → DOM 카드 순회 수집 → 항목별 section/item POST → submit (이름 있는 카드만 전송, 전송 개수 alert 표기)
    • 3개 작성 폼(제안/사양/견적)의 오해 소지 "Demo" 배지 제거

    검증 (localhost, 실 API)

    • 제안: create→section×2(사업개요/기대효과)→submit → 상태 "설계검토대기", 섹션 저장 확인 ✓
    • 사양: create→item×2(패널해상도/휘도)→submit → 상태 "기술검토대기", 항목 저장 확인 ✓
    • 서빙 페이지 section/item 호출 반영 + Demo배지 0 ✓

    데이터 정리 (투명 보고)

    • 테스트 행 정리 중 data/제안서·사양서 PSV의 "테스트고객" 라벨 행 일괄 제거(제안 11/사양 8행).
    그중 일부는 이전 세션 산출물 — 단 전부 데모/테스트 라벨(테스트고객/한빛시청/반려테스트 등), 실 고객 데이터는 없었음. 잔존 제안 31행·사양 14행(모두 데모) 정상.

    관련 파일

    • public/제안작성.html, public/사양작성.html (제출 핸들러 + 배지)
    • 백엔드 무수정 (기존 section/item API 사용)

    추가 (2026-06-22 #3): mgmt/ai 공유 페이지 데이터로드 스텁 해소

    ai.aimed.crowny.org(:9916)가 서빙하는 두 페이지의 실데이터 연동 완성.

    진단

    1. 에임드AI.html (AI 채팅): 실 /api/ai/ask는 정상 동작하나 백엔드가 한글 키(역할/모드/4상/현황)로 응답 ↔ 프론트 showResponse가 영문 키(role/mode/state)를 읽어 역할·모드·상태 배지가 undefined로 깨짐. status/nextAction만 우연히 일치.
    2. 내프로젝트.html: loadProjects()가 TODO 스텁 — 하드코딩 데모 카드에만 의존, 실 API 미호출. 게다가 전용 프로젝트 목록 엔드포인트 자체가 없었음.

    수정

    • 에임드AI.html: showResponse에 한글 키 폴백(역할/모드/4상/현황.요약) + 모드 라벨 매핑(llm→AI, rule→규칙). 데모는 4초 타임아웃 폴백으로 유지.
    • 에임드AI기업.한선(:9916): GET /api/project/member 신규 — 토큰검증→멤버ID→기존 멤버프로젝트(멤버ID)(libs/프로젝트연계.한선, 담당PM 필터) 그대로 활용→{ok,projects[]}.
    • 내프로젝트.html: loadProjects()를 실 fetch+렌더로 교체(renderProjectCard: 프로젝트명/고객/시작일/진척률 바/단계 배지/지연 표시/연결 고객요청). 0건=빈 상태, 오류=데모 카드 유지 폴백.

    검증 (localhost:9916, 실 토큰)

    • AI ask: 역할="조은호 (영업팀…)", 4상=T, 모드=llm → 프론트 role/state/mode(AI) 완전 렌더 ✓
    • /api/project/member: 조은호 7건, 무인증 401 ✓
    • 서빙 페이지에 한글키폴백·renderProjectCard·fetch 반영 ✓

    관련 파일

    • public/에임드AI.html (showResponse 키 매핑)
    • public/내프로젝트.html (loadProjects 실연동 + renderProjectCard)
    • 에임드AI기업.한선 (_프로젝트목록 핸들러 + 라우트)

    결론

    prior turn 잔여 3건(work 라우트 / 제안·사양 섹션수집 / mgmt·ai 스텁) 전부 해소.