🃏 명함 프로필 (종이명함) — 완전 분석 매뉴얼

URL: [서비스URL]/?cur_win=paper_card
이 페이지의 모든 JavaScript 소스, 알고리즘, 데이터 흐름, CSS 스타일까지
한 글자도 빠짐없이 분석하여 초등학생도 이해할 수 있도록 정리했습니다.

📋 명함 프로필이란?

명함 프로필(종이명함, paper_card)은 IAM(아이엠) 플랫폼의 핵심 기능 중 하나로, 실제 종이명함을 디지털로 관리하는 페이지입니다.

이 페이지에서는 다음과 같은 일을 할 수 있습니다:

💡 알아두세요! 이 페이지는 [서비스도메인] 도메인에서 동작하며, cur_win=paper_card라는 URL 파라미터로 어떤 화면을 보여줄지 결정합니다.

🔗 접속 URL 구조

명함 프로필 페이지는 다음과 같은 URL로 접속합니다:

[서비스URL]/?cur_win=paper_card

URL의 각 부분이 하는 역할은 다음과 같습니다:

부분 설명
https:// 보안 연결(HTTPS) 프로토콜
[서비스도메인] 사용자 전용 서브도메인 (송조은님의 IAM)
/? 루트 경로 + 쿼리스트링 시작
cur_win=paper_card 현재 창(window)을 "종이명함"으로 설정
🔑 핵심 포인트: cur_win 파라미터 값에 따라 완전히 다른 화면이 표시됩니다. 예: paper_card=종이명함, we_story=추천피드, my_info=내명함

📦 로딩되는 파일 목록

이 페이지가 로드될 때 함께 불러오는 모든 CSS와 JS 파일입니다:

CSS 파일 (스타일시트) — 총 10개

# 파일 경로 역할
1[내부경로]/[부트스트랩]/bootstrap.min.cssBootstrap UI 프레임워크 (버튼, 모달, 그리드)
2[내부경로]/[한글폰트]한글 폰트 (Noto Sans KR)
3[내부경로]/[아이콘폰트]아이콘 폰트 (Font Awesome 4)
4[내부경로]/[메인스타일]메인 스타일 (IAM 전역 스타일)
5[내부경로]/[스타일]/new_style.css새로운 스타일 추가분
6[내부경로]/[스타일]/grid.min.css그리드 레이아웃 시스템
7[내부경로]/[스타일]/slick.min.css슬라이더/캐러셀 UI
8[내부경로]/[스타일]/style_j.css추가 커스텀 스타일
9[내부경로]/[스타일]/iam.css명함 카드 전용 스타일 (square, content, sample_card)
10/css/pretend-font.cssPretendard 폰트 (현대적 한글 폰트)

JavaScript 파일 — 총 11개

# 파일 경로 핵심 역할
1//developers.kakao.com/sdk/js/kakao.min.js카카오톡 공유 SDK
2[내부경로]/[JS]/jquery-3.1.1.min.jsjQuery 3.1.1 (DOM 조작, AJAX, 이벤트)
3[내부경로]/[JS]/slick.min.js슬라이더 라이브러리
4[내부경로]/[JS]/main.jsUI 토글, 사이드바, 패널 스크롤 애니메이션
5[내부경로]/[부트스트랩]/js/bootstrap.min.jsBootstrap JS (모달, 탭, 드롭다운)
6[내부경로]/[JS]/Sortable.min.js드래그 앤 드롭 정렬
7/js/rlatjd_fun.js유틸함수 모음 (쿠키, 브라우저체크, 숫자포맷, 창 이동)
8/js/rlatjd.js회원관련 함수 (로그인, 회원가입, 비번검사)
9/plugin/toastr/js/toastr.min.js토스트 알림 팝업
10[내부경로]/[JS]/layer.min.js레이어 팝업
11[내부경로]/[JS]/qrcode.min.jsQR코드 생성 라이브러리
📌 추가 인라인 스크립트: 위 파일 외에도 HTML 안에 직접 작성된 인라인 JavaScript 코드가 약 12,000줄 있습니다. 이 인라인 코드가 명함 프로필의 핵심 비즈니스 로직을 모두 담고 있습니다.

🏗️ 전체 아키텍처 구조도

