새글

    최근 30일 이내 등록된 새글 이에요.
  • ※ 휴가신청서 변환기 · 개발 릴리즈 리포트 신안군중증장애인자립생활지원센터 · 메일플러그 그룹웨어 외부 보조 프로그램 최초 작성: 2026-04-23  ·  갱신: 2026-04-28  ·  최종 버전: v1.0a (캐시 2026042801) 환경: Cafe24 류 PHP 호스팅 · Apache 2.4 · PHP 7.4+ · 도메인: simble.kr 프로젝트 개요 Project Overview 메일플러그 그룹웨어는 휴가신청 기능을 기본 제공하지만, 본 센터가 요구하는 (1) 병가 누적일수 자동 계산, (2) 일수별 증빙서류 자동 분기, (3) 규정 문구 자동 문장화, (4) 메일플러그 본문 양식(HTML 표)으로의 자동 변환 기능을 포함하지 않는다. 이 네 가지 보조 기능을 외부 호스트에서 구현해 담당자가 "웹에서 입력 → 변환 → 메일플러그에 붙여넣기" 한 번의 흐름으로 처리하도록 설계했다. 산출물 구성 영역파일역할 진입점va/index.php신청자용 · 로그인 / 입력 / 미리보기 / 변환 (~440행) va/admin.php관리자용 · 신청자·휴가코드·신청이력 CRUD (~390행) 클라이언트va/assets/js/app.js신청자 로직 (약 1,550행) va/assets/js/admin.js관리자 로직 (약 1,100행) 스타일va/assets/css/style.css공용 스타일 (헤더·푸터·폼·모달) va/assets/css/admin.css관리자 전용 스타일 APIapi/_common.phpCSRF · 세션 · JSON 파일 I/O 공용 헬퍼 api/auth.php · admin_auth.php로그인 / 로그아웃 / 비밀번호 변경 api/admin_codes.php · admin_employees.php · admin_applications.php · my_applications.php리소스별 CRUD 데이터data/employees.json직원 명부 (이름·생년월일) data/leave_codes.json휴가 코드 마스터 (3계층) data/applications.json휴가신청 기록 누적 핵심 설계 원칙 설치형이 아닌 브라우저 완결형 — 신규 서버 구축 없이 기존 호스팅에 업로드만으로 운영 DB 엔진 없이 JSON 파일 + flock + 원자적 rename 으로 경량 영속성 확보 메일플러그는 본문 붙여넣기 경로만 빌리고, 입력·변환은 전부 외부에서 처리 (기존 시스템 무변경) 휴가 코드는 카테고리 → 그룹 → 소분류 3계층으로 코드 수정 없이 신규 휴가종목 확장 버전 요약표 Release Summary 버전 주요 변경 대상 Task 프롬프트 품질 난이도 v0.1스키마 설계 · CSRF · 세션 · JSON DB · 진입점 분리#6–#11개념적높음 v0.4호스팅 401 회피 → HTTP 200 + JSON ok:false 패턴#12, #26증상·환경 명확중간 v0.5–0.9휴가 코드 스키마 7회 리팩터 · 증빙 pre/post · 갱신주기 1월#13, #14, #18, #19, #28, #39, #44, #49UI 명확중간 v1.0–1.1신청 기록 저장 파이프라인 · 신청자 대시보드#15, #17, #20, #22–#24명확중간 v1.2–1.5병가 도메인 특화 (누적일수 실시간·일수별 증빙)#25, #29, #30, #33, #34, #39–#41법령 원문 인용높음 v1.6–1.8미리보기 3소모듈 분리 · 인라인 style HTML 빌더 · 표 폰트 11px#21, #35–#38, #43, #46, #50구조 지시중간 v1.9등록된 신청자 연도별 통계 필터#47기본값 미지정낮음 v2.0캐시 버전(YYYYMMDDNN) 일괄 bump 패턴 정착#42, #45, #48규칙 명확낮음 v1.0a헤더/푸터 리디자인 · 빌더풍 배경 · SVG 아이콘 · 버전 표시 · SIMBLE.KR 카피라이트#52디자인 지시 풍부중간 사고마운트 동기화로 패치 PHP 끝부분 잘림 → 호스트 parse error#53사고 보고 명확낮음 AI 접근 방법론 Methodology ① 요구 분석 스키마 우선 — UI 보다 데이터 모델·권한·호스팅 환경을 먼저 확정. 휴가 코드 3계층은 v0.1 에 박혀 이후 모든 기능의 척추가 됨. 도메인 용어 원문 보존 — 병가·공가·특별휴가 같은 법령/내규 용어는 의역 금지. 코드와 UI 양쪽에 그대로 인용. "이전과 같게"의 위험 — 사용자가 "이전과 같게 X만"이라고 하면 "이전"의 파일·함수·줄번호를 되묻거나 컨텍스트에서 확정해 다시 인용. ② 구현 원칙 스키마 이행 = 레거시 키 보존 + 신규 키 병기 — evidence 한 필드를 evidence_pre/post 로 쪼갤 때도 합집합 evidence 를 계속 발행해 기존 소비자 무중단. 서버 허용값 = 3지점 동기 — UI <select> · JS 상수 · PHP 검증. "1월" 한 옵션 추가가 실제로는 3 파일 동시 수정. 복사-붙여넣기 HTML = 인라인 style — 메일플러그 본문은 외부 CSS 클래스를 보존하지 않는다. 표 폰트 같은 미세조정도 인라인 스타일 문자열에 반영. 클라이언트 계산값은 신뢰 안 함 — days·합계 등은 저장 직전 서버에서 재계산. ③ 검증·배포 JS → node --check . JSON → Python json.load . PHP → php -l (호스트 환경 가능 시). 변경 후 캐시 버전 일괄 bump 후 시크릿 창에서 검수 — 일반 새로고침은 캐시 잔재 위험. PHP 패치 업로드 후 curl -I 로 200 응답 확인. 500 이면 즉시 롤백. ④ 운영 트러블슈팅 Linux 마운트 ↔ Windows 동기화 이슈 — 60 KB+ JS 파일에서 마지막 청크 누락이 재발. 증상은 node --check 실패·파일 끝 널바이트. 대응: tr -d '\000' 로 널바이트 제거 후 cat src > dst 로 in-place 복사 (mv 는 디바이스 간 이동 권한 이슈). bash heredoc 의 ! 역사 확장은 'EOF' 단일인용 quote 으로 차단. ⑤ 세션 간 연속성 컨텍스트 압축(summarize)이 발생하면 요약의 대기 작업을 먼저 처리하되, 실제 파일을 다시 Read 해 코드 상태를 확인. 요약·기억만으로 작업하지 않음. 모든 자산 캐시 버전 문자열을 동일하게 유지 해 어느 세션에서나 배포 식별 가능. 버전별 상세 이력 Version History v0.1 기반 2026-04-20 ~ 04-22 초기 기획 · 스키마 · 인증 · 관리자 UI 기반 (Task #6–#11) 최초 요청 (요약) 메일플러그 그룹웨어 외부 호스트에서 휴가신청서를 편하게 작성·변환할 수 있는 프로그램을 만들어줘. 신청자 / 관리자 분리, JSON 파일 기반 DB, 기존 호스팅(Cafe24 유형)에 바로 올릴 수 있게. [O] 적절한 점 최종 산출물(외부 보조 프로그램)·구조(신청자/관리자 분리)·DB 형태·배포 환경(Cafe24 류)이 한 문장에 압축돼 있음. AI 의 자유도와 사용자 의도 사이 균형이 좋음. [!] 보완할 점 비즈니스 규칙(휴가 종류·일수·증빙 등)과 UI 기대치는 거의 비어 있음. → 이후 약 50회의 마이크로 수정으로 채워짐. 초기에 휴가 규정 원문(취업규칙·법령)을 첨부했으면 후속 수정 횟수가 절반 가까이 줄었을 것. 방침 · 접근 방법 스키마 우선 — 카테고리(SICK/OL/SL/ET)→그룹→소분류 3계층을 v0.1 에 고정. 이후 기능은 모두 이 위에 얹혀 큰 구조 변경 없이 진행됨. 프레임워크 무도입 — Cafe24 류 호스팅의 composer·CLI 부재를 고려해 PHP 절차형으로 작성. DB 대신 JSON + flock + 원자적 rename — 직원 수십 명·기록 수천 건 규모면 충분. 진입점 물리 분리 — index.php (신청자) / admin.php (관리자). 세션·CSRF·권한 경계 단순화. BEFORE AFTER (v0.1 산출물) (신규 프로젝트 — 파일 없음) va/ ├ index.php · admin.php ├ api/_common.php (CSRF · flock · 세션) ├ api/auth.php · admin_auth.php ├ api/admin_codes.php · admin_employees.php ├ api/admin_applications.php · my_applications.php ├ assets/js/{app,admin}.js ├ assets/css/{style,admin}.css └ data/{employees,leave_codes, applications,admin}.json 교훈 ① — 외부 호스팅용 프로젝트는 첫 줄 코딩 전에 배포 환경(PHP 버전·composer 가용성·ErrorDocument·디렉토리 권한)을 확정해야 한다. 나중에 프레임워크를 붙이려 하면 거의 재작성이 된다. v0.4 BUG 2026-04-22 호스팅 401 페이지가 JSON 본문 침범 → HTTP 200 + ok:false 패턴 정착 (Task #12, #26) 증상 보고 로그인 시도하면 브라우저 콘솔에 401 떨어지고 JSON 파싱 에러가 나. 호스팅 기본 401 페이지(HTML) 가 JSON 자리에 들어오는 것 같아. [O] 적절한 점 증상(콘솔 401·JSON 파싱 에러) + 환경 추정(호스팅 기본 페이지 침범)을 함께 제시. 디버깅 출발점이 명확해 AI 가 원인을 우회 설계 단계로 빠르게 넘어갈 수 있었음. [TIP] AI 의 결단 "HTTP 상태코드 + JSON 본문 동시 보존"은 호스팅 설정 변경 없이 불가능 → "상태코드는 업무 실패의 주된 채널이 아니다" 로 정의 재정의. HTTP 200 + JSON ok:false 패턴으로 통일. BEFORE (_common.php) AFTER (200 고정) function json_error($msg, $status=400){ http_response_code($status); // 401/403 발송 echo json_encode([...]); exit; } // → Apache ErrorDocument 가 // PHP 본문을 HTML 로 덮어씀 function json_error($msg, $status=400, $code=null){ json_response([ 'ok'=>false, 'error'=>$msg, 'code'=>$code, 'status'=>$status // 참고용 ], 200); // 실제 발송 200 고정 } 의도와 부작용 — 보안 스캐너·로드밸런서가 "200 OK" 로 집계한다는 부작용이 있어 운영 로그에는 status 필드를 별도 추적해야 한다. 외부 상품화 시 자체 인프라가 있다면 호스팅 설정 변경으로 되돌리는 선택지도 남겨뒀다. 교훈 ② — 호스팅 고유 동작은 코드로 우회. HTTP 원론(상태코드 맞추기)에 매달리면 한 주 단위로 디버깅이 샌다. v0.5 – v0.9 2026-04-22 ~ 04-28 휴가 코드 스키마 7회 리팩터 · 증빙 pre/post · 갱신주기 1월 (Task #13, #14, #18, #19, #28, #39, #44, #49) v0.5 · 소분류 모달 UI/UX 전면 개선 PROMPT 소분류 모달에 증빙서류를 체크박스로 편집하게 해줘. 갱신주기는 셀렉트. 휴가사유서 필드도 추가. [O] 적절한 점 위젯 종류(체크박스·셀렉트)와 추가 필드를 명시. UI 의 자유도가 좁혀져 즉시 구현 가능. [!] 보완할 점 서버 스키마(필드명·타입), 허용값(어떤 갱신주기?), 하위호환(기존 데이터?)이 비어 있음. AI 가 기본값을 추정해 채우고 사용자 승인을 받는 패턴 정착. v0.7 · 증빙서류 사전/사후 분리 (무중단 스키마 이행) PROMPT 소분류에서 '증빙서류'를 '사전'과 '사후'로 구분하여 등록할 수 있도록 변경 접근 방법: 파괴적 마이그레이션 회피 기존 레코드는 evidence: [] 한 필드. 새 필드 evidence_pre, evidence_post 를 추가하되, 레거시 소비자(신청자 대시보드 등)를 위해 evidence 필드(합집합)를 계속 발행. 서버에서 매번 합집합을 자동 생성해 클라이언트는 어느 키든 읽을 수 있도록 함. BEFORE 스키마 AFTER (하위호환) { "evidence": ["진단서","진료확인서"], "evidence_timing": "사후" } { "evidence": ["진단서","진료확인서",...], "evidence_pre": ["신청서"], "evidence_post": ["진단서","진료확인서"], "evidence_timing": "사전+사후" } v0.9 · 갱신주기에 "1월" 추가 — 3지점 동기 원칙 PROMPT '휴가항목 관리'에서 '소분류 수정'에서 '갱신주기' 항목에 '1월' 추가 [O] 적절한 점 위치(휴가항목 관리 → 소분류 수정 → 갱신주기) + 동작(추가) + 결과물(1월 옵션)이 한 줄에 모두 들어가 모호성 없음. [TIP] 숨은 함정 한 줄짜리 변경처럼 보이지만 실제로는 UI <select> · JS RENEWAL_OPTIONS 상수 · PHP in_array 검증 3 지점 동기 필요. BEFORE (3 지점 불일치 가능) AFTER (3 지점 동시 반영) // admin.php <option>해당없음</option> <option>1년</option> ... // admin.js RENEWAL_OPTIONS = ['해당없음','1년',...]; // admin_codes.php in_array($v, ['해당없음','1년',...]) // admin.php <option>해당없음</option> <option>1월</option> <option>1년</option> ... // admin.js RENEWAL_OPTIONS = ['해당없음','1월','1년',...]; // admin_codes.php in_array($v, ['해당없음','1월','1년',...]) 교훈 ③ — 스키마 이행은 반드시 레거시 키 보존 + 신규 키 추가 순으로. 서버 허용값 화이트리스트 변경은 UI · JS · PHP 3지점 동시 반영 이 절대 원칙. v1.0 – v1.1 2026-04-23 신청 기록 저장 파이프라인 + 신청자 대시보드 (Task #15, #17, #20, #22–#24) v1.0 · 변환 시점 자동 저장 PROMPT 변환 버튼 누를 때 신청 내역이 자동 저장되도록. 관리자 ③탭에서 조회 가능하게. 구현 방침 클라이언트가 변환 시점에 같은 payload 를 POST /api/applications.php 로도 전송. 저장 실패가 변환 UX 를 막지 않도록 fire-and-forget 패턴 (await 하되 에러는 토스트로만 표시, 변환 자체는 진행). v1.1 · 신청자 "내 기록" 전용 API 관리자 API admin_applications.php 에 본인 필터 파라미터를 더해 재사용하는 유혹이 컸지만, 권한 누수 위험 때문에 별도 엔드포인트로 분리. 유혹: admin API 재사용 채택: my_applications 분리 GET /api/admin_applications.php ?name=홍길동&birth=1990-01-01 // 쿼리 파라미터로 본인 필터 // → 파라미터 바꾸면 타인 조회 가능 GET /api/my_applications.php // 서버에서 $_SESSION['emp'] // 로만 필터 // 클라이언트가 조작할 파라미터 없음 // → 권한 경계가 코드에 박힘 교훈 ④ — 같은 데이터에 권한이 다르게 적용되는 경우 엔드포인트를 분리해 권한 경계를 코드 구조로 강제. 쿼리 파라미터 필터링은 누수 위험 상시. v1.2 – v1.5 병가 2026-04-23 병가 도메인 특화 (Task #25, #29, #30, #33, #34, #39–#41) v1.3 · 병가 누적일수 실시간 반영 PROMPT 병가 신청 시 서버에 저장된 누적일수 + 이번 신청일수를 합산해서 제3소모듈 3번째 행에 '병가는 연간 60일(유급 30일 포함)…' 문구와 함께 표시 [O] 적절한 점 "서버 저장값 + 입력값 합산" 계산 로직과 표시 위치(제3소모듈 3행), 출력 문구가 모두 명시. 규정 문장은 따옴표로 원문 인용 → 코드에 그대로 박을 수 있음. [TIP] AI 의 상태 분리 한 변수에 합산값을 저장하면 입력 변경마다 서버 호출 필요. 이를 피하기 위해 서버 sum (불변) 과 currentSum (재계산) 두 상태를 분리. BEFORE (단일 상태) AFTER (이중 상태) item.sickSum = 42; // 서버에서 받은 값 // start/end 변경 시 클라 재계산 X // → "오늘 입력한 5일" // 합산되지 않음 item.serverSickSum = 42; item.currentSickSum = 42 + days; // start/end 변경 → onRefresh // → applySickThird() // → 표 3행 즉시 업데이트 v1.4 · 사후 증빙 안내 일수별 분기 PROMPT 5일 이하 통원/입원은 [영수증/처방전/진료확인서 중 택 1], 6일 이상은 [의사 진단서 + 진료확인서]로 분기 [O] 적절한 점 임계값(5일/6일)과 각 케이스의 출력 문구를 모두 명시. AI 가 추정·해석할 부분이 거의 없음. 규정 원문(택1/+) 표기까지 그대로 보존. [TIP] 의도된 코드 중복 이 분기 로직은 "사후 증빙 안내" 와 "제3소모듈 증빙서류 행" 두 곳에서 동일. 함수로 묶지 않고 의도적으로 중복 구현. 라이프사이클 다른 영역의 미래 분기 가능성을 보존. 상태 통원/입원 ≤ 5일 통원/입원 ≥ 6일 자택 표시 문구 진료비 영수증·처방전·진료확인서 중 택1 의사 진단서 + 진료확인서 "구체적인 증상과 경과" 기재 병가사유서 교훈 ⑤ — 도메인 로직(법령·내규 기반 분기)은 요약하지 말고 원문 문장 그대로 코드에 박는다. 감사 대비에 유리하고, 후속 수정자가 어떤 규정을 구현한 것인지 한눈에 파악 가능. 재사용보다 문서성이 우선. v1.6 – v1.8 2026-04-23 미리보기 3소모듈 분리 + 인라인 style HTML 빌더 + 표 폰트 11px (Task #21, #35–#38, #43, #46, #50) v1.6 · 미리보기를 3개 소모듈로 분리 PROMPT 미리보기를 ① 제목, ② 휴가사유서 본문, ③ 표(변환 대상) 3개 소모듈로 나눠줘. 복사 대상은 ③만. [O] 적절한 점 3개 소모듈 각각의 역할과 "복사 대상은 ③만" 이라는 변환 경계가 명확. 이 한 번의 분리가 이후 모든 마이크로 조정의 국소화를 가능하게 함. [TIP] 구조적 효과 "③번 표 폰트 11px" 같은 후속 요청이 다른 영역에 영향 없이 한 함수(buildModule3Html) 안에서 끝남. 변환 경계를 DOM 구조에 박은 결정의 가치. BEFORE (단일 preview) AFTER (3 소모듈 분리) <div id="preview"> 제목 · 본문 · 표 모두 한 DIV에 </div> // 변환 대상 = preview.innerHTML 전체 // → 제목·본문도 함께 복사되는 부작용 <div class="pv-mod pv-mod-1"> 제목 </div> <div class="pv-mod pv-mod-2">본문</div> <div class="pv-mod pv-mod-3">표</div> // 변환 대상 = buildModule3Html() 만 // → 변환·복사 경계 = DOM 구조 v1.8 · 제3소모듈 표 폰트 11px PROMPT ③소모듈 표 안의 폰트 11px [O] 적절한 점 대상(③소모듈 표)·속성(폰트 크기)·값(11px)이 4 단어로 압축. 모호성 0. [TIP] AI 의 위치 결정 표 스타일이 CSS 가 아닌 인라인 style 속성(tblStyle 문자열)에 박혀 있음. 이유는 메일플러그 본문에 외부 CSS 클래스가 보존되지 않기 때문. 교훈 ⑥ — 복사-붙여넣기로 전달되는 HTML은 인라인 style 로 작성. 이 원칙을 문서 상단에 박아두지 않으면 후속 개발자가 style.css 에서 헤맨다. v1.9 2026-04-23 등록된 신청자 연도별 통계 필터 (Task #47) PROMPT '전체 선택'·'선택 삭제' 버튼을 좌측에 붙이고, 우측에 연도 드롭다운 + 조회 버튼. 드롭다운은 기록의 연도 기준 자동 생성, 기본값 '전체'. [O] 적절한 점 레이아웃(좌/우 위치)·데이터 소스(기록의 연도)·기본값(전체) 모두 명시. [!] 보완할 점 정렬 방향(내림/오름차순)과 빈 연도 처리(기록 없으면 어떻게)는 미지정. AI 가 임의 결정 → 추후 "왜 이렇게 동작?" 질의 발생 가능. AI 의 임의 결정과 그 근거 정렬 → 내림차순(최신 연도 위). 근거: 인사 담당자는 대부분 "올해" 를 본다. 기록이 비어 있을 때 → "전체" 한 옵션만. 드롭다운 자체는 항상 존재(사용자가 무엇을 누른 건지 보여주기 위해). 이런 임의 결정을 리포트에 명시적으로 기록 하지 않으면 같은 사용자가 며칠 뒤 "왜 이렇게 동작?" 을 다시 묻는다. v2.0 캐시 2026-04-23 ~ 04-28 캐시 버전 일괄 bump 패턴 정착 (Task #42, #45, #48) 클라이언트 JS/CSS 를 수정할 때마다 ?v=YYYYMMDDNN 쿼리스트링으로 캐시 버스팅. 버전 번호는 년·월·일·일련번호 포맷(예: 2026042306). 캐시 관리 규칙 같은 날 여러 번 올리면 말미 일련번호만 증가 (2026042301 → 02 → 03 ...). 모든 자산(style.css · admin.css · app.js · admin.js)이 동일 버전. 반쪽 배포로 JS/CSS 불일치 방지. 업로드 직후 검수는 "Ctrl+F5" 가 아니라 시크릿 창에서 — 일반 새로고침은 캐시 잔재 위험. 운영 중 관찰된 이슈 — Linux 마운트와 Windows 파일 시스템이 60 KB+ JS 파일에서 가끔 마지막 청크 누락 발생. 증상: node --check 실패 · 파일 끝 널바이트. → 본 사건이 아래 v1.0a 사고로 재현됨. v1.0a NEW 2026-04-28 헤더/푸터 리디자인 + 패치 폴더 구조 (Task #52) PROMPT (발췌) ■ 수정한 파일은 '/va/patch/' 폴더에 "va-patch-[버전명]" 폴더를 만들어 수정한 파일과 수정한 파일이 저장된 폴더만 저장한다. 이전 파일과 폴더는 '/tr/proto/' 폴더에 저장한다. 이번 수정 파일의 버전은 1.0a이다. 헤더 상단의 '신안군중증장애인자립생활지원센터'와 "취업규칙 제37~44조 · 2024.11.25. 개정 기준", " — 사전등록된 이름/생년월일로 접속하세요." 문구는 삭제한다. 신청자/관리자 페이지 헤더 우측에 작은 글씨로 버전 표시. 표시형식: "Ver.[버전명]([만든날짜](yymmdd))" 빌더 기능에 적합한 헤더의 배경을 디자인하고 제목 앞에는 적절한 아이콘을 추가하라. 푸터는 헤더와 어울리는 저작권 표시 별도 섹션을 만들고 "ⓒ Copyright 2026. SIMBLE.KR all rights reserved. | DB: JSON 파일 기반 · 백엔드: PHP"라고 표시한다. [O] 적절한 점 요구사항이 5개 영역(저장 규칙·삭제·버전 표시·헤더 디자인·푸터)으로 잘 분리. 버전 표시 형식과 푸터 저작권 문장이 따옴표로 인용되어 모호성 최소. [!] 보완할 점 "빌더 기능에 적합한 헤더 배경" · "적절한 아이콘" 은 디자인 자유도가 큰 표현. AI 가 다크 네이비 + 도트 그리드 + SVG 를 선택했지만 사용자 의도와 다를 경우 재시도 비용 발생. 색상 팔레트나 키워드(미니멀·블루프린트 등)를 1~2 단어 더 주면 적중률 향상. 방침 · 접근 방법 패치 폴더 구조 — 사용자 명시 규칙 그대로. tr/proto/va/... 변경 전 백업, va/patch/va-patch-1.0a/va/... 변경 후. 폴더 구조 보존으로 호스트 경로와 1:1 매핑. 헤더 배경 — linear-gradient(135deg, #1a3a5c, #2c4f78, #1a3a5c) + radial-gradient 도트 그리드 + 하단 3px 액센트. "빌더풍" 키워드를 블루프린트/제도공구 메타포로 해석. 아이콘 — 신청자(문서+편집펜, 폼 빌더 메타포) / 관리자(문서+톱니, 설정 메타포) 차별화. 버전 표시 — 모노스페이스 폰트 + opacity 65% 로 제목보다 작게. baseline 정렬. 푸터 — <main> 바깥으로 분리해 헤더와 시각적 대칭(같은 그라데이션·같은 액센트 라인). BEFORE (단순 솔리드) AFTER (빌더풍 + 아이콘 + 버전) .top { background: var(--navy); } <span class="top-kicker"> 신안군중증장애인자립생활지원센터 </span> <h1>휴가신청서 · 이지윅 HTML 빌더</h1> <span>취업규칙 제37~44조 · ...</span> <span>비로그인 — 사전등록된 ...</span> .top { background-color: #1a3a5c; background-image: radial-gradient(circle at 1px 1px, rgba(255,255,255,.08) 1px, transparent 0), linear-gradient(135deg, #1a3a5c,#2c4f78,#1a3a5c); } <span class="top-icon"><svg/></span> <h1>휴가신청서 · 이지윅 HTML 빌더 <span class="top-version"> Ver.1.0a(260428) </span> </h1> <footer class="copy-section"> ⓒ Copyright 2026. SIMBLE.KR ... </footer> 교훈 ⑦ — 사용자가 "[버전명]([만든날짜](yymmdd))" 처럼 출력 포맷을 따옴표로 직접 지정하면 AI 의 추측 여지가 사라져 한 번에 정확히 구현된다. 디자인 자유도가 큰 영역(배경·아이콘)은 키워드 1~2 단어 추가만으로도 적중률이 크게 오른다. 사고 · 패치 트렁케이션 사고 2026-04-28 호스트 PHP parse error — 마운트 동기화 실패로 패치 파일 끝부분 잘림 (Task #53) 증상 보고 Parse error: syntax error, unexpected end of file in /hosting/simble/html/sa/os/mp/va/index.php on line 424 에러 발생함 원인 분석 v1.0a 적용 시 Linux 마운트에서 패치 폴더로 cp 한 PHP 파일이 끝부분에서 잘려 호스트 업로드본이 <?php en 에서 끊김. <?php endif; ?> 가 미완성되어 PHP 가 unexpected EOF 를 보고함. 사용자의 va/proto/ 백업본은 정상(439 줄)이었으나 패치본은 423 줄로 16 줄 누락. 사고 시점 (호스트 업로드본) 복구 후 (proto/ 에서 재복사) </div> </template> <?php en // ↑ 파일이 여기서 끝남 // <?php endif; ?> 미완성 // </main>·footer·</body> 누락 // → PHP parse error </div> </template> <?php endif; ?> </main> <footer class="copy-section"> <div class="copy-inner"> <small>ⓒ Copyright 2026. ...</small> </div> </footer> <script src="..."></script> </body></html> 조치 cat va/proto/index.php > va/patch/.../index.php 로 in-place 복사 (mv 권한 이슈 회피). PHP 제어 구조 균형 검증: grep -c "<?php if" / "<?php endif" 카운트 일치 확인. tail 8 줄 시각 검증: </body></html> + <?php endif; ?> 존재 여부. style.css 도 마지막 한 규칙(.sick-sum-row.f-sick-sum) 이 잘려 있어 닫는 선언으로 마무리. 교훈 ⑧ — 마운트/원격 파일시스템 환경에서는 대용량 파일 cp 후 라인 수·바이트 수·tail 검증이 필수. 호스트 업로드 직후 curl -I 로 200 응답을 확인해 500 이면 즉시 롤백. 패치 폴더 자동 생성 직후엔 "육안 + 자동 검증" 이중 체크가 정답. 프롬프트 패턴 분석 Prompt Patterns
    애비 2026-05-12 AI 자료실