파일에 작성된 코드를 웹페이지에 삽입하기

nearworld·2023년 8월 8일
1

한 파일에 있는 코드 텍스트를 읽어들여 웹페이지에 출력하려면 다음의 과정이 필요했습니다.

목표 수립 과정
1. markdown 파일 생성
2. Backtick(`)을 이용하여 코드 템플릿 영역을 만들고 프로그래밍 언어를 지정
3. 예시 코드를 코드 템플릿 영역에 작성
4. 예시 코드를 출력할 컴포넌트에서 타겟 파일 읽어들이기
5. 읽어들인 텍스트를 웹 페이지에 출력

  1. 타겟 파일 생성
  2. Backtick(`)을 이용하여 코드 템플릿 영역을 만들고 프로그래밍 언어를 지정
  3. 예시 코드를 코드 템플릿 영역에 작성

위 처럼 example.tsx 파일을 작성해줬습니다.

4. 예시 코드를 출력할 컴포넌트에서 파일 읽어들이기

vite에서는 정적 파일들을 public 폴더에서 관리합니다.
제가 만약 example.tsx 파일을 src에 넣어 놓고 프로젝트를 빌드하면 타입스크립트 파일들은 컴파일되면서 자바스크립트 파일로 변환됩니다.

그럼 화면에서 보여주기로 했던 타입스크립트 코드가 컴파일된 자바스크립트 코드로 나타나게 됩니다.
이것은 제가 의도한 바가 아닙니다!

해결책은 정적 파일들을 관리하는 public 폴더 안으로 옮겨놓고 컴파일이 안되게 방지한 후 해당 파일을 런타임 단계에서 읽어들여야 합니다.

5. 읽어들인 텍스트를 웹 페이지에 출력

fetch('templates/example.tsx')

위 fetch api를 이용하여 example.tsx에 접근합니다.

fetch('templates/example.tsx')
	.then(res => res.text())

Response 인터페이스의 text 메서드를 사용하여 Response stream을 읽어들이고 읽기 작업을 완료시킵니다. text 메서드는 읽기가 완료된 text 데이터를 가지고 있는 Promise를 리턴합니다.

이 텍스트 데이터를 저장할 상태를 마련합니다.

const [code, setCode] = useState('');

그리고 fetch api로 읽어들인 코드를 상태에 저장합니다.

  fetch('templates/example.tsx')
  	.then(res => res.text())
  	.then(text => setCode(text))

아래의 코드에 보이는 markdown 변수에 미리 템플릿 리터럴을 할당합니다.
그리고 그 값에 코드 템플릿을 작성합니다.
작성된 코드 템플릿에 텍스트 데이터를 가지고 있는 상태인 code 상태를 삽입합니다.

const [code, setCode] = useState('');

useEffect(() => {
  fetch('templates/example.tsx')
  	.then(res => res.text())
  	.then(text => setCode(text))
  	.catch(err => console.log(err));
}, [])

const markdown = `
\`\`\`typescript
${code}
\`\`\`
`;

이제 marked 라이브러리를 이용하여 markdown 변수의 템플릿 리터럴 값을 컴파일합니다.

marked 라이브러리는 이번에 처음 사용하게 된 것인데 low-level 마크다운 컴파일러라고 소개되어 있습니다.
https://marked.js.org/

marked(markdown);

marked 함수를 써서 markdown 변수를 전달해주면

<pre>
	<code class='language-tsx'>
    	 ...
    </code>
</pre>

위 결과물이 나오게 되는 것을 알 수 있습니다.
하지만 위 결과물의 데이터 타입은 string입니다.
그래서 dangerouslyInnerHTML 어트리뷰트를 이용하여 html tag로 변환시켜야합니다.

<div dangerouslyInnerHTML={{__html: marked(markdown)}}>
</div>

위 코드는 브라우저 inspector로 보면 아래와 같이 나옵니다.

<div>
  <pre>
  	<code class='language-tsx'>
    	<span>default export function Example() {</span>
        ...
    </code>
  </pre>
</div>

highlight.js<pre>, <code>를 highlighting 하기 때문에 fetch로 읽어들인 코드에 결과적으로 테마가 적용됩니다.

const [code, setCode] = useState('');

useEffect(() => {
  fetch('templates/example.tsx')
  	.then(res => res.text())
  	.then(text => setCode(text))
  	.catch(err => console.log(err));
}, [])

const markdown = `
\`\`\`typescript
${code}
\`\`\`
`;

return (
  <div 
    dangerouslySetInnerHTML={{__html: marked(markdown)}}
  	>
  </div>)

최종적으로 완성된 코드입니다.

아래는 결과물입니다.

profile
깃허브: https://github.com/nearworld

0개의 댓글