행위

"DigitalSinology(2026) NetworkGraph 02.lst"의 두 판 사이의 차이

CNUDH

(연구 결과 02)
 
(같은 사용자의 중간 판 5개는 보이지 않습니다)
1번째 줄: 1번째 줄:
<html>
+
<div style="text-align:justify">
<head>
 
<meta charset="UTF-8">
 
<style>
 
body{
 
    font-family:Arial,sans-serif;
 
    background:#fdfdf9;
 
    text-align:center;
 
    padding:30px;
 
}
 
  
#visualization{
+
<font face="나눔바른고딕">
    width:100%;
+
<br/><br/><br/><br/>
    max-width:1400px;
 
    margin:auto;
 
}
 
  
.row{
+
<html>
    display:flex;
 
    align-items:center;
 
    margin:18px 0;
 
}
 
  
.chapter{
+
<center><font color="#006400" size="11"><b>샹즈와 인력거</b></font>
    width:60px;
+
<br/><br/>
    text-align:right;
+
<font color="#3CB371" size="5"></font></center><br/>
    padding-right:15px;
 
    font-weight:bold;
 
}
 
  
.timeline{
+
</html>
    flex:1;
 
    position:relative;
 
    height:25px;
 
    border-top:2px solid #b5b5b5;
 
}
 
  
.tick-gray{
+
<font face="나눔바른고딕 UltraLight"><p style="text-align:right;"><font color="black" size="4">중어중문학과  <b>정선한</b></font></p>
    position:absolute;
 
    width:1px;
 
    height:7px;
 
    top:0;
 
    background:#999;
 
    cursor:pointer;
 
}
 
  
.tick-gray:hover {
+
</font>
    background: #555;
+
__NOTOC__
    width: 2px;
 
    z-index: 5;
 
}
 
  
.tick-color{
+
<div style="float:center; background:#3CB371; width:100%; height:3px; text-align:right; padding:2px 2px 2px;"></div>
    position:absolute;
 
    width:2px;
 
    height:14px;
 
    top:-12px;
 
    cursor:pointer;
 
    z-index: 10;
 
}
 
  
.tick-color:hover {
+
==='''<span style="color:#006400">문제의식</span>'''===
    width: 4px;
 
    z-index: 15;
 
}
 
  
.count{
+
*『낙타상자』에서 '인력거'라는 중심 사물이 차지하는 비중은 어느 정도인가?<br/>
    width:80px;
+
* 샹즈가 인력거를 '실제'로 가지고 있는 정도가 많을 것인가, '희망'하는 정도가 많을 것인가?
    color:#555;
+
<br/>
    font-weight:bold;
 
    padding-left:10px;
 
    text-align:right;
 
}
 
  
.count .match{
+
==='''<span style="color:#006400">연구 목적</span>'''===
    color:#e74c3c;
+
01. 전체 문장에서 '車(인력거)'가 언급된 분포 시각화
}
+
<br/>
 +
02. 샹즈의 현실과 비현실 속 인력거의 등장 양상 확인
 +
<br/>
 +
<br/>
  
