Vue.js 애플리케이션에 강력한 코드 편집 기능을 추가하려면 Vue-Codemirror 라이브러리가 효과적인 솔루션이 될 수 있습니다. 이 가이드에서는 Vue-Codemirror를 설치하고 설정하여 Vue 프로젝트 내에서 유연한 코드 에디터를 구현하는 방법을 자세히 설명합니다.
필수 패키지 설치
Vue-Codemirror를 사용하기 위해서는 핵심 codemirror 라이브러리와 Vue 래퍼인 vue-codemirror 두 가지 패키지를 모두 설치해야 합니다. 다음 명령어를 사용하여 프로젝트에 추가합니다.
npm install vue-codemirror@4.x --save
npm install codemirror@5.x --save
전역 컴포넌트 등록
애플리케이션의 어느 곳에서든 Codemirror 인스턴스를 쉽게 사용할 수 있도록 main.js 파일에서 전역 컴포넌트로 등록하는 것이 좋습니다. 이 과정에서 필요한 스타일과 언어 모드, 테마 등 Codemirror 애드온을 함께 불러옵니다.
// main.js
import { codemirror } from 'vue-codemirror';
import Vue from 'vue'; // Vue 인스턴스 import (Vue 2.x 기준)
// Codemirror 관련 스타일, 테마, 언어 모드 등 설정 파일 불러오기
import '@/utils/editor-config.js'; // 사용자 정의 설정 파일 경로
// 'code-editor'라는 이름으로 전역 컴포넌트 등록
Vue.component('code-editor', codemirror);
코드 에디터 설정 파일 (editor-config.js)
다양한 Codemirror 기능(테마, 언어 모드, 애드온)을 활성화하려면 해당 CSS와 JavaScript 파일을 가져와야 합니다. 다음은 src/utils/editor-config.js와 같은 파일에 포함할 수 있는 일반적인 설정 예시입니다. 여기에는 여러 테마, 코드 강조 모드, 코드 폴딩, 힌트, 린트 등의 기능이 포함되어 있습니다.
// src/utils/editor-config.js
// Codemirror 기본 스타일
import 'codemirror/lib/codemirror.css';
// 테마 스타일
import 'codemirror/theme/monokai.css';
import 'codemirror/theme/idea.css';
import 'codemirror/theme/ayu-dark.css';
import 'codemirror/theme/base16-light.css';
import 'codemirror/theme/3024-day.css';
import 'codemirror/theme/rubyblue.css';
import 'codemirror/theme/duotone-light.css';
// 언어 모드 (Mode)
import 'codemirror/mode/javascript/javascript.js';
import 'codemirror/mode/python/python.js';
import 'codemirror/mode/htmlmixed/htmlmixed.js';
import 'codemirror/mode/css/css.js';
import 'codemirror/mode/vue/vue.js';
// 애드온: 린트(Lint)
import 'codemirror/addon/lint/lint.css';
import 'codemirror/addon/lint/lint.js';
import 'codemirror/addon/lint/json-lint.js';
import 'codemirror/addon/lint/javascript-lint.js';
// 애드온: 코드 폴딩(Fold)
import 'codemirror/addon/fold/foldgutter.css';
import 'codemirror/addon/fold/foldcode.js';
import 'codemirror/addon/fold/foldgutter.js';
import 'codemirror/addon/fold/brace-fold.js';
import 'codemirror/addon/fold/comment-fold.js';
import 'codemirror/addon/fold/markdown-fold.js';
import 'codemirror/addon/fold/xml-fold.js';
import 'codemirror/addon/fold/indent-fold.js';
// 애드온: 힌트(Hint) / 자동 완성
import 'codemirror/addon/hint/show-hint.css';
import 'codemirror/addon/hint/show-hint.js';
import 'codemirror/addon/hint/javascript-hint.js';
import 'codemirror/addon/hint/xml-hint.js';
import 'codemirror/addon/hint/sql-hint.js';
import 'codemirror/addon/hint/anyword-hint.js';
// 애드온: 검색 및 강조
import 'codemirror/addon/search/match-highlighter.js';
// 애드온: 편집 기능
import 'codemirror/addon/edit/matchbrackets.js'; // 괄호 짝 맞추기
import 'codemirror/addon/edit/closebrackets.js'; // 자동 괄호 닫기
Vue 컴포넌트 내에서 Codemirror 활용
이제 Vue 컴포넌트 내에서 등록된 code-editor 컴포넌트를 사용하여 코드 에디터를 인스턴스화하고 다양한 옵션을 설정할 수 있습니다. v-model을 통해 에디터 내용을 데이터와 양방향으로 바인딩하며, :options 속성을 통해 Codemirror의 세부 동작을 제어합니다.
<template>
<div class="code-editor-wrapper">
<code-editor
class="custom-editor-style"
ref="editorInstanceRef"
v-model="editorContent"
:options="editorOptions"
/>
</div>
</template>
<script>
export default {
name: 'CodeEditorComponent',
data() {
return {
editorContent: `// TypeScript 함수 예시
function calculateSum(a: number, b: number): number {
return a + b;
}
const result = calculateSum(5, 10);
console.log(result); // 15`, // 에디터 초기 내용 설정
editorOptions: {
mode: 'javascript', // 기본 언어 모드 설정 (예: 'javascript', 'python', 'text/html')
theme: 'idea', // 에디터 테마 (예: 'monokai', 'idea', 'ayu-dark')
lineNumbers: true, // 줄 번호 표시 여부
indentUnit: 2, // 들여쓰기 단위 (공백 수)
tabSize: 4, // 탭 크기
firstLineNumber: 1, // 줄 번호 시작 숫자
readOnly: false, // 읽기 전용 모드
lineWrapping: true, // 자동 줄바꿈
autofocus: true, // 페이지 로드 시 에디터에 포커스
autoCloseBrackets: true, // 괄호 자동 닫기
matchBrackets: true, // 괄호 짝 맞추기 하이라이트
smartIndent: true, // 스마트 들여쓰기
styleActiveLine: true, // 현재 활성화된 줄 하이라이트
viewportMargin: Infinity, // 에디터 높이 자동 조절에 유용
foldGutter: true, // 코드 폴딩(접기)을 위한 여백 표시
gutters: ['CodeMirror-lint-markers', 'CodeMirror-linenumbers', 'CodeMirror-foldgutter'], // 여백에 표시할 기능들
lint: true, // 린터 활성화 (해당 모드에 린터가 설정되어 있어야 함)
hintOptions: {
completeSingle: false // 하나의 제안만 있을 때 자동 완성하지 않음
},
highlightSelectionMatches: {
minChars: 2, // 최소 2글자 이상 일치 시 하이라이트
style: 'matchhighlight' // 하이라이트 스타일 클래스
},
showCursorWhenSelecting: true, // 선택 영역이 활성화되었을 때 커서 표시
styleSelectedText: true, // 선택된 텍스트 스타일링
autoRefresh: true, // 에디터 크기 변경 시 자동 새로고침
},
};
},
mounted() {
// Codemirror 인스턴스에 직접 접근하여 API 호출이 필요한 경우
const codeMirrorInstance = this.$refs.editorInstanceRef.codemirror;
if (codeMirrorInstance) {
console.log('CodeMirror 인스턴스가 성공적으로 마운트되었습니다.');
// 예시: 에디터 높이를 자동으로 조절
// codeMirrorInstance.setSize('100%', 'auto');
}
},
};
</script>
<style scoped>
.code-editor-wrapper {
border: 1px solid #ccc;
height: 400px; /* 에디터의 고정 높이 지정 */
overflow: hidden; /* 컨테이너 스크롤 관리 */
font-family: 'Consolas', 'Monaco', monospace; /* 코드 폰트 지정 */
}
/* Vue-Codemirror가 렌더링하는 Codemirror 인스턴스의 높이를 부모 컨테이너에 맞춤 */
.custom-editor-style ::v-deep .CodeMirror {
height: 100%;
}
/* 선택된 텍스트의 배경색을 사용자 정의 */
.custom-editor-style ::v-deep .CodeMirror-selectedtext {
background-color: #d7d4f0 !important;
}
</style>