페이지가 로드되고 동작하는 전체 구조를 도식화하면 다음과 같습니다:

┌─────────────────────────────────────────────────────┐
│                   Browser / WebView                   │
├─────────────────────────────────────────────────────┤
│  1. HTML 파싱 시작                                    │
│     ├──  CSS 10개 로드                          │
│     ├──  JS 11개 로드 (순차적)                   │
│     └── 인라인 script #1: callAppBridge() 정의         │
│                                                       │
│  2. DOMContentLoaded (페이지 로딩 완료)               │
│     ├── 인라인 script #2 실행                          │
│     │   ├── sign_toggle(): 2초 간격 점멸              │
│     │   ├── jQuery(document).ready() #1               │
│     │   │   └── 알림 팝업 체크 & 표시                 │
│     │   ├── jQuery(document).ready() #2               │
│     │   │   ├── cur_win_name 설정                     │
│     │   │   ├── 레이아웃 모드 감지 (key1_gwc_show)     │
│     │   │   │   ├── mode=4: 와이드 모드               │
│     │   │   │   └── mode≠4: 일반 모드                 │
│     │   │   ├── 미디어 높이 계산                       │
│     │   │   ├── 모바일/데스크탑 감지 (checkMobile)     │
│     │   │   └── 카드 너비 동적 설정                    │
│     │   └── 전역 함수 80+개 정의                       │
│     │                                                   │
│  3. 페이지 콘텐츠 렌더링                               │
│     ├── 헤더(header): 로고, 메뉴, 언어, 검색           │
│     ├── 푸터 메뉴(footer_menu): 4개 탭                │
│     │   ├── 앱홈 → goIamHome()                        │
│     │   ├── 내명함 → iam_mystory('my_info')            │
│     │   ├── 추천 → iam_mystory('we_story')            │
│     │   └── 명함관리 → [내부페이지]/[로그인]                  │
│     ├── 미들(middle): 종이명함 검색 & 리스트            │
│     └── 바텀(bottom): 콘텐츠 그리드                    │
│                                                       │
│  4. AJAX 데이터 로딩                                   │
│     ├── getIamPaper() → [내부API]/[명함목록]  │
│     ├── displaySample() → [내부API]/[콘텐츠조회] │
│     └── displayMall() → [내부API]/[상품조회]    │
│                                                       │
│  5. 사용자 인터랙션                                    │
│     ├── 종이명함 추가 → add_paper_card()               │
│     │   ├── 모바일: callAppBridge('goCardCamera')      │
│     │   └── 데스크탑: alert("휴대폰에서 이용해주세요")  │
│     ├── 종이명함 편집 → create_paper()                 │
│     │   └── 모달 #paper_list_edit_modal 열기           │
│     ├── AI명함퍼널 → edit_papersender()                │
│     │   └── 모달 #paper_sender_edit_modal 열기         │
│     ├── 저장 → save_paper()                            │
│     │   └── POST → [내부API]/[명함관리]     │
│     └── 삭제 → delete_paper(id)                        │
│         └── POST → [내부API]/[명함관리]     │
└─────────────────────────────────────────────────────┘
    

🔄 데이터 흐름도

클라이언트(브라우저) ↔ 서버(PHP) 간 데이터가 어떻게 오가는지 보여줍니다:

동작 요청 방식 서버 엔드포인트 보내는 데이터 받는 데이터
종이명함 목록 로드GET[내부API]/[명함목록]card_owner, page, search_str, search_rangeHTML (명함 리스트)
종이명함 저장POST[내부API]/[명함관리]name, job, org, mobile, phone, email, addr, memo, display_top, img_urlJSON {result, seq, msg}
종이명함 삭제POST[내부API]/[명함관리]seq, del='Y'JSON {result}
명함 이미지 OCRPOST[내부API]/[명함관리]image file (multipart)JSON {name, mobile, org_name, job, addr, email, fax, img_url}
콘텐츠 기록 저장POST[내부API]/[콘텐츠처리]post_type='history', mem_id, cont_id, event_kindHTML (로그)
카드 결제POST[내부API]/[명함발송][결제타입], [결제수단], [결제금액], [포인트값], [명함URL], [메시지]JSON {result}
포인트 충전POST[내부API]/[포인트처리][결제방식], [금액], [수수료비율], [결제유형]JSON {result}
AI 발신자 저장POST (FormData)[내부API]/[명함관리]sender_* 필드들, ai_step, prompt_*, filesJSON {result}
AI 프롬프트 미리보기POST[내부API]/[프롬프트미리보기]sys_prompt, user_prompt, generation_modeHTML (미리보기 메시지)