.che{background:#e74c3c;}
+
==='''<span style="color:#006400">연구 방법</span>'''===
.cheRen{background:#3498db;}
+
<span style="background-color: #ACE1AF;">01. 전체 문장에서 '車, 인력거'가 언급된 양상과 분포는 어떻게 나타나는가?</span>
.chePlace{background:#2ecc71;}
+
<br/>
.cheMoney{background:#f39c12;}
+
<br/>
 +
<Sentence> 단위에서 '車'와 '인력거' 전체 마크업
 +
다시 4가지 태그로 분류한다.
 +
<br/>
 +
<div style="border:1px solid #000;">
 +
# che: 인력거
 +
# cheRen: 인력거와 관련된 사람
 +
# chePlace: 인력거와 관련된 장소
 +
# cheMoney: 인력거와 관련된 돈
 +
</div>
 +
<br/>
 +
<br>
 +
<br>
  
#legend{
+
<span style="background-color: #ACE1AF;">02. 샹즈는 '인력거'를 현실에서 접하는가, 희망으로 접하는가?</span>
    margin:25px 0;
+
<br/>
}
+
<br/>
 +
<che>태그 내에서 속성으로 현실과 희망을 구분한다.
  
.legend-item{
+
{| class="wikitable"
    margin:0 15px;
+
|-
}
+
! colspan="2"| <div style="text-align:center;"><b><che 상태="발생/희망/기타" 주체="샹즈/타인/사물"></b></div>
 +
|-
 +
| <div style="text-align:center;">상태</div> || <div style="text-align:center;">주체</div>
 +
|-
 +
| style="width:50%;" |
 +
발생: 현재 발생한 사건, 샹즈에게 이미 일어난 일, 실제로 일어난 것<br/>
 +
희망: 실제로 일어나지는 않았지만 실현되길 바라는 사건, 할 것임을 다짐하는 문장<br/>
 +
기타: 발생/희망에 해당하지 않음<br/>
 +
||
 +
샹즈: 발생/희망/기타 사건의 동작을 하는 주체가 샹즈<br/>
 +
타인: 발생/희망/기타 사건의 동작을 하는 주체가 타인<br/>
 +
사물: 발생/희망/기타 사건의 동작을 하는 주체가 사람이 아님<br/>
 +
|-
 +
|}
 +
<br>
 +
<br>
 +
<br>
  
.box{
+
<span style="background-color: #ACE1AF;">03. <che> 속성의 상태와 주체의 교차 흐름은 어떻게 되는가?</span>
    width:14px;
+
<br/>
    height:14px;
+
<br/>
    display:inline-block;
+
이는 인력거가 존재하는 방식과 그 시점에서의 인력거 소유 주체를 보기 위함이다.<br/>
    margin-right:5px;
+
각 속성값을 생키 다이어그램으로 비율과 흐름을 확인한다.
    vertical-align:middle;
+
<br/>
}
+
<br/>
  
/* 툴팁 Z-index 극대화 */
+
==='''<span style="color:#006400">연구 결과</span>'''===
#tooltip {
+
-----
    position: absolute;
+
===='''<span style="color:#006400">연구 결과 01</span>'''====
    display: none;
+
<div style="border:1px solid #000;">
    background: rgba(0, 0, 0, 0.85);
+
* 전체 문장 1807개 중, 346개만이 '인력거'와 관련이 있다. 비율은 19.15% 이다. <br/>
    color: #fff;
+
:『낙타상자』에서 '인력거'는 가장 주된 사물이지만, 라오서가 서술한 비율은 크지 않다. <br/>
    padding: 15px;
+
:또한 '인력거'가 출현하지 않은 문장은 각각 '낙타', '돈', '결혼' 등의 요소로 내용을 이끌고 있다. <br/>
    border-radius: 6px;
+
</div>
    font-size: 13px;
+
<br/>
    text-align: left;
+
[[파일:인력거시각화1.png]]
    width: max-content;
+
-----
    max-width: 500px;
+
<br/>
    line-height: 1.5;
+
===='''<span style="color:#006400">연구 결과 02</span>'''====
    box-shadow: 0 4px 8px rgba(0,0,0,0.4);
+
<div style="border:1px solid #000;">
    z-index: 999999 !important;
+
* <small>1장 1단락부터 5장 7단락까지의 데이터다.</small><br/>
    pointer-events: none;
+
:샹즈는 인력거를 얻기 위해, 그리고 인력거를 찾기 위해 고군분터하는 인물이다.<br/>
    word-break: keep-all;
+
:따라서 인력거를 희망하며 노력하는 시간이 많을 것으로<small>(<che 상태="희망">이 많을 것으로)</small> 예상했는데 그렇지 않았다.<br/>
    box-sizing: border-box;
+
:다만, 아직 초반 부분이며 전체 장을 마크업하면 흥미로운 결과가 나올 듯 하다..<br/>
}
+
</div>
 +
<br/>
 +
<br/>
 +
<div style="text-align:center;"><font size="7"><che> 속성 공간 분포 (마이크로 닷 히트맵)</font><br/>
 +
<small>
 +
<span style="color:#696969;">각 격자는 하나의 단락을 의미하며, 한 줄에 15개씩 출력되도록 줄바꿈 되었습니다. 격자 좌상단의 작은 숫자는 단락의 순번입니다.</span></small></div><br/>
 +
<div style="text-align:center;">[[파일:인력거시각화2-1.png]]</div>
 +
<br/>
 +
<div style="text-align:center;">[[파일:인력거시각화2-2.png]]</div>
 +
-----
 +
<br/>
  
#tooltip strong {
+
===='''<span style="color:#006400">연구 결과 03</span>'''====
     color: #ffd700;
+
<div style="border:1px solid #000;">
}
+
* <che> 속성의 상태와 주체의 교차 흐름의 결과, 주체는 샹즈가 단연 제일 큰 비중이었다.<br/>
 
+
:샹즈 중심의 서술이므로 샹즈의 발생-희망 비율(53.5%)이 타인의 발생-희망(17.0%)보다 높은 수치를 보였다.<br/>
.tooltip-sentence-info {
+
:이때, '타인'을 각 인물명으로 세분화하면 여전히 발생-희망 비율이 유사하게 나타날 것인가? 인물별로 달라지리라 예상한다. <br/>
    color: #a8d8ea;
+
:연구결과02에서 언급했듯, 작품의 후반부까지 마크업하면 샹즈와 연결된 '발생-희망'의 비율이 어떻게 달라질 것인가? 역전할 것인가?
    font-weight: bold;
+
</div>
    margin-bottom: 8px;
+
<html lang="ko">
    display: inline-block;
+
<head>
}
+
    <meta charset="UTF-8">
</style>
+
    <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>
 
</head>
 
<body>
 
<body>
 +
    <div style="text-align:center;"><small><h1>&lt;che&gt; 속성 교차 흐름 (상태 → 주체)</h1></small></div>
 +
    <div class="desc">
 +
        1~5장에 등장하는 전체 &lt;che&gt; 마크업의 속성값을 바탕으로 작성된 생키 다이어그램입니다.<br>
 +
        선의 두께는 동시 출현 빈도(결합 강도)에 비례하며, 노드에 마우스를 올리면 상세 수치를 확인할 수 있습니다.
 +
    </div>
  
<h2>駱駝祥子 인력거(車) 관련 어휘 공간적 분포</h2>
+
    <div class="chart-box" id="sankey-container"></div>
 +
    <div class="tooltip" id="tooltip"></div>
  
<div id="legend">
+
    <script>
    <span class="legend-item">
+
        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}]};
        <span class="box che"></span> che
