#666 57개의 스레드 ✕ 해제
이온디
이온디 1개월 전
시리즈 ← 이전 편 · 다음 편 → 바이브코딩의 위험성 ② — 범인은 autogenerate였다 1091줄짜리 시한폭탄을 만든 건 사람이 아니라 자동화 도구 자신이었다. — 시리즈 2편 / 진짜 원인 발견과 해체 작업 Alembic autogenerate가 그러는 이유 Alembic은 SQLAlchemy 기반 프로젝트의 마이그레이션 도구다. alembic revision --autogenerate라는 명령을 치면, 현재 모델 정의(SQLAlchemy Base.metadata)와 실제… 시리즈 ← 이전 편 · 다음 편 → 바이브코딩의 위험성 ② — 범인은 autogenerate였다 1091줄짜리 시한폭탄을 만든 건 사람이 아니라 자동화 도구 자신이었다. — 시리즈 2편 / 진짜 원인 발견과 해체 작업 Alembic autogenerate가 그러는 이유 Alembic은 SQLAlchemy 기반 프로젝트의 마이그레이션 도구다. alembic revision --autogenerate라는 명령을 치면, 현재 모델 정의(SQLAlchemy Base.metadata)와 실제 DB 스키마를 비교해서 그 차이를 마이그레이션 파일로 자동 생성해준다. 컬럼 추가, 인덱스 추가, 테이블 추가 같은 변경을 사람이 손으로 SQL을 적지 않아도 되게 해주는 편리한 도구다. 문제는 이 비교의 방향성이다. Alembic은 "모델에는 있는데 DB에 없는 것"을 추가 작업으로 인식하고, 동시에 "DB에는 있는데 모델에 없는 것"을 삭제 작업으로 인식한다. 후자가 함정이다. Base.metadata에 어떤 모델이 등록되지 않은 상태에서 autogenerate를 돌리면, 실제로는 코드 어딘가에 살아 있는 모델이라도 alembic 입장에선 "사라진 테이블"이 된다. 그러면 친절하게 op.drop_table('...')을 자동으로 만들어준다. alembic/env.py를 열어봤다. from app.models import document, member, comment, file, module, site_config, site from app.models import hosting_site, hosting_subscription, project, inquiry, member_profile from app.models import sale_product, order, revenue, settlement from app.models import project_issue, kakao_chat, project_billing, project_file, project_comment 손으로 적은 import가 21개. 그런데 app/models/ 디렉터리에는 모델 파일이 57개. 빠진 36개의 정체: audit_log.py bank_transaction.py blog_post.py client.py hosting_setup_log.py marketing.py notification_log.py spam.py wiki.py analytics_report.py module_group.py newsletter.py ... 폭탄 마이그레이션이 DROP하려던 그 테이블들이, 정확히 env.py에서 import 누락된 모델 파일들과 일치했다. .title { font-size: 22px; font-weight: 700; fill: #111; } .subtitle { font-size: 14px; fill: #666; } .label { font-size: 14px; fill: #222; font-weight: 500; } .num { font-size: 28px; font-weight: 700; } .small { font-size: 12px; fill: #555; } .bad { fill: #c83737; } .good { fill: #1f7a3f; } .arrow { stroke: #777; stroke-width: 1.6; fill: none; } .arrow-bad { stroke: #c83737; stroke-width: 1.8; fill: none; stroke-dasharray: 4 3; } .arrow-good { stroke: #1f7a3f; stroke-width: 1.8; fill: none; } .box { stroke: #ccc; stroke-width: 1; fill: #fff; rx: 8; } .box-bad { stroke: #e0a8a8; stroke-width: 1; fill: #fff5f5; rx: 8; } .box-good { stroke: #a8d4b8; stroke-width: 1; fill: #f3faf5; rx: 8; } .row-label{ font-size: 13px; fill: #888; font-weight: 600; letter-spacing: 1px; } env.py의 침묵하는 누락 손으로 적은 import 21개 vs 디렉터리에 실재하는 모델 57개 BEFORE — 사고 시점 app/models/ 57 실재 모델 파일 env.py 21 손으로 적은 import Base.metadata 21 등록된 테이블 autogenerate −36 DROP TABLE 자동 생성 metadata에 없는 36개 모델은 alembic 입장에서 "사라진 테이블"로 보임 → 1091줄짜리 폭탄 마이그레이션 파일이 자동 생성됨 AFTER — env.py 자동 import 적용 app/models/ 57 실재 모델 파일 env.py auto pkgutil.iter_modules Base.metadata 78 전체 자동 등록 autogenerate 0 false-DROP 차단 새 모델 파일을 추가해도 env.py에 손대지 않아도 됨 — 잊을 수 있는 자리 자체가 사라짐 env.py에 손으로 적은 21개 import vs 디렉터리에 실재하는 57개 모델 — 그 격차가 폭탄을 만든다. 원인 확정. 사람의 게으름이 아니라, 시스템 설계의 문제였다. 새 모델을 추가할 때마다 env.py에 한 줄을 손으로 더 적어야 하는 구조 자체가, 언젠가 누락이 생길 시한폭탄이었다. 백업이 가장 먼저 원인을 알았다고 해서 바로 수정 작업에 들어가면 안 된다. binlog가 꺼진 상태에서, 잘못된 한 줄이 더 큰 사고를 만들 수도 있다. 이번 작업의 모든 안전성은 현재 시점 백업 한 장에 달려 있었다. 백업 스크립트를 짜기 전에 한 가지 고려사항이 있었다 — eondcms는 트래픽이 꽤 있는 사이트라 카운터·통계·API 호출 로그 테이블 3개가 매우 크다. 이걸 그대로 풀 덤프하면 시간도 오래 걸리고 용량도 부담스럽다. 이 3개는 데이터는 빼고 스키마만 보존하기로 했다. 복원 후에도 빈 테이블 껍데기는 만들어져야 ORM이 INSERT를 시도할 때 에러가 나지 않으니까. 핵심 패턴은 단순하다. mysqldump를 두 번 호출해서 stdout을 이어붙인 뒤 한 번에 gzip으로 압축한다. 결과물은 단일 파일. { mysqldump --single-transaction --routines --triggers --events \ --default-character-set=utf8mb4 --hex-blob \ --ignore-table=$DB.xe_counter_log \ --ignore-table=$DB.xe_api_call_logs \ --ignore-table=$DB.xe_stats_log \ "$DB" mysqldump --no-data --default-character-set=utf8mb4 \ "$DB" xe_counter_log xe_api_call_logs xe_stats_log } | gzip > "$OUT_FILE" 스크립트 첫 줄에 set -euo pipefail을 박아두는 게 중요하다. 한 줄이라도 실패하면 즉시 멈추도록. 백업이 도중에 깨졌는데 "성공"이라고 착각하는 사고가 가장 흔하니까. 결과물은 압축 후 37MB. 압축 전 원본 기준 약 300~450MB 추정. 이걸 웹에서 절대 보이지 않는 디렉터리에 저장하는 것도 중요했다. 백업 파일에는 비밀번호 해시·세션 토큰·이메일 같은 민감정보가 그대로 들어 있어서, "private"이라는 이름의 디렉터리에 둔다고 해도 실제로 웹서버 설정이 막아주지 않으면 누구나 다운로드 가능하다. env.py 자동화 — 사람의 주의력에 의존하지 않기 이제 진짜 수정. env.py를 손으로 import 목록을 유지하는 방식이 사고의 근본 원인이라면, 답은 자동 import다. 새 모델 파일이 추가될 때마다 자동으로 등록되도록 바꾸면, 누구도 손으로 적는 걸 까먹을 수 없다. import importlib import pkgutil import app.models as _models_pkg for _info in pkgutil.iter_modules(_models_pkg.__path__): if _info.name.startswith("_") or _info.name == "base": continue importlib.import_module(f"app.models.{_info.name}") pkgutil.iter_modules는 패키지 안의 모든 모듈을 순회해주는 표준 라이브러리. 베이스 모듈만 제외하고 전부 import한다. 검증 결과 55개 모듈이 자동 로드되어 78개 테이블이 metadata에 등록되었다. 이전 21개 import로 잡지 못했던 36개 모델이 이번에 모두 합류했다. 이 변경 한 줄이 의미하는 바는 명확하다. 앞으로 누가 새 모델 파일을 만들어도 env.py를 손대지 않아도 된다. autogenerate가 잘못된 DROP을 만들 가능성이 구조적으로 차단된다. 폭탄 마이그레이션 무력화 남은 일은 1091줄짜리 폭탄을 어떻게 처리할 것인가였다. 선택지는 두 개: A. 파일 자체를 삭제 — 깔끔해 보이지만, alembic 입장에선 chain의 한 노드가 사라지는 것이라 후속 마이그레이션이 깨진다. B. 내용만 비우기 — revision과 down_revision 필드는 그대로 두고, upgrade()와 downgrade() 함수 본문을 pass로 교체한다. chain은 그대로, 동작만 무력화. B를 골랐다. 사고 경위와 신원 보존이 되는 주석을 헤더에 적어두고: """add_random_order_to_board_config (NEUTRALIZED) ⚠️ 이 마이그레이션은 의도적으로 비워졌습니다 (2026-04-28). 사고 경위: alembic env.py가 app/models/ 아래 일부 모델만 import하던 상태에서 --autogenerate 가 실행되어, 누락된 36개 모델이 "사라진 테이블"로 인식 → 30+ 테이블 DROP을 자동 생성한 1091줄짜리 폭탄 마이그레이션이 됨. """ def upgrade() -> None: pass def downgrade() -> None: pass 이 주석은 미래의 누군가가 — 6개월 뒤의 자기 자신을 포함해서 — "왜 이 파일이 비어있지?" 라고 물었을 때, 짧은 단서가 되어줄 것이다. 코드 자체가 자기 역사를 설명할 수 있어야 한다. 안전한 적용 절차 수정한 파일들을 production에 보내기 전, 한 가지 더 확인할 게 있었다. dry-run. alembic upgrade --sql은 offline 모드로 동작해서, DB에 연결조차 하지 않고 실행될 SQL을 텍스트로만 출력한다. 진짜 실행 전에 무엇이 production에서 일어날지 미리 보여주는 안전 기능이다. alembic upgrade --sql c3d4e5f6a1b2:head | grep -E "DROP TABLE|TRUNCATE" \ && echo "❌ 아직 위험" \ || echo "✅ no destructive ops" grep이 무언가 잡히면 → 위험. 아무것도 안 나오면 → 안전. 아주 단순하지만 마음 편한 검증이다. 처음 production에서 dry-run을 돌렸을 때는 DROP 문이 좌라락 출력되었다. 잠깐 가슴이 철렁했지만, 곧 이유를 알았다 — 우리가 로컬에서 비운 두 파일이 production에는 아직 안 갔던 것. rsync로 동기화 후 재실행: Running upgrade c3d4e5f6a1b2 -> a6ae466f8b07, add_random_order_to_board_config (NEUTRALIZED) ✅ no destructive ops (NEUTRALIZED) 표시가 떠 있는 게 결정적 증거였다. production이 우리가 비운 새 파일을 정상적으로 읽고 있다는 뜻. 이제 진짜로 적용해도 안전하다. $ alembic upgrade head INFO Running upgrade c3d4e5f6a1b2 -> a6ae466f8b07, add_random_order_to_board_config (NEUTRALIZED) $ alembic current a6ae466f8b07 (head) DB 변경 0건, 데이터 손실 0건, 다운타임 0초. alembic_version 테이블의 한 행만 갱신되었다. 폭탄 해체 완료. 다음 편 — ③ 바이브코딩의 위험과 안전망 — 사람은 잊지만 코드는 잊지 않는다
이온디
이온디 6개월 전
<style> @import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css'); .page { max-width: 800px; margin: 0 auto; padding: 60px 50px; } … <style> @import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css'); .page { max-width: 800px; margin: 0 auto; padding: 60px 50px; } @media print { .page { padding: 40px; } .page-break { page-break-before: always; } } /* Header */ .header { text-align: center; margin-bottom: 50px; padding-bottom: 40px; border-bottom: 3px solid #2563eb; } .logo { width: 120px; margin-bottom: 20px; } .header h1 { font-size: 32px; font-weight: 700; color: #1a1a1a; margin-bottom: 10px; } .header .subtitle { font-size: 18px; color: #2563eb; font-weight: 500; } .header .company { margin-top: 20px; font-size: 14px; color: #666; } /* Section */ .section { margin-bottom: 45px; } .section h2 { font-size: 22px; font-weight: 700; color: #1a1a1a; margin-bottom: 20px; padding-bottom: 10px; border-bottom: 2px solid #e5e7eb; } .section h3 { font-size: 18px; font-weight: 600; color: #374151; margin: 25px 0 15px 0; } .section p { margin-bottom: 15px; color: #374151; } /* Problem List */ .problem-list { list-style: none; padding: 0; } .problem-list li { padding: 12px 0 12px 30px; position: relative; border-bottom: 1px solid #f3f4f6; } .problem-list li:before { content: "⚠️"; position: absolute; left: 0; } /* Comparison Table */ .comparison-table { width: 100%; border-collapse: collapse; margin: 20px 0; } .comparison-table th, .comparison-table td { padding: 15px; text-align: left; border: 1px solid #e5e7eb; } .comparison-table th { background: #f8fafc; font-weight: 600; color: #1a1a1a; } .comparison-table td:last-child { background: #eff6ff; color: #1e40af; font-weight: 500; } /* Highlight Box */ .highlight-box { background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%); border-left: 4px solid #2563eb; padding: 25px; margin: 25px 0; border-radius: 0 8px 8px 0; } .highlight-box p { margin: 0; font-size: 16px; color: #1e40af; font-weight: 500; } /* Speed List */ .speed-list { list-style: none; padding: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; margin: 20px 0; } .speed-list li { background: #f0fdf4; padding: 15px; border-radius: 8px; text-align: center; border: 1px solid #bbf7d0; } .speed-list li strong { color: #15803d; } /* Demo Table */ .demo-table { width: 100%; border-collapse: collapse; margin: 20px 0; } .demo-table th, .demo-table td { padding: 15px; text-align: left; border-bottom: 1px solid #e5e7eb; } .demo-table th { font-weight: 600; width: 30%; } .demo-table a { color: #2563eb; text-decoration: none; } /* Pricing Card */ .pricing-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin: 25px 0; } .pricing-card { border: 2px solid #e5e7eb; border-radius: 12px; padding: 25px; text-align: center; } .pricing-card.featured { border-color: #2563eb; background: #eff6ff; } .pricing-card h4 { font-size: 16px; color: #374151; margin-bottom: 10px; } .pricing-card .price { font-size: 28px; font-weight: 700; color: #1a1a1a; margin-bottom: 15px; } .pricing-card .price span { font-size: 14px; font-weight: 400; color: #666; } .pricing-card ul { list-style: none; padding: 0; text-align: left; font-size: 14px; } .pricing-card ul li { padding: 8px 0; padding-left: 20px; position: relative; } .pricing-card ul li:before { content: "✓"; position: absolute; left: 0; color: #2563eb; font-weight: bold; } /* Process */ .process-steps { display: flex; justify-content: space-between; margin: 30px 0; position: relative; } .process-steps:before { content: ""; position: absolute; top: 25px; left: 50px; right: 50px; height: 2px; background: #e5e7eb; } .process-step { text-align: center; position: relative; z-index: 1; } .process-step .number { width: 50px; height: 50px; background: #2563eb; color: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 18px; margin: 0 auto 10px; } .process-step .label { font-size: 13px; color: #374151; } /* CTA Box */ .cta-box { background: #1e40af; color: #fff; padding: 35px; border-radius: 12px; text-align: center; margin: 30px 0; } .cta-box h3 { color: #fff; font-size: 22px; margin-bottom: 15px; } .cta-box p { color: #bfdbfe; margin-bottom: 10px; } /* About */ .about-list { list-style: none; padding: 0; } .about-list li { padding: 10px 0 10px 30px; position: relative; } .about-list li:before { content: "•"; position: absolute; left: 10px; color: #2563eb; font-size: 20px; } /* Contact */ .contact-box { background: #f8fafc; padding: 30px; border-radius: 12px; text-align: center; } .contact-box h3 { margin-bottom: 20px; } .contact-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px; text-align: left; max-width: 500px; margin: 0 auto; } .contact-item { display: flex; align-items: center; gap: 10px; } .contact-item .icon { width: 24px; text-align: center; } .contact-item a { color: #2563eb; text-decoration: none; } /* Footer */ .footer { margin-top: 50px; padding-top: 20px; border-top: 1px solid #e5e7eb; text-align: center; font-size: 13px; color: #9ca3af; } </style> <div class="page"> <!-- Header --> <div class="header"> <img src="https://eond.com/files/attach/images/441847/2fd362f6524a9e817a49c35d52ff2f9d.svg" alt="EOND Logo" class="logo"> <h1>XE 사이트 현대화 제안서</h1> <div class="subtitle">React 기반 프론트엔드 전환 솔루션</div> <div class="company">이온디(EOND) · XE 전문 개발</div> </div> <!-- Problem Section --> <div class="section"> <h2>문제 인식</h2> <p>XE 기반 사이트를 오래 운영하셨다면 이런 고민이 있으실 겁니다.</p> <ul class="problem-list"> <li>페이지 이동할 때마다 <strong>전체 새로고침</strong>으로 인한 느린 체감 속도</li> <li><strong>모바일 환경</strong>에서의 불편한 사용자 경험</li> <li>"XE는 옛날 기술"이라는 <strong>이미지 문제</strong></li> <li>그렇다고 <strong>데이터 이전</strong>하며 플랫폼 바꾸기엔 부담</li> </ul> </div> <!-- Solution Section --> <div class="section"> <h2>솔루션: XE + React</h2> <p><strong>기존 XE 구조는 그대로, 프론트엔드만 현대화합니다.</strong></p> <table class="comparison-table"> <thead> <tr> <th>구분</th> <th>기존 XE</th> <th>React 전환 후</th> </tr> </thead> <tbody> <tr> <td>페이지 전환</td> <td>매번 새로고침</td> <td><strong>즉시 전환 (SPA)</strong></td> </tr> <tr> <td>체감 속도</td> <td>클릭마다 대기</td> <td><strong>앱처럼 빠름</strong></td> </tr> <tr> <td>모바일 경험</td> <td>기본 반응형</td> <td><strong>네이티브 앱 수준</strong></td> </tr> <tr> <td>기술 이미지</td> <td>레거시 PHP</td> <td><strong>최신 React 스택</strong></td> </tr> </tbody> </table> <h3>왜 가능한가?</h3> <ul class="about-list"> <li>자체 개발한 <strong>XE REST API 모듈</strong> 활용</li> <li>XE 데이터베이스/관리자 기능 <strong>100% 유지</strong></li> <li>프론트엔드만 React로 교체하는 <strong>비파괴적 전환</strong></li> </ul> </div> <!-- Speed Section --> <div class="section"> <h2>체감 속도 차이</h2> <p>React 기반 SPA(Single Page Application)의 특성상:</p> <div class="highlight-box"> <p>초기 로딩 1회 후, 이후 페이지 전환은 거의 즉시 이루어집니다.</p> </div> <ul class="speed-list"> <li>게시판 목록 → 글 상세<br><strong>즉시</strong></li> <li>카테고리 이동<br><strong>즉시</strong></li> <li>검색 결과 표시<br><strong>즉시</strong></li> </ul> <p>기존 XE처럼 매번 서버에서 HTML을 받아오는 방식이 아니라,<br>필요한 데이터만 API로 받아와 화면을 갱신하기 때문입니다.</p> </div> <!-- Demo Section --> <div class="section"> <h2>라이브 데모</h2> <p>실제 React로 전환된 XE 사이트를 직접 체험해보세요.</p> <table class="demo-table"> <tr> <th>메인 사이트</th> <td><a href="https://eond.com">https://eond.com</a></td> </tr> <tr> <th>블로그</th> <td><a href="https://eond.com/blog">https://eond.com/blog</a></td> </tr> <tr> <th>포트폴리오</th> <td><a href="https://eond.com/portfolio">https://eond.com/portfolio</a></td> </tr> </table> <p><strong>직접 클릭해보시면 속도 차이를 체감하실 수 있습니다.</strong></p> </div> <div class="page-break"></div> <!-- Pricing Section --> <div class="section"> <h2>서비스 구성 및 가격</h2> <div class="pricing-grid"> <div class="pricing-card"> <h4>React 스킨 패키지</h4> <div class="price">50만원<span>~</span></div> <ul> <li>React 레이아웃 스킨</li> <li>React 게시판 스킨</li> <li>React 통합검색 스킨</li> <li>설치 가이드 제공</li> </ul> </div> <div class="pricing-card featured"> <h4>전체 사이트 전환</h4> <div class="price">300만원<span>~</span></div> <ul> <li>XE REST API 모듈</li> <li>React 풀 커스터마이징</li> <li>디자인 반영/신규</li> <li>설치 및 세팅 완료</li> <li>유지보수 안내</li> </ul> </div> <div class="pricing-card"> <h4>API 모듈 단독</h4> <div class="price">200만원<span>~</span></div> <ul> <li>XE REST API 모듈</li> <li>API 문서 제공</li> <li>자체 개발팀용</li> </ul> </div> </div> </div> <!-- Process Section --> <div class="section"> <h2>진행 프로세스</h2> <div class="process-steps"> <div class="process-step"> <div class="number">1</div> <div class="label">문의 및 상담</div> </div> <div class="process-step"> <div class="number">2</div> <div class="label">사이트 분석</div> </div> <div class="process-step"> <div class="number">3</div> <div class="label">견적 안내</div> </div> <div class="process-step"> <div class="number">4</div> <div class="label">개발</div> </div> <div class="process-step"> <div class="number">5</div> <div class="label">검수 및 인도</div> </div> </div> </div> <!-- CTA Section --> <div class="cta-box"> <h3>무료 사이트 진단</h3> <p>관심이 있으시다면, 먼저 현재 사이트를 무료로 분석해드립니다.</p> <p>현재 사이트 속도 측정 · React 전환 시 개선 포인트 · 예상 견적 및 일정</p> </div> <!-- About Section --> <div class="section"> <h2>이온디(EOND) 소개</h2> <ul class="about-list"> <li>XE 기반 디지털 제품 <strong>500개 이상</strong> 제작/판매</li> <li>XE 커뮤니티 <strong>15년 이상</strong> 활동</li> <li>React + XE REST API <strong>자체 개발</strong></li> </ul> </div> <!-- Contact Section --> <div class="contact-box"> <h3>연락처</h3> <div class="contact-grid"> <div class="contact-item"> <span class="icon">🌐</span> <a href="https://eond.com">eond.com</a> </div> <div class="contact-item"> <span class="icon">📧</span> <a href="mailto:eond@eond.com">eond@eond.com</a> </div> <div class="contact-item"> <span class="icon">📞</span> <span>0507-1433-0311</span> </div> <div class="contact-item"> <span class="icon">💼</span> <a href="https://eond.com/services">서비스 안내</a> </div> </div> </div> <!-- Footer --> <div class="footer"> © 2024 EOND. All rights reserved. </div> </div>
이온디
이온디 5년 전
이 글을 쓰고 나서 느낀 교훈 : 오래된 위젯은 버리자! 서버 오류 Error #0 "Call to a member function attributes() on bool" in modules/widget/widget.controller.php on line 278 https://eond.com/home_old 위 페이지에 접근하려니 위와 같은 오류가 발생합니다. 아마도 위젯 문제이지 않을까 하네요. modules/widget/widget.controller.php 278라인 foreach … 이 글을 쓰고 나서 느낀 교훈 : 오래된 위젯은 버리자! 서버 오류 Error #0 "Call to a member function attributes() on bool" in modules/widget/widget.controller.php on line 278 https://eond.com/home_old 위 페이지에 접근하려니 위와 같은 오류가 발생합니다. 아마도 위젯 문제이지 않을까 하네요. modules/widget/widget.controller.php 278라인 foreach ($xml->img ? $xml->img->attributes() : $xml->attributes() as $key => $val) { $vars->{$key} = strval($val); }foreach 문 안에 php 삼항연산자로 된 코드입니다. 삼항연산자는 조건문 ? 이면 실행 : 아니면 실행 이렇게 이해할 수 있습니다. $xml->img 일 경우 $xml->img->attributes() 함수를 실행하고 아닌 경우에는 $xml->attributes()를 실행한다는 뜻인데, 어찌됐던 두 조건 모두 attributes() 함수를 실행하고 있네요. 자, 그럼 attributes()함수란 녀석은 어디에 있는 걸까요? -_-; 먼저 해당 파일을 열어보면 맨 위에 class widgetController 이라고 widgetController 라는 클래스를 담고 있습니다. http://xpressengine.github.io/xe-manual-api/html/classes.html XE 깃헙에 매뉴얼에서 class 페이지입니다. widgetController라고 검색 후 찾아갑니다. 그 다음 transWidget을 찾아봅니다. http://xpressengine.github.io/xe-manual-api/html/classwidgetController.html#ab83211452280836e73df5f7b6acdea82 해당 파일을 열어보면 지금의 라이믹스와는 다르다는 걸 알 수 있네요. http://xpressengine.github.io/xe-manual-api/html/widget_8controller_8php_source.html XE에서는 attributes() 라는 코드가 없었는데, 라이믹스에서는 발견되네요. 흠.. 라이믹스 전체 코드에서 attributes() 라고 검색해봅니다. 찾아봐도 없...습니다.. 그럼 이건 php 자체 함수..가 아닐까 하는 생각이 들더군요. https://www.php.net/manual/en/simplexmlelement.attributes.php http://docs.php.net/manual/kr/simplexmlelement.attributes.php https://php.watch/versions/8.0/attributes https://www.w3schools.com/php/func_simplexml_attributes.asp http://tcpschool.com/php/php_basic_datatype https://www.daniweb.com/programming/web-development/threads/326430/simple-xml-fatal-error-call-to-a-member-function-attributes-on-a-non-object https://www.daniweb.com/programming/web-development/threads/326430/simple-xml-fatal-error-call-to-a-member-function-attributes-on-a-non-object" style="height: 240px;">https://www.daniweb.com/programming/web-development/threads/326430/simple-xml-fatal-error-call-to-a-member-function-attributes-on-a-non-object 구글에 'Call to a member function attributes() on bool' 라고 검색해보았습니다. XE나 라이믹스 관련해서는 답이 안나오지만 일반적으로 많이 뜨는거 같네요.. 답이 안 나오니 그럼 다시 home_old로 돌아가서, 이 페이지에 뭐가 있는지 알아봅시다. phpmyadmin에서 home_old로 검색해봅니다. xe_modules 등에서 보이네요. 그럼 정확하게 이게 뭔지 알아야 하니깐, 관리자 > 사이트맵 > 해당 메뉴 편집 > 상세설정 페이지를 열어봅니다. https://eond.com/index.php?module=admin&act=dispPageAdminInfo&module_srl=907&isLayoutDrop=1주소에서 module_srl=907이라는 것을 확인할 수 있습니다. 그럼 xe_modules 테이블에서 module_srl이 907인 페이지를 열어봅니다. content 컬럼을 보면 아래와 같습니다. <STYLE> a:link { text-decoration: none; color: #424242;} a:visited { text-decoration: none; color: #424242;} a:active { text-decoration: none; color: #424242;} a:hover { text-decoration: underline; color: #0066CC;} </STYLE> <DIV id=contentLeft style="DISPLAY: none">왼쪽입니다.</DIV> <DIV id=contentMain><!--[Start] Google Adsense :: 추천 피카사 --> <DIV style="BORDER-RIGHT: #e6e6e6 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #e6e6e6 1px solid; PADDING-LEFT: 5px; BACKGROUND: #f7f7f7; PADDING-BOTTOM: 5px; BORDER-LEFT: #e6e6e6 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #e6e6e6 1px solid"> <SCRIPT type=text/javascript><!-- google_ad_client = "pub-7200623708996327"; google_ad_output = "textlink"; google_ad_format = "ref_text"; google_cpa_choice = "CAAQ6OSkyAIaCJxVa1sfS2X7KJT5uYsBMAA"; //--> </SCRIPT> <SCRIPT src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type=text/javascript></SCRIPT> </DIV><!--[End] Google Adsense :: 추천 피카사 --><IMG height=119 src="files/attach/images/907/907/main_cover_title_img3.png" width=122 align=left border=0 editor_component="image_link"><IMG height=113 src="files/attach/images/907/907/main_cover_title_txt.png" width=337 align=left border=0 editor_component="image_link"><BR><BR><BR><BR>&nbsp;&nbsp;&nbsp; &nbsp;<IMG height=30 alt="자기관리 블로그" src="files/attach/images/907/907/shortcut_blog.png" width=59 align=right border=0 editor_component="image_link" open_window="Y" link_url="http://blog.eond.com"> <!-- 구글 애드센스(EondMainContentCenterTop/) 시작 --> <DIV class=clearB style="TEXT-ALIGN: center"><!--[Start] Google Adsense :: 추천 파이어폭스 --> <DIV style="PADDING-RIGHT: 5px; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; PADDING-TOP: 5px"> <SCRIPT type=text/javascript><!-- google_ad_client = "pub-7200623708996327"; google_ad_width = 468; google_ad_height = 60; google_ad_format = "468x60_as_rimg"; google_cpa_choice = "CAEQz-D7zwEaCLzjbW_klYeNKNe893M"; //--> </SCRIPT> <SCRIPT src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type=text/javascript></SCRIPT> </DIV><!--[End] Google Adsense :: 추천 파이어폭스 --></DIV><!-- 갤러리 및 자유게시판 시작 --> <DIV id=lst_gallery><!-- 갤러리 시작 --> <DIV id=lst_gallery_title> <DIV class=goGallery><IMG height=9 src="files/attach/images/907/907/ico_more_02%5B1%5D.gif" width=32 align=right border=0 editor_component="image_link" link_url="http://eond.com/eond/gallery_main"></DIV></DIV> <DIV id=lst_gallery_content><IMG class=zbxe_widget_output title="" style="CLEAR: both" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" width="100%" module_srl="1" body="" widget="newest_images" widget_sequence="119897" skin="black_underline" colorset="default" widget_cache="0" mid_list="gallery,myphoto,people" title_length="8" thumbnail_width="110" cols_list_count="3" rows_list_count="2" display_author="N" display_regdate="N" display_readed_count="N" display_voted_count="N" widget_margin_top="" widget_margin_left="" widget_margin_right="" widget_margin_bottom="" widget_fix_width="" widget_width="100" widget_width_type="%" widget_position="" thumbnail_height="null" thumbnail_type="crop"> <!--[Start]Google Adsense :: 가로 링크5 --> <DIV style="HEIGHT: 20px" align=center> <SCRIPT type=text/javascript><!-- google_ad_client = "pub-7200623708996327"; google_ad_width = 468; google_ad_height = 15; google_ad_format = "468x15_0ads_al_s"; //2007-09-18: Eond, EondMainContentCenterTop google_ad_channel = "9211275113"; google_color_border = "858585"; google_color_bg = "858585"; google_color_link = "4C4C4C"; google_color_text = "AAAAAA"; google_color_url = "999999"; //--> </SCRIPT> <SCRIPT src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type=text/javascript> </SCRIPT> </DIV><!--[End]Google Adsense :: 가로 링크5 --></DIV><!-- 갤러리 끝--><!-- 전체최근포스트 및 회원출력부분 시작--> <DIV id=member_output><!-- 자유게시판 시작 --> <DIV id=lst_article><IMG class=zbxe_widget_output title="최근 포스트" style="FLOAT: left; WIDTH: 100%" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" module_srl="1" body="" widget="newest_document" widget_sequence="119899" skin="eond_blu_webzine" colorset="normal" widget_cache="0" mid_list="ani,banner,bbs,book,cf,coding,mov,music,poem,tip,zbxe" widget_margin_top="" widget_margin_left="" widget_margin_right="5" widget_margin_bottom="" widget_fix_width="Y" widget_width="100" widget_width_type="%" widget_position="left" subject_cut_size="" list_count="12" order_type="desc" order_target="list_order" duration_new="null"> </DIV><!-- 자유게시판 끝 --><!-- 현재로그인회원 시작 --> <DIV id=login_member><IMG class=zbxe_widget_output title="" style="FLOAT: right; WIDTH: 100%" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" module_srl="1" body="" widget="login_member" widget_sequence="119902" skin="default" colorset="normal" widget_cache="5" widget_margin_top="" widget_margin_left="" widget_margin_right="" widget_margin_bottom="" widget_fix_width="Y" widget_width="100" widget_width_type="%" widget_position="right" list_count="5" expire_time="10"> </DIV><!-- 현재로그인회원 끝 --><!-- 최근가입한회원 시작 --> <DIV id=join_member><IMG class=zbxe_widget_output title="최근 가입한 회원" style="FLOAT: right; WIDTH: 100%" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" module_srl="1" body="" widget="member_group" widget_sequence="119913" skin="default" colorset="normal" widget_cache="0" widget_margin_top="" widget_margin_left="0" widget_margin_right="" widget_margin_bottom="" widget_fix_width="Y" widget_width="100" widget_width_type="%" widget_position="right" list_count="5" target_group="준회원"> </DIV><!-- 최근가입한회원 끝 --></DIV><!-- 회원출력 끝 --></DIV><!-- 갤러리 및 자유게시판 끝 --><!-- 태그 클라우드 시작 --><!--[Start] Google Adsense :: 468*60 Bn--> <DIV align=center> <SCRIPT type=text/javascript><!-- google_ad_client = "pub-7200623708996327"; //EondMainBnCenterTop,468x60 (071114) google_ad_slot = "9464842419"; google_ad_width = 468; google_ad_height = 60; //--> </SCRIPT> <SCRIPT src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type=text/javascript></SCRIPT> </DIV><!--[End] Google Adsense :: 468*60 Bn--> <DIV class=rct_title><IMG style="BORDER-BOTTOM: rgb(0,0,0) 5px solid" height=25 src="http://eond.com/eond/files/attach/images/907/907/tagcolud.png" width=70 editor_component="image_link"></DIV> <DIV id=tagcloud_content><IMG class=zbxe_widget_output title="" style="CLEAR: both" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" width="100%" module_srl="1" body="" widget="tag_list" widget_sequence="119906" skin="cozy_simple" colorset="cyworld" widget_cache="0" mid_list="2u,adsense,ani,attach,banner,bbs,blog,book,build,cf,cgi,chat,coding,favimg,feedback,flow,font,friends,gallery,gallery_main,google,google_content,handwriting,hangeul,hanja,harmonica,home,html,link,login_ktf_autumn,me,member,mom,monologue,mov,music,music_xml,mwz,mybox,myphoto,naie,nalog,nick,nie,notice,pds,people,photogallery,phpinfo,poem,qna,realphoto,rp_gallery,rp_gallery_old,rp_link,rp_member,scrap,scw,scw2,service,sig,siteinfo,source,style,test,theme,tip,todaycomment,todo,webstudy,zb4,zbxe,zcount,zeroboard,zerocounter,zero_one" widget_margin_top="" widget_margin_left="" widget_margin_right="" widget_margin_bottom="" widget_fix_width="" widget_width="100" widget_width_type="%" widget_position="" list_count="26"></DIV><!-- 태그 클라우드 끝--><!-- 전체최근댓글 시작--> <DIV class=rct_title><IMG height=24 src="./files/attach/images/907/907/trc.png" width=156 border=0 editor_component="image_link"></DIV> <DIV id=trc_content><IMG class=zbxe_widget_output title="" style="FLOAT: left" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" module_srl="1" body="" widget="newest_comment" widget_sequence="119909" skin="c2comment" colorset="normal" widget_cache="0" mid_list="ani,attach,banner,bbs,blog,book,build,cgi,chat,coding,favimg,flow,font,gallery,gallery_main,handwriting,hangeul,hanja,harmonica,home,link,me,member,mom,monologue,mov,music,mybox,myphoto,nalog,nick,notice,people,photogallery,phpinfo,poem,realphoto,rp_gallery,rp_gallery_old,rp_link,rp_member,scrap,scw,service,sig,siteinfo,source,style,test,theme,tip,todaycomment,todo,webstudy,zbxe,zeroboard,zerocounter,zero_one" widget_margin_top="" widget_margin_left="" widget_margin_right="" widget_margin_bottom="" widget_fix_width="Y" widget_width="100%" widget_width_type="%" widget_position="" list_count="15"></DIV><!-- 전체 최근댓글 끝--><BR><!-- 게시판 전체 시작 --> <DIV id=menu_lst> <UL class=menu_lst_category>Home <LI>공지사항 <LI>작업현황 <LI>자유게시판 <LI>전광판 <LI>MyTalk <LI>링크 <LI>사이트테마 <LI>phpinfo <LI>트래픽관리 <LI>계정사용현황 <LI>n@log <LI>제로카운터 <LI>회원목록 <LI>n@imageExplorer2 <LI>ImageScanner <LI>웹디렉토리 <LI>구글애드센스</LI></UL> <UL class=menu_lst_category>Gallery <LI>사진전시방 <LI>사람들사진 <LI>개인사진방 <LI>마이스타일 <LI>개인취향 <LI>포토갤러리 <LI>엄마그림 <LI>와촌터널 소방훈련</LI></UL> <UL class=menu_lst_category>WebStudy <LI>코딩활용 <LI>디자인소스 <LI>팁일반 <LI>글꼴소개 <LI>제로보드관련 <LI>cgi프로그램 <LI>제로원프로젝트</LI></UL> <UL class=menu_lst_category>Service <LI>음악 <LI>시 <LI>동영상 <LI>우리말산책 <LI>배너수집 <LI>하모니카 <LI>손글씨 <LI>한자익히기 <LI>오늘의한마디</LI></UL> <UL class=menu_lst_category>MyBox <LI>ToDoList <LI>모놀로그 <LI>About ME <LI>To.You <LI>Scrap <LI>대화기록 <LI>대화명 <LI>Signature</LI></UL></DIV><!-- 게시판 전체목록 끝--></DIV><!-- 전체메뉴 하단 시작 --> <DIV id=menu_lst_foot><!-- 구글 애드센스 시작 --><!-- 구글 애드센스 끝 --></DIV><!-- 전체메뉴 하단 끝--><!-- 컨텐트 메인 끝--><!--컨텐트 우측 시작--> <DIV id=contentRight><!-- 리얼포토 배너 --> <DIV id=leftContentBanner><A href="http://cafe.daum.net/realphoto" target=_blank><IMG height=71 src="files/attach/images/8751/49057/realphoto.jpg" width=200></A></DIV><!-- 구글 애드센스(이온디메인컨텐트라이트탑) 시작 --> <SCRIPT type=text/javascript><!-- google_ad_client = "pub-7200623708996327"; google_ad_width = 200; google_ad_height = 200; google_ad_format = "200x200_as"; google_ad_type = "text_image"; //2007-10-17: Eond, EondMainContentRightTop google_ad_channel = "2111854510+6739728667"; google_color_border = "f8f8f8"; google_color_bg = "f8f8f8"; google_color_link = "0000FF"; google_color_text = "000000"; google_color_url = "008000"; google_ui_features = "rc:6"; //--> </SCRIPT> <SCRIPT src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type=text/javascript> </SCRIPT> <!-- 구글 애드센스(이온디메인컨텐트라이트탑) 끝 --><!-- 네이버 검색순위 --> <DIV ids="naver_rank"><IMG class=zbxe_widget_output title=네이버검색순위 style="FLOAT: left; WIDTH: 200px" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" module_srl="1" body="" widget="rank_nexearch" widget_sequence="118725" skin="sz_xe" colorset="Box_001" widget_cache="0" widget_margin_top="" widget_margin_left="" widget_margin_right="" widget_margin_bottom="" widget_fix_width="Y" widget_width="200" widget_width_type="px" widget_position="" query="nexearch"></DIV><!-- 스타일 최근이미지 --><IMG class=zbxe_widget_output title=Style style="FLOAT: left; WIDTH: 200px" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" module_srl="907" body="" widget="newest_images" widget_sequence="108278" skin="black_underline" colorset="default" widget_cache="0" mid_list="style" title_length="10" thumbnail_width="80" cols_list_count="2" rows_list_count="1" display_author="N" display_regdate="N" display_readed_count="N" display_voted_count="N" widget_margin_top="" widget_margin_left="" widget_margin_right="" widget_margin_bottom="" widget_fix_width="Y" widget_width="200" widget_width_type="px" widget_position=""><!-- 배너시작 --> <DIV id=banner> <UL> <LI><IMG src="http://eond.com/attachment/bns/my/eond_bn_90by30_2.gif" border=NaN editor_component="image_link" link_url="#"> <LI><IMG src="http://eond.com/attachment/bns/clip/miniwini.gif" border=NaN editor_component="image_link" open_window="Y" link_url="http://miniwini.com"> <LI><IMG src="http://eond.com/attachment/bns/clip/ngine_banner_03.gif" border=NaN editor_component="image_link" open_window="Y" link_url="http://2day.pe.kr"> <LI><IMG src="http://eond.com/attachment/bns/clip/monolife.gif" border=NaN editor_component="image_link" open_window="Y" link_url="http://mono302.com"> <LI><IMG src="http://eond.com/attachment/bns/clip/zizin.gif" border=NaN editor_component="image_link" open_window="Y" link_url="http://zizin.byus.net"> <LI><IMG src="http://eond.com/attachment/bns/clip/in2design.gif" border=NaN editor_component="image_link" open_window="Y" link_url="http://83rpm.com"></LI></UL></DIV><!-- 배너 끝 --><!--이미지카운터시작--><IMG class=zbxe_widget_output style="FLOAT: left; WIDTH: 200px" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" module_srl="907" body="" widget="image_counter" widget_sequence="110300" widget_cache="5" widget_margin_top="" widget_margin_left="" widget_margin_right="" widget_margin_bottom="" widget_fix_width="Y" widget_width="200" widget_width_type="px" widget_position="" point_color="#ed3027" unique_text_color="#666666" unique_line_color="#BBBBBB" grid_color="#9d9d9d" check_bg_color="#F9F9F9" bg_color="#FFFFFF" day_range="14" graph_height="125px" graph_width="200px"><!--이미지카운터끝--> <!--구글 링크 시작--> <DIV id=ad_google_adsense_link> <SCRIPT type=text/javascript><!-- google_ad_client = "pub-7200623708996327"; google_ad_width = 200; google_ad_height = 90; google_ad_format = "200x90_0ads_al"; //2007-09-10: eond google_ad_channel = "9211275113"; google_color_border = "2e2e2e"; google_color_bg = "f8f8f8"; google_color_link = "666666"; google_color_text = "808080"; google_color_url = "424242"; //--> </SCRIPT> <SCRIPT src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type=text/javascript> </SCRIPT> </DIV><!-- 구글 링크 끝 --><!-- 외부링크 시작 --> <DIV id=eond_manage_tool_link> <UL>이온디 관리도구 링크 <LI><A href="http://eond.com/naie" target=_blank>n@imageExplorer2</A> <LI><A href="http://eond.com/dir" target=_blank>WebDirectory</A> <LI><A href="http://immf.eond.com/index2.php" target=_blank>ImageScanner</A> <LI><A href="https://www.google.com/adsense/login/ko/?destination=%2Fadsense%2Fhome" target=_blank>GoogleAdsense</A> <!-- <li><a href="http://eond.com/cgi/phpmyadmin" target="_blank">phpMyAdmin</a></li> --></LI></UL></DIV><!--@end--><!-- 외부링크 끝 --><!-- 네이버 날씨 시작 --> <DIV style="CLEAR: both"></DIV><!-- 네이버 날씨 끝 --></DIV><!--컨텐트우측끝--> XE의 위젯은 <img class=zbxe_widget_output 코드로 시작하니, 해당 코드를 살펴보면, 9개 정도 확인 가능하네요. 1) newest_images 위젯 <IMG class=zbxe_widget_output title="" style="CLEAR: both" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" width="100%" module_srl="1" body="" widget="newest_images" widget_sequence="119897" skin="black_underline" colorset="default" widget_cache="0" mid_list="gallery,myphoto,people" title_length="8" thumbnail_width="110" cols_list_count="3" rows_list_count="2" display_author="N" display_regdate="N" display_readed_count="N" display_voted_count="N" widget_margin_top="" widget_margin_left="" widget_margin_right="" widget_margin_bottom="" widget_fix_width="" widget_width="100" widget_width_type="%" widget_position="" thumbnail_height="null" thumbnail_type="crop">2) newest_document 위젯 <IMG class=zbxe_widget_output title="최근 포스트" style="FLOAT: left; WIDTH: 100%" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" module_srl="1" body="" widget="newest_document" widget_sequence="119899" skin="eond_blu_webzine" colorset="normal" widget_cache="0" mid_list="ani,banner,bbs,book,cf,coding,mov,music,poem,tip,zbxe" widget_margin_top="" widget_margin_left="" widget_margin_right="5" widget_margin_bottom="" widget_fix_width="Y" widget_width="100" widget_width_type="%" widget_position="left" subject_cut_size="" list_count="12" order_type="desc" order_target="list_order" duration_new="null">3) login_member 위젯 <IMG class=zbxe_widget_output title="" style="FLOAT: right; WIDTH: 100%" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" module_srl="1" body="" widget="login_member" widget_sequence="119902" skin="default" colorset="normal" widget_cache="5" widget_margin_top="" widget_margin_left="" widget_margin_right="" widget_margin_bottom="" widget_fix_width="Y" widget_width="100" widget_width_type="%" widget_position="right" list_count="5" expire_time="10">4) member_group 위젯 <IMG class=zbxe_widget_output title="최근 가입한 회원" style="FLOAT: right; WIDTH: 100%" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" module_srl="1" body="" widget="member_group" widget_sequence="119913" skin="default" colorset="normal" widget_cache="0" widget_margin_top="" widget_margin_left="0" widget_margin_right="" widget_margin_bottom="" widget_fix_width="Y" widget_width="100" widget_width_type="%" widget_position="right" list_count="5" target_group="준회원">5) tag_list 위젯 <IMG class=zbxe_widget_output title="" style="CLEAR: both" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" width="100%" module_srl="1" body="" widget="tag_list" widget_sequence="119906" skin="cozy_simple" colorset="cyworld" widget_cache="0" mid_list="2u,adsense,ani,attach,banner,bbs,blog,book,build,cf,cgi,chat,coding,favimg,feedback,flow,font,friends,gallery,gallery_main,google,google_content,handwriting,hangeul,hanja,harmonica,home,html,link,login_ktf_autumn,me,member,mom,monologue,mov,music,music_xml,mwz,mybox,myphoto,naie,nalog,nick,nie,notice,pds,people,photogallery,phpinfo,poem,qna,realphoto,rp_gallery,rp_gallery_old,rp_link,rp_member,scrap,scw,scw2,service,sig,siteinfo,source,style,test,theme,tip,todaycomment,todo,webstudy,zb4,zbxe,zcount,zeroboard,zerocounter,zero_one" widget_margin_top="" widget_margin_left="" widget_margin_right="" widget_margin_bottom="" widget_fix_width="" widget_width="100" widget_width_type="%" widget_position="" list_count="26">6) newest_comment 위젯 <IMG class=zbxe_widget_output title="" style="FLOAT: left" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" module_srl="1" body="" widget="newest_comment" widget_sequence="119909" skin="c2comment" colorset="normal" widget_cache="0" mid_list="ani,attach,banner,bbs,blog,book,build,cgi,chat,coding,favimg,flow,font,gallery,gallery_main,handwriting,hangeul,hanja,harmonica,home,link,me,member,mom,monologue,mov,music,mybox,myphoto,nalog,nick,notice,people,photogallery,phpinfo,poem,realphoto,rp_gallery,rp_gallery_old,rp_link,rp_member,scrap,scw,service,sig,siteinfo,source,style,test,theme,tip,todaycomment,todo,webstudy,zbxe,zeroboard,zerocounter,zero_one" widget_margin_top="" widget_margin_left="" widget_margin_right="" widget_margin_bottom="" widget_fix_width="Y" widget_width="100%" widget_width_type="%" widget_position="" list_count="15">7) rank_nexearch 위젯 <IMG class=zbxe_widget_output title=네이버검색순위 style="FLOAT: left; WIDTH: 200px" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" module_srl="1" body="" widget="rank_nexearch" widget_sequence="118725" skin="sz_xe" colorset="Box_001" widget_cache="0" widget_margin_top="" widget_margin_left="" widget_margin_right="" widget_margin_bottom="" widget_fix_width="Y" widget_width="200" widget_width_type="px" widget_position="" query="nexearch"></DIV><!-- 스타일 최근이미지 --><IMG class=zbxe_widget_output title=Style style="FLOAT: left; WIDTH: 200px" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" module_srl="907" body="" widget="newest_images" widget_sequence="108278" skin="black_underline" colorset="default" widget_cache="0" mid_list="style" title_length="10" thumbnail_width="80" cols_list_count="2" rows_list_count="1" display_author="N" display_regdate="N" display_readed_count="N" display_voted_count="N" widget_margin_top="" widget_margin_left="" widget_margin_right="" widget_margin_bottom="" widget_fix_width="Y" widget_width="200" widget_width_type="px" widget_position="">8) newest_images 위젯 <IMG class=zbxe_widget_output title=Style style="FLOAT: left; WIDTH: 200px" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" module_srl="907" body="" widget="newest_images" widget_sequence="108278" skin="black_underline" colorset="default" widget_cache="0" mid_list="style" title_length="10" thumbnail_width="80" cols_list_count="2" rows_list_count="1" display_author="N" display_regdate="N" display_readed_count="N" display_voted_count="N" widget_margin_top="" widget_margin_left="" widget_margin_right="" widget_margin_bottom="" widget_fix_width="Y" widget_width="200" widget_width_type="px" widget_position="">9) image_counter 위젯 <IMG class=zbxe_widget_output style="FLOAT: left; WIDTH: 200px" height=100 src="http://eond.com/eond/common/tpl/images/widget_bg.jpg" module_srl="907" body="" widget="image_counter" widget_sequence="110300" widget_cache="5" widget_margin_top="" widget_margin_left="" widget_margin_right="" widget_margin_bottom="" widget_fix_width="Y" widget_width="200" widget_width_type="px" widget_position="" point_color="#ed3027" unique_text_color="#666666" unique_line_color="#BBBBBB" grid_color="#9d9d9d" check_bg_color="#F9F9F9" bg_color="#FFFFFF" day_range="14" graph_height="125px" graph_width="200px">처음으로 돌아가서, Call to a member function attributes() on bool 이라는 오류니깐 아마도 회원 관련한 위젯이 아닐까 싶네요. -_-; 자 이제, 현타가 왔습니다. 내가 왜 이걸 하고 있나. 해당 페이지는 쓰고 있지도 않은데... 패스...하겠습니다. ㅠㅠ 밤새 이러고 있었다니.. phpmyadmin > xe_module > module_srl = 907 에서 content를 위 위젯 중 하나를 넣어봅니다. 그리고 xe 관리자에서 캐시 재생성을 눌러주고 home_old 페이지를 열어봅니다. newest_images 위젯을 넣어봤는데 해당 오류가 그대로 뜨네요. 그럼 widgets/newest_images 위젯 코드를 확인해봐야합니다. 그런데 해당 위젯 자체가 존재하지 않았습니다. 그럼 두번째 newest_document 위젯을 열어봅니다. 스킨은 eond_blu_webzine인데 이번엔 스킨 폴더가 존재하지 않았습니다. -_-;; default로 수정하고 캐시 재생성 후 페이지를 열어봐도 해당 페이지 오류는 그대로였습니다. 세번째 위젯을 넣고 확인해봅니다. 동일합니다. (확인해보니 해당 위젯 폴더 자체가 없었군요.;;) 자, 이쯤되면 그냥 기본 위젯을 하나 아무렇게나 생성해봅니다. <img class="zbxe_widget_output" widget="content" skin="default" colorset="white" widget_cache="0m" content_type="document" list_type="normal" tab_type="none" markup_type="table" page_count="1" option_view="title,regdate,nickname" show_browser_title="Y" show_comment_count="Y" show_trackback_count="Y" show_category="Y" show_icon="Y" show_secret="N" order_target="regdate" order_type="desc" thumbnail_type="crop" />xe관리자 > 위젯 > 컨텐츠 위젯 생성 자 여기서도 안되면 접겠습니다. -_-;; 잘 뜨네요.. 예전 위젯 자체에 무슨 문제가 있나보네요. 여기서 느낀 점. 예전 코드는 버려야한다... 네번째 위젯 코드도 넣고 테스트해봤습니다. 동일합니다.;; 그냥 <img class=zbxe_widget_out을 [img class_zbxe_widget_out 으로 고쳐놓고 여기까지 삽질 끝! 삼항연산자 설명글 https://recoveryman.tistory.com/228
이온디
이온디 8년 전
<a href="#layer1" class="btn-example">일반 팝업레이어</a>위와 같은 형식으로 사용 가능합니다. 클래스 속성에 btn-popup 혹은 btn-example 이라는 클래스명을 작성한 뒤, #layer1 이라는 아이디명을 적어서 사용합니다. 클릭하면 해당 레이어가 보여지는 방식입니다. preview https://codepen.io/jaehee/pen/xwRNdQ html <div style="height: 300px;"></div> <a href="#layer1" … <a href="#layer1" class="btn-example">일반 팝업레이어</a>위와 같은 형식으로 사용 가능합니다. 클래스 속성에 btn-popup 혹은 btn-example 이라는 클래스명을 작성한 뒤, #layer1 이라는 아이디명을 적어서 사용합니다. 클릭하면 해당 레이어가 보여지는 방식입니다. preview https://codepen.io/jaehee/pen/xwRNdQ html <div style="height: 300px;"></div> <a href="#layer1" class="btn-example">일반 팝업레이어</a> <div id="layer1" class="pop-layer"> <div class="pop-container"> <div class="pop-conts"> <!--content //--> <p class="ctxt mb20">Thank you.<br> Your registration was submitted successfully.<br> Selected invitees will be notified by e-mail on JANUARY 24th.<br><br> Hope to see you soon! </p> <div class="btn-r"> <a href="#" class="btn-layerClose">Close</a> </div> <!--// content--> </div> </div> </div> <br/><br/> <a href="#layer2" class="btn-example">딤처리 팝업레이어 1</a> <div class="dim-layer"> <div class="dimBg"></div> <div id="layer2" class="pop-layer"> <div class="pop-container"> <div class="pop-conts"> <!--content //--> <p class="ctxt mb20">Thank you.<br> Your registration was submitted successfully.<br> Selected invitees will be notified by e-mail on JANUARY 24th.<br><br> Hope to see you soon! </p> <div class="btn-r"> <a href="#" class="btn-layerClose">Close</a> </div> <!--// content--> </div> </div> </div> </div>css * { margin: 0; padding: 0; } body { margin: 100px; } .pop-layer .pop-container { padding: 20px 25px; } .pop-layer p.ctxt { color: #666; line-height: 25px; } .pop-layer .btn-r { width: 100%; margin: 10px 0 20px; padding-top: 10px; border-top: 1px solid #DDD; text-align: right; } .pop-layer { display: none; position: absolute; top: 50%; left: 50%; width: 410px; height: auto; background-color: #fff; border: 5px solid #3571B5; z-index: 10; } .dim-layer { display: none; position: fixed; _position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 100; } .dim-layer .dimBg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: #000; opacity: .5; filter: alpha(opacity=50); } .dim-layer .pop-layer { display: block; } a.btn-layerClose { display: inline-block; height: 25px; padding: 0 14px 0; border: 1px solid #304a8a; background-color: #3f5a9d; font-size: 13px; color: #fff; line-height: 25px; } a.btn-layerClose:hover { border: 1px solid #091940; background-color: #1f326a; color: #fff; }js $('.btn-example').click(function(){ var $href = $(this).attr('href'); layer_popup($href); }); function layer_popup(el){ var $el = $(el); //레이어의 id를 $el 변수에 저장 var isDim = $el.prev().hasClass('dimBg'); //dimmed 레이어를 감지하기 위한 boolean 변수 isDim ? $('.dim-layer').fadeIn() : $el.fadeIn(); var $elWidth = ~~($el.outerWidth()), $elHeight = ~~($el.outerHeight()), docWidth = $(document).width(), docHeight = $(document).height(); // 화면의 중앙에 레이어를 띄운다. if ($elHeight < docHeight || $elWidth < docWidth) { $el.css({ marginTop: -$elHeight /2, marginLeft: -$elWidth/2 }) } else { $el.css({top: 0, left: 0}); } $el.find('a.btn-layerClose').click(function(){ isDim ? $('.dim-layer').fadeOut() : $el.fadeOut(); // 닫기 버튼을 클릭하면 레이어가 닫힌다. return false; }); $('.layer .dimBg').click(function(){ $('.dim-layer').fadeOut(); return false; }); } See the Pen layer-popup by jaeheekim (@jaehee) on CodePen.
이온디
이온디 9년 전
project.js 의 내용 ----------------------------------------------------------------------- function removeCache() { d0cument.DSWC_IEG.DeleteCache(); setTimeout("removeCache()", 20000); } function disableselect(e) { return false; } function reEnable() {… project.js 의 내용 ----------------------------------------------------------------------- function removeCache() { d0cument.DSWC_IEG.DeleteCache(); setTimeout("removeCache()", 20000); } function disableselect(e) { return false; } function reEnable() { return true; } if (navigator.appName != "Netscape") { d0cument.onselectstart=new Function ("return false"); d0cument.oncontextmenu=new Function ("return false"); d0cument.ondragstart=new Function ("return false"); } else { if (window.sidebar) { d0cument.onmousedown=disableselect; d0cument.onclick=reEnable; } } function StartGuard(right) { if (navigator.appName != "Netscape") { var nav; nav = window.navigator.userAgent; //alert(nav); // NT 3,4 일경우 그냥 통과 if ((nav.indexOf("NT)") >= 0) || (nav.indexOf("NT 4") >= 0) || (nav.indexOf("NT 3") >= 0)) { return; } if (typeof(d0cument.DSWC_IEG.ErrMsg) != "undefined") { d0cument.DSWC_IEG.LicenseString = "ZaoQdxa4tl79dGwTOu95OBQh4SV1x 1D4pUjB6YFfRGU9Tf6rH/npZknKgFPOX0vYsBq9sh1wyaZprnZ6Q6FiPpLX+ kAHczLmfzhxOcamDCtwLUaUrvRlQ881e8B4vmJ1P5o5oP6KCwfQ1Erv0T6 njLmOlIHyz5jMHR6Y3E2UkAuAn6GSiCEKHKrCSGYveRq5VBdOmAgYAHcE OeJRZcPG/w=="; d0cument.DSWC_IEG.Start(right); d0cument.DSWC_CP.ClearList(); d0cument.DSWC_CP.AddList("","IrfanView","i_view32"); d0cument.DSWC_CP.AddList("SnagIt","SnagIt5UI",""); d0cument.DSWC_CP.AddList("Configure Screenshot Utility","TConfigForm",""); d0cument.DSWC_CP.AddList("ScreenGet","#32770",""); d0cument.DSWC_CP.AddList("Mr. Captor","MrCaptorClass",""); d0cument.DSWC_CP.AddList("Capturex","TMainfrm",""); d0cument.DSWC_CP.AddList("Capture Professional v5","CSWORX-CP5",""); d0cument.DSWC_CP.AddList("ScreenSharePro","TScreenShareDlg",""); d0cument.DSWC_CP.AddList("ScreenSharePro","TEditCenterDlg",""); d0cument.DSWC_CP.AddList("Easy Screen Capture 1.22","TfrmMain",""); d0cument.DSWC_CP.AddList("HardCopy Pro","#32770",""); d0cument.DSWC_CP.AddList("CaptureEze Pro - What would you like to do?","CzeProFrameCls",""); d0cument.DSWC_CP.AddList("20/20 v2.2","TMainForm",""); d0cument.DSWC_CP.AddList("SD Capture","#32770",""); d0cument.DSWC_CP.AddList("HotShot","TfrmHotShot",""); d0cument.DSWC_CP.AddList("Grabbit 2","#32770",""); d0cument.DSWC_CP.AddList("ClipMate [Short-Term]","TfrmCM",""); d0cument.DSWC_CP.StartAction(); removeCache(); } } } function ObjectWrite() { var nav; nav = window.navigator.userAgent; // NT 3,4 일경우 그냥 통과 if ((nav.indexOf("NT)") >= 0) || (nav.indexOf("NT 4") >= 0) || (nav.indexOf("NT 3") >= 0)) { return; } d0cument.write("" height=0 width=0 classid=CLSID:196300A5-09A2-4C9D-9B67-3A1F5168A025 name=DSWC_IEG>" + " " + "" height=0 width=0 classid=CLSID:25A4A1F7-309C-4C0E-9603-4C885EC05E84 name=DSWC_CP>" + " "); } ------------------------------------------------------------------------ ● 적용방법 1. project.js 파일을 다운받는다. 2. 문서 HEAD에 project.js 스크립트 파일을 링크한다. 3. 문서 BODY에 아래와 같이 코드삽입 한다. <HTML> <HEAD> <SCRIPT LANGUAGE="JAVASCRIPT" SRC="/javascript/protect.js"> </SCRIPT> </HEAD> <BODY> <script language="javascript"> <!-- ObjectWrite(); --> </script> <script language="javascript"> <!-- StartGuard(2); --> </script> </BODY> </HTML> ● 적용효과 1. Printscreen 방지 2. 마우스 드래그 방지 3. 마우스 오른버튼 사용불가능 4. 웹브라우저의 "보기>소스보기" 메뉴 사용불가능
?
geusgod 9년 전
@charset "utf-8"; /* Common */ html{overflow-y: scroll;} body{margin:0} p,h1,h2,h3,h4,h5,h6,ul,ol,li,dl,dt,dd,table,th,td,form,fieldset,legend,input,textarea,button,select{margin:0;padding:0} body,input,textarea,select,button,table{font-family:'돋움',dotum,applegothic,sans-s… @charset "utf-8"; /* Common */ html{overflow-y: scroll;} body{margin:0} p,h1,h2,h3,h4,h5,h6,ul,ol,li,dl,dt,dd,table,th,td,form,fieldset,legend,input,textarea,button,select{margin:0;padding:0} body,input,textarea,select,button,table{font-family:'돋움',dotum,applegothic,sans-serif;font-size:12px} img,fieldset{border:0} ul,ol{list-style:none} em,address{font-style:normal} a{color:#666;text-decoration:none} a:hover,a:active,a:focus{color:#666;text-decoration:underline} legend{display:none} table,th,td{border:0 none} hr{display:none} button{overflow:hidden;border:0;cursor:pointer} textarea{overflow:hidden;overflow-y:auto;padding:3px 6px;border:1px solid;border-color:#a3a3a3 #d7d7d7 #d7d7d7 #a3a3a3;line-height:18px;color:#868686;letter-spacing:-1px} .blind{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:1px;height:1px;font-size:0;line-height:0} .chk{width:14px;height:14px;vertical-align:middle} .input_text{height:16px;padding:3px 4px 2px;border:1px solid #b9b9b9;font-size:12px;line-height:16px;color:#666} /*.input_text.focus{border:1px solid #0072bc}*/ .input_text2{height:18px;padding:3px 4px 2px;border:2px solid #b9b9b9;font-size:12px;line-height:18px;color:#666} /*.input_text2.focus1,.input_text3.focus1{border:2px solid #0072bc}*/ .input_text3{height:18px;padding:3px 4px 2px;border:1px solid #b9b9b9;font-size:12px;line-height:16px;color:#666} .input_txt{width:182px;height:16px;margin-right:2px;*margin-top:-1px;padding:4px 4px 1px;border:1px solid #b9b9b9;background:#fff;color:#bbb;letter-spacing:-1px;vertical-align:top} .input_tx{height:16px;margin-right:2px;padding:4px 4px 1px;border:1px solid #b9b9b9;background:#fff;color:#666;vertical-align:middle} /*.input_tx.focus2{border:1px solid #0072bc}*/ img{vertical-align:middle} select{height:19px;line-height:18px} input,select{vertical-align:middle} @charset "utf-8"; /* NHN (developers@xpressengine.com) */ /* HTML Reset*/ body, input, button, textarea, table{font-family:돋움, Dotum, Tahoma, Geneva, sans-serif} html, body{height:100%} html{background:#4c4c4c url(bgBody.gif) center 0 repeat-y} body{margin:0;padding:0;} form, fieldset{border:0;margin:0;padding:0}
?
geusgod 9년 전
@charset "utf-8"; /* Element Reset */ body,table,input,textarea,select,button{font-family:Tahoma,Geneva,sans-serif;font-size:12px} img{border:0} /* Button */ .btn{position:relative;display:inline-block;vertical-align:middle} .btn *{display:inline-block;padding:0 8px;font-size:12p… @charset "utf-8"; /* Element Reset */ body,table,input,textarea,select,button{font-family:Tahoma,Geneva,sans-serif;font-size:12px} img{border:0} /* Button */ .btn{position:relative;display:inline-block;vertical-align:middle} .btn *{display:inline-block;padding:0 8px;font-size:12px;height:24px;line-height:22px;margin:0;font-weight:bold !important;color:#fff;text-decoration:none !important;border:1px solid;cursor:pointer;overflow:visible;border-radius:3px;box-shadow:inset 0 0 1px #fff;background-color:#666;text-shadow:0 -1px 0 #333;zoom:1} .btn *[type=submit][disabled=disabled], .btn *[type=button][disabled=disabled]{opacity:.5;*filter:alpha(opacity=50)} .btn a, .btn button[type=button]{border-color:#ccc;color:#333 !important;background:#eee -webkit-gradient(linear,0% 0%,0% 100%,from(#fff),to(#ddd));background:#eee -moz-linear-gradient(top,#fff,#ddd);background-color:#eee;text-shadow:1px 1px 0 #fff;filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#ffffff, endColorStr=#dddddd)} .btn input, .btn button[type=submit]{border-color:#666;background:#333 -webkit-gradient(linear,0% 0%,0% 100%,from(#777),to(#777),color-stop(0.5,#333),color-stop(0.5,#000)) !important;background:#333 -moz-linear-gradient(top,#777,#000) !important;background-color:#333 !important;color:#ffc !important;filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#777777, endColorStr=#333333)} .btn a{height:22px} .btn.medium *{padding:0 12px;font-size:16px;height:30px;line-height:28px} .btn.medium a{height:28px} .btn.large *{padding:0 18px;font-size:22px;height:36px;line-height:34px} .btn.large a{height:34px} /* Button - Regucy */ span.button, a.button{position:relative;display:inline-block;vertical-align:top} span.button *, a.button *{display:inline-block;padding:0 8px;font-size:12px;height:24px;line-height:22px;margin:0;font-weight:bold !important;color:#fff;text-decoration:none !important;border:1px solid;cursor:pointer;overflow:visible;border-radius:3px;box-shadow:inset 0 0 1px #fff;background-color:#666;text-shadow:0 -1px 0 #333;zoom:1} span.button *[type=submit][disabled=disabled], span.button *[type=button][disabled=disabled]{opacity:.5;*filter:alpha(opacity=50)} a.button span, span.button button[type=button]{border-color:#ccc;color:#333 !important;background:#eee -webkit-gradient(linear,0% 0%,0% 100%,from(#fff),to(#ddd));background:#eee -moz-linear-gradient(top,#fff,#ddd);background-color:#eee;text-shadow:1px 1px 0 #fff;filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#ffffff, endColorStr=#dddddd)} span.button input, span.button button[type=submit]{border-color:#666;background:#333 -webkit-gradient(linear,0% 0%,0% 100%,from(#777),to(#777),color-stop(0.5,#333),color-stop(0.5,#000));background:#333 -moz-linear-gradient(top,#777,#000);background-color:#333;color:#ffc !important;filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#777777, endColorStr=#333333)} a.button span{height:22px} /* Button Area */ .btnArea{margin:1em 0;text-align:right;zoom:1} .btnArea:after{content:"";display:block;clear:both} .btnArea .etc{float:left} /* Text Button */ input[type=submit].text, input[type=button].text, button[type=submit].text, button[type=button].text{border:0;overflow:visible;padding:0;margin:0 4px 0 0;color:#33a !important;background:none;text-decoration:underline;cursor:pointer} /* Popup Menu Area */ #popup_menu_area{position:absolute;background:#fff;border:1px solid #e9e9e9;border-radius:5px;padding:10px;line-height:1.3;box-shadow:0 0 6px #666;font-size:12px;filter:progid:DXImageTransform.Microsoft.Shadow(color=#999999,direction=135, strength=5)} #popup_menu_area ul{list-style:none;margin:0;padding:0} #popup_menu_area li{margin:0;padding:0} #popup_menu_area a{text-decoration:none;color:#333} #popup_menu_area a:hover, #popup_menu_area a:avtive, #popup_menu_area a:focus{text-decoration:underline} /* Message */ .message{border:1px solid #ddd;background:#f8f8f8;margin:1em 0;padding:0 1em;border-radius:5px;line-height:1.4;font-size:12px} body>.message{margin:1em} .message p{margin:1em 0 !important} .message em{font-style:normal;color:#e00} .message.info, .message.error, .message.update{padding-left:55px} .message.info{border-color:#E0E8EC;background:#EDF9FF url(../../common/img/msg.Info.png) no-repeat 1em .5em} .message.error{border-color:#EFDCDC;background:#FFECEC url(../../common/img/msg.error.png) no-repeat 1em .5em} .message.update{border-color:#EAE9DC;background:#FFFDEF url(../../common/img/msg.update.png) no-repeat 1em .5em} /* Waiting for server response */ .wfsr{display:none;position:absolute;position:fixed;left:0;top:0;z-index:100; border:1px solid #EAE9DC;background:#FFFDEF url(../../common/img/msg.loading.gif) no-repeat 1em .5em;margin:1em;padding:1em 1em 1em 55px;border-radius:5px;line-height:1.4;font-size:12px;font-weight:bold} /* Waiting for server response - Modal Window */ .wfsr_fog{position:absolute;top:0;left:0;width:100%;_height:100%;min-height:100%;z-index:100} .wfsr_fog .bg{position:absolute;position:fixed;background:#000;_background:none;width:100%;height:100%;opacity:.5;z-index:2;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);zoom:1} .wfsr_fog .ie6{position:absolute;left:0;top:0;width:100%;height:100%;border:0;opacity:0;filter:alpha(opacity=0);z-index:1} 아래는 몇군데 확인하고 넘어가야 부분들이다. /* Element Reset */ body,table,input,textarea,select,button{font-family:Tahoma,Geneva,sans-serif;font-size:12px} img{border:0} /* Text Button */ input[type=submit].text, input[type=button].text, button[type=submit].text, button[type=button].text{border:0;overflow:visible;padding:0;margin:0 4px 0 0;color:#33a !important;background:none;text-decoration:underline;cursor:pointer} /* Popup Menu Area */ #popup_menu_area{position:absolute;background:#fff;border:1px solid #e9e9e9;border-radius:5px;padding:10px;line-height:1.3;box-shadow:0 0 6px #666;font-size:12px;filter:progid:DXImageTransform.Microsoft.Shadow(color=#999999,direction=135, strength=5)} #popup_menu_area ul{list-style:none;margin:0;padding:0} #popup_menu_area li{margin:0;padding:0} #popup_menu_area a{text-decoration:none;color:#333} #popup_menu_area a:hover, #popup_menu_area a:avtive, #popup_menu_area a:focus{text-decoration:underline} /* Message */ .message{border:1px solid #ddd;background:#f8f8f8;margin:1em 0;padding:0 1em;border-radius:5px;line-height:1.4;font-size:12px} body>.message{margin:1em} .message p{margin:1em 0 !important} .message em{font-style:normal;color:#e00} .message.info, .message.error, .message.update{padding-left:55px} .message.info{border-color:#E0E8EC;background:#EDF9FF url(../../common/img/msg.Info.png) no-repeat 1em .5em} .message.error{border-color:#EFDCDC;background:#FFECEC url(../../common/img/msg.error.png) no-repeat 1em .5em} .message.update{border-color:#EAE9DC;background:#FFFDEF url(../../common/img/msg.update.png) no-repeat 1em .5em} /* Waiting for server response */ .wfsr{display:none;position:absolute;position:fixed;left:0;top:0;z-index:100; border:1px solid #EAE9DC;background:#FFFDEF url(../../common/img/msg.loading.gif) no-repeat 1em .5em;margin:1em;padding:1em 1em 1em 55px;border-radius:5px;line-height:1.4;font-size:12px;font-weight:bold} /* Waiting for server response - Modal Window */ .wfsr_fog{position:absolute;top:0;left:0;width:100%;_height:100%;min-height:100%;z-index:100} .wfsr_fog .bg{position:absolute;position:fixed;background:#000;_background:none;width:100%;height:100%;opacity:.5;z-index:2;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);zoom:1} .wfsr_fog .ie6{position:absolute;left:0;top:0;width:100%;height:100%;border:0;opacity:0;filter:alpha(opacity=0);z-index:1}
?
클론 9년 전
@charset "utf-8"; /* Common */ html{overflow-y: scroll;} body{margin:0} p,h1,h2,h3,h4,h5,h6,ul,ol,li,dl,dt,dd,table,th,td,form,fieldset,legend,input,textarea,button,select{margin:0;padding:0} body,input,textarea,select,button,table{font-family:'돋움',dotum,applegothic,sans-s… @charset "utf-8"; /* Common */ html{overflow-y: scroll;} body{margin:0} p,h1,h2,h3,h4,h5,h6,ul,ol,li,dl,dt,dd,table,th,td,form,fieldset,legend,input,textarea,button,select{margin:0;padding:0} body,input,textarea,select,button,table{font-family:'돋움',dotum,applegothic,sans-serif;font-size:12px} img,fieldset{border:0} ul,ol{list-style:none} em,address{font-style:normal} a{color:#666;text-decoration:none} a:hover,a:active,a:focus{color:#666;text-decoration:underline} legend{display:none} table,th,td{border:0 none} hr{display:none} button{overflow:hidden;border:0;cursor:pointer} textarea{overflow:hidden;overflow-y:auto;padding:3px 6px;border:1px solid;border-color:#a3a3a3 #d7d7d7 #d7d7d7 #a3a3a3;line-height:18px;color:#868686;letter-spacing:-1px} .blind{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:1px;height:1px;font-size:0;line-height:0} .chk{width:14px;height:14px;vertical-align:middle} .input_text{height:16px;padding:3px 4px 2px;border:1px solid #b9b9b9;font-size:12px;line-height:16px;color:#666} /*.input_text.focus{border:1px solid #0072bc}*/ .input_text2{height:18px;padding:3px 4px 2px;border:2px solid #b9b9b9;font-size:12px;line-height:18px;color:#666} /*.input_text2.focus1,.input_text3.focus1{border:2px solid #0072bc}*/ .input_text3{height:18px;padding:3px 4px 2px;border:1px solid #b9b9b9;font-size:12px;line-height:16px;color:#666} .input_txt{width:182px;height:16px;margin-right:2px;*margin-top:-1px;padding:4px 4px 1px;border:1px solid #b9b9b9;background:#fff;color:#bbb;letter-spacing:-1px;vertical-align:top} .input_tx{height:16px;margin-right:2px;padding:4px 4px 1px;border:1px solid #b9b9b9;background:#fff;color:#666;vertical-align:middle} /*.input_tx.focus2{border:1px solid #0072bc}*/ img{vertical-align:middle} select{height:19px;line-height:18px} input,select{vertical-align:middle} @charset "utf-8"; /* NHN (developers@xpressengine.com) */ /* HTML Reset*/ body, input, button, textarea, table{font-family:돋움, Dotum, Tahoma, Geneva, sans-serif} html, body{height:100%} html{background:#4c4c4c url(bgBody.gif) center 0 repeat-y} body{margin:0;padding:0;} form, fieldset{border:0;margin:0;padding:0}
?
클론 9년 전
@charset "utf-8"; /* Element Reset */ body,table,input,textarea,select,button{font-family:Tahoma,Geneva,sans-serif;font-size:12px} img{border:0} /* Button */ .btn{position:relative;display:inline-block;vertical-align:middle} .btn *{display:inline-block;padding:0 8px;font-size:12p… @charset "utf-8"; /* Element Reset */ body,table,input,textarea,select,button{font-family:Tahoma,Geneva,sans-serif;font-size:12px} img{border:0} /* Button */ .btn{position:relative;display:inline-block;vertical-align:middle} .btn *{display:inline-block;padding:0 8px;font-size:12px;height:24px;line-height:22px;margin:0;font-weight:bold !important;color:#fff;text-decoration:none !important;border:1px solid;cursor:pointer;overflow:visible;border-radius:3px;box-shadow:inset 0 0 1px #fff;background-color:#666;text-shadow:0 -1px 0 #333;zoom:1} .btn *[type=submit][disabled=disabled], .btn *[type=button][disabled=disabled]{opacity:.5;*filter:alpha(opacity=50)} .btn a, .btn button[type=button]{border-color:#ccc;color:#333 !important;background:#eee -webkit-gradient(linear,0% 0%,0% 100%,from(#fff),to(#ddd));background:#eee -moz-linear-gradient(top,#fff,#ddd);background-color:#eee;text-shadow:1px 1px 0 #fff;filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#ffffff, endColorStr=#dddddd)} .btn input, .btn button[type=submit]{border-color:#666;background:#333 -webkit-gradient(linear,0% 0%,0% 100%,from(#777),to(#777),color-stop(0.5,#333),color-stop(0.5,#000)) !important;background:#333 -moz-linear-gradient(top,#777,#000) !important;background-color:#333 !important;color:#ffc !important;filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#777777, endColorStr=#333333)} .btn a{height:22px} .btn.medium *{padding:0 12px;font-size:16px;height:30px;line-height:28px} .btn.medium a{height:28px} .btn.large *{padding:0 18px;font-size:22px;height:36px;line-height:34px} .btn.large a{height:34px} /* Button - Regucy */ span.button, a.button{position:relative;display:inline-block;vertical-align:top} span.button *, a.button *{display:inline-block;padding:0 8px;font-size:12px;height:24px;line-height:22px;margin:0;font-weight:bold !important;color:#fff;text-decoration:none !important;border:1px solid;cursor:pointer;overflow:visible;border-radius:3px;box-shadow:inset 0 0 1px #fff;background-color:#666;text-shadow:0 -1px 0 #333;zoom:1} span.button *[type=submit][disabled=disabled], span.button *[type=button][disabled=disabled]{opacity:.5;*filter:alpha(opacity=50)} a.button span, span.button button[type=button]{border-color:#ccc;color:#333 !important;background:#eee -webkit-gradient(linear,0% 0%,0% 100%,from(#fff),to(#ddd));background:#eee -moz-linear-gradient(top,#fff,#ddd);background-color:#eee;text-shadow:1px 1px 0 #fff;filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#ffffff, endColorStr=#dddddd)} span.button input, span.button button[type=submit]{border-color:#666;background:#333 -webkit-gradient(linear,0% 0%,0% 100%,from(#777),to(#777),color-stop(0.5,#333),color-stop(0.5,#000));background:#333 -moz-linear-gradient(top,#777,#000);background-color:#333;color:#ffc !important;filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#777777, endColorStr=#333333)} a.button span{height:22px} /* Button Area */ .btnArea{margin:1em 0;text-align:right;zoom:1} .btnArea:after{content:"";display:block;clear:both} .btnArea .etc{float:left} /* Text Button */ input[type=submit].text, input[type=button].text, button[type=submit].text, button[type=button].text{border:0;overflow:visible;padding:0;margin:0 4px 0 0;color:#33a !important;background:none;text-decoration:underline;cursor:pointer} /* Popup Menu Area */ #popup_menu_area{position:absolute;background:#fff;border:1px solid #e9e9e9;border-radius:5px;padding:10px;line-height:1.3;box-shadow:0 0 6px #666;font-size:12px;filter:progid:DXImageTransform.Microsoft.Shadow(color=#999999,direction=135, strength=5)} #popup_menu_area ul{list-style:none;margin:0;padding:0} #popup_menu_area li{margin:0;padding:0} #popup_menu_area a{text-decoration:none;color:#333} #popup_menu_area a:hover, #popup_menu_area a:avtive, #popup_menu_area a:focus{text-decoration:underline} /* Message */ .message{border:1px solid #ddd;background:#f8f8f8;margin:1em 0;padding:0 1em;border-radius:5px;line-height:1.4;font-size:12px} body>.message{margin:1em} .message p{margin:1em 0 !important} .message em{font-style:normal;color:#e00} .message.info, .message.error, .message.update{padding-left:55px} .message.info{border-color:#E0E8EC;background:#EDF9FF url(../../common/img/msg.Info.png) no-repeat 1em .5em} .message.error{border-color:#EFDCDC;background:#FFECEC url(../../common/img/msg.error.png) no-repeat 1em .5em} .message.update{border-color:#EAE9DC;background:#FFFDEF url(../../common/img/msg.update.png) no-repeat 1em .5em} /* Waiting for server response */ .wfsr{display:none;position:absolute;position:fixed;left:0;top:0;z-index:100; border:1px solid #EAE9DC;background:#FFFDEF url(../../common/img/msg.loading.gif) no-repeat 1em .5em;margin:1em;padding:1em 1em 1em 55px;border-radius:5px;line-height:1.4;font-size:12px;font-weight:bold} /* Waiting for server response - Modal Window */ .wfsr_fog{position:absolute;top:0;left:0;width:100%;_height:100%;min-height:100%;z-index:100} .wfsr_fog .bg{position:absolute;position:fixed;background:#000;_background:none;width:100%;height:100%;opacity:.5;z-index:2;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);zoom:1} .wfsr_fog .ie6{position:absolute;left:0;top:0;width:100%;height:100%;border:0;opacity:0;filter:alpha(opacity=0);z-index:1} 아래는 몇군데 확인하고 넘어가야 부분들이다. /* Element Reset */ body,table,input,textarea,select,button{font-family:Tahoma,Geneva,sans-serif;font-size:12px} img{border:0} /* Text Button */ input[type=submit].text, input[type=button].text, button[type=submit].text, button[type=button].text{border:0;overflow:visible;padding:0;margin:0 4px 0 0;color:#33a !important;background:none;text-decoration:underline;cursor:pointer} /* Popup Menu Area */ #popup_menu_area{position:absolute;background:#fff;border:1px solid #e9e9e9;border-radius:5px;padding:10px;line-height:1.3;box-shadow:0 0 6px #666;font-size:12px;filter:progid:DXImageTransform.Microsoft.Shadow(color=#999999,direction=135, strength=5)} #popup_menu_area ul{list-style:none;margin:0;padding:0} #popup_menu_area li{margin:0;padding:0} #popup_menu_area a{text-decoration:none;color:#333} #popup_menu_area a:hover, #popup_menu_area a:avtive, #popup_menu_area a:focus{text-decoration:underline} /* Message */ .message{border:1px solid #ddd;background:#f8f8f8;margin:1em 0;padding:0 1em;border-radius:5px;line-height:1.4;font-size:12px} body>.message{margin:1em} .message p{margin:1em 0 !important} .message em{font-style:normal;color:#e00} .message.info, .message.error, .message.update{padding-left:55px} .message.info{border-color:#E0E8EC;background:#EDF9FF url(../../common/img/msg.Info.png) no-repeat 1em .5em} .message.error{border-color:#EFDCDC;background:#FFECEC url(../../common/img/msg.error.png) no-repeat 1em .5em} .message.update{border-color:#EAE9DC;background:#FFFDEF url(../../common/img/msg.update.png) no-repeat 1em .5em} /* Waiting for server response */ .wfsr{display:none;position:absolute;position:fixed;left:0;top:0;z-index:100; border:1px solid #EAE9DC;background:#FFFDEF url(../../common/img/msg.loading.gif) no-repeat 1em .5em;margin:1em;padding:1em 1em 1em 55px;border-radius:5px;line-height:1.4;font-size:12px;font-weight:bold} /* Waiting for server response - Modal Window */ .wfsr_fog{position:absolute;top:0;left:0;width:100%;_height:100%;min-height:100%;z-index:100} .wfsr_fog .bg{position:absolute;position:fixed;background:#000;_background:none;width:100%;height:100%;opacity:.5;z-index:2;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);zoom:1} .wfsr_fog .ie6{position:absolute;left:0;top:0;width:100%;height:100%;border:0;opacity:0;filter:alpha(opacity=0);z-index:1}
이온디
이온디 10년 전
기존의 상용 차트 라이브러리와 오픈소스 차트 라이브러리는 다양한 종류의 차트를 구현할 수 있지만 데이터를 시각적으로 표현하는 데만 중점을 둡니다. 그렇기 때문에 스크린 리더 등의 보조 기기로 차트에 접근하면 스크린 리더가 차트 자체를 이미지로 판단해 전달하려는 실질적인 데이터는 읽을 수 없습니다. 네이버에서 차트 라이브러리를 개발하게 된 계기는 네이버 사이트의 접근성 현황을 효율적으로 표현할 방법이 필요했기 때문입니다. 지침별 수준을 수치화하는 폴리곤 모양의 레이더 차트가 필요하다고 판단하… 기존의 상용 차트 라이브러리와 오픈소스 차트 라이브러리는 다양한 종류의 차트를 구현할 수 있지만 데이터를 시각적으로 표현하는 데만 중점을 둡니다. 그렇기 때문에 스크린 리더 등의 보조 기기로 차트에 접근하면 스크린 리더가 차트 자체를 이미지로 판단해 전달하려는 실질적인 데이터는 읽을 수 없습니다. 네이버에서 차트 라이브러리를 개발하게 된 계기는 네이버 사이트의 접근성 현황을 효율적으로 표현할 방법이 필요했기 때문입니다. 지침별 수준을 수치화하는 폴리곤 모양의 레이더 차트가 필요하다고 판단하여 오픈소스 기반의 차트를 사용하려 했습니다. 그러나 원하는 정보를 표현할 수 있는 차트를 제공하는 라이브러리를 찾지 못해 내부에서 직접 차트 라이브러리를 개발하기로 결정했습니다. 개발 초기에는 폴리곤 형태를 표현할 수 있는 레이더 차트의 개발만 염두에 두었습니다. 이후 다른 형태의 정보를 효율적으로 표현할 수 있는 Polar Pie 차트, 비교 차트 등 기존의 라이브러리에서 찾아볼 수 없는 여러 형태의 차트를 추가해 종합 차트 라이브러리인 Nwagon(http://html.nhncorp.com/nwagon) 을 개발했습니다. 그리고 여러 곳에 널리 사용되기를 바라는 마음으로 Nwagon을 NULI 사이트(http://html.nhncorp.com) 에 오픈소스로 공개했습니다. 'Nwagon'이라는 이름은 접근성을 뜻하는 'web accessibility'와 라이브러리 개발의 계기가 된 'polygon'의 'gon'을 조합해 만든 이름입니다. 이름이 뜻하는 대로 추가 작업이 없어도 차트를 볼 수 없는 사용자들에게 동일한 정보를 제공할 수 있도록 접근성을 향상시킨 차트 라이브러리입니다. 이 글에서는 Nwagon의 특징과 간단한 사용 방법을 소개하겠습니다. Nwagon의 특징 접근성 데이터 포함 Nwagon이 기존의 차트 라이브러리와 다른 점 중에 가장 눈에 띄는 점은 자동으로 삽입되는 접근성 데이터일 것이다. 기존의 차트 라이브러리를 사용하면 사용자에게 전달되어야 하는 정보가 차트라는 시각적인 요소로 웹에 표현된다. 이 차트에 스크린 리더와 같은 보조 기기로 접근하면 차트가 단순한 이미지로만 판단되어 정보 전달이 이루어지지 않게 된다. 기존 라이브러리로 차트를 구현하면 접근성을 보장하기 위해 추가적인 작업이 필요하다. Nwagon을 사용하면 차트를 구현하는 동시에, 제공된 정보가 보조 기기를 통해서도 전달될 수 있도록 텍스트 형태의 정보를 자동으로 삽입한다. 삽입된 정보는 화면에서는 보이지 않게 처리하여 디자인 구성을 방해하지 않는다. 다음 그림은 Nwagon이 제공하는 텍스트 형태의 정보를 Chrome의 개발자 도구로 펼쳐 본 모습이다. 그림 1 접근성을 위해 자동으로 삽입되는 텍스트 형태의 정보 새로운 형태의 차트 구현 Nwagon으로 구현할 수 있는 차트의 종류는 약 11가지 정도다. 이 중에서 라인 차트나 칼럼 차트는 비교적 구현이 쉽고 구현 방법이 보편화되어 있어 다른 여러 라이브러리도 많이 제공한다. Nwagon을 개발할 때는 이러한 일반적인 차트에서 벗어나 복잡한 데이터를 좀 더 효율적으로 표현하는 방법을 찾기 위해 노력했다. 그렇게 해서 개발된 대표적인 차트로 Polar Area 차트와 Polar Pie 차트, 비교 차트 등을 꼽을 수 있다. Polar Area 차트 Polar Area 차트는 우리가 알고 있는 파이 차트와 흡사하다. 파이 차트에서는 나눠진 부채꼴의 반지름은 모두 같고 나타내려는 값으로 부채꼴의 각도를 결정한다. 반면에 Polar Area 차트에서는 표현하려는 항목의 수에 따라 일률적으로 부채꼴의 각도가 정해지고, 나타내려는 값은 부채꼴의 반지름으로 표현된다. 또한 하나의 원을 원하는 개수만큼 나누어 표현할 수도 있다. 채색된 영역의 투명도도 설정할 수 있다. Polar Area 차트는 주기적으로 일어나는 일을 기록하는 데 유용하게 쓰일 수 있다. 다음은 온도가 낮을수록 투명도가 높아지는 차트를 구현하는 코드의 예다. 예제 1 Polar Area 차트를 구현하기 위해 쓰인 코드 'dataset': { title: 'Average monthly temp', values:[[42, 55, 66], [75, 88, 97],[77,65,45], [30, 15, 25]], colorset: ['#3EB400', '#DC143C', '#2BC8C9', '#666666'], fields: ['Sping', 'Summer', 'Fall', ;Winter'], opacity:[0.3, 0.5, 0.7, 0.9] }, 위의 코드로 구현한 Polar Area 차트는 다음과 같다. 그림 2 Polar Area 차트 Polar Pie 차트 Polar Pie 차트는 Polar Area 차트를 변형한 차트다. Polar Area 차트에서는 부채꼴의 각도가 항목의 개수에 의해 결정된다. 하지만 Polar Pie 차트에서는 부채꼴의 각도가 데이터 값을 결정하는데 사용된 하위 항목의 개수에 따라 결정된다. 예를 들어, 분당구에 있는 종합 병원의 환자별 평균 진료비와 집계에 포함된 환자의 수를 동시에 표현할 때 Polar Pie 차트가 유용하게 쓰일 수 있다. 표 1 Polar Pie 차트의 데이터 예제 병원 환자의 수 평균 진료비(단위: 천 원) A 510 32 B 180 78 C 310 42 Nwagon으로 구현한 다음 차트에서 위 표에 있는 평균 진료비는 부채꼴의 반지름에 반영되어 있다. 집계에 참여한 환자의 수는 부채꼴의 각도를 결정하는데 사용되었다. 그림 3 Polar Pie 차트 Polar Pie 차트는 네이버 서비스의 접근성 현황을 집계해 보여 주는 사내 시스템인 N-WARS(NAVER Web Accessibility Reporting System)에서 본부별 접근성 현황과 평균을 집계하는 데 쓰인 본부별 표본 페이지의 개수를 동시에 보여 줄 때 실제로 사용된다. 비교 차트 비교 차트는 개발 업무에 종종 쓰이는 이슈 트래킹 시스템인 JIRA에서 착안하여 개발한 차트다. 일반적으로 사용하는 영역 차트(area chart)와 유사하지만 분명하게 다른 점이 있다. 영역 차트에서는 데이터 세트를 여러 개 사용해도 무방하지만, 비교 차트에서는 데이터 세트를 두 개만 사용해야 한다. 비교 차트는 두 개의 데이터를 비교해 그 차이를 극명하게 보여 주는 것이 목적이기 때문이다. 비교 차트는 다음 그림처럼 경쟁사와 판매 수익의 차이를 표현하는 데 효율적으로 사용될 수 있다. 그림 4 테이터의 차이를 색으로 표현하여 우열 관계를 표시하는 비교 차트 레이더 차트 강화 부분 비활성화 레이더 차트에 보편적으로 쓰는 데이터에는 한 개 이상의 영역에 '해당 없음(N/A)' 값이 입력될 수 있다. 기존 차트 라이브러리는 '0'인 값과 '해당 없음' 값을 표현할 때 차이가 없다. 이를 구별해서 보이려면 이미지를 추가로 겹치는 등 별도의 작업이 필요하다. 이러면 마크업 작업에도 어려움이 있고, 이미지에 가려진 차트 부분이 제 기능(예를 들어, 마우스 이벤트나 클릭 이벤트에 반응하기)을 할 수 없어 또 다른 문제가 일어날 수도 있다. 이 문제를 해결하기 위해 '해당 없음'이나 'N/A'로 표기된 영역을 라이브러리가 자동으로 처리하게 했다. '0'인 값과 구별함은 물론 차트에 적용된 이벤트 등의 사용에도 문제가 없게 됐다. 그림 5 Epilepsy Prevent 영역이 비활성화 된 레이더 차트 겹쳐 보이기 기능 레이더 차트를 사용할 때 여러 개의 데이터 세트를 한 배경 위에 겹쳐 그려 목표에 어느 정도 도달했는지 측정하는 경우가 있다. 기존 차트 라이브러리에서는 그리는 폴리곤의 수만큼 배경이 그려지기 때문에 뜻하지 않게 중복되는 배경이 생겨 배경이 흐리게 보일 수 있고, 불필요한 요소를 렌더링하기 때문에 배경의 수가 많을수록 성능도 저하된다. Nwagon은 JSON 데이터에 값을 추가하는 간단한 방법으로 이 문제를 해결한다. 다음 예처럼 두 세트 이상의 데이터가 있으면 하나의 배경에 겹쳐서 그리기를 자동으로 실행한다. 아래는 데이터 세트를 추가한 코드의 예다. 예제 2 겹침 기능을 위해 추가된 데이터 세트의 예 'dataset': { title: 'Web accessibility status', values:[[74, 93, 67, 23, 78, 45, 69, 98], [65, 84, 67, 85,89, 67, 95, 67], [89, 87, 95, 65, 34, 67, 85, 45]], bgColor: '#F9F9F9', fgVolor: '#DC143C' }, 다음은 위의 데이터를 이용해 Nwagon으로 구현한 레이더 차트다. 그림 6 데이터가 겹쳐진 레이더 차트 SVG 기반으로 빠르고 선명한 그래프 생성 Nwagon은 빠른 렌더링과 고화질을 강점으로 꼽는 SVG(scalable vector graphics)를 기반으로 개발되었다. SVG는 또한 객체 하나하나를 DOM 요소로 간주하여 CSS 속성과 이벤트를 DOM 요소와 동일하게 적용할 수 있다. 다음 그림은 jQuery 사용자들 사이에서 많이 쓰이는, Canvas 기반의 jqPlot 라이브러리로 구현한 파이 차트와 SVG 기반의 Nwagon으로 구현한 파이 차트를 비교한 그림이다. 원과 구분선이 Canvas를 기반으로 한 그래프보다 선명한 것을 확인할 수 있다. 그림 7 Canvas 기반의 차트(왼쪽)와 SVG 기반의 차트(오른쪽) 사용 방법 소스코드 다운로드 Nwagon 사용 방법은 다른 라이브러리의 사용 방법과 비슷하다. Nwagon 페이지(http://html.nhncorp.com/nwagon) 에서 소스코드를 다운로드한 다음 차트를 구현할 페이지에 CSS 파일과 JS 파일을 포함시킨다. <link rel="stylesheet" href="Nwagon.css" type="text/css"> <script src="Nwagon.js"></script> JSON 문법 차트를 구현하기 전에 준비해야 할 것은 JSON 형태의 데이터다. 차트의 종류에 따라 차이가 있으나 기본 형식은 다음과 같다. 차트 종류별로 더 자세한 사용 방법은 Nwagon 페이지를 참고한다. 표 2 레이터 차트를 위한 JSON 데이터 형식 키 이름 값의 형식 설명 legend JSON 객체 차트 항목의 이름과 링크 정보 names 문자열 차트 항목의 이름 hrefs 배열 항목에 링크할 URL로 이루어진 배열(선택) dataset JSON 객체 차트의 기본 정보와 차트에 표시할 값 title 문자열 차트의 제목 values 배열 차트 항목의 값으로 이루어진 배열 bgColor 문자열 차트의 배경색(예: #f9f9f9) fgColor 문자열 차트 항목의 값을 연결해 생성된 폴리곤의 색깔(예: #30a1ce) chartDiv 문자열 차트를 그릴 DIV 요소의 ID chartType 문자열 차트 종류 chartSize JSON 객체 차트의 크기 정보 width 숫자 차트의 너비(단위: 픽셀) height 숫자 차트의 높이(단위: 픽셀) 다음은 JSON으로 데이터를 생성해 레이더 차트를 구현하는 예제 코드다. 예제 3 레이더 차트를 위한 JSON 데이터 예제 <div id="Nwagon"></div> <script> var options = { 'legend':{ names: [ 'Perceivable', 'Information Loss', 'Understandable', 'Enough Time', 'Epilepsy Prevent', 'Operable', 'Navigation', 'Error Prevent' ], hrefs: [ 'http://nuli.nhncorp.com/accessibility#k1', 'http://nuli.nhncorp.com/accessibility#k2', 'http://nuli.nhncorp.com/accessibility#k3', 'http://nuli.nhncorp.com/accessibility#k4', 'http://nuli.nhncorp.com/accessibility#k5', 'http://nuli.nhncorp.com/accessibility#k6', 'http://nuli.nhncorp.com/accessibility#k7', 'http://nuli.nhncorp.com/accessibility#k8' ] }, 'dataset': { title: 'Web accessibility status', values: [[34,53,67,23,78,45,69,98]], bgColor: '#f9f9f9', fgColor: '#30a1ce', }, 'chartDiv': 'Nwagon', 'chartType': 'radar', 'chartSize': { width: 500, height: 300 } }; Nwagon.chart(options); </script> 위의 코드로 구현한 레이더 차트는 다음과 같다. 그림 8 레이더 차트 마치며 웹 페이지에서 제공하는 정보의 형태가 일반 텍스트를 넘어서 그래프, 이미지, 동영상, 애니메이션 등 점점 더 다양해지고 있다. 한편으로는 정보의 종류가 다양해지고 풍부해짐을 의미하지만, 접근성 측면에서 생각하면 그만큼 다양한 혜택에서 소외당하는 사용자가 생겨날 수 있음을 의미하기도 한다. 접근성 데이터를 고려한 차트를 개발하게 된 계기도 정보를 어떤 형태로 제공하든지 모든 사용자에게 동일한 정보를 제공해야 한다는 웹의 근본이념을 고려했으면 하는 바람에서였다. 필요하면 그때 가서 처리하면 되겠지 하는 생각을 버리고 시작부터 접근성을 염두에 둔다면 시간과 노력을 줄일 수 있을 뿐 아니라 사용자의 만족도 또한 높아질 것이다. Nwagon 개발 초기에는 네이버의 사내 시스템에서 사용할 작은 라이브러리를 만드는 것이 목표였는데 이런저런 아이디어를 담다 보니 독창적이고 신선한 그래프들이 탄생했다. 오픈소스로 공개되는 만큼 많은 사용자의 의견을 받아 완성도를 높이는 작업을 지속적으로 시행할 예정이다. 새로운 차트 종류에 대한 아이디어도 같이 공유했으면 하는 바람이다.
이온디
이온디 10년 전
한국의 전통 색상표 출처 : http://study4you.kr/xe/pds/752 무채색계(無彩色界) - 10색 흑백 1D1E23 93,89,83,52 백색 FFFFFF 0,0,0,0 회색 A4AAA7 38,27,31,… 한국의 전통 색상표 출처 : http://study4you.kr/xe/pds/752 무채색계(無彩色界) - 10색 흑백 1D1E23 93,89,83,52 백색 FFFFFF 0,0,0,0 회색 A4AAA7 38,27,31,0 구색 959EA2 45,32,32,0 치색 616264 72,64,62,4 연지회색 6F606E 55,58,40,20 설백색 DDE7E7 12,4,7,0 유배색 E7E6D2 9,5,18,0 지배색 E3DDCB 6,6,17,4 소색 D8C8B2 10,15,26,5 적색계(赤色界) - 21색 적색 B82647 21,98,68,8 홍색 F15B5B 0,80,60,0 적토색 9F494C 29,80,64,17 휴색 683235 40,80,66,44 갈색 966147 31,61,73,21 호박색 BD7F41 21,51,84,8 추향색 C38866 19,48,61,6 육색 D77964 11,62,59,2 주색 CA5E59 15,75,62,4 주홍색 C23352 18,94,60,5 담주색 EA8474 4,59,50,0 진홍색 BF2F7B 20,94,17,4 선홍색 CE5A9E 16,79,2,0 연지색 BE577B 19,77,28,7 훈색 D97793 9,64,20,2 진분홍색 DB4E9C 9,84,0,0 분홍색 E2A6B4 7,39,14,1 연분홍색 E0709B 6,69,11,1 장단색 E16350 6,75,70,1 석간주색 8A4C44 30,71,65,30 흑홍색 8E6F80 40,54,31,15 청록색계(靑綠色界) - 32색 청색 0B6DB7 89,56,0,0 벽색 00B5E3 73,5,4,0 천청색 5AC6D0 59,0,20,0 담청색 00A6A9 96,4,40,0 취람색 5DC19B 62,0,51,0 양람색 6C71B5 64,58,0,0 벽청색 448CCB 72,36,0,0 청현색 006494 99,59,22,3 감색 026892 93,57,26,2 남색 6A5BA8 68,73,0,0 연람색 7963AB 60,69,0,0 벽람색 6979BB 64,52,0,0 숙람색 45436C 86,84,40,9 군청색 4F599F 80,73,6,0 녹색 417141 82,44,95,9 명록색 16AA52 81,5,94,0 유록색 6AB048 64,8,97,0 유청색 569A49 72,20,96,1 연두색 C0D84D 29,0,87,0 춘유록색 CBDD61 24,0,78,0 청록색 009770 97,15,74,0 진초록색 0A8D5E 87,26,82,1 초록색 1C9249 85,20,98,2 흑록색 2E674E 89,52,83,9 비색 72C6A5 55,0,45,0 옥색 9ED6C0 38,0,30,0 삼청색 5C6EB4 71,59,0,0 뇌록색 397664 74,27,59,6 양록색 31B675 74,0,74,0 하염색 245441 83,43,75,39 흑청색 1583AF 84,39,17,0 청벽색 18B4E9 69,8,0,0 황색계(黃色界) - 16색 황색 F9D537 3,13,89,0 유황색 EBBC6B 6,25,67,1 명황색 FEE134 2,7,89,0 담황색 F5F0C5 4,2,27,0 송화색 F8E77F 4,4,62,0 자황색 F7B938 2,29,89,0 행황색 F1A55A 3,40,73,0 두록색 E5B98F 8,27,45,1 적황색 ED9149 4,51,80,0 토황색 C8852C 18,50,97,5 지황색 D6B038 14,26,91,3 토색 9A6B31 30,54,91,20 치자색 F6CF7A 3,18,61,0 홍황색 DDA28F 9,39,38,2 자황색 BB9E8B 22,33,40,7 금색 코드값이 없습니다. 자색계(紫色界) - 11색 자색 6D1B43 41,95,45,40 자주색 89236A 40,96,18,20 보라색 9C4998 42,85,1,1 홍람색 733E7F 58,85,10,15 포도색 5D3462 70,90,35,20 청자색 403F95 90,90,1,1 벽자색 84A7D3 47,25,1,1 회보라색 B3A7CD 28,32,1,1 담자색 BEA3C9 23,36,1,1 다자색 47302E 75,86,85,35 적자색 BA4160 15,86,42,13
이온디
이온디 10년 전
천연소가죽(물소,버팔로, 내츄럴가죽)과 독고가죽(속피가죽) 구분요령 ⊙ 소파에 사용되는 가죽 1.물소가죽(버팔로, 내츄럴가죽)은 부위에 따라 다르게 나타납니다. -목,배부분은 주름이 크고 많으므로 소파, 가방, 핸드백등의 옆, 밑,뒷부분등에 사용합니다 -등,허리,엉덩이 부분은 가죽이 매끈하여 앞쪽, 윗부분, 주로 사람이 많이 사용하는 부분에 사용합니다. ※ 가죽소파의 경우 부위별로 무늬가 다른 것을 발견할 수 있습니다. 이것은 가죽의 하자가 아니라 오… 천연소가죽(물소,버팔로, 내츄럴가죽)과 독고가죽(속피가죽) 구분요령 ⊙ 소파에 사용되는 가죽 1.물소가죽(버팔로, 내츄럴가죽)은 부위에 따라 다르게 나타납니다. -목,배부분은 주름이 크고 많으므로 소파, 가방, 핸드백등의 옆, 밑,뒷부분등에 사용합니다 -등,허리,엉덩이 부분은 가죽이 매끈하여 앞쪽, 윗부분, 주로 사람이 많이 사용하는 부분에 사용합니다. ※ 가죽소파의 경우 부위별로 무늬가 다른 것을 발견할 수 있습니다. 이것은 가죽의 하자가 아니라 오히려 고급 천연가죽(물소,버팔로, 내츄럴가죽)임을 유념하시길... . 전체면이 고른 것은 독고가죽(속피가죽의 은면코팅)입니다. 2.독고가죽이란? 1)소가죽에서 은면층(가죽겉판)을 한 겹을 벗겨낸다음 그 다음 가죽을 가공 염색처리를 하여 가죽처럼 만든 것을 말합니다. 2)보통가죽가격보다 1/2가격이므로 판촉물 가죽에 많이 사용하며, 소파에는 저렴한 가격대에 사용합니다. 3)두께가 일정하고 은면코팅이 두껍지 않으며, 늘리거나 구긴 후 복원력이 좋으면 좋은 가죽임. 실용성있는 가죽을 원하시면 양피보다 우피가 내구성이 좋습니다. 4)은면이 매끈하며 깔끔하고 시각적인 아름다움이 있는 것도 좋은 가죽이라 할 수 있습니다. ※ 소파에서 사용되는 대부분의 가죽은 우피(소가죽)입니다. 소비자가 가구점에서 가죽소파를 구입하려할 경우, 물소가죽, 버팔로가죽, 내츄럴가죽 또한 천연소가죽, 면피가죽,속피가죽,독고가죽. 엠보가죽 등 여러 가지로 가죽에 대한 설명을 듣게 되는데 이해하는데 난감할 경우가 많습니다. 1)가구점에서 물소가죽, 버팔로가죽, 내츄럴가죽을 혼용하여 사용하며, 두께는 약 3mm내외, 평당 약 2,500원-3,000원 2) 독고가죽은 가구점에서 속피가죽으로 불리우고 있습니다.(가구점에서 물소 또는 버팔로가죽이라하지않고 소가죽 또는 천연가죽이라 하면 대부분 속피가죽을 말합니다.) 또한 엠보가죽은 속피가죽을 은면코팅하면서 울퉁불퉁하게 무늬를 나타나게한 가죽을 말하며 은면이 깔끔한 가죽에 비해 약간 비싼편입니다. 두께는 약1.5mm내외이며 평당 단가는 약1.500원 3)최근들어 면피 가죽을 사용하는 소파가 많아졌습니다. 면피가죽은 속피가죽에 비해 부드럽습니다. 가격도 조금 비싸구요 일반적으로 가방,핸드백 구두 지갑 소파등에서 90%이상이 소가죽을 사용하고 있다 . .외국소한마리는 50-60평 .한국소한마리 40-44평 .카프(calf)는 6개월미만의 송아지 가죽을 말한다.(한마리8-11평) .버팔로가죽은17-21평 .크기는 보통 1평(스퀘어 피 : 30.38 X 30.39 =929 cm2) [출처] ◈ 천연소가죽(물소,버팔로, 내츄럴가죽)과 독고가죽(속피가죽) 구분요령|작성자 아르누보
이온디
이온디 10년 전
※ 비혼(非婚) 여성들의 귀농, 귀촌 이야기를 담은 기획 “이 언니의 귀촌” 기사가 연재됩니다. 이 시리즈는 한국언론진흥재단 언론진흥기금의 지원을 통해 제작됩니다. [편집자 주] ‘여자들을 위한 민박이 있다면 좋겠다’ 가평으로 이주하면서 주 40시간 전일제 노동 시장을 떠나기로 이미 마음먹은 터, 다양한 방식의 먹고 살 길을 개척해야 한다. 게스트하우스에 대한 생각은 몇 년 전부터 막연하게, 혹은 구체적으로 가지고 있었던 것 같다. 혼자 여행을… ※ 비혼(非婚) 여성들의 귀농, 귀촌 이야기를 담은 기획 “이 언니의 귀촌” 기사가 연재됩니다. 이 시리즈는 한국언론진흥재단 언론진흥기금의 지원을 통해 제작됩니다. [편집자 주] ‘여자들을 위한 민박이 있다면 좋겠다’ 가평으로 이주하면서 주 40시간 전일제 노동 시장을 떠나기로 이미 마음먹은 터, 다양한 방식의 먹고 살 길을 개척해야 한다. 게스트하우스에 대한 생각은 몇 년 전부터 막연하게, 혹은 구체적으로 가지고 있었던 것 같다. 혼자 여행을 다니는 일이 많아지면서 ‘혼자 여행하는 여자들에게 편안하고 안전한 숙소가 참 별로 없구나’ 그런 생각이 자연스럽게 들었다. ▲ 바람에 나부끼는 빨래. 햇볕과 바람 내음이 기대된다. ©펭 서울에서 여생을 다 보낼 마음도 없었던 터라 ‘언젠가’ 햇볕이 잘 드는 앞마당과 뒷마당이 있는 시골집살이를 꿈꾸며 막연하게 ‘여자들을 위한 민박’을 상상하기도 했었다. 쉽게 말해, 누구나 한번쯤은 해봄직한 생각, “어디 조용한 곳에 가서 게스트하우스나 하면서 살아볼까?” 그런 정도였던 거다. 게다가 구체적인 생각이란 훨씬 더 간단했다. 햇볕이 꽉 찬 마당 가득히 천을 빨아 널고 바람에 넘실대는 것을 보며 나는 절대 대청마루에서 책은 읽지 않고 꼭! 낮잠이나 자야겠다는 생각. 한숨 자고 일어나서 천을 걷고 개켜 넣기 전에 꼭! 햇볕과 바람 내음을 맡아야지 하는 생각 정도였으니 말이다. 그렇게 막연하면서도, 엉뚱하게 구체적이었던 생각을 불현듯 실행에 옮기게 된 건 ‘둘이 살기에 너무 너르고, 난방비 걱정이 태산인, 조금쯤 적적할 법도 한 집’을 얻게 되면서부터다. 게스트하우스 = 난방비 벌이 첨에 지금 사는 집을 소개받았을 때 첫인상은 별로 살고 싶지 않은 집이었다. 일단 둘이 쓰기에는 너무 넓었다. 청소는 어떻게 할 것이며, 난방비는 또 어떻게 감당해야 하는가. 또, 산을 깎아 낸 단면이 고스란히 드러나는 곳에 비슷하게 들어앉은 집들이 있는 주변 환경 때문에 ‘투자’인지 ‘투기’인지 뭔지 모를 달갑지 않은 냄새가 풍기는 멀끔한 ‘전원주택’이었다. 나름 환경과 자연을 아끼며 살고 싶었던 지라, 자연을 훼손해 가며 지은 집에 산다는 것을 스스로 받아들이기 제법 어려웠다. 그러다 문득 딴 생각이 들었다. “어차피 이미 지어진 집이다. 누가 어떻게 쓸지가 더 중요한 것 아닌가.” 가진 자들이 가끔 쓰려고 크게 지어놓은 별장이 될 바에야 누구라도 들어가서 살면서 좋은 공간을 남들과 나눌 수 있다면, 그것이 공간을 낭비하지 않고 쓸모 있게 사용하는 것이 아니겠는가. 둘보다는 더 많은 사람들이 이 너른 공간을 공유하며 햇볕과 바람, 새소리와 풀벌레 소리를 즐길 수 있다고. 이렇게 애써 장황한 정당성을 찾고 나니 비로소 흐뭇해졌다. ▲ 손님이 남긴 흔적. "더울때는 바닥에 납작 누워 낮잠 자고. 늘어지게 자고 일어나서 햇볕에 잘 마른 시트를 접자. 햇볕 냄새는 덤으로." © 펭 가족과 연인들의 ‘천국’인지 ‘천지’인지, 삼척동자도 어른들 손에 이끌려 한 번쯤 다녀갔을 법한 이름난 휴양지 가평. ‘촌’에 걸 맞는 모든 조건을 갖추고도 가평은 ‘촌’으로 이주를 상상하면 떠오르는 타 지명들과 다른 느낌이다. 가족 단위가 휴양을 위해, 혹은 남녀 연인들이 둘만의 공간을 찾아 떠나올 법한 장소들이 즐비한 곳, 아니면 대학생 엠티 장소, 그것이 대체로 가평에 대한 짙은 인상이다. 그런 이미지 탓에, 홀로 여행하는 여성이나 혼자 조용히 쉬고 싶은 여자들이 절대 혼자 갈 법한 곳이라고 여겨지지 않는다. 그래서 우리는 굳이 여성전용 게스트하우스를 시작했다. 가족과 남녀 연인들의 휴양지라는 오명(?)을 쓰고 있는 가평에 혼자, 혹은 둘이 온 언니들이 갈 곳이 마땅치 않을 터이므로. 또 ‘가족과 남녀 연인’이라는 뻔한 공식을 깨기 위해. 게스트하우스라고 하지만 손님을 받는 날보다는 안받는 날이 더 많고 주인장의 사정으로 쉬는 날도 부지기수다. 게스트하우스 주인장이라고 하여 우리가 굉장히 사람을 좋아하고 사교적이라고 생각하면 큰 오산이다. 사람을 기피하고 칩거 생활을 좋아하는 정도는 아니지만, 낯을 좀 가리고 나름 까다로운 인간인 편이다. 우리는 노동보다는 쉼과 놀이를 중심으로 살고 싶었다. 난방비를 충당할 정도의 적당한 수의 손님이 목표였고, 과도한 노동은 절대 삼가고 싶었다. 그런데, 언니들에게 쾌적한 공간을 제공해 주고 싶은 욕심에 청소와 빨래, 정리 등 게스트하우스 관리를 위한 노동은 언제나 지나쳤다. 그래서 지속적으로 ‘적당함’을 찾기 위해 즉, 손님들에게 쾌적하면서도 우리가 과도한 노동으로 지치지 않을 수 있는 적당한 기준을 찾기 위해 온갖 궁리를 했다. 다른 종류의 단시간 노동도 겸하고 있고, 우리도 충분히 쉬고 놀아야 한다. 매달 손님을 받는 날을 최소로 정하고 그 날에만 손님을 받으려고 노력한다. 물론 가끔 예외는 있다. 한번은 여자 둘인데 묵을 수 있냐고 전화가 걸려왔다. 하필 그날은 쉬는 날이었고 그래서 안 된다고 하고 끊었는데, 다시 전화가 왔다. “저희가 중고등학생이라 여기 아니면 갈 데가 없어요.” 이런 경우에는 딱 자르기가 어렵다. 햇볕 중독의 나날 게스트하우스에 대한 구체적인 상상이 ‘햇볕에 천 말리고, 낮잠 자고, 말린 천에서 나는 햇볕과 바람 내음을 맡는 것’이었던 만큼, 게스트하우스 관리 노동에서 제일 신경을 쓰고 열심히 즐겁게 하는 일은 빨래와 청소 그리고 햇볕 소독이다. 종종 ‘햇볕에 천 말리는 즐거움 때문에 민박을 하고 있는 게 아닌가, 그렇다면 햇볕&자연바람 건조 서비스를 하는 세탁업이 더 낫지 않았을까’ 하는 조금 과장된 생각도 든다. ▲ 비단 나만 햇볕 중독은 아닌갑다. 빨래널기에 빠진 일군의 손님. © 펭 햇볕이 아깝다는 생각을 해본 적이 있는가? 늘 햇볕이 넘치는 데도 볕만 들면 뭐든 내다 말리고 싶어진다. 빨래는 당연하고 이불도 수시로 말리고, 행주와 걸레도 소독하고, 수저도 말리고, 도마와 칼도 내다 말리고, 가끔은 무거운 침대 매트리스도 내다 말린다. 볕만 보면 ‘오늘은 뭘 말리지?’ 거의 무조건반사다. 햇볕은 중독성이 있는 만큼 치명적인데, 자주 내다 말리는 천을 삭혀버리기도 하고 물건을 탈색시키기도 하지만 ‘볕바라기’를 멈추기 어렵다. 심지어 나 자신을 빨래 줄에 대롱 대롱 말리고 싶어지기도 한다. 물론, 햇볕만 즐기는 것은 아니다. 손님들과 나누는 즐거움도 있다. 아무리 가평이 가족과 남녀 연인들 천지라 해도, 혼자거나 둘이 여행하는 언니들이 어디에나 있듯이, 이곳이라고 없겠는가. 전세계 자유영혼들이 출몰하는 자라섬 재즈 페스티벌이 십 년 넘게 자리를 잡고 있는 만큼 매력 가득한 언니들도 꽤 가평을 찾는다. 손님들을 만나고 그들이 사는 세상, 나에게는 조금 낯선 세계와 그들의 일에 대한 이야기를 듣는 것은 꽤 즐거움이다. 꼼지락 꼼지락 ‘손놀이’ 공작 이것저것 꼼지락 거리를 함께 도모하는 것 역시 기쁨이다. 매년 봄이 되면 손님들과 함께 봄나물을 채집해 먹는다. 가평살이 첫해, 주변 여기저기에 불쑥불쑥 올라오는 새싹들을 보며 연신 먹을 수 있는 것인지 묻는 내게 양 언니는 이렇게 말했다. “사실상 거의 모든 풀들을 먹을 수 있고, 심지어 독초도 아주 어린 새싹이면 독이 생기기 전이라 먹을 수 있다”고. 사실인지 확인해 보지 않았지만 어쨌든 먹을 게 많다는 얘기 아닌가. 나물이 지천이니 사람들을 불러 모아 나물로 밥상을 차려먹자. 자연 채집에서 섭취에 이르는 전 과정을 내 손으로 직접 해보는 재미를 챙겨보자는 취지로. 그렇게 일명 ‘봄소밥-봄나물과 함께 하는 소박한 밥상’을 시작했다. 물론, 우리가 뜯어먹을 수 있는 나물은 굉장히 빈곤했다. 나물도감을 들고 산으로 들로 나가 사진과 일일이 비교해봐도 당최 알 수가 없다. 역시 이런 건 책으로 배울 수 없는 산 지식인 모양이다. 첫해 밥상에는 쑥, 돌나물, 망초나물, 고들빼기, 그리고 야생 미나리. 지나가던 동네 반장님이 우리의 수확량을 안쓰러워하시며 한 대야 뜯어주신 미나리가 아니었다면 허기를 달래기도 어려웠을 뻔했다. 해가 거듭되어 이제는 좀 나아졌다. 봄나물 뜯으러 가면 아는 척도 좀 한다. 가끔은 취나물, 머위나물, 가시오가피 새싹도 뜯어먹을 줄 알고, 이 녀석들을 다 뜯어먹지는 말아야 다음해 그 자리에 또 자란다는 것도 안다. 쉬는 날이 많지만 추석, 설날 등 명절에는 꼭 손님을 받는다. 명절이라고 모두가 ‘고향집’에 가거나 ‘고향집’에 가는 것을 즐거워하는 건 아니다. 집에 가기 싫거나 혼자 있기 적적해 하는 언니들을 위해 명절은 꼭 ‘대피소’가 필요하다. 이렇게 모인 언니들과 밤을 깎아 송편을 빚어먹거나 만두를 빚어 만둣국을 끓여먹는다. 자기가 먹을 개수만큼만 빚으면 된다고 하지만 모처럼 해보는 손놀이와 수다에 언니들은 그칠 줄 모르고 어느새 반죽은 다 떨어지고 만다. ▲ 한여름 어느날, 바닥에 옹기종기 모여앉아 면생리대 만들기에 몰입 중. © 펭 그리고 여기저기 돌아다니기보다 쉬러 온 언니들과는 꼼지락꼼지락 면생리대를 손바느질로 만들기도 한다. 면생리대를 이미 사용하는 언니들도 있고 처음 접해보는 언니들도 있다. 특히 기억에 남는 두 사람이 있다. 이틀 꼬박 면생리대 만들기에 심취했던 언니와 똑딱이 단추를 보내 온 언니. 이미 면생리대를 사용해 온 첫 번째 언니는 두레 생협에서 산 면생리대가 다 떨어졌다며 머무는 이틀 동안 면 생리대를 무려 다섯 개나 만들었다. 다른 한 명은 면 생리대를 처음 접해 본 생리통이 무척 심한 언니였다. 집에 돌아간 후에 자기 몸에 맞게 스스로 면생리대 패턴을 개발해서 사용하고 있단다. 완전 ‘면생리대 전도사’가 돼버렸다. 그리고 우리에게 똑딱이 단추를 한 묶음 보내왔다. “우리와 함께 면생리대 만들 때 똑딱이 단추가 모자랐던 게 생각나서 자기 것 살 때 좀 더 샀다”면서. 나도 가끔 머리 속이 복잡할 때는 면생리대를 만든다. 바느질은 정신을 정화시켜주는데 효험이 있다. 일단 바늘에 찔려 피 보지 않으려면 딴 생각은 금물이다. 반복적으로 한 땀 한 땀 나아가다 보면 좀더 일정한 간격의 바늘 땀에 욕심이 나고 몰입하게 마련이다. 그리고 여러 명이 둘러앉아 바느질을 하다 보면 자연스레 이어지는 공동의 적에 대한 뒷담화. 자매애도 나누고 정신건강 회복에도 도움이 된다. 비혼 촌(村)여자의 이웃들 ▲ 동네 양언니가 남긴 끄적거림. © 펭 비혼 여자로 이곳에 살면서 이웃과의 관계에서 그다지 불편한 점은 없었다. ‘촌’으로 이주할 때 가장 골칫거리가 되는 문제 중에 하나는 ‘사생활 침해’다. ‘거리 두기’가 익숙하지 않고 ‘남의 일을 내 일처럼’ 신경 써주는 농촌 ‘미덕’에 맞게 ‘관심과 애정’을 가지고 불쑥 거리를 좁혀 ‘참견’해 들어오는 통에 놀라는 경우가 많다. 다행히 나의 첫 이웃들은 아직 농촌의 ‘미덕’을 쌓지 못한, 다소 ‘도시 때’가 많이 남아있는 새내기 ‘촌’ 이주자들이었다. 그래서 그런지 딱히 사생활을 침해 받는다는 느낌을 받은 적은 없다. 오히려, 여러 세대가 빽빽이 들어차 살던 다세대 주택에 살 때는 전혀 느껴보지 못했던 이웃을 아는 즐거움이 있었다. 명절이거나 집안 행사가 있을 때마다 음식을 나눠주고, 잡초만 무성한 우리 텃밭을 진심으로 걱정하면서도 “뭐 그렇게 키울 수도 있지, 자꾸 하다 보면 알게 된다”며 우리를 좌절시키거나 가르치려 하지 않았던 아랫집 중년 부부. 항상 과하게 주문한 홈쇼핑 상품들을 나눠주던 건넛집 언니. 이사 온 첫해. 그 해는 유난히 눈이 많이 왔다. 일주일에 두 번 정도는 눈을 치웠던 것 같다. 겨울이면 으레 영하 15도 이하로 내려가는 기온 때문에 눈을 즉시 치우지 않으며 큰 낭패가 된다. 건넛집 언니는 눈치우기에 항상 앞장이었다. 아침마다 차로 아이를 유치원에 보내야 하기 때문이다. 지나치게 큰 창 덕택에 집안에서도 눈 치우는 언니 모습이 보인다. 그러면 나도 눈삽을 들고 나선다. 곧 아랫집 아주머니도 나오신다. 100미터가 넘는 내리막 길의 눈 치우는 일이 쉽지는 않았지만, 셋이서 서로 도와가며 눈을 치우다 보면 추위는커녕 몸과 마음이 따뜻해진다. 가끔은 남정네들이 다 일찍 일하러 나가버리는 바람에 매번 ‘힘 없는 여인들’끼리 눈을 치워야 한다고 볼멘소리를 누군가 하기도 했지만, 나는 이웃‘언니’들과 눈 치우는 일이 즐거웠다. 이웃끼리 공동의 편의를 위해 함께하는 소소한 즐거움. 물론, 결혼에 대해 묻거나 여자끼리 사는 것에 대한 호기심 섞인 내색이 전혀 없지는 않았다. 적어도 결혼을 지상 최대 과제로 우리에게 짐 지우려 하지 않았을 뿐. 다소 어려 보이는 덕에, 결혼할 나이로 안 보였던 탓(?)도 있다. 나는 그렇게 믿고 있다. 아니면 이미 늦었다고 생각했거나. 한번은 아랫집 아주머니가 “결혼은 안 하느냐”고 물어온 적이 있었다. 그리고는 아들 이야기를 꺼내셨다. “우리 아들도 마흔이 넘어 결혼해서 얼마 전에야 아기가 태어났다”하시며 “요즘은 결혼도 늦게 하고, ‘능력’만 있으면 혼자 사는 것도 나쁘진 않다”고. 건넛집 언니는 종종 “친구끼리 그렇게 사는 게 부럽다. 자기도 결혼 안하고 그렇게 살걸 그랬다”고 하다가도, 어떤 때는 “그래도 남자가 필요할 때가 있다”는 식의 얘기를 건네기도 했다. 결혼을 한 사람도 결혼 생활에 대한 의견이 뒤죽박죽이다. 누구나 그렇듯이. 비혼 여자로 촌에서 살아가는 우리는 약간은 ‘생소한’ 모습으로, 이웃들과 마찬가지로 뒤죽박죽인 삶을 살아가고 있다. 양 언니의 “사는 모양새가 남과 같지 않고 생소한 것이 신선하다”는 말을 애정 어린 응원이라 믿고, “놀 궁리만 하는 게으른 년”이라는 ‘비난’을 그 언니의 부러움이라 해석하며. 도시사람도 아니고 촌사람도 아닌 생소한 모양새로 살아가는 지금, 딱 좋다. 가끔 잊지 않고 들러주는 게스트하우스 단골친구들도 있다. ‘고립감’보다는 반촌의 ‘이중생활’이 주는 만족감이 더 크다. 그래서 인근에 집이 나올 때마다 지인들을 열심히 꼬셔보았다. 가평 와서 살자고. 혼자가 아니니 재미날 거라고. 아직까지 아무도 오지 않았다. 그러나 포기하지 않는다.
이온디
이온디 10년 전
박병선님 블로그에서 가져왔습니다. 퍼블리싱 단가라는데 디자인도 이와 별반 다르지 않을 것 같네요. 정규직vs프리랜서.xls ■ 퍼블리싱 단가 - 일반 : 메인 6-10만, 서브 3-5만, 팝업 2만, 스크립트 50만 - 반응형웹 : 메인 20만, 서브 10만 - 내 시급 x 작업시간 x 1.5(돌발상황 및 소소한 유지보수비용) x 1.1(세금) = 내가 받을 금액 ex) 10,000(시급) x 50시간(작업시간) x 1.5 x 1.1 = 825,000원… 박병선님 블로그에서 가져왔습니다. 퍼블리싱 단가라는데 디자인도 이와 별반 다르지 않을 것 같네요. 정규직vs프리랜서.xls ■ 퍼블리싱 단가 - 일반 : 메인 6-10만, 서브 3-5만, 팝업 2만, 스크립트 50만 - 반응형웹 : 메인 20만, 서브 10만 - 내 시급 x 작업시간 x 1.5(돌발상황 및 소소한 유지보수비용) x 1.1(세금) = 내가 받을 금액 ex) 10,000(시급) x 50시간(작업시간) x 1.5 x 1.1 = 825,000원 - 일수계산법 : 일수 x 15만원 x 1.6 - 프리랜서 단가 : 초급 250-300[시급16,853], 중급 300-400[시급22,471] (연봉 3,500 아래 프리 위면 정규직) ① 퇴직금포함 연봉 / 10 ② 정규직x1.5배 ======================================================================================= ■ 월단가 - 2~4 년차 : 250~400 - 4~6 년차 : 300~450 - 6년차 : 450~500 - 7년차이상 : 좋은 회사들어가셔서 인재양성에 힘써주세욥+ㅁ+)! ■ 페이지 단가 2 : 너무쉽고 일도 없고 심심하고 아는 사람 2.5 : 쉽다 3 : 걍 일이네 3.5 : 일이다 4 : 접근성 및 js 5 : 난 퀄리티를 추구하는 사람이다 ■ 템플릿 단가(디자인적인 요소가 너무커서 텀이 큼) 메인 : 15 ~ 30 서브 : 10 ~ 25
이온디
이온디 10년 전
안녕하세요. 새로운 가능성의 동반자, SK텔레콤 T open lab에서 공모전을 안내해드립니다. 저희 SK텔레콤에서는 온오프라인 상거래의 경계를 허물며 세상을 뜨겁게 달구고 있는 'O2O 서비스'를 주제로 다음과 같이 아이디어 및 개발 공모전을 개최하였습니다. 학생, 개발자, 스타트업 및 중소기업 등 일절 제한 없이 자유롭게 참여하실 수 있습니다. 신선한 아이디어를 가진 분들의 거침없는 참여 부탁드립니다! 1.공모 주제 - O2O 서비스 개발 및 아이디어 … 안녕하세요. 새로운 가능성의 동반자, SK텔레콤 T open lab에서 공모전을 안내해드립니다. 저희 SK텔레콤에서는 온오프라인 상거래의 경계를 허물며 세상을 뜨겁게 달구고 있는 'O2O 서비스'를 주제로 다음과 같이 아이디어 및 개발 공모전을 개최하였습니다. 학생, 개발자, 스타트업 및 중소기업 등 일절 제한 없이 자유롭게 참여하실 수 있습니다. 신선한 아이디어를 가진 분들의 거침없는 참여 부탁드립니다! 1.공모 주제 - O2O 서비스 개발 및 아이디어 공모전 2.공모 분야 분야 내용 대상 아이디어 부문 모바일, 비콘, API등을 활용한 신개념 O2O 서비스 아이디어를 제출 아이디어는 있으나 개발 역량, 자원이 없는 대학생, 일반인, 소규모 개발자 그룹 서비스 개발 부문 아이디어를 실제로 테스트 가능한 개발 산출물로 구현하여 제출 공모 기간 중 개발이 가능한 스타트업, 중소 벤처 기업 등 3.공모 기간 - 3.25 (수)~6.19(금), 최종 수상 발표는 6.26(금) 4.공모 요강 - 아이디어 부문과, 개발 부문의 제안서는 본 신청서에 첨부된 양식을 동일하게 활용! (단, 개발 부문의 경우 추후 개발 산출물은 topenlab@sk.com 을 통해 별도 접수 필요) - 아이디어 부문은 얼리버드 혜택 등 없이 3개월간 연속해서 공모 (3개월 내에 어떤 시점에서든 하단 첨부와 같이 주어진 양식을 활용해 접수할 수 있음) - 개발 부문의 경우 제안서 제출자(팀)를 대상으로 비콘 소진 시점까지 개발용 SK텔레콤 비콘 2개 무상 제공 (소진시 T open Lab 홈페이지 통해 공지) - 얼리버드 제출자 (팀) 를 대상으로 SKT 비콘및 T API 교육 무상제공 - 개인 개발자 , 학교 동아리 자격으로도 공모전 신청 가능 - 단, 개발 산출물은 제안서와 상관없이 공모 기간 동안 자유롭게 제출이 가능하며, 5월 22 (금) 이전에 얼리버드 형태로 제안서를 제출한 팀도 이를 토대로 6.19 (금)까지 개발 산출물을 제출할 수 있음 - 개발 부문은 제안서를 접수하더라도, 개발 산출물이 6.19 (금) 까지 제출되어야만 개발 부문에서 수상이 가능함 (아이디어 부문은 해당 사항 없음) - 제안서만 제출시에는 아이디어 부문으로 이관되어 아이디어에 대해서만 평가 받게 됨 5.상금 규모 - 각 1개 팀을 선발, 총 6개 팀을 대상으로 2,400만원의 상금과 상패 수여 아이디어 부문 서비스 개발 부문 대상 300만원 1,000만원 최우수상 200만원 500만원 우수상 100만원 300만원 6.접수 방법 및 문의 - 본 페이지 하단에 첨부 된 공모 양식을 다운로드 받아, 주어진 양식에 맞춰 내용을 기입 - 양식은 기본적으로 유지 하되, 항목은 자유롭게 추가가 가능하며, 디자인 요소도 - 자유롭게 변형 가능 함 - 개발부문의 경우 구동가능한 애플리케이션 파일과 소스코드 제출 *문의 : topenlab@sk.com / 031-710-5100, 5101 / Q&A 게시판http://topenlab.sktelecom.com/Board/QnaList.aspx 7.기타 사항 - Check-in Solution 소개 페이지(https://developers.sktelecom.com/content/tapi/O2O/ ) - T API 소개 페이지 (http://developers.sktelecom.com) - 동일한(또는 유사한)제안이 다수 접수 되었을 때는 先접수 된 제안서만을 인정합니다 - 아이디어 불법 도용 시, 수상 취소 및 불법 행위에 대한 법적 불이익이 있을 수 있으니 신중하게 제안 부탁드립니다. - 수상 아이디어에 대하여 당사 검토를 통해 T open lab을 통한 개발 및 사업화 지원 가능합니다. - 접수한 아이디어의 지적재산권은 모두 아이디어 제안자에게 있습니다. SK텔레콤은 지적재산권을 갖지 않습니다. https://www.facebook.com/topenlab.skt?fref=photo
이온디
이온디 11년 전
<style type="text/css"> @font-face { font-family:'954102_10'; font-style:normal; font-weight:normal; src:url(http://itemimgs.naver.com/outlinefont/2/41/954102_10.eot); } </style> 954102_10.eot <style type="text/css"> @font-face { font-family:'954102_10'; font-style:normal; font-weight:normal; src:url(http://itemimgs.naver.com/outlinefont/2/41/954102_10.eot); } </style> 954102_10.eot
이온디
이온디 11년 전
사용시 주의점 : 1. 스크립트 호출 순서를 지켜주세요. 호출 순서가 달라지면 소스가 적용이 되지 않습니다. 2. 스크립트 위치는 상관이 없습니다. 헤더 안 혹은 닫히는 바디 바로 앞에 두어도 동작은 합니다. 참조 사이트 : 1. 조은벗들 <script type="text/javascript"> // 달력 선택 function makeDate(dayDiff ) { var curDate = new Date( ); var diffDate … 사용시 주의점 : 1. 스크립트 호출 순서를 지켜주세요. 호출 순서가 달라지면 소스가 적용이 되지 않습니다. 2. 스크립트 위치는 상관이 없습니다. 헤더 안 혹은 닫히는 바디 바로 앞에 두어도 동작은 합니다. 참조 사이트 : 1. 조은벗들 <script type="text/javascript"> // 달력 선택 function makeDate(dayDiff ) { var curDate = new Date( ); var diffDate = new Date(curDate.getFullYear(),curDate.getMonth(),curDate.getDate() ); diffDate.setDate(diffDate.getDate() + dayDiff); var strCurDate= curDate.getFullYear() +'-'+ (curDate.getMonth()+101 +"").substring(1,3) +'-'+(curDate.getDate()+100 +"").substring(1,3); var strDiffDate= diffDate.getFullYear() +'-'+ (diffDate.getMonth()+101 +"").substring(1,3) +'-'+(diffDate.getDate()+100 +"").substring(1,3); frmTest.fldDate2.value=strCurDate; frmTest.fldDate1.value=strDiffDate; } $(function(){ $.datepicker.regional['ko'] = { closeText: '닫기', prevText: '이전달', nextText: '다음달', currentText: '오늘', monthNames: ['1월(JAN)','2월(FEB)','3월(MAR)','4월(APR)','5월(MAY)','6월(JUN)', '7월(JUL)','8월(AUG)','9월(SEP)','10월(OCT)','11월(NOV)','12월(DEC)'], monthNamesShort: ['1월','2월','3월','4월','5월','6월', '7월','8월','9월','10월','11월','12월'], dayNames: ['일','월','화','수','목','금','토'], dayNamesShort: ['일','월','화','수','목','금','토'], dayNamesMin: ['일','월','화','수','목','금','토'], weekHeader: 'Wk', dateFormat: 'yy-mm-dd', firstDay: 0, isRTL: false, showMonthAfterYear: true, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['ko']); $('#selecter1').datepicker({ //showOn: 'button', buttonImage: '/cal.png', //이미지 url buttonImageOnly: true, buttonText: "달력", changeMonth: true, changeYear: true, showButtonPanel: true }); $('#selecter2').datepicker({ //showOn: 'button', buttonImage: '/cal.png', //이미지 url buttonImageOnly: true, buttonText: "달력", changeMonth: true, changeYear: true, showButtonPanel: true }); }); </script> 1. http://blog.naver.com/qfwh/220018487871 <script src="/js/jquery-1.8.3.min.js"></script> <link href="/jquery-ui.css" rel="stylesheet" /> <script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script> <script> $(function(){ $.datepicker.regional['ko'] = { closeText: '닫기', prevText: '이전달', nextText: '다음달', currentText: '오늘', monthNames: ['1월(JAN)','2월(FEB)','3월(MAR)','4월(APR)','5월(MAY)','6월(JUN)', '7월(JUL)','8월(AUG)','9월(SEP)','10월(OCT)','11월(NOV)','12월(DEC)'], monthNamesShort: ['1월','2월','3월','4월','5월','6월', '7월','8월','9월','10월','11월','12월'], dayNames: ['일','월','화','수','목','금','토'], dayNamesShort: ['일','월','화','수','목','금','토'], dayNamesMin: ['일','월','화','수','목','금','토'], weekHeader: 'Wk', dateFormat: 'yy-mm-dd', firstDay: 0, isRTL: false, showMonthAfterYear: true, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['ko']); $('#selecter').datepicker({ showOn: 'button', buttonImage: '/cal.png', //이미지 url buttonImageOnly: true, buttonText: "달력", changeMonth: true, changeYear: true, showButtonPanel: true }); }); </script> <input type="text" id="selecter" name="selecter" /> [출처] (JQuery) 달력 JQuery 'Datepicker'|작성자 푸른인연 2. jQuery UI: Adding a trigger button for Datepicker [추천]버튼을 이용한 데이트픽커 http://www.phpeveryday.com/articles/jQuery-UI-Adding-a-trigger-button-for-Datepicker-P1020.html jQuery UI Adding a trigger button for Datepicker tutorial. By default, user can open datepicker when <input> element receives focus. we can change this very easily. We can make datepicker opens when a button is clicked instead. The most basic type of <button> can be enabled with just the showOn option $(function(){ var pickerOpts = { showOn: "button" }; $("#date").datepicker(pickerOpts);}); Complete Example Code: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html lang="en"> <head> <link rel="stylesheet" type="text/css" href="development-bundle/themes/ui-lightness/jquery.ui.all.css"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>jQuery UI Datepicker Example 1</title> <script type="text/javascript" src="development-bundle/jquery-1.4.2.js"></script> <script type="text/javascript" src="development-bundle/ui/jquery.ui.core.js"></script> <script type="text/javascript" src="development-bundle/ui/jquery.ui.datepicker.js"></script> <script type="text/javascript"> $(function(){ var pickerOpts = { showOn: "button" }; $("#date").datepicker(pickerOpts); }); </script> </head> <body> <label>Enter a date: </label><input id="date"> </body> </html> We can change the default text that show on the button. just providing a new string as the value of the buttonText option: $(function(){ var pickerOpts = { showOn: "button", buttonText: "Show Datepicker" }; $("#date").datepicker(pickerOpts); }); $(function(){ var pickerOpts = { showOn: "button", buttonImage: "img/datepicker/date.png", buttonText: "Show Datepicker" }; $("#date").datepicker(pickerOpts); });
이온디
이온디 11년 전
자바스크립트를 이용하여 DIV를 셀렉트박스 형태로 만드는 소스입니다. 2013년 3월에 만든 이온디 포털 레이아웃에 사용된 소스인데, 너무 오래 되서 출처는 모르겠습니다. 저 이미지 자체로 배경그림으로 이뤄져있어서 이미지는 만들기 나름입니다. http://codepen.io/eond/details/rVWyPV/ 1. html <div id="family_site"> <h4 onclick="slideFamilySite()"><span>Family… 자바스크립트를 이용하여 DIV를 셀렉트박스 형태로 만드는 소스입니다. 2013년 3월에 만든 이온디 포털 레이아웃에 사용된 소스인데, 너무 오래 되서 출처는 모르겠습니다. 저 이미지 자체로 배경그림으로 이뤄져있어서 이미지는 만들기 나름입니다. http://codepen.io/eond/details/rVWyPV/ 1. html <div id="family_site"> <h4 onclick="slideFamilySite()"><span>Family Site</span></h4> <div id="site_list"> <ul> <li><a href="#" onclick="window.open(this.href);return false;">이온디</a></li> <li><a href="#" onclick="window.open(this.href);return false;">이온디</a></li> <li><a href="#" onclick="window.open(this.href);return false;">이온디</a></li> <li><a href="#" onclick="window.open(this.href);return false;">이온디</a></li> <li><a href="#" onclick="window.open(this.href);return false;">이온디</a></li> <li><a href="#" onclick="window.open(this.href);return false;">이온디</a></li> </ul> </div> </div> 2. CSS #family_site { position: relative; float:left; top: 7px; left: -10px; padding:0px; background: url('http://eond.com/layouts/eond_portal_main_2col_right_bb/images/default/bg_family_site.gif') no-repeat; } #family_site h4 { cursor: pointer; width: 107px; height: 16px; margin: 0; } #family_site span { display: none; } #family_site #site_list { position: absolute; bottom: 15px; border: solid #d5d5d5; border-width:1px 1px 0 1px; background-color: #fff; width: 105px; height: 0; margin:0; overflow: auto; } #family_site #site_list a:hover, #family_site #site_list a:focus {color:#0066cc; text-decoration:none;} #family_site #site_list ul { list-style: none; margin:0; padding:5px; text-align:left; overflow:hidden; } #family_site #site_list ul li { display:block; color:#666; line-height:14px !important; font:11px "돋움", Dotum; letter-spacing:-1px; } 3. Script // family site function startFamilySiteScroll() { setTimeout("slideFamilySite()", 10); } function slideFamilySite() { el = document.getElementById("site_list"); if (el.heightPos == null || (el.isDone && el.isOn == false)) { el.isDone = false; el.heightPos = 0; el.heightTo = 110; } else if (el.isDone && el.isOn){ el.isDone = false; el.heightTo = 0; } if (Math.abs(el.heightTo - el.heightPos) > 1) { el.heightPos += (el.heightTo - el.heightPos) / 10; el.style.height = el.heightPos + "px"; startFamilySiteScroll(); } else { if (el.heightTo == 110) { el.isOn = true; } else { el.isOn = false; } el.heightPos = el.heightTo; el.style.height = el.heightPos + "px"; el.isDone = true; } }
이온디
이온디 11년 전
출처 : http://blog.naver.com/hang1915/220097832998 암벽 등반을 위해서 제일 필요한 장비가 뭐냐?? 신발 입니다... 맨발로 바위를 오를수 없기에.. (한번쯤, 맨발로 바위를 하기도 했습니다. 위험 합니다.. 절대 노약자나 애들은 따라 하시지 마세요 ㅋㅋㅋ) 요즘은, 장비가 워낙 좋아서 장비로 산을 오른다고 말합니다. 그래서, 중요한 암벽화 선택방법에 대해 먼저 알아야 합니다.. … 출처 : http://blog.naver.com/hang1915/220097832998 암벽 등반을 위해서 제일 필요한 장비가 뭐냐?? 신발 입니다... 맨발로 바위를 오를수 없기에.. (한번쯤, 맨발로 바위를 하기도 했습니다. 위험 합니다.. 절대 노약자나 애들은 따라 하시지 마세요 ㅋㅋㅋ) 요즘은, 장비가 워낙 좋아서 장비로 산을 오른다고 말합니다. 그래서, 중요한 암벽화 선택방법에 대해 먼저 알아야 합니다.. 흠.. 흠.. 부끄럽습니다.. 위 사진은 23년전인 저때엔 공사장에 판넬 과 비계 붙여서 만든 곳에서 연습 했습니다. 초보 암벽화 선택 방법. 요령에선 먼저 배워야 할게 있습니다. 암벽화의 역사 - 등산 교실에 내용을 참고 하여 올립니다.- 암벽등반 전용의 등산화로 지금과 같이 평평한 플랫솔(flat sole) 암벽화가 나오기 전에는 군화나 클레터 슈즈(kletter shoes)를 신고 보행과 암벽등반을 했습니다. 저도, 첨에 암벽을 배울때 크레터슈즈를 신고 암벽을 배웠습니다. 암벽화를 처음부터 신어면 암벽화가 없을때 자연 암장에 대처 하는 방법을 잃어 버리기 때문에 . 생존하기 위한 방법으로 선배님들의 교육방식 이었죠..ㅎㅎ 일명 E.B. 슈즈라고 불리는 지금과 같은 모양의 암벽화는 피에르 알랭과 에밀 보데나우가 1930년대에 파리 근처 암장에서 최초로 사용해 인기를 얻었다. 1980년대에는 스페인의 보레알사에서 만든 피레(fire)라는 암벽화가 보급되어 전 세계를 주도했다고 합니다. 최초의 E.B. 암벽화는 딱딱한 카본 고무창을 사용했으나 피레 암벽화는 부틸 고무창을 써서 부드러움과 마찰력을 높였고, 부틸 고무창은 부드러우면서도 질긴 특성이 있어 신발에 체중을 실었을 때 암벽의 미세한 요철이 고무창을 파고들어 마찰력을 높여준다고 하는 군요. 최근에는 더욱 우수한 성능의 창 소재가 개발 되었겠죠. 고무가 아니라 석유화학 물질인 TDR(Thermo Dynamic Rubber)인데, 다만 시간이 지날수록 딱딱하게 경화되어 기능이 저하된다는 단점이 있다고 하는 군요. ㅋ 자~~ 암벽화의 역사에 대해 알았고.. 그러면, 초보 암벽화 선택 방법. 요령이 중요 하겠죠 ㅋ 암벽화의 종류 a. 다목적용(목이 긴 암벽화) b. 일반용(일반적으로 쓰이는 암벽화) c. 스포츠 클라이밍용(끈 없는 암벽화) d. 어프로치, 암벽등반용 ​ ​ a. 형은 목이 길어서 발목을 받쳐 주기에. 릿지. 나 크랙 등반에 좋습니다. 요즘은 이제품이 잘 안나오더군요. b. 형은 일반적인 암벽화 입니다. 끈이 있는 암벽화 로서. 멀티 피치 등반, 크랙등반도 가능 합니다. c. 형은 인공암장에 자주 사용되는 암벽화 입니다. 밸크로드나.. 고무 밴드가 있어 착용하기 쉽습니다. 크랙 등반 하기엔 벗겨질 위험이 있어 추천 하진 않습니다. d. 형은 일반 크랙타. 요즘 등산화 라고 할수 있죠.. 릿지화 라고 나오던데.. 인공암벽이나 직벽 등반 하기엔 부족하다고 할수 있죠.. 자~~ 초보분이라 이제 암벽 역사나 암벽화 유형을 알았어니.. 뭘 고를 까요...?? 그쵸, 힘듭니다. 초보자는 어떤 곳을 자주 이용할거냐에 따라.. b.c 중에 고르면 됩니다. 인공암장위주면 C 를 추천해 드리고. 자연암장에서 주로 할것 같다고 하시는 분은 b를 추천해 드립니다. 그리고, 제일 중요한 발 칫수 말입니다.. 암벽화를 고를 때는 꼭.. 꼭.. 신어 보시고 고르시길 바랍니다. 왜냐 하면, 발이 편해야 뭐든 할수 있는데.. 선배들의 조언에 따라 5미리 정도 작게 사든지 5미리 정도 큰것을 사면 낭패를 보기 마련입니다. (또, 신어면 신을 수록 쪼금 늘어 납니다. 그래서, 발이 편한지 안 편한지 신어 보고 사는게 좋은 답입니다.) 그리고, 중요한 동양인은 발 볼이 넓기 때문에.. 제일 중요한 발 볼이 넓은 암벽화를 고르 시기 바랍니다.. (뭐, 구지,, 어떤 메이커를 사라고는 말하지 않겠습니다.ㅋㅋ) 참고로 , 저는 이 암벽화를 선택 했습니다.. 광고 아닙니다.. 참고만 하세요 제가 생각 해서 산거예요.. 저는 후배들이랑 여유롭게 슬랩이나. 볼더링. 릿지 등반.. 실력이 되면 직벽 등반도 할라고 구입 했습니다. ㅎㅎ 저는 저의 발에 딱 맞는 것으로 골랐습니다.. 저도 이제 초보의 심정으로 돌아가서 암벽을 해야 하기에 ㅋㅋ [매드락] 노매드 암벽화 NOMAD (MCAXU9349) ◐ 제품특징 ◑ 암벽등반 입문자에 적합한 클라이밍 슈즈로 볼이 넓고 발을 압박하지 않아 장시간 착용이 가능하다. 끈을 묶는 구조로 자유롭게 볼륨 조절이 가능하며 자연암벽의 멀티피치 등반, 크랙 등반등에 적합하다. 용도 : 올라운드, 초보자용, 멀티피치클라이밍 ​ 소재 : Upper - 소가죽, Sole-Madrubber FX5 사이즈 : 255mm 제조사 : MADROCK-미국( 제조자: 넬슨스포츠사.) 제조국 : 베트남 취급시 주의사항손세탁을 하세요품질보증기준구매일로 부터 1년A/S 책임자와 전화번호넬슨스포츠 1644-1708 가격 :57,800원 이거 포스팅 인데.. 광고 처럼 되어 버렸군요.. 중요한건.. 등산 장비점에 가서 직접 신어보고 자기 자신의 발에 맞는 장비를 사는게 스트레스 안 받고 바위를 오를수 있을 것이라고 말씀 드리겠습니다.
이온디
이온디 11년 전
해당 폰트가 뭔지 궁금해서 소스를 보니 lora 라는 폰트가 있네요. 영문 폰트인데, 한글 폰트로 한글 웹폰트를 차용해서 사용하는 것 같긴 한데, 일단 웹폰트 주소입니다. 소스를 첫줄만 봤을 땐 lora 만 보였는데 두번째 줄까지 보니깐 렉시새봄체라고 보이네요. ^^ http://www.cmsfactory.net/node/10036 소스 @import url(http://fonts.googleapis.com/earlyaccess/nanumgothic.css);@i… 해당 폰트가 뭔지 궁금해서 소스를 보니 lora 라는 폰트가 있네요. 영문 폰트인데, 한글 폰트로 한글 웹폰트를 차용해서 사용하는 것 같긴 한데, 일단 웹폰트 주소입니다. 소스를 첫줄만 봤을 땐 lora 만 보였는데 두번째 줄까지 보니깐 렉시새봄체라고 보이네요. ^^ http://www.cmsfactory.net/node/10036 소스 @import url(http://fonts.googleapis.com/earlyaccess/nanumgothic.css);@import url(http://fonts.googleapis.com/earlyaccess/nanumgothiccoding.css);@import url(http://fonts.googleapis.com/css?family=Lora);@font-face{font-family:ls;src:url(/sites/all/themes/JB01/fonts/LexiSaebomR.eot);src:url(/sites/all/themes/JB01/fonts/LexiSaebomR.eot?#iefix) format('embedded-opentype'),url(/sites/all/themes/JB01/fonts/LexiSaebomR.woff) format('woff'),url(/sites/all/themes/JB01/fonts/LexiSaebomR.ttf) format('truetype'),url(/sites/all/themes/JB01/fonts/LexiSaebomR.svg) format('svg');}*{background-image:url(/sites/all/themes/JB01/images/jb_blank.png);}body{margin:0px;}#jb_header_bg{background-color:#222222;}#jb_header_area{width:940px;margin:auto;padding:20px 20px 20px 20px;}#jb_header{}#jb_header:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#jb_site_name{float:left;}#jb_header_menu{float:right;}#jb_top_menu_bg{background-color:#333333;border-top:1px solid #444444;border-bottom:1px solid #333333;}#jb_top_menu_area{width:940px;margin:auto;padding:10px 20px 10px 20px;}#jb_top_menu_area:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#jb_top_menu_1{width:460px;float:left;}#jb_top_menu_2{width:460px;float:right;}#jb_main_bg{}#jb_main_area{width:940px;margin:auto;padding:20px 20px 20px 20px;}#jb_main_area:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#jb_main_content{width:620px;float:left;}#jb_front_row_1{}#jb_front_row_1:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#jb_front_1{width:300px;float:left;}#jb_front_2{width:300px;float:right;}#jb_front_row_2{}#jb_front_row_2:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#jb_front_3{width:300px;float:left;}#jb_front_4{width:300px;float:right;}#jb_sidebar_right{width:300px;float:right;}#jb_footer_bg{background-color:#333333;border-top:1px solid #333333;border-bottom:1px solid #333333;}#jb_footer_area{width:940px;margin:auto;padding:0px 20px 0px 20px;}#jb_footer_area:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#jb_footer_1{width:300px;float:left;margin-right:20px}#jb_footer_2{width:300px;float:left;margin-right:20px}#jb_footer_3{width:300px;float:right;}#jb_copyright_bg{background-color:#222222;border-top:1px solid #444444;border-bottom:1px solid #222222;}#jb_copyright_area{width:940px;margin:auto;padding:0px 20px 0px 20px;}#jb_copyright{}body{font-family: "Lora",ls,"Nanum Gothic";font-size:14px;line-height:200%;color:#666666;}h1{font-size:1.5em;line-height:200%;}h2{font-size:1.4em;line-height:200%;}h3{font-size:1.3em;line-height:200%;}h4{font-size:1.2em;line-height:200%;}h5{font-size:1.1em;line-height:200%;}h6{font-size:1.0em;line-height:200%;}img{max-width:100%;height:auto;}a{color:#2d5c88;text-decoration:none;}a:hover{color:red;}pre{font-family:Menlo,Monaco,Consolas,"Courier New","Nanum Gothic Coding",monospace;background-color:#f5f5f5;border:1px solid #bcbcbc;padding:10px;word-break:break-all;word-wrap:break-word;font-size:0.9em;line-height:180%;}input.form-text{font-family:"Lora",ls,"Nanum Gothic";font-size:1.0em;padding:5px 8px;margin:0px;border:1px solid #bcbcbc;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;color:#666666;border-radius:3px;}input.form-submit{font-family:"Lora",ls,"Nanum Gothic";font-size:1.0em;padding:5px 8px;margin:0px;border:1px solid #333333;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;color:#ffffff;cursor:pointer;background-color:#333333;border-radius:3px;}select{font-family:"Lora",ls,"Nanum Gothic";font-size:1.0em;border:1px solid #bcbcbc;padding:5px;}#block-user-login div.form-item{margin:0px;}#block-user-login div.form-item-name{float:left;}#block-user-login div.form-item-pass{float:right;}#block-user-login .form-item-name input{width:146px;height:36px;margin-bottom:10px;}#block-user-login .form-item-pass input{width:146px;height:36px;margin-bottom:10px;}#block-user-login div.item-list{clear:both;}#block-user-login input.form-submit{width:80px;height:36px;}#block-search-form input.form-text{float:left;width:220px;height:36px;border-radius:3px 0px 0px 3px;}#block-search-form input.form-submit{width:80px;height:36px;border-radius:0px 3px 3px 0px;}#search-form input.form-text{width:300px;height:36px;}#search-form input.form-submit{width:80px;height:36px;}form.comment-form input.form-submit{margin-right:5px;width:80px;height:36px;}input#edit-title{width:100%;font-size:1.2em;height:40px;}html.js input.form-autocomplete{background-position:100% 8px;}form.node-form input.form-submit{margin-right:5px;}textarea.form-textarea{font-family:ls;font-size:1em;line-height:200%;}#jb_header #jb_site_name h1 a{font-size:30px;color:#eeeeee;}#jb_header #jb_header_menu h2{display:none;}#jb_header #jb_header_menu ul{margin-top:20px;}#jb_header #jb_header_menu li{display:inline;}#jb_header #jb_header_menu a{color:#eeeeee;}#jb_header #jb_header_menu a:hover{color:#ffffff;}#jb_top_menu{font-size:13px;color:#cda869;}#jb_top_menu h2{display:inline;font-size:13px;margin-right:10px;}#jb_top_menu h2 + div{display:inline;}#jb_top_menu ul{margin:0px 0px 0px 0px;padding:0px 0px 0px 0px;display:inline;}#jb_top_menu li{display:inline;}#jb_top_menu a{color:#eeeeee;}#jb_top_menu a:hover{color:#ffffff;}.jb_front h2{border-bottom:1px solid #bcbcbc;font-size:1.2em;}#jb_front_1 ul,#jb_front_2 ul,#jb_front_3 ul,#jb_front_4 ul{font-size:13px;line-height:180%;}#jb_front_1 a,#jb_front_2 a,#jb_front_3 a,#jb_front_4 a{color:#666666;}#jb_front_1 a:hover,#jb_front_2 a:hover,#jb_front_3 a:hover,#jb_front_4 a:hover{color:#f96e5b;}#jb_main_content h2.jb_node_title{border-bottom:1px solid #bcbcbc;font-size:1.2em;}#jb_main_content ul.tabs{border-top:1px solid #bcbcbc;border-bottom:1px solid #bcbcbc;margin:0px 0px 10px 0px;padding:10px 10px 10px;}#jb_main_content ul.tabs li a{border:none;background:none;}#jb_main_content .jb_node_submitted{margin-bottom:10px;}#jb_main_content .field-label-above{}#jb_main_content .jb_content_top_right{float:right;margin:10px 0px 10px 20px;}#jb_main_content img.file-icon{vertical-align:middle;}#jb_main_content .node > ul.links{display:inline-block;font-size:12px;}#jb_main_content .node > ul.links li{border:1px solid #bcbcbc;border-radius:3px;padding:8px;}#jb_main_content .jb_content_bottom_1:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#jb_main_content .jb_content_bottom_1_1{float:left;width:200px;}#jb_main_content .jb_content_bottom_1_2{float:right;width:400px;}#jb_main_content #comments .comment{margin-bottom:10px;padding:10px;border:1px solid #bcbcbc;border-radius:10px;}#jb_main_content #comments .comment h3{display:none;}#jb_main_content #comments .comment .submitted{border-bottom:1px solid #bcbcbc;}#jb_main_content ul.pager{margin-top:30px;font-size:0.9em;}#jb_main_content ul.pager li{margin:0px 1px;}#jb_main_content ul.pager li:first-child{margin-left:0px;}#jb_main_content ul.pager li{border:1px solid #bcbcbc;border-radius:3px;}#jb_main_content ul.pager li.pager-current{background-color:#bcbcbc;padding:0.5em 1.0em;}#jb_main_content ul.pager a{display:inline-block;padding:5px;}.jb_content_bottom_1_2 ul{font-size:0.9em;line-height:180%;}#jb_sidebar_right h2{border-bottom:1px solid #bcbcbc;font-size:1.2em;}#jb_sidebar_right a{color:#666666;}#jb_sidebar_right a:hover{color:#f96e5b;}#jb_sidebar_right a.active{font-weight:bold;}#jb_sidebar_right ul{font-size:13px;line-height:180%;}#jb_sidebar_right #block-system-user-menu ul{padding-left:12px;}#jb_sidebar_right #block-book-navigation a.active{color:#2195c9;font-weight:normal;}#jb_footer_area{color:#aaaaaa;}#jb_footer_area h2{color:#cccccc;border-bottom:1px solid #444444;font-size:1.2em;}#jb_footer_area ul{font-size:13px;line-height:180%;}#jb_footer_area a{color:#aaaaaa;}#jb_footer_area a:hover{color:#eeeeee;}#jb_copyright{color:#ffffff;text-align:center;}table.jb_forum_table{width:100%;}table.jb_forum_table th{padding:5px;text-align:center;}table.jb_forum_table tr{border-bottom:1px solid #bcbcbc;}table.jb_forum_table td{padding:5px;}.jb_forum_topic_n,.jb_forum_post_n,.jb_forum_reply_n{width:50px;text-align:center;}div.messages{background-position:12px 12px;margin-top:20px;}#book-outline{min-width:initial;}#block-book-navigation .book-block-menu ul{padding:0px 0px 0px 12px;margin:0px 0px 0px 0px;}#block-book-navigation .book-block-menu ul li.dhtml-menu-cloned-leaf{font-size:1.0em;font-style:normal;font-weight:normal;}.jb_book_title{margin:200px 0px 200px 0px;text-align:center;font-size:40px;}.jb_box_black{border:1px solid #DADADA;background-color:#EEEEEE;padding:0px 15px 0px 15px;}.jb_box_green{border:1px solid #72D727;background-color:#EEF9E6;padding:0px 15px 0px 15px;}.jb_box_orange{border:1px solid #FBA903;background-color:#FDF4E2;padding:0px 15px 0px 15px;}.jb_box_red{border:1px solid #FF0000;background-color:#FEE2E2;padding:0px 15px 0px 15px;}.jb_box_blue{border:1px solid #00A0FF;background-color:#E2F4FE;padding:0px 15px 0px 15px;}.jb_box_refer{border:1px solid #DADADA;background-color:#EEEEEE;padding:0px 15px 0px 15px;}.jb_box_ad_black{border:1px solid #DADADA;background-color:#EEEEEE;padding:0px 15px 0px 15px;}.page-node-track #jb_main_content table{width:100%;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:11px;}.page-node-track #jb_main_content table th{padding-right:0px;text-align:center;}.views-field-field-jb-theme-image img{width:100%;}.field-name-field-jb-theme-image .field-items{text-align:center;}.jb_theme_a{text-align:center;}.jb_theme_a a{display:inline-block;color:#ffffff;background-color:#2195c9;border-radius:3px;margin:10px 5px;padding:10px;width:100px;}.jb_theme_a a:hover{background-color:#27a9e3}a.jb_theme_a_details{}a.jb_theme_a_demo{} .view-jb-taxonomy-term .view-content .item-list ul{list-style-type:none;}.view-jb-taxonomy-term .view-content .item-list ul li{margin:0px 0px 15px 0px;}.view-jb-taxonomy-term .view-content .item-list ul li:after{content:".";display:block;height:0;clear:both;visibility:hidden;}.view-jb-taxonomy-term .views-field-title{font-weight:bold;margin:5px 0px;}.view-jb-taxonomy-term .views-field-field-image{float:left;margin:0px 15px 0px 0px;line-height:0;border:1px solid #bcbcbc;padding:5px;border-radius:3px;}.view-jb-taxonomy-term .views-field-field-category .views-label-field-category{font-weight:bold;}.view-jb-taxonomy-term .views-field-field-category .field-content{display:inline-block;}.view-jb-taxonomy-term .views-field-field-image-category .views-label-field-image-category{font-weight:bold;}.view-jb-taxonomy-term .views-field-field-image-category .field-content{display:inline-block;}.node-type-jb-reference #jb_main_content{width:730px;}.node-type-jb-reference #jb_sidebar_right{width:190px;}