📊 함수 분류 체계

페이지 내에 정의된 80개 이상의 함수를 8가지 카테고리로 분류했습니다:

1️⃣ 페이지 초기화 함수 (6개)

2️⃣ 데이터 로딩 함수 (8개)

3️⃣ 종이명함 CRUD 함수 (7개)

4️⃣ 검색·정렬·필터 함수 (6개)

5️⃣ 결제·포인트 함수 (8개)

6️⃣ 네비게이션 함수 (5개)

7️⃣ SNS·공유 함수 (4개)

8️⃣ 유틸리티 함수 (10+)

🧮 핵심 알고리즘 요약

알고리즘 #1: 디바이스 감지 (checkMobile)

User-Agent 문자열을 소문자로 변환한 후, 모바일 키워드가 포함되어 있는지 확인합니다:

입력: navigator.userAgent (브라우저 정보 문자열)
처리:
  1. userAgent를 소문자로 변환
  2. mobileKeywords = ['iphone','ipod','ipad','android','windows phone','blackberry','nokia','opera mini','mobile']
  3. mobileKeywords 배열을 순회하면서 userAgent에 포함되어 있는지 확인
  4. 하나라도 포함되어 있으면 → true (모바일)
  5. 없으면 → false (데스크탑)
출력: boolean
    

알고리즘 #2: 이미지 크기 조정 (resize)

로고 이미지가 주어진 최대 크기를 넘지 않도록 비율을 유지하며 축소합니다:

입력: img (이미지 객체), maxW (최대 너비), maxH (최대 높이)
처리:
  1. 현재 이미지 너비(width)와 높이(height)를 가져옴
  2. IF width > maxW:
       ratio = maxW / width
       너비를 maxW로, 높이를 height * ratio로 설정
  3. 조정된 너비/높이를 다시 읽음
  4. IF height > maxH:
       ratio = maxH / height
       높이를 maxH로, 너비를 width * ratio로 설정
출력: 없음 (DOM 직접 수정)
    

알고리즘 #3: 쿠키 읽기 (getCookie)

입력: name (찾을 쿠키 이름)
처리:
  1. document.cookie를 ';' 기준으로 분리해서 배열 생성
  2. 각 항목을 trim()으로 공백 제거
  3. 항목이 name + '=' 으로 시작하는지 확인
  4. 시작하면 '=' 이후 문자열을 반환
  5. 끝까지 찾지 못하면 null 반환
출력: string | null
    

알고리즘 #4: AJAX 무한 스크롤 (displaySample)

입력: lim (한 번에 가져올 개수), off (시작 위치)
처리:
  1. 쿠키에서 'contents_mode' 값을 읽음
  2. GET 요청: [내부API]/[콘텐츠조회]
     파라미터: limit=lim, offset=off, search_key="", sample_type="paper_card"
  3. 응답 HTML을 .sample_main에 추가(append)
  4. 응답이 10자 이하면 → window.busy = true (더 이상 데이터 없음)
     응답이 10자 초과면 → window.busy = false
출력: 없음 (DOM 직접 수정)
    

🎒 초등학생도 따라 하는 종이명함 등록 가이드

📖 이 가이드는 컴퓨터를 처음 배우는 초등학생도 따라 할 수 있도록 아주 쉽게 설명했어요. 차근차근 따라 해 보세요!

📜 전체 소스코드 주석 해설

페이지의 전체 인라인 JavaScript 코드를 한 줄 한 줄 분석했습니다. 각 함수가 어떤 일을 하는지, 왜 이렇게 작성했는지 설명합니다.

📖 총 17페이지에 걸쳐 명함 프로필의 모든 것을 담았습니다.
왼쪽 사이드바 메뉴에서 원하는 주제를 클릭하면 상세 내용을 볼 수 있어요!