
옛날 옛적 Chat GPT가 없던 시절...
첫 회사 생활을 시작한 나는 입사와 동시에 웹사이트 프로젝트에 투입되었다.
프로젝트는 웹사이트에서 차트를 이용해 각종 정보를 보여주는 시스템이였다.
여러 차트 라이브러리 중 하이차트를 사용하기로( = 사용하라고) 하였다.
프로젝트가 마무리되어 가던 어느 날.
웹에서 Ctrl+C로 차트를 복사한 뒤 한글, 워드, 엑셀 같은 문서에 Ctrl+V로 붙여넣기 할 수 있게 해달라는 요구사항이 있었다.
지금이야 GPT에게 만들어줘 한마디 하면 샘플 코드가 몇 초 만에 나오겠지만
그 당시 개발자 3개월 아주 초보 개발자 + 웹 처음으로 당황했건 기억이있다.
폭풍 구글링을 통해 만들었던...
예전에 한 번 블로그에 정리했던 내용인데
오랜만에 다시 보니 추억도 떠오르고 지금 기준으로는 꽤 간단한 기능이라 다시 기록해 보기로 했다.
요즘은 라이브러리도 많고 브라우저 API도 좋아져서 더 쉽고 깔끔한 방법이 있을 것이다.
동작하는 순서는 이렇다.
웹에서 하이차트를 클릭 → Ctrl+C → 문서(한글, 워드, 엑셀 등)에서 Ctrl+V로 붙여넣기
예전 소스는 이렇다.
<head>
<title>Copy Highcharts to Clipboard Test</title>
<!--차트 구역 경계선 스타일 지정-->
<style>
.chartContainer {
border-color: rgba(0, 0, 0, .0);
border-style: solid;
border-width: 2px;
border-radius: 2px;
}
</style>
<!-- highchart 사용을 위한 CDN-->
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
<script src="https://unpkg.com/highcharts/highcharts.js"></script>
<script src="https://unpkg.com/highcharts/modules/exporting.js"></script>
</head>
<body id="body">
<!-- 차트 들어가는 div구역 -->
<div class="chartContainer" id="container"></div>
<!-- 셀렉트 박스 들어가는 구역 -->
<div style="text-align : center ">
<select id="ChType">
<option value="column">column</option>
<option value="pie"> pie</option>
<option value="line">line</option>
</select>
</div>
<!-- 차트에서 추출한 이미지 들어가는 구역. 높이 1px, 투명도 .0으로 설정하여 숨김 -->
<div id="imgContainer" class="copyable" style="height:1px; opacity: 0.0;"></div>
</body>
<script>
//X축에 들어갈 배열
var albumName = ['2Cool4School', 'O!RUL8,2', 'School Love Affair', 'Dark&Wild', '화양연화 pt.1',
'화양연화 pt.2', '화양연화 Young Forever', 'WINGS', 'WINGS 외전', 'LoveYourslef'];
//시리즈 데이터에들어갈 배열
var albumNum = [101637, 118170, 191444, 199090, 353063, 432740, 440367, 827947, 749954, 1376915];
//셀렉트의 첫번째 옵션값으로 차트의 초기 타입 설정
var newType = ChType.options[0].value;
//차트 생성 함수 호출
chartCreate();
//차트구역에 클릭이벤트 발생 시 경계선 스타일변경과 복사를 수행
$(".chartContainer").click(function (e) {
//차트 구역에 클릭이벤트 발생 시 경계선 표시
$('.chartContainer').css('border-color', '#BDBDBD');
//전체 body에 키 이벤트 발생 시 수행
document.getElementById("body").onkeydown = function () {
//발생한 키 이벤트가 ctrl+c일 경우
if ((event.keyCode == 67) && (event.ctrlKey == true)) {
//다시 경계선을 숨김
$('.chartContainer').css('border-color', 'rgba(0, 0, 0, .0)');
//셀렉션 객체 생성
var selection = window.getSelection();
//레인지 객체 생성
var range = document.createRange();
//레인지가 copyable 노드를 포함
range.selectNodeContents($(".copyable").get(0));
//레인지를 삭제
selection.removeAllRanges();
//셀렉션에 레인지를 넣어줌
selection.addRange(range);
//클립보드에 현재 내용을 복사
document.execCommand('copy');
//셀렉션에서 모든 레인지를 삭제
window.getSelection().removeAllRanges();
}
}
});
//셀렉트 박스 변경시 수행하는 함수
$('#ChType').change(function () {
//changeType함수에 인자로넘겨줄 series에 시리즈를 넣어준다.
var series = chart.series[0];
//셀렉트 박스에서 선택된 값을 newType에 넣어준다.
newType = jQuery('#ChType option:selected').val();
//시리즈,타입 변경 함수 호출
changeType(series, newType);
//셀렉트 박스 변경 시 경계선을 투명하게 되돌림
$('.chartContainer').css('border-color', 'rgba(0, 0, 0, .0)');
})
//차트 옵션 변경 함수
function changeType(series, newType) {
//로드 이후에 차트에 시리즈 변경
series.chart.addSeries({
type: newType,
name: series.name,
data: series.options.data
}, false);
//기존의 시리즈 내용 삭제
series.remove();
//기존에 있던 추출된 이미지 삭제
$("#copyimage").remove();
//다시 차트를 생성하기위한 obj 비우기
obj = null;
//함수 생성 함수 호출
chartCreate();
}
//차트 생성 함수
function chartCreate() {
options = {
//차트 타입
chart: {
type: newType
},
//우측 하단 로고
credits: {
text: 'MTFIS',
},
//차트 타이틀
title: {
text: 'BTS Album Sale Rate',
//스타일 두껍게
style: {
fontWeight: 'bold'
}
},
//색상 설정
colors: [
'#B40404'
],
//서브 타이틀 설정
subtitle: {
text: 'BTS(bangtanboys) total sales trend album by sale rate.'
},
//Y축 타이틀 설정
yAxis: {
title: {
text: '앨범 발매 일순 / 단위 : 장'
}
},
//X축에 들어갈 배열
xAxis: {
categories: albumName
},
series: [{
data: albumNum,
name: 'Sale rate'
}],
//exporting시 파일이름, exporting.url 설정
exporting: {
filename: 'BTS Album Sale Rate',
url: 'http://export.highcharts.com/'
}
},
chart = Highcharts.chart('container', options);
//ajax통신에 사용할 테이터 생성
obj = {},
//exportUrl을 차트 옵션의 exporting.url을 넣어준다.
exportUrl = options.exporting.url;
//옵션을 보내고 문자열 형태로 받아오기 위해 JSON.stringify사용
obj.options = JSON.stringify(options);
//이미지 파일은 png
obj.type = 'image/png';
//동기 통신으로 설정. 데이터의 결과를 수신 받은 다음 진행 함
obj.async = true;
$.ajax({
//전송 방식
type: 'post',
//전송 url
url: exportUrl,
//전송할 데이터
data: obj,
//전송 성공시 함수 수행
success: function (data) {
//imgContainer는 위 이미지가 들어갈 구역의 id 저장
var imgContainer = $("#imgContainer");
//이미지에 태그 설정
$('<img>').attr('src', exportUrl + data).attr('width', '400px')
.attr('id', 'copyimage')
.attr('style', 'height:1px; opacity: 0.0;')
//<img src="http://export.highcharts.com/+data"
//width="400px" id="copyimage" style="height:1px; opacity: 0.0;">
//위의 이미지태그가 imgContainer에 들어가 이미지가 생성된다.
.appendTo(imgContainer);
}
});
}
</script>
당시에는 블로그 글을 작성하면서 한 줄 한 줄 주석을 엄청 자세하게 달아놨기 때문에 지금 봐도 대충 어떤 의도로 작성했는지 이해가 될것이다.
지금은 이 소스가 동작하지 않는다.
너무 오래된 방식이기 때문이다.
'IT SW 개발' 카테고리의 다른 글
| [Highcharts] 하이차트 Ctrl+C, Ctrl+V로 문서에 복사 붙여넣기_(2) (0) | 2026.06.17 |
|---|---|
| [Windows+Docker+Spring Boot+VScode] Window에서 Docker를 이용한 Spring Boot 환경 세팅_(1) (0) | 2026.06.11 |