Vue.js에서의 Monaco Editor 적용기

beenvyn·2024년 12월 10일

Vue.js

목록 보기
1/3
post-thumbnail

🤔 Monaco Editor vs CodeMirror

코드미러와 비교했을 때 모나코 에디터는...

  • 더 다양한 언어(TypeScript, SQL 언어 등)
  • 코드 자동 완성 기능
  • 키워드 하이라이트 기능
  • 괄호 매칭 기능

등을 지원하고..
텍스트 편집기 중 사용자 수 1위인 VS code도 모나코 에디터를 기반으로 하기 때문에 대다수의 사용자들에게 익숙함을 줄 수 있다는 점에서 모나코 에디터로 결정!!

🔍 Monaco Editor 기본 동작

1. 설치

npm install @monaco-editor/loader
or
yarn add @monaco-editor/loader

2. 사용법

import loader from '@monaco-editor/loader';

loader.init().then(monaco => {
  monaco.editor.create(`monacoEditor DOM 요소`, {
    `monacoEditor 설정 값(e.g. value, language..)`
  });
});

⌨️ Monaco Editor로 코드 입력 받기

<template>
  <div class="code-editor__wrap">
    <div id="monacoCodeEditor" style="width: 100%; height: 100%" />
  </div>
</template>

<script>
import loader from "@monaco-editor/loader";
import githubLightTheme from "monaco-themes/themes/GitHub Light.json";

export default {
  data(){
    return {
      editor: undefined,
      tags: ""
    }
  },
  methods: {
    async monacoInit() {
      loader.init().then((monaco) => {
        monaco.editor.defineTheme("github-light", githubLightTheme);
        this.editor = monaco.editor.create(
          document.getElementById("monacoCodeEditor"),
          {
            value: this.tags, 				// 에디터에 표시할 코드
            language: "html", 				// 에디터 언어 설정 
            automaticLayout: true,         // 창 크기 변경 시 자동 레이아웃 조정
            minimap: { enabled: false },   // 미니맵 비활성화
            theme: "github-light",        // 테마 설정
          }
        );
      });
    },
    dispose() {
      if (this.editor) {
        try {
          this.editor.dispose();
        } catch (e) {
          console.log(e);
        }
      }
    },
  },
  mounted() {
    this.$nextTick(() => {
      this.monacoInit();
    });
  },
  beforeDestroy() {
    this.dispose();
  },
}
</script>

<style lang="scss" scoped>
.code-editor__wrap {
  width: 100%;
  height: 300px;
  overflow: hidden;
  border-radius: 4px;
  -ms-overflow-style: none; /* IE and Edge */
  scrollbar-width: none; /* Firefox */

  &::-webkit-scrollbar {
    display: none;
  }
}
</style>

⭐ 주요 코드

  • <div id="monacoCodeEditor">: Monaco Editor가 렌더링될 DOM 요소.
  • editor : Monaco Editor 객체가 생성되면 여기에 저장된다.
  • monacoInit() 메서드 : monaco.editor.create을 통해 에디터를 생성하고 설정값을 적용한다.
  • dispose() 메서드 : 에디터 인스턴스를 삭제하고 관련 리소스를 해제한다.

🏓 진행 순서

  1. #monacoCodeEditor DOM이 렌더링된다.
  2. mounted 라이프사이클 호출 → monacoInit()를 호출해 Monaco Editor를 초기화한다.
  3. loader.init()를 통해 Monaco Editor를 로드하고, 에디터를 생성하며, GitHub Light 테마를 적용한다.
  4. 컴포넌트 파괴 시 dispose()를 호출하여 Monaco Editor 리소스를 정리한다.

🪄 결과물

🖨️ Monaco Editor로 코드 보여 주기

<template>
  <div v-if="feedbackCode" class="code-editor__wrap">
    <div id="monacoCodeEditor" style="width: 100%;" />
  </div>
</template>