+
         const tooltip = d3.select("#tooltip");
    </span>
 
    <span class="legend-item">
 
        <span class="box cheRen"></span> cheRen
 
    </span>
 
    <span class="legend-item">
 
        <span class="box chePlace"></span> chePlace
 
    </span>
 
    <span class="legend-item">
 
         <span class="box cheMoney"></span> cheMoney
 
    </span>
 
</div>
 
  
<div id="visualization"></div>
+
        const margin = {top: 30, right: 150, bottom: 30, left: 150};
 +
        const width = 1000 - margin.left - margin.right;
 +
        const height = 600 - margin.top - margin.bottom;
  
<div id="tooltip"></div>
+
        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})`);
  
<textarea id="xmlDataBlock" style="display:none;">
+
        // 색상 스케일
 +
        const colorScale = d3.scaleOrdinal()
 +
            .domain(["발생", "희망", "기타", "샹즈", "타인", "사물"])
 +
            .range(["#ff7f0e", "#2ca02c", "#7f7f7f", "#1f77b4", "#9467bd", "#8c564b"]);
  
</textarea>
+
        // 생키 레이아웃 설정
 +
        const sankey = d3.sankey()
 +
            .nodeWidth(30)
 +
            .nodePadding(60)
 +
            .extent([[0, 0], [width, height]]);
  
<script>
+
        const {nodes, links} = sankey(data);
window.addEventListener("DOMContentLoaded", function() {
 
    // 1. 미디어위키 레이아웃 제약을 벗어나기 위해 툴팁을 body 최상단으로 강제 이동
 
    var tooltip = document.getElementById("tooltip");
 
    if (tooltip && tooltip.parentNode !== document.body) {
 
        document.body.appendChild(tooltip);
 
    }
 
  
    // 2. textarea에서 XML 문자열을 안전하게 추출
+
        // 링크(흐름선) 그리기
    var xmlString = document.getElementById("xmlDataBlock").value.trim();
+
        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);
 +
            });
  
    if(xmlString === "") {
+
        // 노드(막대) 그리기
        alert("HTML 코드 내의 <textarea id='xmlDataBlock'> 영역에 XML 데이터를 붙여넣어 주세요.");
+
        const node = svg.append("g")
        return;
+
            .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));
  
    var parser = new DOMParser();
+
        node.append("rect")
    var xmlDoc = parser.parseFromString(xmlString, "text/xml");
+
            .attr("height", d => d.y1 - d.y0)
 
+
            .attr("width", sankey.nodeWidth())
    if(xmlDoc.getElementsByTagName("parsererror").length > 0){
+
            .attr("fill", d => colorScale(d.name))
        alert("XML 데이터 구조에 오류가 있습니다. 원본 XML 파일의 내용을 다시 확인해 주세요.");
+
            .on("mouseover", function(event, d) {
        return;
+
                // 하이라이트 연결된 링크
    }
+
                 link.style("stroke-opacity", l => (l.source === d || l.target === d) ? 0.8 : 0.1);
 
+
               
    draw(xmlDoc, tooltip);
+
                tooltip.style("opacity", 1)
});
+
                      .html(`<strong>${d.name}</strong><br>총합: ${d.value}건`)
 
+
                      .style("left", (event.pageX + 15) + "px")
function draw(xmlDoc, tooltip){
+
                      .style("top", (event.pageY - 15) + "px");
    var container = document.getElementById("visualization");
+
             })
    container.innerHTML = "";
+
             .on("mouseout", function() {
   
+
                 link.style("stroke-opacity", 0.4);
    var chapters = xmlDoc.getElementsByTagName("Chapter");
+
                tooltip.style("opacity", 0);
 
 
    var globalTotalSentences = 0;
 
    var globalTotalMatches = 0;
 
 
 
    for(var i=0; i<chapters.length; i++){
 
        var chapter = chapters[i];
 
        var sentences = chapter.getElementsByTagName("Sentence");
 
 
 
        if(sentences.length === 0) continue;
 
 
 
        globalTotalSentences += sentences.length;
 
 
 
        var row = document.createElement("div");
 
        row.className = "row";
 
 
 
        var label = document.createElement("div");
 
        label.className = "chapter";
 
        label.innerHTML = (i+1) + "장";
 
 
 
        var timeline = document.createElement("div");
 
        timeline.className = "timeline";
 
 
 
        var count = 0;
 
 
 
        var moveHandler = function(e) {
 
            var tooltipWidth = tooltip.offsetWidth;
 
            var windowWidth = window.innerWidth;
 
            var x = e.pageX;
 
            var y = e.pageY;
 
           
 
            if (x > windowWidth / 2) {
 
                 tooltip.style.left = (x - tooltipWidth - 20) + "px";
 
            } else {
 
                tooltip.style.left = (x + 20) + "px";
 
            }
 
            tooltip.style.top = (y + 15) + "px";
 
        };
 
 
 
        for(var s=0; s<sentences.length; s++){
 
            var sentence = sentences[s];
 
            var left = (s/(sentences.length-1))*100;
 
            if(sentences.length === 1) left = 0;
 
           
 
            var paragraph = sentence.parentNode;
 
            var pId = paragraph && paragraph.tagName === "Paragraph" ? paragraph.getAttribute("id") : "정보 없음";
 
            var pTitle = paragraph && paragraph.tagName === "Paragraph" ? paragraph.getAttribute("title") : "단락 정보 없음";
 
            var sTitle = sentence.getAttribute("title") || "문장 정보 없음";
 
           
 
            var textOrElem = sentence.getElementsByTagName("TextOr")[0];
 
            var textTrElem = sentence.getElementsByTagName("TextTr")[0];
 
           
 
            var textOr = textOrElem ? textOrElem.textContent : "원문 데이터가 없습니다.";
 
            var textTr = textTrElem ? textTrElem.textContent : "번역 데이터가 없습니다.";
 
 
 
            var tooltipHtml = "<strong>[" + pTitle + "]</strong> (" + pId + ")<br>" +
 
                              "<span class='tooltip-sentence-info'>문장: " + sTitle + "</span><br><br>" +
 
                              "<strong>원문:</strong> " + textOr + "<br><br>" +
 
                              "<strong>번역:</strong> " + textTr;
 
 
 
            var gray = document.createElement("div");
 
            gray.className = "tick-gray";
 
            gray.style.left = left + "%";
 
              
 
             gray.addEventListener("mouseover", (function(html) {
 
                 return function(e) {
 
                    tooltip.style.display = "block";
 
                    tooltip.innerHTML = html;
 
                };
 
            })(tooltipHtml));
 
           
 
            gray.addEventListener("mousemove", moveHandler);
 
           
 
            gray.addEventListener("mouseout", function() {
 
                tooltip.style.display = "none";
 
 
             });
 
             });
           
 
            timeline.appendChild(gray);
 
  
             var tagType = null;
+
        // 노드 텍스트 라벨
 +
        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})`);
  
            if(sentence.getElementsByTagName("che").length > 0) tagType = "che";
