"DigitalSinology(2026) NetworkGraph 02.lst"의 두 판 사이의 차이
CNUDH
JSH CNUGrad (토론 | 기여) (JSH CNUGrad (토론)의 31631판 편집을 되돌림) (태그: 편집 취소) |
JSH CNUGrad (토론 | 기여) (→연구 결과) |
||
| 90번째 줄: | 90번째 줄: | ||
:또한 '인력거'가 출현하지 않은 문장은 각각 '낙타', '돈', '결혼' 등의 요소로 내용을 이끌고 있다. <br/> | :또한 '인력거'가 출현하지 않은 문장은 각각 '낙타', '돈', '결혼' 등의 요소로 내용을 이끌고 있다. <br/> | ||
</div> | </div> | ||
| − | + | <br/> | |
| + | [[파일:인력거시각화1.png]] | ||
----- | ----- | ||
| + | <br/> | ||
===='''<span style="color:#006400">연구 결과 02</span>'''==== | ===='''<span style="color:#006400">연구 결과 02</span>'''==== | ||
<div style="border:1px solid #000;"> | <div style="border:1px solid #000;"> | ||
| 99번째 줄: | 101번째 줄: | ||
:다만, 아직 초반 부분이며 전체 장을 마크업하면 흥미로운 결과가 나올 듯 하다..<br/> | :다만, 아직 초반 부분이며 전체 장을 마크업하면 흥미로운 결과가 나올 듯 하다..<br/> | ||
</div> | </div> | ||
| − | + | <br/> | |
| + | <div style="text-align:center;"><big><b><che> 속성 공간 분포 (마이크로 닷 히트맵)</b><big> <br/> | ||
| + | <small>각 격자는 하나의 단락을 의미하며, 한 줄에 15개씩 출력되도록 줄바꿈 되었습니다.</small><br/> | ||
| + | <small>격자 좌상단의 작은 숫자는 단락의 순번입니다.</small></div><br/> | ||
| + | <div style="text-align:center;">[[파일:인력거시각화2-1.png]]</div> | ||
| + | <br/> | ||
| + | <div style="text-align:center;">[[파일:인력거시각화2-2.png]]</div> | ||
----- | ----- | ||
| + | <br/> | ||
===='''<span style="color:#006400">연구 결과 03</span>'''==== | ===='''<span style="color:#006400">연구 결과 03</span>'''==== | ||
<div style="border:1px solid #000;"> | <div style="border:1px solid #000;"> | ||
| 108번째 줄: | 117번째 줄: | ||
:연구결과02에서 언급했듯, 작품의 후반부까지 마크업하면 샹즈와 연결된 '발생-희망'의 비율이 어떻게 달라질 것인가? 역전할 것인가? | :연구결과02에서 언급했듯, 작품의 후반부까지 마크업하면 샹즈와 연결된 '발생-희망'의 비율이 어떻게 달라질 것인가? 역전할 것인가? | ||
</div> | </div> | ||
| + | <html lang="ko"> | ||
| + | <head> | ||
| + | <meta charset="UTF-8"> | ||
| + | <title>낙타샹즈 상태-주체 생키 다이어그램</title> | ||
| + | <script src="https://d3js.org/d3.v7.min.js"></script> | ||
| + | <script src="https://unpkg.com/d3-sankey@0.12.3/dist/d3-sankey.min.js"></script> | ||
| + | <style> | ||
| + | body { font-family: 'Malgun Gothic', sans-serif; background-color: #f8f9fa; margin: 0; padding: 20px; display: flex; flex-direction: column; align-items: center; } | ||
| + | h1 { color: #2c3e50; margin-bottom: 10px; } | ||
| + | .desc { color: #666; margin-bottom: 30px; font-size: 14px; text-align: center; } | ||
| + | .chart-box { background: #fff; padding: 30px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); } | ||
| + | |||
| + | .node rect { cursor: move; fill-opacity: 0.9; shape-rendering: crispEdges; stroke: #333; stroke-width: 1px; } | ||
| + | .node text { pointer-events: none; text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff; font-weight: bold; font-size: 14px; } | ||
| + | |||
| + | .link { fill: none; stroke-opacity: 0.4; transition: stroke-opacity 0.2s; } | ||
| + | .link:hover { stroke-opacity: 0.8 !important; } | ||
| + | |||
| + | .tooltip { position: absolute; text-align: center; padding: 10px; font-size: 13px; background: rgba(0,0,0,0.85); color: #fff; border-radius: 6px; pointer-events: none; opacity: 0; transition: opacity 0.2s; z-index: 10; box-shadow: 0 4px 6px rgba(0,0,0,0.2); } | ||
| + | </style> | ||
| + | </head> | ||
| + | <body> | ||
| + | <div style="text-align:center;"><small><h1><che> 속성 교차 흐름 (상태 → 주체)</h1></small></div> | ||
| + | <div class="desc"> | ||
| + | 1~5장에 등장하는 전체 <che> 마크업의 속성값을 바탕으로 작성된 생키 다이어그램입니다.<br> | ||
| + | 선의 두께는 동시 출현 빈도(결합 강도)에 비례하며, 노드에 마우스를 올리면 상세 수치를 확인할 수 있습니다. | ||
| + | </div> | ||
| + | |||
| + | <div class="chart-box" id="sankey-container"></div> | ||
| + | <div class="tooltip" id="tooltip"></div> | ||
| + | |||
| + | <script> | ||
| + | const data = {"nodes": [{"name": "\ubc1c\uc0dd", "category": "state"}, {"name": "\ud76c\ub9dd", "category": "state"}, {"name": "\uae30\ud0c0", "category": "state"}, {"name": "\uc0f9\uc988", "category": "subject"}, {"name": "\ud0c0\uc778", "category": "subject"}, {"name": "\uc0ac\ubb3c", "category": "subject"}], "links": [{"source": 0, "target": 4, "value": 47}, {"source": 2, "target": 5, "value": 35}, {"source": 1, "target": 4, "value": 8}, {"source": 0, "target": 3, "value": 127}, {"source": 1, "target": 3, "value": 68}, {"source": 2, "target": 4, "value": 6}, {"source": 2, "target": 3, "value": 24}, {"source": 0, "target": 5, "value": 16}, {"source": 1, "target": 5, "value": 4}]}; | ||
| + | const tooltip = d3.select("#tooltip"); | ||
| + | |||
| + | const margin = {top: 30, right: 150, bottom: 30, left: 150}; | ||
| + | const width = 1000 - margin.left - margin.right; | ||
| + | const height = 600 - margin.top - margin.bottom; | ||
| + | |||
| + | const svg = d3.select("#sankey-container").append("svg") | ||
| + | .attr("width", width + margin.left + margin.right) | ||
| + | .attr("height", height + margin.top + margin.bottom) | ||
| + | .append("g") | ||
| + | .attr("transform", `translate(${margin.left},${margin.top})`); | ||
| + | |||
| + | // 색상 스케일 | ||
| + | const colorScale = d3.scaleOrdinal() | ||
| + | .domain(["발생", "희망", "기타", "샹즈", "타인", "사물"]) | ||
| + | .range(["#ff7f0e", "#2ca02c", "#7f7f7f", "#1f77b4", "#9467bd", "#8c564b"]); | ||
| + | |||
| + | // 생키 레이아웃 설정 | ||
| + | const sankey = d3.sankey() | ||
| + | .nodeWidth(30) | ||
| + | .nodePadding(60) | ||
| + | .extent([[0, 0], [width, height]]); | ||
| + | |||
| + | const {nodes, links} = sankey(data); | ||
| + | |||
| + | // 링크(흐름선) 그리기 | ||
| + | const link = svg.append("g") | ||
| + | .attr("fill", "none") | ||
| + | .selectAll(".link") | ||
| + | .data(links) | ||
| + | .enter().append("path") | ||
| + | .attr("class", "link") | ||
| + | .attr("d", d3.sankeyLinkHorizontal()) | ||
| + | .attr("stroke", d => colorScale(d.source.name)) | ||
| + | .attr("stroke-width", d => Math.max(1, d.width)) | ||
| + | .on("mouseover", function(event, d) { | ||
| + | d3.selectAll(".link").style("stroke-opacity", 0.1); | ||
| + | d3.select(this).style("stroke-opacity", 0.8); | ||
| + | |||
| + | tooltip.style("opacity", 1) | ||
| + | .html(`<strong>${d.source.name} → ${d.target.name}</strong><br>빈도: ${d.value}건`) | ||
| + | .style("left", (event.pageX + 15) + "px") | ||
| + | .style("top", (event.pageY - 15) + "px"); | ||
| + | }) | ||
| + | .on("mouseout", function() { | ||
| + | d3.selectAll(".link").style("stroke-opacity", 0.4); | ||
| + | tooltip.style("opacity", 0); | ||
| + | }); | ||
| + | |||
| + | // 노드(막대) 그리기 | ||
| + | const node = svg.append("g") | ||
| + | .selectAll(".node") | ||
| + | .data(nodes) | ||
| + | .enter().append("g") | ||
| + | .attr("class", "node") | ||
| + | .attr("transform", d => `translate(${d.x0},${d.y0})`) | ||
| + | .call(d3.drag() | ||
| + | .subject(d => d) | ||
| + | .on("start", function() { this.parentNode.appendChild(this); }) | ||
| + | .on("drag", dragmove)); | ||
| + | node.append("rect") | ||
| + | .attr("height", d => d.y1 - d.y0) | ||
| + | .attr("width", sankey.nodeWidth()) | ||
| + | .attr("fill", d => colorScale(d.name)) | ||
| + | .on("mouseover", function(event, d) { | ||
| + | // 하이라이트 연결된 링크 | ||
| + | link.style("stroke-opacity", l => (l.source === d || l.target === d) ? 0.8 : 0.1); | ||
| + | |||
| + | tooltip.style("opacity", 1) | ||
| + | .html(`<strong>${d.name}</strong><br>총합: ${d.value}건`) | ||
| + | .style("left", (event.pageX + 15) + "px") | ||
| + | .style("top", (event.pageY - 15) + "px"); | ||
| + | }) | ||
| + | .on("mouseout", function() { | ||
| + | link.style("stroke-opacity", 0.4); | ||
| + | tooltip.style("opacity", 0); | ||
| + | }); | ||
| + | |||
| + | // 노드 텍스트 라벨 | ||
| + | node.append("text") | ||
| + | .attr("x", d => d.x0 < width / 2 ? 40 : -10) | ||
| + | .attr("y", d => (d.y1 - d.y0) / 2) | ||
| + | .attr("dy", "0.35em") | ||
| + | .attr("text-anchor", d => d.x0 < width / 2 ? "start" : "end") | ||
| + | .text(d => `${d.name} (${d.value})`); | ||
| + | |||
| + | // 드래그 앤 드롭 함수 (위아래 이동) | ||
| + | function dragmove(event, d) { | ||
| + | d.y0 = Math.max(0, Math.min(height - (d.y1 - d.y0), event.y)); | ||
| + | d.y1 = d.y0 + (d.y1 - d.y0); | ||
| + | d3.select(this).attr("transform", `translate(${d.x0},${d.y0})`); | ||
| + | sankey.update(data); | ||
| + | link.attr("d", d3.sankeyLinkHorizontal()); | ||
| + | } | ||
| + | |||
| + | // 컬럼 라벨 (상태, 주체) | ||
| + | svg.append("text") | ||
| + | .attr("x", 15) | ||
| + | .attr("y", -10) | ||
| + | .attr("text-anchor", "middle") | ||
| + | .style("font-size", "16px") | ||
| + | .style("font-weight", "bold") | ||
| + | .style("fill", "#2c3e50") | ||
| + | .text("상태 (State)"); | ||
| + | |||
| + | svg.append("text") | ||
| + | .attr("x", width - 15) | ||
| + | .attr("y", -10) | ||
| + | .attr("text-anchor", "middle") | ||
| + | .style("font-size", "16px") | ||
| + | .style("font-weight", "bold") | ||
| + | .style("fill", "#2c3e50") | ||
| + | .text("주체 (Subject)"); | ||
| + | |||
| + | </script> | ||
| + | </body> | ||
| + | </html> | ||
<br/> | <br/> | ||
<br/> | <br/> | ||
<br/> | <br/> | ||
| + | |||
==='''<span style="color:#006400">나가며</span>'''=== | ==='''<span style="color:#006400">나가며</span>'''=== | ||
<br/> | <br/> | ||
2026년 6월 18일 (목) 15:53 판
중어중문학과 정선한
문제의식
- 『낙타상자』에서 '인력거'라는 중심 사물이 차지하는 비중은 어느 정도인가?
- 샹즈가 인력거를 '실제'로 가지고 있는 정도가 많을 것인가, '희망'하는 정도가 많을 것인가?
연구 목적
01. 전체 문장에서 '車(인력거)'가 언급된 분포 시각화
02. 샹즈의 현실과 비현실 속 인력거의 등장 양상 확인
연구 방법
01. 전체 문장에서 '車, 인력거'가 언급된 양상과 분포는 어떻게 나타나는가?
<Sentence> 단위에서 '車'와 '인력거' 전체 마크업
다시 4가지 태그로 분류한다.
- che: 인력거
- cheRen: 인력거와 관련된 사람
- chePlace: 인력거와 관련된 장소
- cheMoney: 인력거와 관련된 돈
02. 샹즈는 '인력거'를 현실에서 접하는가, 희망으로 접하는가?
<che>태그 내에서 속성으로 현실과 희망을 구분한다.
<che 상태="발생/희망/기타" 주체="샹즈/타인/사물">
| |
|---|---|
상태 |
주체
|
|
발생: 현재 발생한 사건, 샹즈에게 이미 일어난 일, 실제로 일어난 것 |
샹즈: 발생/희망/기타 사건의 동작을 하는 주체가 샹즈 |
03. <che> 속성의 상태와 주체의 교차 흐름은 어떻게 되는가?
이는 인력거가 존재하는 방식과 그 시점에서의 인력거 소유 주체를 보기 위함이다.
각 속성값을 생키 다이어그램으로 비율과 흐름을 확인한다.
연구 결과
연구 결과 01
- 전체 문장 1807개 중, 346개만이 '인력거'와 관련이 있다. 비율은 19.15% 이다.
- 『낙타상자』에서 '인력거'는 가장 주된 사물이지만, 라오서가 서술한 비율은 크지 않다.
- 또한 '인력거'가 출현하지 않은 문장은 각각 '낙타', '돈', '결혼' 등의 요소로 내용을 이끌고 있다.
연구 결과 02
- 1장 1단락부터 5장 7단락까지의 데이터다.
- 샹즈는 인력거를 얻기 위해, 그리고 인력거를 찾기 위해 고군분터하는 인물이다.
- 따라서 인력거를 희망하며 노력하는 시간이 많을 것으로(<che 상태="희망">이 많을 것으로) 예상했는데 그렇지 않았다.
- 다만, 아직 초반 부분이며 전체 장을 마크업하면 흥미로운 결과가 나올 듯 하다..
각 격자는 하나의 단락을 의미하며, 한 줄에 15개씩 출력되도록 줄바꿈 되었습니다.
연구 결과 03
- <che> 속성의 상태와 주체의 교차 흐름의 결과, 주체는 샹즈가 단연 제일 큰 비중이었다.
- 샹즈 중심의 서술이므로 샹즈의 발생-희망 비율(53.5%)이 타인의 발생-희망(17.0%)보다 높은 수치를 보였다.
- 이때, '타인'을 각 인물명으로 세분화하면 여전히 발생-희망 비율이 유사하게 나타날 것인가? 인물별로 달라지리라 예상한다.
- 연구결과02에서 언급했듯, 작품의 후반부까지 마크업하면 샹즈와 연결된 '발생-희망'의 비율이 어떻게 달라질 것인가? 역전할 것인가?
<che> 속성 교차 흐름 (상태 → 주체)
선의 두께는 동시 출현 빈도(결합 강도)에 비례하며, 노드에 마우스를 올리면 상세 수치를 확인할 수 있습니다.
나가며
추후 진행되어야 할 작업과 남아 있는 질문은 다음과 같다.
전체 데이터의 마크업이 완료되면,
<che 상태="발생/희망/기타"> 마크업 샹즈는 '인력거를 끄는' 인물이 될 것인가, '인력거를 갈하는' 인물이 될 것인가?
<che 상태="발생/희망/기타"> 마크업 서사의 진행에 따라 '인력거'가 샹즈의 현실과 비현실에 존재하는 모습은 어떤 변화를 보일 것인가?
<che 주체="타인"> 구체화 각 인물별로 인력거를 소유하고, 바라는 비율은 어떻게 될 것인가?
<che 주체="타인"> 구체화 직업(신분)별로 어떠한 양상을 보일 것인가? 인력거꾼들과, 샹즈의 비율을 유사한 수치를 보일 것인가?
'인력거' 외 주요 사물 마크업 서사를 진행하는 중심 사물은 무엇으로 이동하는가? 라오서가 사용한 주요 매개체가 '인력거'가 정말 맞을 것인가?
이 작품의 첫 문장이다.
我們所要介紹的是祥子,不是駱駝, 내가 소개하고자 하는 이는 샹즈祥子이지 낙타駱駝가 아니다.
'샹즈'에 관한 소개인 『낙타상자』에서 각각의 사물은 언제 등장하며, '낙타'는 무엇의 시발점이 되는가?