<script>
import loader from "@monaco-editor/loader";
import nightOwlTheme from "monaco-themes/themes/Night Owl.json";

export default {
  props: {
    feedbackCode: {
      type: String,
    },
  },
  data(){
    return {
      editor: undefined,
      monacoEditor: undefined,
    }
  },
  watch: {
    editor(editor) {
      if (editor) {
        this.updateHeight();
      }
    },
    feedbackCode: {
      immediate: true,
      handler() {
        this.$nextTick(() => {
          this.monacoEditor = document.getElementById("monacoCodeEditor");
          if (this.monacoEditor) {
            this.monacoInit();
          }
        });
      },
    },
  },
  methods: {
    updateHeight() {
      const height = this.editor.getScrollHeight(); // 에디터의 스크롤 높이를 가져옴
      this.monacoEditor.style.height = `${height}px`; // DOM 요소 높이를 조정

      this.editor.layout(); // 레이아웃을 재조정
    },
    async monacoInit() {
      loader.init().then((monaco) => {
        monaco.editor.defineTheme("night-owl", nightOwlTheme);
        this.editor = monaco.editor.create(this.monacoEditor, {
          value: this.feedbackCode,
          language: this.codeLang,
          theme: "night-owl",
          readOnly: true,                // 읽기 전용 모드로 설정 (코드 편집 불가)
          lineNumbers: "off",            // 라인 넘버 비활성화
          wordWrap: "on",                // 긴 줄이 화면에 맞춰 줄바꿈되도록 설정
          automaticLayout: true,         // 창 크기 변경 시 자동 레이아웃 조정
          renderIndentGuides: false,     // 들여쓰기 가이드 숨김
          minimap: { enabled: false },   // 미니맵 비활성화
          scrollbar: {
            vertical: "hidden",          // 수직 스크롤바를 숨김
            handleMouseWheel: false,     // 마우스 휠로 스크롤 금지
          },
        });
      });
    },
    dispose() {
      if (this.editor) {
        try {
          this.editor.dispose();
        } catch (e) {
          console.log(e);
        }
      }
    },
  },
  beforeDestroy() {
    this.dispose();
  },
}
</script>

<style lang="scss" scoped>
.code-editor__wrap {
  width: 100%;
  height: auto;
  overflow: hidden;
  padding: 24px 1px;
  background-color: black;
  border-radius: 4px;
  -ms-overflow-style: none; /* IE and Edge */
  scrollbar-width: none; /* Firefox */

  &::-webkit-scrollbar {
    display: none;
  }
}
</style>

⭐ 주요 코드

  • feedbackCode : 모나코 에디터로 보여줄 코드로, 이 값이 있을 때만 #monacoCodeEditor DOM을 렌더링한다.
  • editor : Monaco Editor 인스턴스를 저장한다.
  • monacoEditor : Monaco Editor가 렌더링될 DOM 요소(#monacoCodeEditor)를 참조한다.
  • watch > editor() : Monaco Editor 인스턴스가 생성되면 호출된다.
  • updateHeight() : Monaco Editor의 내용 높이에 맞춰 DOM 요소의 높이를 조정한다.

🏓 진행 순서

  1. feedbackCode 값 확인 후 feedbackCode가 있으면 #monacoCodeEditor가 렌더링된다.
  2. Watcher 실행 (feedbackCode) → DOM 요소를 찾은 후 monacoInit() 메서드를 호출한다.
  3. Monaco Editor를 생성하고 사용자 정의 테마 및 설정을 적용한다.
  4. updateHeight()이 실행되어 에디터 내용에 맞춰 editor 높이를 동적으로 조정한다.
  5. 컴포넌트 파괴 시 dispose()를 호출하여 Monaco Editor 리소스를 정리한다.

🪄 결과물

이렇게 드래그한 코드의 높이와 맞는 모나코 에디터 창이 생성된다!

profile
୧ʕ•̀ᴥ•́ʔ୨

0개의 댓글