+
        // 드래그 앤 드롭 함수 (위아래 이동)
            if(sentence.getElementsByTagName("cheRen").length > 0) tagType = "cheRen";
+
        function dragmove(event, d) {
            if(sentence.getElementsByTagName("chePlace").length > 0) tagType = "chePlace";
+
            d.y0 = Math.max(0, Math.min(height - (d.y1 - d.y0), event.y));
            if(sentence.getElementsByTagName("cheMoney").length > 0) tagType = "cheMoney";
+
             d.y1 = d.y0 + (d.y1 - d.y0);
 
+
            d3.select(this).attr("transform", `translate(${d.x0},${d.y0})`);
             if(tagType){
+
            sankey.update(data);
                count++;
+
            link.attr("d", d3.sankeyLinkHorizontal());
               
 
                var tick = document.createElement("div");
 
                tick.className = "tick-color " + tagType;
 
                tick.style.left = left + "%";
 
               
 
                var colorTooltipHtml = "<strong>[" + pTitle + "]</strong> (" + pId + ") - <span style='color:#ff7f0e;'>발견태그: &lt;" + tagType + "&gt;</span><br>" +
 
                                      "<span class='tooltip-sentence-info'>문장: " + sTitle + "</span><br><br>" +
 
                                      "<strong>원문:</strong> " + textOr + "<br><br>" +
 
                                      "<strong>번역:</strong> " + textTr;
 
               
 
                tick.addEventListener("mouseover", (function(html) {
 
                    return function(e) {
 
                        tooltip.style.display = "block";
 
                        tooltip.innerHTML = html;
 
                    };
 
                })(colorTooltipHtml));
 
               
 
                tick.addEventListener("mousemove", moveHandler);
 
               
 
                tick.addEventListener("mouseout", function() {
 
                    tooltip.style.display = "none";
 
                });
 
               
 
                timeline.appendChild(tick);
 
            }
 
 
         }
 
         }
 +
       
 +
        // 컬럼 라벨 (상태, 주체)
 +
        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)");
  
        globalTotalMatches += count;
