D2 렌더링 응용
스크립트를 통한 서버 실행 및 종료 자동화
Hugo 빌드 과정에서 서버를 자동으로 실행하고, 빌드가 완료되면 서버를 종료하도록 스크립트를 작성할 수 있습니다. 다음은 Windows Batch 스크립트 예시입니다.
build.bat
@echo off
:: Go HTTP 서버 실행
start "" "%~dp0\d2server.exe"
for /f "tokens=2" %%a in ('tasklist ^| findstr /i "d2server.exe"') do set PID=%%a
:: Hugo 빌드 실행
hugo --gc --minify
:: Go HTTP 서버 종료
taskkill /PID %PID% /F
echo Build completed and server stopped.
- 서버 실행:
start "" "%~dp0\d2server.exe"
명령으로 Go 서버를 백그라운드에서 실행합니다. - PID 저장:
tasklist
와findstr
을 사용하여 실행된 서버의 프로세스 ID(PID)를 찾아 저장합니다. - Hugo 빌드 실행:
hugo --gc --minify
명령어로 Hugo 사이트를 빌드합니다. - 서버 종료: 빌드가 완료된 후, 저장된 PID를 사용하여
taskkill
명령어로 서버를 종료합니다.
Dark 모드 설정
Go 서버 코드 수정
Go 서버에서 D2 다이어그램을 렌더링할 때 Dark Mauve (테마 ID: 200) 또는 Dark Flagship Terrastruct (테마 ID: 201)을 적용합니다. 서버 소스에서 renderText
부분을 수정합니다.:
func renderText(content string) (string, error) {
// D2 명령어 실행에 다크 테마 적용
command := exec.Command("d2", "--theme=200", "-") // 다크 모드 적용 (Dark Mauve)
command.Stdin = bytes.NewBuffer([]byte(content))
// 명령어 실행 및 에러 처리
output, err := command.CombinedOutput()
if err != nil {
return "", err
}
return string(output), nil
}
- 수정 후에는 go 서버를 다시 빌드 합니다.
go build -o d2server.exe d2server.go
불필요한 메세지 제거
Go 서버에서 렌더링 시, D2 다이어그램 밑에 다음과 같은 메세지가 추가될 수 있습니다.
success: successfully compiled - to - in 77.7552ms
output을 로깅해 보면, 다음과 같이 마지막에 해당 메시지가 추가되어 있습니다.
...
<rect x="-100" y="-121" width="970" height="614" fill="white"></rect>
<rect x="362.000000" y="-21.000000" width="46" height="36" fill="rgba(0,0,0,0.75)"></rect>
<rect x="62.500000" y="72.500000" width="82" height="21" fill="rgba(0,0,0,0.75)"></rect>
<rect x="363.000000" y="200.000000" width="44" height="31" fill="rgba(0,0,0,0.75)"></rect>
<rect x="249.500000" y="72.500000" width="82" height="21" fill="rgba(0,0,0,0.75)"></rect>
<rect x="436.500000" y="72.500000" width="82" height="21" fill="rgba(0,0,0,0.75)"></rect>
<rect x="623.500000" y="72.500000" width="83" height="21" fill="rgba(0,0,0,0.75)"></rect>
<rect x="83.500000" y="288.500000" width="41" height="21" fill="rgba(0,0,0,0.75)"></rect>
<rect x="270.500000" y="288.500000" width="41" height="21" fill="rgba(0,0,0,0.75)"></rect>
<rect x="457.500000" y="288.500000" width="41" height="21" fill="rgba(0,0,0,0.75)"></rect>
<rect x="644.500000" y="288.500000" width="42" height="21" fill="rgba(0,0,0,0.75)"></rect>
</mask></svg></svg>
success: successfully compiled - to - in 77.7552ms
이를 그대로 출력하면 의도하지 않는 success 메세지도 함께 출력되므로, Regex 를 이용해 svg 태그만 출력하도록 수정할 수 있습니다.
package main
import (
"bytes"
"fmt"
"io"
"log"
"net/http"
"os/exec"
"regexp"
)
func handleRenderRequest(w http.ResponseWriter, r *http.Request) {
requestBody, err := io.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
defer r.Body.Close()
output, err := renderText(string(requestBody))
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fmt.Fprintf(w, output)
}
func renderText(content string) (string, error) {
// D2 명령어 실행에 다크 테마 적용
command := exec.Command("d2", "--theme=200", "-")
command.Stdin = bytes.NewBuffer([]byte(content))
// 명령어 실행 및 에러 처리
output, err := command.CombinedOutput()
if err != nil {
log.Printf("Command failed: %s", err)
return "", err
}
// 출력 결과에서 <svg> 태그만 추출
outputStr := string(output)
re := regexp.MustCompile(`(?s)<svg.*</svg>`) // 전체 SVG 태그를 찾는 정규 표현식
svgOnly := re.FindString(outputStr) // <svg> 태그만 추출
return svgOnly, nil
}
func main() {
http.HandleFunc("/render", handleRenderRequest)
http.ListenAndServe(":8080", nil)
}
디버깅
만약 D2 다이어그램이 정상적으로 렌더링되지 않거나 에러가 발생한다면, 명령어 실행 상태를 확인해야 할 수 있습니다. 이때 콘솔 로그를 추가하여 디버깅할 수 있습니다. 다음은 콘솔 로그를 추가하여 디버깅하는 방법입니다:
콘솔 로그 추가 코드
func renderText(content string) (string, error) {
// D2 명령어 실행에 다크 테마 적용
command := exec.Command("d2", "--theme=200", "-")
command.Stdin = bytes.NewBuffer([]byte(content))
// 명령어를 문자열로 변환하여 로그에 기록
fullCommand := strings.Join(command.Args, " ")
log.Printf("Executing command: %s", fullCommand)
// 명령어 실행 및 에러 처리
output, err := command.CombinedOutput()
if err != nil {
log.Printf("Command failed: %s", err)
return "", err
}
// 결과에서 성공 메시지 필터링
outputStr := string(output)
if strings.Contains(outputStr, "success: successfully compiled") {
outputStr = strings.Split(outputStr, "\n")[0] // 성공 메시지를 제외한 첫 번째 라인만 가져오기
}
// 명령어가 성공적으로 실행되었음을 기록
log.Println("Command executed successfully.")
return outputStr, nil
}
디버깅 절차:
- 콘솔 로그 확인: 명령어가 정확하게 실행되는지 확인하려면, 콘솔에 출력되는 실제 실행된 명령어와 에러 메시지를 확인합니다.
- 명령어 문제 해결: 실행된 명령어에서 문제가 발생하면, D2 CLI의 인자 또는 경로 등을 확인하여 문제를 해결합니다.