xZine 공식 웹사이트 작업
솔루션 소개- 세상에 없는 웹진/매거진 솔루션- 이제 찾아가는 시대입니다. 앉아만 있으면 그 누구도 우리의 일에 관심을 가져주지 않습니다.- AI 시대, SEO 최적화, SNS 자동 운영.. 지금 내가 바로 홍보 마케팅 전문가입니다.- 블로그 기반의 웹진편집 발행, 팔팔하게 살아있는 매거진으로 쉽게 꾸미고, 드러낼 수 있습니다.
솔루션 안내- 패키지형 구매, 패키지 당 300만원 (Pro급), 엔터프라이즈 급 문의- 인쇄용 매거진 편집, SNS 운영지원, 별도 계약 가능
템플릿- 업종별 웹진 템플릿 (내 웹진에 적용, 수정으로 간단히 발행 가능)- 업종별 매거진 템플릿 (내 매거진에 적용, 수정으로 간단히 발행 가능)- 기능별 템플릿
홍보센터- 활용사례- 사용법 강의- 사용자 포럼
커뮤니티- 소식/이벤트- 자주하는 질문- 1:1 문의
구성은 기존의 홈페이지와 별도로 웹진/매거진에 최적화 된 별도의 블로그 사이트 운영(AI 자동 글쓰기, SEO 최적화로 블로그 글 등록시 포털/AI 검색 노출, SNS 자동화로 등록된 블로글을 기반으로 인스타그램, X, 페이스북 등 버튼 하나로 자동발행, 이제 더이상 잠자고 있는 홈페이지 블로그는 가라~)이렇게 운영되는 블로그를 기반으로 원 페이지 무제한 웹진 발행, 마우스 클릭만으로 이미지, 텍스트, 블로그 게시물 연동까지, 여기에 화려한 애니메이션 까지, 전문가가 아니라도 쉽게 고품격 웹진을 발행할 수 있습니다.과거 월간지 매거진 발행은 많은 비용과 편집 전문가의 손을 빌어야 발행이 가능했습니다. 그나마 그것이 힘겨워 중단되는 시점부터 지금까지 고객과의 소통 고리는 공백으로 남겨져 왔습니다. 이제 다시 시작할 때입니다. 편집 전문가가 아니라도 마우스 몇번의 클릭만으로 살아있는 매거진을 발행할 수 있습니다. 애니메이션이 적용된 이북을 스마트폰으로 볼 수 있는 우리만의 매거진으로 이제 다시 고객의 곁으로 찾아가십시오.세상에 없는 xZine, 웹진/매거진 솔루션
이 컨셉으로 누구나 홈페이지를 보면 우리회사도, 우리 기관, 우리 대학, 우리 종교단체, 우리 동호회도 xZine을 쓰고 싶다는 마음이 들 정도로 강한 후킹포인트를 넣어 홈페이지 메인과, 솔루션 소개, 안내 등 메뉴별 콘텐츠 구성을 다크모드, 메인 색은 그린계열로, 완벽한 반응형(모바일에서는 좌우 여백사용 최소화, 가능하면 박스사용 금지, 최소폰트 15px 이상 사용으로 가독성 중심)으로 꾸며주세요. https://lucide.dev/icons/ 아이콘을 사용하고 css 애니메이션으로 과도하지 않게 자연스러운 애니메이션이 되게 html 코딩해주세요. 구조화 하지말고 css는 각 메뉴별로 <style>로 상단에 배치해주고 필요시 하단에 <script>를 포함시켜주세요.
2026.06.15
본문 및 레이어 크기 조절/드래그 좌표계 안정화 및 제약 조건 구현 계획서
이 계획서는 프레임(레이어) 크기 조절 시 세로 크기가 가변적으로 불안정하게 임의로 커지는 버그를 해결하고, 본문 텍스트가 위쪽 프레임에서 사라지고 아래쪽 프레임으로만 몰려 비어버리는 현상을 수정하며, 본문 편집/이동 시 안정성을 대폭 향상시키기 위한 작업 계획입니다.
문제 원인 분석 (Root Cause)
위쪽 프레임이 비어버리고 아래쪽 프레임으로 텍스트가 쏠리는 버그:
reflowText 함수 내에서 본문 프레임에 텍스트가 넘치는지 판단하는 기준 코드가 아래와 같았습니다: if (f.scrollHeight > f.clientHeight || wrapper.scrollHeight > f.clientHeight)
여기서 f는 레이어 프레임 자체(.layer-element)입니다. 이 레이어 프레임은 내부에 크기 조절 핸들(resize-handle, bottom: -8px 등)과 회전 핸들 등의 UI 요소를 자식으로 포함하고 있으며, overflow: visible 상태입니다.
이로 인해 텍스트가 전혀 없거나 아주 조금만 들어있어도, 하단에 튀어나온 조절 핸들 등의 위치 때문에 f.scrollHeight가 항상 f.clientHeight보다 큰 상태가 유지되었습니다.
그 결과 이진 탐색(binary search) 연산이 오동작하여 첫 프레임에는 0글자만 넣어도 오버플로우가 발생했다고 판단하게 되고, 결국 첫 프레임은 빈 프레임이 되고 모든 텍스트가 마지막 프레임(아래쪽 프레임)으로 쏠려버리는 치명적인 버그가 유발되었습니다.
해결 방법:
핸들 등 외곽 UI 요소를 포함하는 부모 프레임 f 대신, 순수하게 텍스트 단락들만 담고 있는 .text-content-wrapper(wrapper)의 scrollHeight만을 프레임 높이(f.clientHeight)와 비교하도록 수정합니다.
if (wrapper.scrollHeight > f.clientHeight)
이와 함께 CSS에서 .text-content-wrapper에 height: 100% !important;를 설정하여, 텍스트 래퍼의 높이가 부모 프레임 크기를 초과하여 임의로 늘어나지 않도록 견고하게 제어합니다.
인라인 편집 시 백스페이스로 인한 프레임 삭제 버그:
인라인 편집기(contentEditable=true) 상태에서 사용자가 백스페이스를 누를 때, activeElement가 DIV이므로 일반 입력 필드로 인식되지 못하고 레이어 삭제 이벤트가 트리거되던 문제를 방지합니다.
확대 배율(Zoom)과 크기 조절/이동의 좌표 충돌:
getBoundingClientRect()의 확대 픽셀값 대신 unscaled 고유 레이아웃 값(offsetWidth, offsetHeight 등)을 사용하여 120% 줌 상태에서도 튐 현상 없이 안정적으로 크기가 조절되도록 보정합니다.
Proposed Changes (제안된 변경 사항)
[Views Component]
[MODIFY] _magazine_editor_core.php
CSS 규칙 변경 (약 455라인):
css
.layer-element[data-type="bodytext"] .text-content-wrapper {
overflow: hidden;
height: 100% !important; /* 항상 부모 레이어 프레임 크기 내에 고정되도록 제약 */
}
Mousedown 이벤트 리스너 수정 (리사이즈 및 드래그 시작) (약 3026, 3072라인 부근):
getBoundingClientRect() 사용 부분을 제거하고 layer.offsetWidth, layer.offsetHeight, layer.offsetLeft, layer.offsetTop을 사용하여 드래그 타겟 데이터를 빌드합니다.
Mousemove 이벤트 리스너 수정 (Resizing 및 Dragging 처리) (약 3333, 3435라인 부근):
마우스 무브 변화율(dx, dy) 계산 및 부모의 너비/높이 계산(parentEl.offsetWidth/offsetHeight)을 교정하여 페이지 하단 경계를 초과하지 못하도록 최종 제한합니다.
Keydown 삭제 감지 및 삭제 로직 보정 (약 2030, 2039라인 부근):
deleteSelectedLayer() 및 keydown 핸들러를 수정하여, isContentEditable 편집 상태에서는 백스페이스/Delete 삭제 단축키가 작동하지 않도록 방어하고, 프레임 삭제 시 체인 링크를 자동 복구하고 텍스트 유실 없이 리플로우를 수행합니다.
Reflow 텍스트 높이 판단 조건 수정 (약 2405, 2437라인 부근):
reflowText 함수 내 이진 탐색 및 오버셋 표시 여부 결정 시, 핸들 위치에 영향받는 부모 높이 비교(f.scrollHeight)를 제외하고 순수한 텍스트 높이 비교(wrapper.scrollHeight > f.clientHeight)만 수행하도록 교정합니다.
Verification Plan (검증 계획)
수동 검증 및 시나리오
프레임 간 텍스트 자동 분배 검증:
2개 이상의 본문 프레임을 연결한 상태에서 첫 번째 프레임의 위치를 옮기거나 크기를 변경해 봅니다.
첫 번째 프레임에 설정한 세로 크기 한도만큼 텍스트가 정상적으로 남고, 초과하는 분량만 다음 프레임으로 자연스럽게 넘어가는지 확인합니다. 첫 번째 프레임이 텅 비어버리는 현상이 완벽하게 해결되었는지 검증합니다.
글자 지우기(Backspace) 작동 확인:
본문 텍스트 프레임 내부에서 백스페이스로 글자를 지울 때 프레임이 제거되지 않는지 확인합니다.
프레임 하단 경계 제한 및 리사이즈 조작 확인:
크기 조절 시 프레임의 하단 경계선이 페이지 밖으로 나가지 않고 걸리며, 조작감이 가변적으로 튀지 않고 1px 단위로 견고하게 고정/조절되는지 검증합니다.
2026.06.14
매거진 페이지별 편집기 기능 확장 구현 계획서
이 계획서는 브라우저에서 인디자인이나 캔바와 같은 출판 경험을 제공할 수 있도록 매거진 편집기의 고급 기능(페이지 확대, 판형별 자동 생성, 프레임 텍스트 연결 및 자동 흐름, 도형 주변 텍스트 흐름, 문자 단위 스타일 편집 툴팁)을 구현하기 위한 세부 계획입니다.
제안된 변경 사항
1. 편집기 캔버스 확대(Zoom) 및 자동 페이지 생성
다양한 모니터 화면에서 작업하기 편리하도록 기본 편집 페이지의 크기를 화면에 차게 1.5배(150%) 더 확대하여 렌더링하고, 우측 상단 툴바에 배율 선택 드롭다운(100%, 120%, 150%, 180%, 200%)을 추가합니다.
CSS transform: scale()을 사용하여 캔버스를 확대할 때 스크롤바가 정상적으로 작동할 수 있도록 #canvasFrame을 #canvasScaleContainer로 감쌉니다.
드래그(Drag), 크기 조절(Resize), 라쏘 선택(Lasso Select) 시 마우스 좌표 계산식에 확대 배율(window.editorZoom)을 반영하여, 확대/축소 상태에서도 요소 편집이 정확하게 작동하도록 좌표 계산 코드를 보정합니다.
매거진 초기 생성 시, 기존에 생성된 페이지가 없다면 설정된 전체 페이지 수(magazine_page_count)만큼 판형(A4, A5 등) 크기에 맞게 자동으로 빈 페이지들을 생성합니다.
2. 스타일 유지가 가능한 본문 프레임 연결 및 자동 흐름 (Rich HTML Reflow Chain)
본문 텍스트 프레임이 넘쳐 다음 프레임으로 연결될 때, 글자 굵기, 색상, 소제목 스타일 등이 유실되지 않도록 HTML 태그 기반의 텍스트 배분 알고리즘(Token-based HTML Splitting)을 적용합니다.
HTML 텍스트를 태그(<strong>, <span> 등)와 일반 텍스트 문자로 분리하고, 프레임 경계에서 잘린 열린 태그들을 자동으로 닫고 다음 프레임 시작에 열어주어 스타일이 유실되지 않도록 연결합니다.
전체 연결된 텍스트의 HTML 원본을 가장 첫 번째 프레임(Head Frame)의 data-chain-html 속성에 저장하여 원본 서식이 보존되도록 처리합니다.
3. 도형 프레임 주변의 본문 텍스트 흐름 (Text Wrap around Shape Frames)
도형 속성 패널에 "프레임 고정 (도형 주변으로 본문 흐름)" 체크박스를 추가합니다.
도형의 위치를 조정하거나 크기를 바꿀 때(mouseup 이벤트 시) 및 텍스트 자동 흐름이 계산될 때, 도형과 본문 텍스트 레이어의 중첩 영역을 계산합니다.
중첩 영역 크기만큼의 Float Spacer(CSS float 속성을 가진 빈 div)를 본문 텍스트 안에 동적으로 삽입하여 글자들이 도형 주변을 자연스럽게 피해 흐르도록 구현합니다. 원형 도형의 경우 CSS shape-outside: circle(50%)을 지정하여 텍스트가 둥글게 감싸며 흐르도록 합니다.
4. 문자 단위 서식 편집 (인라인 편집 및 툴팁 팝업)
본문 텍스트 프레임을 더블클릭하면 해당 프레임이 바로 편집 가능한 상태(contentEditable = true)가 되도록 전환합니다.
텍스트 영역 내부에서 마우스로 범위를 지정(드래그)하면, 선택 영역 바로 위에 서식 편집용 툴팁 팝업(#text-style-tooltip)이 표시되도록 합니다.
툴팁에는 다음과 같은 단추들을 구성합니다:
굵게 (Bold) / 기울임 (Italic) / 밑줄 (Underline)
글자 색상 (Color Picker)
글자 크기 드롭다운 (12px ~ 36px)
스타일 템플릿 (소제목, 강조 등)
편집이 끝나고 프레임 외부를 클릭하여 포커스를 잃으면(blur), 자동으로 전체 HTML을 병합하고 다음 연결 프레임들로 텍스트를 다시 흐르게 한 뒤 상태를 저장합니다.
개별 문자 서식은 글자 자체에 style 속성으로 적용되므로, 나중에 전체 텍스트 레이어의 기본 글꼴이나 글자 크기를 변경하더라도 개별 지정된 글자 속성은 유지됩니다.
[Views Component]
[MODIFY] _magazine_editor_core.php
#canvasFrame을 #canvasScaleContainer 내부로 감싸는 구조 변경.
인라인 편집용 클래스, 스타일 툴팁 UI 및 텍스트 흐름을 위한 CSS 정의 추가.
상단 툴바에 Zoom(배율) 드롭다운 메뉴 추가 및 setZoom() 함수 구현.
DOMContentLoaded 핸들러에서 초기 페이지 자동 생성 및 기본 1.5배 줌 초기화 적용.
페이지 넘버 표시 영역 아래에 개별 [새 페이지 추가] 및 [페이지 삭제] 버튼 삽입.
HTML 토큰 구조 기반의 새로운 reflowText 함수 구현.
도형과의 겹침 영역을 계산하고 float spacer를 주입하는 adjustTextWrap() 함수 추가.
mouseup 시점에 도형의 프레임 고정 상태에 맞춰 주변 본문을 갱신하는 트리거 바인딩.
본문 더블클릭 시 편집 모드 활성화 및 선택 영역 감지 기반의 #text-style-tooltip 툴팁 표시 제어 바인딩.
도형 속성 패널 내 "프레임 고정 (도형 주변으로 본문 흐름)" 체크박스 HTML 삽입 및 속성 저장 로직 연동.
검증 계획 (Verification Plan)
수동 검증
페이지 초기화: 새 매거진을 열었을 때 설정한 판형으로 1.5배 기본 확대된 페이지들이 깔끔하게 노출되는지 확인.
텍스트 프레임 연결 흐름: 긴 텍스트를 입력하고 여러 개의 본문 프레임을 연결하였을 때 텍스트가 잘 나뉘어 흐르는지 확인. 소제목 서식을 지정한 텍스트가 다음 프레임으로 밀려나더라도 소제목 서식이 그대로 적용되어 있는지 확인.
도형 주변 흐름: 사각형 및 원형 도형을 본문 텍스트 위에 얹고 "프레임 고정"을 켰을 때 텍스트가 도형 가장자리를 피해서 흘러가는지 확인.
인라인 스타일 유지: 특정 텍스트 블록을 드래그하여 글자 크기, 굵기, 색상을 수정한 후 전체 레이어의 폰트를 바꾸어도 개별 지정된 개성 있는 글자 스타일이 그대로 보존되는지 확인.
2026.06.14
매거진 관리 기능 복제 (웹진 기능 기반)
목표
현재 작동 중인 웹진 관리의 모든 기능(데이터베이스, 컨트롤러, 뷰, 에디터 등)을 매거진 관리로 복제합니다. 기본적인 편집 기능은 동일하게 유지하되, 추후 매거진만의 고유한 기능(페이지별 관리 등)을 독립적으로 개발할 수 있도록 구조를 분리합니다.
제안된 변경 사항
1. 데이터베이스 구조 생성
웹진과 동일한 구조의 매거진 전용 테이블을 생성합니다.
magazines 테이블 생성 (webzines 테이블 구조와 동일)
magazine_categories 테이블 생성 (webzine_categories 테이블 구조와 동일)
2. 백엔드 (Controller & Routing)
Controller 복제: src/Controllers/WebzineAdminController.php를 복사하여 MagazineAdminController.php를 생성합니다.
내부 로직의 DB 참조를 magazines, magazine_categories로 변경.
라우팅 및 리다이렉션 경로를 admin/magazine으로 변경.
Routing 수정 (public/index.php):
기존에 WebzineAdminController를 가리키고 있던 admin/magazine 및 admin/magazine/editor 라우트를 새로운 MagazineAdminController로 연결합니다.
admin/magazine/category-save, admin/magazine/update, admin/magazine/delete 등 매거진 전용 라우트를 추가합니다.
매거진 에디터 저장용 API 라우트(admin/api/magazine/save)를 추가합니다.
3. 프론트엔드 (Admin Views)
뷰 파일을 완전히 분리하여 향후 매거진 페이지별 관리 기능을 추가할 때 웹진 쪽에 영향을 주지 않도록 합니다.
목록 페이지: views/admin/webzine_list.php ➔ views/admin/magazine_list.php로 복사 (내부 텍스트 "웹진" ➔ "매거진" 수정)
에디터 껍데기: views/admin/webzine_editor.php ➔ views/admin/magazine_editor.php로 복사
에디터 코어 스크립트: views/admin/_webzine_editor_core.php ➔ views/admin/_magazine_editor_core.php로 복사
저장 API 엔드포인트를 /admin/api/magazine/save로 변경.
사용자 검토 필요 (User Review Required)
IMPORTANT
데이터베이스 테이블 분리 현재 제안된 방식은 magazines와 magazine_categories라는 완전히 새로운 테이블을 생성하는 방식입니다. 만약 기존 webzines 테이블에 type 컬럼을 추가하여 구분하는 방식을 원하신다면 알려주시기 바랍니다. 하지만 향후 매거진에서 "페이지별 관리" 기능 등 구조적 차이가 발생한다면 테이블을 물리적으로 분리하는 것이 훨씬 안정적이며, 현재 계획도 분리하는 방향으로 설정되어 있습니다.
검증 계획 (Verification Plan)
매거진 관리 메뉴 접속 시 정상적으로 목록이 표시되는지 확인.
매거진 카테고리 추가/삭제 및 새 매거진 생성 테스트.
매거진 에디터 접속 시 웹진과 동일한 에디터가 표시되며 모듈들이 정상 작동하는지 확인.
저장 버튼 클릭 시 admin/api/magazine/save로 성공적으로 저장되는지 확인.
2026.06.14
게시물 모듈 구현 계획
본 문서에서는 http://localhost/xzine.kr/admin/webzine/editor?id=3의 웹진 편집기 프레임워크 내에 게시물 모듈을 구현하기 위한 계획을 정리합니다.
User Review Required
IMPORTANT
표시 갯수 속성 추가 요구사항에 "표시갯수보다 많을 경우", "표시갯수만큼 세로배열" 등의 조건이 있습니다. 이를 위해 속성 패널(게시물 모듈 선택 시)에 표시 갯수 (PC) 와 표시 갯수 (모바일) 입력란을 추가하려고 합니다. 기본값으로 카드#1형 등에서 말씀하신 PC 3 / 모바일 1 등의 값을 설정할 수 있도록 할 예정입니다.
WARNING
오디오 첨부 판별 방식 posts 테이블에는 오디오 여부를 직접 나타내는 필드가 없기 때문에, post_files 테이블에 업로드된 파일 확장자가 .mp3, .wav 등인지 검사하여 파랑색 스피커 아이콘을 표시하도록 구현하겠습니다.
Proposed Changes
[Controller]
WebzineAdminController.php 내의 API를 수정하여 게시물 데이터와 함께 유튜브 링크 및 오디오 첨부 여부를 반환하도록 합니다.
[MODIFY] WebzineAdminController.php
apiGetPosts() 메서드 수정
SELECT 쿼리에 youtube_url 필드 추가
각 게시물(post_id)에 대해 post_files 테이블을 조회하여 확장자가 오디오 파일인지 확인 후 has_audio 플래그를 추가.
[Editor Core / Views]
_webzine_editor_core.php를 수정하여 다양한 표시형태(UI)와 무한스크롤, 썸네일 아이콘을 구현합니다.
[MODIFY] _webzine_editor_core.php
속성 패널 업데이트 (prop-module-panel)
"게시물 모듈" 선택 시 보여지는 패널에 "표시 갯수(PC)" 및 "표시 갯수(모바일)" 입력 컨트롤 추가
데이터 로딩 및 속성 저장 업데이트 (fetchPostsForBoard, applyPostStyle)
선택된 표시 갯수를 data-pc-count, data-mob-count 등의 속성으로 layer-element에 저장
렌더링 로직 업데이트 (renderPostElement)
공통 썸네일 및 아이콘 로직:
youtube_url이 있으면 썸네일 중앙에 빨간색 플레이 아이콘 (ph-fill ph-play-circle) 표시
has_audio가 참이면 제목 앞에 파란색 스피커 아이콘 (ph-fill ph-speaker-high) 표시
리스트형: 제목과 [작성일]을 한 줄씩 표시. (게시물이 표시 갯수보다 많으면 세로 무한 스크롤 스와이퍼 적용)
웹진#1형: 좌측 50% 썸네일, 우측 50% 텍스트. slidesPerView: 1 설정으로 1건씩 좌우 무한 슬라이드 및 하단 도트(Pagination) 추가.
웹진#2형: 좌측 썸네일, 우측 텍스트로 구성되며 스크롤 없이 표시갯수만큼 세로로 나열.
웹진#3형: 좌측 텍스트, 우측 썸네일로 구성되며 스크롤 없이 표시갯수만큼 세로로 나열.
카드#1형: 썸네일 / 제목 / 내용 3줄 구성. Swiper를 사용해 PC/모바일에 맞춰 표시 갯수 설정, 개수 초과 시 무한 루프 및 스와이프 기능 활성화.
카드#2형: 썸네일 / 제목 구성. Swiper를 사용해 PC/모바일에 맞춰 표시 갯수 설정, 개수 초과 시 무한 루프 및 스와이프 기능 활성화.
Verification Plan
Automated Tests
없음
Manual Verification
관리자 페이지로 로그인 후 웹진 편집기(id=3)에 접속합니다.
모듈을 추가하고 "게시물 모듈"로 변경합니다.
게시판을 선택하고 속성 창에서 각 스타일(리스트형, 웹진형 1/2/3, 카드형 1/2)을 차례대로 변경해 봅니다.
표시 갯수보다 많이 체크하여 스크롤(상하/좌우 무한 스크롤)이 정상적으로 동작하는지 확인합니다.
유튜브 링크가 있거나 오디오 파일이 첨부된 게시물에 대해 올바른 아이콘(빨강/파랑)이 표시되는지 확인합니다.
2026.06.14
단일 페이지 방식의 웹진 에디터 개편 및 UI 최적화
웹진의 본질적인 특성(가로폭 고정, 세로로 길게 스크롤되는 단일 페이지)에 맞추어 에디터의 구조를 재편하고, 사용성을 높이기 위해 불필요한 UI를 제거하며 필요한 애니메이션 기능을 가볍게 복구합니다.
User Review Required
IMPORTANT
애니메이션 구현 방식 확인이전에는 GSAP이라는 무거운 라이브러리를 사용해 애니메이션(타임라인 등)을 구현했으나, 이번에는 GSAP 없이 바닐라 자바스크립트(Vanilla JS)와 CSS Transition을 활용하여 스크롤 시 화면에 나타나는(Scroll Reveal) 형태의 가벼운 '상하좌우 슬라이드/페이드인' 애니메이션으로 대체하려고 합니다. 이렇게 진행해도 괜찮으신가요?
Proposed Changes
views/admin/_webzine_editor_core.php
1. 에디터 캔버스 구조 변경 (단일 페이지화)
최근 추가했던 '슬라이드(페이지) 추가/삭제/이전/다음' 네비게이션 UI를 상단 바에서 제거합니다.
pages 배열 대신 단일 캔버스의 HTML 데이터를 저장하는 방식으로 되돌리거나, pages 배열을 사용하되 UI상에서는 단일 페이지만 편집하도록 고정합니다.
캔버스 너비는 webzine_canvas_width 설정값을 우선적으로 반영하여 에디터 뷰에 적용합니다. (세로 높이는 콘텐츠에 따라 늘어나도록 하거나, 에디터 영역 내에서 스크롤되도록 처리)
2. 상단 및 좌측 툴바 다이어트
상단 툴바: '요소삭제' 버튼 삭제(Delete 키로 대체됨), '전체저장' 버튼 삭제(우측 상단의 기본 저장 버튼 및 자동저장 사용). Undo/Redo 버튼은 좌측에 배치하고 PC/Mobile 화면 모드 버튼은 우측에 유지합니다.
좌측 툴바: '배경' 요소 추가 버튼을 삭제합니다. (배경색이 필요한 경우 도형을 추가하여 설정하도록 유도)
3. 속성 패널 다이어트 및 애니메이션 복구
우측 속성 패널에서 '배경' 탭/패널을 완전히 삭제합니다.
삭제했던 '애니메이션' 탭을 다시 추가합니다.
GSAP 없이 CSS 클래스 기반으로 요소의 나타남(Fade In, Slide Up/Down/Left/Right)을 설정할 수 있도록, 애니메이션 종류, 재생 시간(Duration), 딜레이(Delay)를 설정하는 UI를 부활시킵니다.
뷰어(프론트엔드)에서 스크롤을 내릴 때 해당 요소가 화면에 나타나면 CSS 기반으로 애니메이션이 재생되도록 (Intersection Observer 활용) 구현합니다.
4. JavaScript 오류 수정
에디터 내 변수 중복 선언(Identifier 'canvas' has already been declared) 오류를 수정합니다. (Scope 문제 해결)
Unexpected end of input 구문 오류를 찾아 수정합니다.
templates/default_light/webzine/view.php
프론트엔드 뷰어에서도 다중 슬라이드(Swiper.js) 방식을 제거하고, 단일 페이지 안에서 가로폭을 맞춘 상태로 세로 스크롤이 되도록 구조를 단순화합니다.
스크롤 시 요소들이 지정된 애니메이션 속성에 맞추어 등장하도록 가벼운 JS(Intersection Observer) 스크립트를 추가합니다.
Verification Plan
Manual Verification
에디터 진입 시 JavaScript 오류가 발생하지 않는지 확인합니다.
불필요한 슬라이드 탭 및 버튼들이 사라지고, 캔버스가 지정된 가로폭을 유지하며 세로로 자유롭게 늘어나는지 확인합니다.
우측 애니메이션 탭에서 속성을 설정한 뒤, 저장 후 사용자 화면(프론트)에서 스크롤을 내릴 때 요소가 정상적으로 나타나는지 확인합니다.
2026.06.10
웹진/매거진 에디터 및 뷰어 아키텍처 재검토 계획
현재 xslide 모듈(GSAP 애니메이션 기반)을 웹진 에디터에 그대로 가져와 사용하면서 구조가 복잡해지고 무거워진 상태입니다. 웹진의 본질(상하좌우 자연스러운 페이지 전환과 콘텐츠 전달)에 집중하기 위해 다음과 같이 구조를 전면 개편할 것을 제안합니다.
1. 렌더링 엔진 변경 (GSAP 제거 -> Swiper.js 도입)
제거: 무겁고 복잡한 타임라인 애니메이션을 위한 GSAP 라이브러리를 제거합니다.
도입: 모바일 터치 스와이프와 상하좌우 부드러운 전환(Slide, Fade 등)에 최적화된 Swiper.js를 웹진/매거진의 코어 뷰어 엔진으로 사용합니다.
2. 웹진 섹션/블록 JSON 데이터 구조 확정
복잡한 애니메이션 속성을 덜어내고, "페이지(Section) 단위"의 직관적인 JSON 구조를 설계합니다.
json
{
"canvasWidth": 1000,
"pages": [
{
"id": "page_1",
"background": {
"type": "color", // color, image, gradient
"value": "#ffffff"
},
"transition": "vertical", // vertical, horizontal, fade
"elements": [
{
"id": "elem_1",
"type": "text", // text, image, shape, button, video
"content": "<h1>웹진 타이틀</h1>",
"position": { "x": 100, "y": 200, "width": 800, "height": 100 },
"style": {
"fontFamily": "Pretendard",
"fontSize": 48,
"color": "#333333",
"textAlign": "center"
}
}
]
}
]
}
3. 에디터 UI/UX 단순화 (webzine_editor.php)
애니메이션 탭 삭제: 우측 속성 패널에서 타임라인, 애니메이션 설정 탭을 완전히 제거합니다.
페이지(슬라이드) 관리 강화: 하단이나 좌측에 '페이지 썸네일 리스트'를 두고, 슬라이드(페이지) 단위로 추가/삭제/순서변경(Sortable)을 직관적으로 할 수 있게 만듭니다.
프레임 캔버스: 요소의 드래그 앤 드롭, 리사이징 기능은 유지하되, 저장 시 위 JSON 구조로 깔끔하게 떨어지도록 파서 로직을 다시 작성합니다.
4. editor_xzine.php 의 iframe 방식 제거
게시판에서 웹진 형태의 글을 작성할 때 사용되는 editor_xzine.php가 무거운 public/xslide/index.html을 iframe으로 불러오고 있습니다.
개선: iframe을 제거하고, webzine_editor.php에서 구축한 가벼운 순수 JS 기반의 에디터 모듈을 컴포넌트화하여 직접 삽입합니다. 이렇게 하면 사이트 전체의 톤앤매너가 일치하고 데이터 연동(PostMessage 대신 직접 폼 서밋)이 훨씬 안정적입니다.
5. 향후 매거진(Magazine) 뷰어 확장에 대비
웹진(단일 이슈)과 매거진(여러 이슈의 모음) 뷰어 모두 동일한 JSON을 파싱하여 Swiper.js 로 렌더링하도록 Viewer 클래스를 분리하여 개발합니다. 이는 추후 독자적인 뷰어 페이지(/viewer?id=3)를 구축할 때 코드 재사용성을 극대화합니다.
User Review Required
IMPORTANT
이 작업은 webzine_editor.php 의 2,900줄이 넘는 코드를 크게 다이어트하고 로직을 재작성하는 대규모 리팩토링입니다.
애니메이션(요소가 날아오거나 페이드인 되는 등) 기능을 완전히 배제하고 페이지 전환(스와이프)만 지원하는 것에 동의하시나요?
제안된 JSON 구조와 개발 방향에 수정하고 싶은 부분이 있으신지 확인 부탁드립니다.
2026.06.10
업로드 디렉토리 구조 개편 및 파일 삭제 로직 추가
현재 모든 업로드 파일이 public/uploads/ 디렉토리에 혼재되어 저장되고 있습니다. 추후 데이터 관리가 용이하도록 파일 유형 및 목적에 따라 서브 디렉토리에 저장되도록 구조를 개편하고, 게시물이나 설정이 삭제될 때 관련된 파일(첨부파일, 썸네일, 본문 삽입 이미지 등)도 서버에서 물리적으로 삭제되도록 개선합니다.
변경되는 업로드 디렉토리 구조
새로운 파일이 업로드될 때 목적에 맞는 디렉토리가 없으면 자동으로 생성(mkdir)한 후 저장합니다. 기존에 업로드된 파일들은 호환성을 위해 이동하지 않고 그대로 둡니다.
에디터 삽입 이미지: public/uploads/editor_images/
에디터 오디오 파일: public/uploads/audio/
게시판 첨부파일 및 썸네일: public/uploads/board_attachments/
프로필 이미지: public/uploads/profile_images/
사이트 설정 에셋 (로고, 파비콘, 배너, 팝업 등): public/uploads/site_assets/
파일 삭제 연동 처리 (Cascading Deletion)
게시물, 팝업, 게시판 등이 삭제될 때 연관된 파일들을 식별하여 서버 저장소에서 함께 삭제합니다.
게시물 삭제 시 (PostController / AdminController)
게시물에 등록된 썸네일 이미지 삭제
게시물에 첨부된 일반 파일들 (post_files 테이블 연동) 삭제
게시물 본문(content)에 삽입된 에디터 업로드 이미지 및 오디오 URL을 추출하여 물리 파일 삭제
팝업 삭제 시 (AdminController::popupsDelete)
팝업에 등록된 이미지 파일 삭제
게시판 삭제 시 (AdminController::boardsDelete)
해당 게시판에 속한 모든 게시물을 순회하며 관련 파일 일괄 삭제 후 게시물 삭제
작업 대상 컴포넌트
1. src/Controllers/AdminController.php
[MODIFY] AdminController.php
uploadImage(): 확장자를 체크하여 이미지면 editor_images/, 오디오면 audio/ 디렉토리에 저장되도록 수정합니다.
uploadFile(): 저장 위치를 board_attachments/ 로 변경합니다.
handleFileUploads(): 다중 첨부파일을 board_attachments/에 저장하도록 변경합니다.
delete($id): 삭제 전 해당 Post의 썸네일, post_files, 그리고 content 내의 업로드 파일 URL 정규식 추출을 통한 물리 파일 삭제 로직을 추가합니다.
boardsDelete($id): 게시판 삭제 시 단순 쿼리가 아닌 소속 게시물별로 파일 삭제 로직을 먼저 수행하도록 수정합니다.
popupsSave() & popupsDelete(): 팝업 이미지 업로드 경로를 site_assets/로 변경하고 삭제 시 파일 삭제 로직을 추가합니다.
2. src/Controllers/TenantAdminController.php (및 _recovered.php)
[MODIFY] TenantAdminController.php
uploadFile(): 로고, 파비콘, 슬라이드 이미지 등이 저장되는 경로를 public/uploads/site_assets/로 변경합니다.
삭제 기능이 존재할 경우 파일 삭제 로직을 보완합니다.
3. src/Controllers/AuthController.php
[MODIFY] AuthController.php
회원정보 수정 시 업로드되는 프로필 이미지를 public/uploads/profile_images/ 디렉토리로 저장하도록 변경합니다.
User Review Required
IMPORTANT
기존 파일 호환성: 디렉토리 구조가 변경된 이후에 새로 업로드되는 파일들에 대해서만 새 디렉토리에 저장됩니다. 기존 파일들은 경로를 강제로 바꾸지 않으므로 사이트 운영상 깨지는 이미지는 발생하지 않습니다.
본문 에디터 이미지 삭제 로직: 게시물 삭제 시 본문에 포함된 editor_images/와 audio/ 파일들이 함께 삭제됩니다. 만약 동일한 이미지를 여러 게시물에서 복사&붙여넣기로 공유해서 쓰고 계신다면 삭제 시 다른 게시물에서도 보이지 않게 될 수 있습니다.
일반적인 에디터 사용 패턴(게시물마다 개별 업로드)을 따른다면 문제가 없습니다.
2026.06.10