+
    </script>
 
+
</body>
        var countDiv = document.createElement("div");
+
</html>
        countDiv.className = "count";
 
        countDiv.innerHTML = "<span class='match'>" + count + "</span> / " + sentences.length;
 
 
 
        row.appendChild(label);
 
        row.appendChild(timeline);
 
        row.appendChild(countDiv);
 
  
        container.appendChild(row);
+
<br/>
    }
+
<br/>
 +
<br/>
  
    if (globalTotalSentences > 0) {
+
==='''<span style="color:#006400">나가며</span>'''===
        var ratio = ((globalTotalMatches / globalTotalSentences) * 100).toFixed(2);
+
<br/>
       
+
추후 진행되어야 할 작업과 남아 있는 질문은 다음과 같다.<br/>
        var ratioDiv = document.createElement("div");
+
<br/>
        ratioDiv.style.marginTop = "40px";
+
전체 데이터의 마크업이 완료되면, <br/>
        ratioDiv.style.fontSize = "28px";
+
<small><code><che 상태="발생/희망/기타"> 마크업</code></small> 샹즈는 '인력거를 끄는' 인물이 될 것인가, '인력거를 갈하는' 인물이 될 것인가?<br/>
        ratioDiv.style.fontWeight = "bold";
+
<small><code><che 상태="발생/희망/기타"> 마크업</code></small> 서사의 진행에 따라 '인력거'가 샹즈의 현실과 비현실에 존재하는 모습은 어떤 변화를 보일 것인가?<br/>
        ratioDiv.style.color = "#e74c3c";
+
<small><code><che 주체="타인"> 구체화</code></small> 각 인물별로 인력거를 소유하고, 바라는 비율은 어떻게 될 것인가?<br/>
        ratioDiv.innerHTML = ratio + "%";
+
<small><code><che 주체="타인"> 구체화</code></small>  직업(신분)별로 어떠한 양상을 보일 것인가? 인력거꾼들과, 샹즈의 비율을 유사한 수치를 보일 것인가?<br/>
       
+
<small><code>'인력거' 외 주요 사물 마크업</code></small> 서사를 진행하는 중심 사물은 무엇으로 이동하는가? 라오서가 사용한 주요 매개체가 '인력거'가 정말 맞을 것인가?<br/>
        container.appendChild(ratioDiv);
+
<br/>
    }
+
이 작품의 첫 문장이다.<br>
}
+
<blockquote>
</script>
+
我們所要介紹的是祥子,不是駱駝,
</body>
+
내가 소개하고자 하는 이는 샹즈祥子이지 낙타駱駝가 아니다. <br/>
</html>
+
<span style="background-color: #F08080;"><span style="color:white;">
 +
'샹즈'에 관한 소개인 『낙타상자』에서 각각의 사물은 언제 등장하며, '낙타'는 무엇의 시발점이 되는가? 
 +
</span>
 +
</blockquote>

2026년 6월 18일 (목) 15:59 기준 최신판





샹즈와 인력거


중어중문학과 정선한


문제의식

  • 『낙타상자』에서 '인력거'라는 중심 사물이 차지하는 비중은 어느 정도인가?
  • 샹즈가 인력거를 '실제'로 가지고 있는 정도가 많을 것인가, '희망'하는 정도가 많을 것인가?


연구 목적

01. 전체 문장에서 '車(인력거)'가 언급된 분포 시각화
02. 샹즈의 현실과 비현실 속 인력거의 등장 양상 확인

연구 방법

01. 전체 문장에서 '車, 인력거'가 언급된 양상과 분포는 어떻게 나타나는가?

<Sentence> 단위에서 '車'와 '인력거' 전체 마크업 다시 4가지 태그로 분류한다.

  1. che: 인력거
  2. cheRen: 인력거와 관련된 사람
  3. chePlace: 인력거와 관련된 장소
  4. cheMoney: 인력거와 관련된 돈




02. 샹즈는 '인력거'를 현실에서 접하는가, 희망으로 접하는가?

<che>태그 내에서 속성으로 현실과 희망을 구분한다.

<che 상태="발생/희망/기타" 주체="샹즈/타인/사물">
상태
주체

발생: 현재 발생한 사건, 샹즈에게 이미 일어난 일, 실제로 일어난 것
희망: 실제로 일어나지는 않았지만 실현되길 바라는 사건, 할 것임을 다짐하는 문장
기타: 발생/희망에 해당하지 않음

샹즈: 발생/희망/기타 사건의 동작을 하는 주체가 샹즈
타인: 발생/희망/기타 사건의 동작을 하는 주체가 타인
사물: 발생/희망/기타 사건의 동작을 하는 주체가 사람이 아님




03. <che> 속성의 상태와 주체의 교차 흐름은 어떻게 되는가?

이는 인력거가 존재하는 방식과 그 시점에서의 인력거 소유 주체를 보기 위함이다.
각 속성값을 생키 다이어그램으로 비율과 흐름을 확인한다.

연구 결과


연구 결과 01

  • 전체 문장 1807개 중, 346개만이 '인력거'와 관련이 있다. 비율은 19.15% 이다.
『낙타상자』에서 '인력거'는 가장 주된 사물이지만, 라오서가 서술한 비율은 크지 않다.
또한 '인력거'가 출현하지 않은 문장은 각각 '낙타', '돈', '결혼' 등의 요소로 내용을 이끌고 있다.


인력거시각화1.png



연구 결과 02

  • 1장 1단락부터 5장 7단락까지의 데이터다.
샹즈는 인력거를 얻기 위해, 그리고 인력거를 찾기 위해 고군분터하는 인물이다.
따라서 인력거를 희망하며 노력하는 시간이 많을 것으로(<che 상태="희망">이 많을 것으로) 예상했는데 그렇지 않았다.
다만, 아직 초반 부분이며 전체 장을 마크업하면 흥미로운 결과가 나올 듯 하다..



<che> 속성 공간 분포 (마이크로 닷 히트맵)

각 격자는 하나의 단락을 의미하며, 한 줄에 15개씩 출력되도록 줄바꿈 되었습니다. 격자 좌상단의 작은 숫자는 단락의 순번입니다.

인력거시각화2-1.png


인력거시각화2-2.png


연구 결과 03

  • <che> 속성의 상태와 주체의 교차 흐름의 결과, 주체는 샹즈가 단연 제일 큰 비중이었다.
샹즈 중심의 서술이므로 샹즈의 발생-희망 비율(53.5%)이 타인의 발생-희망(17.0%)보다 높은 수치를 보였다.
이때, '타인'을 각 인물명으로 세분화하면 여전히 발생-희망 비율이 유사하게 나타날 것인가? 인물별로 달라지리라 예상한다.
연구결과02에서 언급했듯, 작품의 후반부까지 마크업하면 샹즈와 연결된 '발생-희망'의 비율이 어떻게 달라질 것인가? 역전할 것인가?

낙타샹즈 상태-주체 생키 다이어그램

<che> 속성 교차 흐름 (상태 → 주체)

1~5장에 등장하는 전체 <che> 마크업의 속성값을 바탕으로 작성된 생키 다이어그램입니다.
선의 두께는 동시 출현 빈도(결합 강도)에 비례하며, 노드에 마우스를 올리면 상세 수치를 확인할 수 있습니다.




나가며


추후 진행되어야 할 작업과 남아 있는 질문은 다음과 같다.

전체 데이터의 마크업이 완료되면,
<che 상태="발생/희망/기타"> 마크업 샹즈는 '인력거를 끄는' 인물이 될 것인가, '인력거를 갈하는' 인물이 될 것인가?
<che 상태="발생/희망/기타"> 마크업 서사의 진행에 따라 '인력거'가 샹즈의 현실과 비현실에 존재하는 모습은 어떤 변화를 보일 것인가?
<che 주체="타인"> 구체화 각 인물별로 인력거를 소유하고, 바라는 비율은 어떻게 될 것인가?
<che 주체="타인"> 구체화 직업(신분)별로 어떠한 양상을 보일 것인가? 인력거꾼들과, 샹즈의 비율을 유사한 수치를 보일 것인가?
'인력거' 외 주요 사물 마크업 서사를 진행하는 중심 사물은 무엇으로 이동하는가? 라오서가 사용한 주요 매개체가 '인력거'가 정말 맞을 것인가?

이 작품의 첫 문장이다.

我們所要介紹的是祥子,不是駱駝, 내가 소개하고자 하는 이는 샹즈祥子이지 낙타駱駝가 아니다.
'샹즈'에 관한 소개인 『낙타상자』에서 각각의 사물은 언제 등장하며, '낙타'는 무엇의 시발점이 되는가?