Hugo (휴고) 심층 분석: 이상적인 정적 블로그 프레임워크

Hugo (휴고) 심층 분석: 이상적인 정적 블로그 프레임워크

Hugo (휴고)의 일반적인 사용 기술 소개

Hugo (휴고)는 오픈 소스인 goldmark (골드마크)를 마크다운 파서로 사용하며, 이는 GitHub (깃허브)와 호환됩니다.

소개

Hugo (휴고)는 Golang (고랭)으로 작성된 정적 웹사이트 페이지 생성 도구이며, Ruby (루비)로 작성된 Jekyll (지킬)보다 효율성이 훨씬 높습니다.

Github (깃허브)에서 직접 바이너리 패키지를 다운로드한 후 압축을 풀고 PATH (패스) 환경 변수에 추가하여 사용할 수 있습니다.

SCSS (에스씨에스에스) 기능을 지원하고 테마 개발에 적합한 hugo-extended (휴고 익스텐디드) 버전을 설치하는 것이 좋습니다.

또한 goldmark (골드마크)를 통해 많은 확장이 구현되었으며, 가장 일반적으로 사용되는 것은 작업 목록입니다.

자세한 목록은 MarkdownGuide (마크다운가이드)의 소개를 참조할 수 있습니다.

Hugo (휴고)는 고도로 사용자 정의할 수 있으며, 설계 중 마크다운 구문과 호환되도록 노력합니다.

기본 사용법

테마를 통해 페이지 사용자 정의: 선택할 수 있는 테마가 많으며, themes.gohugo.io (테마즈 점 고휴고 점 아이오)에서 볼 수 있습니다.

hugo-geekdoc (휴고 긱독)을 예로 들면, 다운로드 후 프로젝트의 themes (테마즈) 디렉터리에 직접 넣습니다.


설치 성공 여부 확인:


hugo version (휴고 버전)


현재 디렉터리에 새 프로젝트 만들기:


hugo new site hugo (휴고 뉴 사이트 휴고)


테마 템플릿을 themes (테마즈) 디렉터리에 추가하고, 구성 파일 config.toml (콘피그 점 티오엠엘)에 theme="doks" (테마 이퀄 독스)를 추가하거나 --theme hyde (대시 대시 테마 하이드) 매개변수로 시작합니다.


git clone --depth 1 --recursive https://github.com/h-enk/doks.git themes (깃 클론 대시 뎁스 일 대시 리커시브 에이치티티피에스 콜론 슬래시슬래시 깃허브 쩜 컴 슬래시 에이치 대시 엔케이 슬래시 독스 점 깃 테마즈)


글(Article) 만들기:


hugo --verbose new post/create-hugo-blog.md (휴고 대시 버보스 뉴 포스트 슬래시 크리에이트 대시 휴고 대시 블로그 점 엠디)


서비스 시작:


hugo server --buildDrafts --bind="0.0.0.0" --port=38787 (휴고 서버 대시 빌드드래프츠 대시 바인드 이퀄 쌍따옴표 영쩜영쩜영쩜영 쌍따옴표 대시 포트 이퀄 삼팔칠팔칠)


정적 파일 생성(초안 포함), buildDir (빌드디렉터리) 디렉터리(기본적으로 public (퍼블릭))에 저장:


hugo -D (휴고 대시 디)

구성 파일

기본적으로 루트 디렉터리의 hugo.toml (휴고 점 티오엠엘), hugo.yaml (휴고 점 와이에이엠엘), hugo.json (휴고 점 제이슨)과 같은 구성 파일이 사용됩니다.

--config a.toml,b.toml (대시 콘피그 에이 점 티오엠엘 콤마 비 점 티오엠엘) 방식으로 구성 파일을 지정할 수도 있습니다.

그러나 디렉터리를 사용하는 것이 권장되며, 기본적으로 config (콘피그) 디렉터리이고 구성 파일의 configDir (콘피그디어) 구성 항목을 사용하여 수정할 수 있습니다.

hugo.toml (또는 config 디렉토리 사용 시 루트에는 없음)
config/
  |-_default/  # 기본 구성
  |  |-hugo.toml
  |  |-languages.toml
  |  |-menus.en.toml
  |  |-menus.cn.toml
  |  `-params.toml
  |-develop/    # 개발 환경 구성
  |  |-hugo.toml
  |  `-params.toml
  `-production/ # 프로덕션 환경 구성
    `-hugo.toml



디렉터리의 첫 번째 계층은 환경이며, _default (언더바디폴트) 기본 구성과 일반적으로 production (프로덕션) 디렉터리도 구성됩니다.

예를 들어 --environment production (대시 인바이런먼트 프로덕션)으로 시작하면 _default (언더바디폴트)의 구성이 production (프로덕션)의 구성과 병합되며, 템플릿에서 다음 방식으로 확인할 수 있습니다.

{{ if eq hugo.Environment "production" }}
<div> Production Mode </div> <!-- 프로덕션 모드일 때 표시 -->
{{ else }}
<div> Development Mode </div> <!-- 개발 모드일 때 표시 -->
{{ end }}



두 번째 계층은 구성 항목의 최상위 수준에 해당합니다.

일반적으로 [Params] (대괄호 파람즈 대괄호)는 params.toml (파람즈 점 티오엠엘)에 해당하고, [Menu] (대괄호 메뉴 대괄호)는 다른 언어를 포함하여 menu.toml (메뉴 점 티오엠엘)에 해당합니다.

기본 개념

섹션 (Section)

콘텐츠 디렉터리 구조를 기반으로 정의된 페이지 모음입니다.

이 디렉터리 아래의 첫 번째 수준 하위 디렉터리는 모두 섹션입니다.

하위 디렉터리를 섹션으로 만들려면 디렉터리에 _index.md (언더바인덱스 점 엠디) 파일을 정의해야 하며, 이런 식으로 모든 섹션이 섹션 트리를 형성합니다.

content/
  `-blog/                <-- 섹션, content의 하위 디렉터리이므로
    |-funny-cats/
    |  |-mypost.md
    |  `-kittens/         <-- 섹션, _index.md를 포함하므로
    |    `-_index.md
    `-tech/              <-- 섹션, 위와 동일
        `-_index.md



섹션을 통해 콘텐츠를 분류하는 것 외에도 타입(Type) 사용자 정의도 허용됩니다.

페이지에 타입(Type)이 없으면 섹션(Section)에 해당하는 값이 기본적으로 사용됩니다.

사용할 때 다음 조회 순서를 참조할 수 있습니다.

템플릿 타입(Type)이 섹션(Section)보다 우선순위가 높아 더 나은 사용자 정의가 가능함을 알 수 있습니다.

페이지(page), 섹션(section), 용어(term), 홈(home), 분류(taxonomy) 등 다양한 페이지 유형도 처리할 수 있습니다. 즉, .Kind (점 카인드) 변수입니다.

공식 Methods Kind (메서드 카인드)의 소개를 참조할 수 있습니다.

템플릿 (Templates)

Hugo (휴고)는 GoLang (고랭)의 html/template (에이치티엠엘 슬래시 템플릿) 라이브러리를 템플릿 엔진으로 사용하며, 세 가지 유형의 템플릿으로 나뉩니다.

단일(single): 단일 페이지 렌더링에 사용됩니다.


목록(list): 디렉터리의 모든 콘텐츠와 같이 관련된 콘텐츠 집합을 렌더링합니다.


부분(partial): 페이지 헤더 및 페이지 푸터와 같이 다른 템플릿에서 참조할 수 있으며 템플릿 수준 구성 요소 역할을 합니다.


이 중 baseof.html (베이스오브 점 에이치티엠엘)은 다른 섹션(Section)의 루트 템플릿 역할을 하며 템플릿 조회 메커니즘이 있습니다.

콘텐츠와 완전히 일치하는 템플릿을 찾을 수 없으면 한 수준 위로 이동하여 거기서부터 검색합니다.

기본 템플릿 baseof.html (베이스오브 점 에이치티엠엘)의 조회 규칙은 다음과 같습니다.

/layouts/section/<TYPE>-baseof.html
/themes/<THEME>/layouts/section/<TYPE>-baseof.html <--- 다른 타입(Type)에 대한 템플릿
/layouts/<TYPE>/baseof.html
/themes/<THEME>/layouts/<TYPE>/baseof.html
/layouts/section/baseof.html
/themes/<THEME>/layouts/section/baseof.html <--- 다른 섹션(Section)에 대한 템플릿
/layouts/_default/<TYPE>-baseof.html
/themes/<THEME>/layouts/_default/<TYPE>-baseof.html
/layouts/_default/baseof.html
/themes/<THEME>/layouts/_default/baseof.html <--- 기본값



템플릿에서 Partials (파셜즈) 모듈은 {{ partial "xx" . }} (중괄호 두 개 파셜 쌍따옴표 엑스엑스 쌍따옴표 점 중괄호 두 개)를 통해 도입되며, 모듈의 해당 페이지 정보는 {{ . }} (중괄호 두 개 점 중괄호 두 개)를 통해 볼 수 있습니다.

또한 {{ partial "header.html" (dict "current" . "param1" "1" "param2" "2" ) }} (중괄호 두 개 파셜 쌍따옴표 헤더 점 에이치티엠엘 쌍따옴표 괄호 딕트 쌍따옴표 커런트 쌍따옴표 점 쌍따옴표 파람원 쌍따옴표 쌍따옴표 일 쌍따옴표 쌍따옴표 파람투 쌍따옴표 쌍따옴표 이 쌍따옴표 괄호 중괄호 두 개)와 같이 매개변수를 추가할 수 있습니다.

위에서 Partials (파셜즈)를 도입하는 방법 외에도 {{ define "main" }} ... {{ end }} (중괄호 두 개 디파인 쌍따옴표 메인 쌍따옴표 중괄호 두 개 점점점 중괄호 두 개 엔드 중괄호 두 개)를 통해 다른 유형(예: 단일(single), 목록(list) 등)으로 모듈을 사용자 정의한 다음 {{ block "main" . }} ... {{ end }} (중괄호 두 개 블록 쌍따옴표 메인 쌍따옴표 점 중괄호 두 개 점점점 중괄호 두 개 엔드 중괄호 두 개) 방식으로 사용할 수 있습니다.

변수 참조

템플릿에서 변수는 {{ xxx }} (중괄호 두 개 엑스엑스엑스 중괄호 두 개) 방식으로 참조되며, 변수 사용 방법은 다음과 같습니다.

전역 구성: 예를 들어, .Site.Params.titile (점 사이트 점 파람즈 점 타이틀)은 hugo.toml (휴고 점 티오엠엘)의 [Params] (대괄호 파람즈 대괄호) 또는 config/_default/params.toml (콘피그 슬래시 언더바디폴트 슬래시 파람즈 점 티오엠엘)의 구성에 해당합니다.


페이지 매개변수: 시작 부분에 지정할 수 있으며 .Params.xxx (점 파람즈 점 엑스엑스엑스) 방식으로 참조할 수 있습니다.


기타 매개변수: 일부 내장 매개변수가 포함되며 .Title (점 타이틀), .Section (점 섹션), .Content (점 콘텐츠), .Page (점 페이지) 등과 같이 직접 사용할 수 있습니다.


지역화 매개변수: 일반적으로 i18n "global-identifier" (아이일팔엔 쌍따옴표 글로벌 대시 아이덴티파이어 쌍따옴표)로 지정하거나 i18n .Site.Params.xxx (아이일팔엔 점 사이트 점 파람즈 점 엑스엑스엑스)로 변환됩니다.


함수 사용: 예를 들어, hugo.Environment (휴고 점 인바이런먼트), hugo.IsExtended (휴고 점 이즈익스텐디드) 등이 있습니다.

다른 내용은 Functions (펑션즈) 콘텐츠를 참조할 수 있습니다.


위 변수 외에도 json (제이슨), yaml (와이에이엠엘), toml (티오엠엘), xml (엑스엠엘)과 같은 형식의 데이터 파일을 data (데이터) 디렉터리에 저장하고 템플릿에서 .Site.Data.xxx (점 사이트 점 데이터 점 엑스엑스엑스) 방식으로 참조할 수 있습니다.

기본 구문

템플릿은 {{ }} (중괄호 두 개 중괄호 두 개)로 래핑되며, 내부 내용은 액션(Action)이라고 하며 일반적으로 두 가지 유형이 있습니다.

데이터 평가: 변수를 직접 사용하는 것을 포함하여 템플릿에 직접 출력됩니다.


제어 구조: 조건, 루프, 함수 등을 포함합니다.


또한 각 줄을 래핑할지 여부를 제어할 수 있으며, - (대시)로 제어됩니다.

예를 들어 {{- -}} (중괄호 두 개 대시 대시 중괄호 두 개)는 시작과 끝 모두 래핑하지 않음을 의미하지만 끝에서 압축할 수도 있습니다.

----- 주석
{{/* comment */}} <!-- 주석 처리 -->

----- 기존 변수, 사용자 정의 변수 접근
{{ .Title }} <!-- 현재 페이지 제목 접근 -->
{{ $var }} <!-- 이전에 선언된 변수 $var 접근 -->
{{ $var := "Value" }} <!-- 변수 $var에 "Value" 문자열 할당 -->
{{ $var := `Hello
World` }} <!-- 변수 $var에 여러 줄 문자열 할당 -->

----- 슬라이스(배열)와 맵(딕셔너리) 비교
----- 슬라이스는 배열에 해당하며 일반적인 작업은 다음과 같습니다:

{{ $fruit := slice "Apple" "Banana" }} <!-- "Apple", "Banana"를 요소로 하는 슬라이스 생성 -->

{{ $fruit = append "Cherry" $fruit }} <!-- 슬라이스 앞에 "Cherry" 추가 (주의: append는 뒤에 추가하는 것이 일반적, Hugo에서는 다를 수 있음, 확인 필요) -->
                                    <!-- Hugo의 append는 두 번째 인자로 전달된 슬라이스의 뒤에 첫 번째 인자를 추가합니다. -->
                                    <!-- 따라서 이 코드는 $fruit 뒤에 "Cherry"를 추가합니다. -->
                                    <!-- $fruit = append $fruit "Cherry" 와 같이 사용해야 합니다. -->
                                    <!-- 여기서는 예시로 제시된 것이므로, 정확한 사용법은 공식 문서를 참고해야 합니다. -->
{{ $fruit = append $fruit (slice "Pear") }} <!-- $fruit 뒤에 "Pear"를 요소로 하는 새 슬라이스를 추가 -->
{{ $fruit = append (slice "Cherry" "Peach") $fruit }} <!-- $fruit 앞에 "Cherry", "Peach" 슬라이스 추가 (append의 일반적인 동작과 다름, Hugo 방식 확인 필요) -->
                                                  <!-- 이 역시 $fruit = append $fruit (slice "Cherry" "Peach") 가 되어야 합니다. -->

{{ $fruit = uniq $fruit }} <!-- 슬라이스에서 중복 요소 제거 -->

{{ range $fruit }} <!-- $fruit 슬라이스를 반복 -->
  I love {{ . }} <!-- 각 요소를 출력 -->
{{ end }}

{{ range $index, $value := $fruit }} <!-- $fruit 슬라이스를 인덱스와 값으로 반복 -->
  {{ $value }} or {{ . }} is at index {{ $index }} <!-- 값과 인덱스 출력 -->
{{ end }}

{{ $first := first 2 $fruit }} <!-- $fruit 슬라이스에서 처음 2개 요소 가져오기 -->
{{ $last := last 3 $fruit }} <!-- $fruit 슬라이스에서 마지막 3개 요소 가져오기 -->
{{ $third := first 3 $fruit | last 1 }} <!-- 처음 3개 요소 중 마지막 1개 (세 번째 요소) 가져오기 -->
{{ $third := index $fruit 2 }} <!-- 인덱스 2 (세 번째 요소) 가져오기 -->

----- 딕셔너리 사용법은 다음과 같습니다:

{{ $hero := dict "firstame" "John" "lastname" "Lennon" }} <!-- "firstame", "lastname" 키를 가진 딕셔너리 생성 -->

{{ $hero = merge $hero (dict "birth" "1940") }} <!-- $hero 딕셔너리에 "birth" 키와 값 추가/병합 -->

{{ $hero.firstame }} <!-- $hero의 "firstame" 값 접근 -->
{{ $firstname := index $hero "firstname" }} <!-- "firstname" 키로 값 접근 (주의: 이전 키는 "firstame"이었음) -->
{{ range $key, $value := $hero }} <!-- $hero 딕셔너리를 키와 값으로 반복 -->
  {{ $key }}: {{ $value }} <!-- 키와 값 출력 -->
{{ end }}

{{ $basis := "lastname" }} <!-- 변수 $basis에 "lastname" 할당 -->
{{ if eq $relation "friend" }} <!-- $relation 변수가 "friend"와 같으면 -->
  {{ $basis = "firstname" }} <!-- $basis에 "firstname" 할당 (주의: "firstame" 오타 가능성) -->
{{ end }}
Hello {{ index $hero $basis }}! <!-- $hero에서 $basis 키에 해당하는 값 출력 -->

{{ range slice "firstname" "lastname" }} <!-- "firstname", "lastname" 문자열 슬라이스 반복 -->
  {{ . }}: {{ index $hero . }} <!-- 각 문자열을 키로 사용하여 $hero에서 값 출력 -->
{{ end }}



사용할 때 {{ if reflect.IsSlice $value }} (중괄호 두 개 이프 리플렉트 점 이즈슬라이스 달러밸류 중괄호 두 개) 또는 IsMap (이즈맵)을 통해 특정 유형을 판단할 수 있습니다.

논리적 판단

if (이프) 문은 특정 값의 참 또는 거짓을 판단하는 데 사용되지만, with (위드)를 사용하는 것이 권장되며, 이때 컨텍스트는 범위 내에서 다시 바인딩됩니다.

{{ if .IsHome }} xxx {{ end }}          <!-- .IsHome이 true일 때 호출되며, 그렇지 않으면 not을 사용합니다. -->
{{ if eq .Title "Home" }} xxx {{ end }} <!-- 변수가 같은지 판단하며, ne는 같지 않음을 의미합니다. -->
{{ if and .IsHome .Params.show }} xxx {{ end }}   <!-- 여러 조건이 동시에 충족되거나, or는 조건 중 하나가 충족됨을 의미합니다. -->
{{ if strings.Contains "hugo" "go" }} xxx {{end}} <!-- 지정된 문자열을 포함하는지 판단합니다. -->

<!-- 다음 두 가지 방법은 동일하며, 비어 있으면 건너뜁니다. -->
{{ if isset .Params "title" }} <!-- .Params에 "title" 키가 설정되어 있으면 -->
    <h4>{{ index .Params "title" }}</h4> <!-- 해당 값을 출력합니다. -->
{{ end }}
{{ with .Params.title }} <!-- .Params.title 값이 존재하면 -->
    <h4>{{ . }}</h4> <!-- 해당 값을 출력합니다. (.은 현재 컨텍스트를 의미) -->
{{ end }}

<!-- 그러나 if는 else if 문을 사용할 수 있습니다. -->
{{ if (isset .Params "description") }} <!-- .Params에 "description"이 있으면 -->
    {{ index .Params "description" }}
{{ else if (isset .Params "summary") }} <!-- 그렇지 않고 .Params에 "summary"가 있으면 -->
    {{ index .Params "summary" }}
{{ else }} <!-- 둘 다 없으면 -->
    {{ .Summary }} <!-- 페이지의 기본 요약을 사용합니다. -->
{{ end }}

<!-- 다음은 약간 더 복잡한 논리입니다. -->
{{ if (and (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr")) }}
    <!-- .Params에 (title 또는 caption 중 하나가 있고) 그리고 attr이 설정되어 있으면 -->
    <div class="caption {{ index .Params "attr" }}">
        {{ if (isset .Params "title") }}
            <h4>{{ index .Params "title" }}</h4>
        {{ end }}
        {{ if (isset .Params "caption") }}
            <p>{{ index .Params "caption" }}</p>
        {{ end }}
    </div>
{{ end }}



Param (파람)에 description (디스크립션) 속성이 설정되어 있으면 Param (파람)의 description (디스크립션) 내용이 출력되고, 그렇지 않으면 Summary (써머리) 내용이 출력됩니다.

{{ with .Param "description" }} <!-- .Param "description" 값이 존재하면 -->
    {{ . }} <!-- 해당 값을 출력합니다. -->
{{ else }} <!-- 그렇지 않으면 -->
    {{ .Summary }} <!-- 페이지의 기본 요약을 출력합니다. -->
{{ end }}



반복 (Iteration)

딕셔너리 데이터의 경우 {{ range $idx, $var := .Site.Data.xxx }} (중괄호 두 개 레인지 달러아이디엑스 콤마 달러바 콜론 이퀄 점 사이트 점 데이터 점 엑스엑스엑스 중괄호 두 개)를 통해 순회할 수 있고, 배열의 경우 {{ range $arr }} (중괄호 두 개 레인지 달러에이알알 중괄호 두 개) 방식으로 순회할 수 있습니다.

또한 위 데이터를 예로 들어 다음과 같은 방법으로 데이터를 정렬, 필터링 및 가져올 수 있습니다.

<!-- 여기서 컨텍스트는 배열 요소에 접근합니다. 전역 컨텍스트에 접근하려면 $.를 사용해야 합니다. -->
{{ range $array }} <!-- $array를 순회합니다. -->
    {{ . }} <!-- 각 요소를 출력합니다. -->
{{ end }}

<!-- 변수와 요소 인덱스를 선언할 수 있습니다. -->
{{ range $val := $array }} <!-- $array를 순회하며 각 요소를 $val에 할당합니다. -->
    {{ $val }}
{{ end }}
{{ range $idx, $val := $array }} <!-- $array를 순회하며 인덱스를 $idx에, 요소를 $val에 할당합니다. -->
   {{ $idx }} -- {{ $val }}
{{ end }}

<!-- 맵 요소의 인덱스(키)와 값에 대한 변수를 선언합니다. -->
{{ range $key, $val := $map }} <!-- $map을 순회하며 키를 $key에, 값을 $val에 할당합니다. -->
   {{ $key }} -- {{ $val }}
{{ end }}

<!-- 전달된 매개변수가 비어 있으면 else 문이 실행됩니다. -->
{{ range $array }}
    {{ . }}
{{else}}
    <!-- $array가 비어 있을 때만 실행됩니다. -->
{{ end }}




또한 다음과 같은 방법을 사용할 수 있습니다.

<ul>
  <!-- .Site.Data.books.fiction을 "title" 기준으로 정렬하여 순회합니다. -->
  {{ range sort .Site.Data.books.fiction "title" }}
    <li>{{ .title }} ({{ .author }})</li>
  {{ end }}
</ul>

<!-- .Site.Data.books.fiction에서 "isbn"이 "978-0140443530"인 항목을 필터링하여 순회합니다. -->
{{ range where .Site.Data.books.fiction "isbn" "978-0140443530" }}
  <li>{{ .title }} ({{ .author }})</li>
{{ end }}

<!-- .Site.Data.books에서 "historical-fiction" 키에 해당하는 값을 가져옵니다. -->
{{ index .Site.Data.books "historical-fiction" }}



이런 식으로 다른 변수에 따라 필터링할 수 있으며, .Site.Pages (점 사이트 점 페이지즈)와 같은 내장 변수도 마찬가지입니다.

다음은 조건부 필터링 처리입니다.

{{- if and (isset .Params "math") (eq .Params.math true) }} <!-- .Params에 math가 있고 그 값이 true이면 -->
{{- end -}}



페이지 필터링

다음은 먼저 현재 섹션(Section)의 데이터를 필터링하고 페이지에 class: "page" (클래스 콜론 쌍따옴표 페이지 쌍따옴표) 옵션을 설정해야 합니다.

먼저 연도별로 집계한 다음 날짜별로 내림차순 정렬하고 날짜와 해당 제목 정보를 표시합니다.

{{ $blogs := where (where .Site.Pages "Section" .Section) "Params.Class" "==" "page" -}}
<!-- 현재 섹션의 페이지 중 Params.Class가 "page"인 페이지만 필터링하여 $blogs에 할당합니다. -->
{{ range $blogs.GroupByDate "2006" "desc" }} <!-- $blogs를 "2006" (연도) 형식으로 그룹화하고 내림차순 정렬하여 순회합니다. -->
<h1>{{ .Key }}</h1> <!-- 그룹의 키 (연도)를 출력합니다. -->
<ul>
{{ range .Pages.ByDate.Reverse }} <!-- 그룹 내 페이지를 날짜 역순으로 정렬하여 순회합니다. -->
  <li><span>{{ .Date.Format "2006-01-02" }}</span> <a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
  <!-- 날짜와 제목 링크를 출력합니다. -->
{{ end }}
</ul>
{{ end }}



페이지에서 사용 가능한 변수는 Page Variables (페이지 변수)를 통해 볼 수 있으며, {{ . }} (중괄호 두 개 점 중괄호 두 개)를 통해 직접 인쇄하면 파일 경로가 표시됩니다.

기타 일반적으로 사용되는 예는 다음과 같습니다.

{{ range .Data.Pages }}                        <!-- .Data.Pages를 순회합니다. -->
{{ range where .Data.Pages "Section" "blog" }} <!-- .Data.Pages를 순회하며 Section이 "blog"인 데이터만 필터링합니다. -->
{{ range first 10 .Data.Pages }}               <!-- .Data.Pages를 순회하며 처음 10개 데이터를 가져옵니다. -->
{{ range last 10 .Data.Pages }}                <!-- .Data.Pages를 순회하며 마지막 10개 데이터를 가져옵니다. -->
{{ range after 10 .Data.Pages }}               <!-- .Data.Pages를 순회하며 10번째 이후 데이터를 가져옵니다. -->
{{ range until 10 .Data.Pages }}               <!-- .Data.Pages를 순회하며 10번째 이전 데이터를 가져옵니다. -->



숏코드 (Short Codes)

숏코드(ShortCodes)는 주로 마크다운에서 표현하기 불편한 일부 처리 로직을 처리하는 데 사용되므로 일부 원본 HTML (에이치티엠엘) 코드 작성을 생략합니다.

공식적으로 일부 비디오 웹사이트 링크, relref (렐레프) 등과 같은 몇 가지 기본 구현을 제공하며, 소스 코드는 Github (깃허브)에서 참조할 수 있습니다.

foobar (푸바) 숏코드(ShortCode)가 있다고 가정하면 다음과 같은 방식으로 사용할 수 있습니다.

매개변수를 래핑하는 방식에 유의하십시오.

현재 렌더링을 방지하는 더 나은 방법은 찾지 못했습니다.

{{< foobar "foo" "bar" >}} <!-- foobar 숏코드에 "foo"와 "bar" 매개변수 전달 -->
Some short codes <!-- 숏코드 내부 콘텐츠 (선택 사항) -->
{{< /foobar >}}



숏코드(ShortCode) 템플릿에서 위 매개변수를 가져오는 방법에는 여러 가지가 있습니다.

.Get 0 (점 겟 영)을 통해 가져오는 것이 가장 간단하고 직접적입니다.

또는 index .Params 0 (인덱스 점 파람즈 영)을 통해 가져올 수 있으며, 내부 내용은 .Inner (점 이너) 메서드를 통해 읽을 수 있으며 호출해야 합니다.

또한 Hugo ShortCodes (휴고 숏코즈)의 몇 가지 예를 참조할 수 있습니다.

일반적으로 사용되는 함수

템플릿에서는 {{ with .Site.Data.Resume . }} {{ .SomeData }} {{ end }} (중괄호 두 개 위드 점 사이트 점 데이터 점 레쥬메 점 중괄호 두 개 중괄호 두 개 점 썸데이터 중괄호 두 개 중괄호 두 개 엔드 중괄호 두 개) 방식으로 참조할 수 있습니다.

고급 사용법

정적 파일 (Static Files)

이미지, CSS (씨에스에스), JavaScript (자바스크립트) 등을 포함하며, 일반적으로 타사 라이브러리 Bootstrap (부트스트랩), FontAwesome (폰트어썸) 등과 같이 기존 파일입니다.

참조할 때 static (스태틱) 디렉터리에 배치해야 하며, 템플릿에서는 해당 디렉터리에 배치해야 자동으로 복사됩니다.

{{ "css/bootstrap.min.css" | absURL }} (중괄호 두 개 쌍따옴표 씨에스에스 슬래시 부트스트랩 점 민 점 씨에스에스 쌍따옴표 파이프 에이비에스유알엘 중괄호 두 개) 방식으로 참조할 수 있습니다.

이때 http://foobar.com/css/bootstrap.min.css (에이치티티피 콜론 슬래시슬래시 푸바 쩜 컴 슬래시 씨에스에스 슬래시 부트스트랩 점 민 점 씨에스에스)에 액세스하면 static/css/bootstrap.min.css (스태틱 슬래시 씨에스에스 슬래시 부트스트랩 점 민 점 씨에스에스) 파일에 매핑됩니다.

마운트 (Mounts)

npm (엔피엠)을 통해 타사 JS (제이에스) 패키지를 관리할 수 있지만, 이때 구성 파일의 module.mounts (모듈 점 마운츠)를 통해 구성해야 합니다.

[module]
  [[module.mounts]]
    source = "node_modules/katex/dist" # 원본 경로
    target = "static/katex"           # 대상 경로 (static 디렉토리 하위)




그런 다음 템플릿에서 다음과 같은 방식으로 사용할 수 있습니다.

<script type="text/javascript" src="{{ "katex/katex.min.js" | absURL }}"></script>`
<link rel="stylesheet" href="{{ "katex/katex.min.css" | absURL }}"/>



CSS (씨에스에스)

0.43 버전부터 Hugo (휴고)는 SASS (사스) 컴파일을 지원합니다.

그러나 소스 파일은 /assets/scss/ (슬래시 애셋 슬래시 에스씨에스에스 슬래시) 또는 /themes/<NAME>/assets/scss/ (슬래시 테마즈 슬래시 꺽쇠 네임 꺽쇠 슬래시 애셋 슬래시 에스씨에스에스 슬래시) 디렉터리에만 배치할 수 있습니다.

그런 다음 다음과 같은 방식으로 도입할 수 있습니다.

{{ $opts := dict "transpiler" "libsass" "targetPath" "css/style.css" }}
<!-- 컴파일 옵션 설정: transpiler는 libsass, targetPath는 css/style.css -->
{{ with resources.Get "sass/main.scss" | toCSS $opts | minify | fingerprint }}
  <!-- sass/main.scss 파일을 가져와 toCSS로 컴파일하고, minify로 압축하고, fingerprint로 해시값을 생성합니다. -->
  <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
  <!-- 생성된 CSS 파일 링크를 추가합니다. -->
{{ end }}



resources.Get (리소스즈 점 겟)을 사용하여 SCSS (에스씨에스에스) 파일의 내용을 가져온 다음 파이프라인을 사용하여 컴파일, 압축 및 지문(fingerprint)을 생성합니다.

이렇게 하면 생성된 파일에 해시 파일 이름을 추가하여 캐시된 이전 파일 대신 CDN (씨디엔)에서 최신 CSS (씨에스에스)를 가져올 수 있습니다.

또한 위 CSS (씨에스에스) 컴파일 구성 옵션 외에도 다음을 참조할 수 있습니다.

{{ $opts := (dict "outputStyle" "compressed" "enableSourceMap" true "includePaths" (slice "node_modules")) -}}
<!-- outputStyle: compressed (압축), enableSourceMap: true (소스맵 활성화), includePaths: node_modules 디렉토리 포함 -->




코드 강조 표시는 다음 명령을 통해 생성할 수 있으며, 예는 Style Longer (스타일 롱거) 및 Style (스타일)에서 참조할 수 있습니다.

hugo gen chromastyles --style=monokai > syntax.css (휴고 젠 크로마스타일즈 대시 스타일 이퀄 모노카이 부등호 신택스 점 씨에스에스)

구성 매개변수 codeFences=true (코드펜시즈 이퀄 트루)를 설정해야 하며, 그렇지 않으면 줄 번호와 같은 정보가 테이블 형태로 표시되어 비정상적인 표시가 발생합니다.

JavaScript (자바스크립트)

CSS (씨에스에스)와 유사하게 JS (제이에스) 스크립트는 다음과 같은 방식으로 도입할 수 있습니다.

{{ $params := dict "api" "https://example.org/api" }} <!-- 스크립트 내에서 사용할 파라미터 설정 -->
{{ with resources.Get "js/main.js" }} <!-- js/main.js 파일을 가져옵니다. -->
  {{ if hugo.IsDevelopment }} <!-- 개발 환경인 경우 -->
    {{ with . | js.Build }} <!-- js.Build를 사용하여 빌드합니다. (옵션 없음) -->
      <script src="{{ .RelPermalink }}"></script>
    {{ end }}
  {{ else }} <!-- 프로덕션 환경인 경우 -->
    {{ $opts := dict "minify" true "params" $params }} <!-- minify: true, params: 위에서 설정한 $params -->
    {{ with . | js.Build $opts | fingerprint }} <!-- js.Build에 옵션을 전달하고, fingerprint를 생성합니다. -->
      <script src="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"></script>
    {{ end }}
  {{ end }}
{{ end }}



스크립트에서 매개변수는 import * as params from '@params'; (임포트 별표 애즈 파람즈 프롬 골뱅이파람즈 세미콜론) 방식으로 참조할 수 있으며, React (리액트) 코드는 Shims (쉼즈) 방법을 통해 도입할 수도 있습니다.

더 많은 기능은 Hugo JS (휴고 제이에스)를 참조할 수 있습니다.

이미지 렌더링

Hugo (휴고)에서 이미지 형식을 사용자 정의하는 것은 약간 번거롭습니다.

![name](uri){: width="420"} (느낌표 대괄호 네임 대괄호 괄호 유알아이 괄호 중괄호 콜론 위드 이퀄 쌍따옴표 사백이십 쌍따옴표 중괄호)와 같은 방식을 지원하지 않습니다.

직접 HTML (에이치티엠엘)을 지원하므로 다음과 같은 방식으로 구성할 수 있습니다.

<img src="picture.png" alt="some message" width="50%" />

css (씨에스에스)에서 img (이미지)의 정렬을 사용자 정의할 수 있지만, 이때는 하나의 정렬만 사용할 수 있습니다.

또한 공식적으로 figure (피겨)의 숏코드(shortcodes) 코드를 제공하여 사용할 수 있지만 다른 플랫폼에서 호환성 문제가 발생할 수 있습니다.

또 다른 방법이 있습니다.

layouts/_default/_markup/render-image.html (레이아웃 슬래시 언더바디폴트 슬래시 언더바마크업 슬래시 렌더 대시 이미지 점 에이치티엠엘)에서 이미지 렌더링 방법을 사용자 정의한 다음 ![name](uri?width=100px) (느낌표 대괄호 네임 대괄호 괄호 유알아이 물음표 위드 이퀄 백픽셀 괄호)와 같은 방식으로 사용하지만, 지원되는 매개변수는 위 파일에 구성해야 합니다.

더 많은 다른 렌더링 후크(Hooks)는 Render Hooks (렌더 후크) 콘텐츠를 참조할 수 있습니다.

데이터 전송

데이터는 Scratch (스크래치)를 통해 전송할 수 있으며, 이는 페이지(Page)와 숏코드(ShortCodes) 간에 데이터를 전송하는 데 사용됩니다.

템플릿에서 임시 데이터 전송을 사용하려면 newScratch (뉴스크래치)를 통해 새로 만들 수 있습니다.

아래 Hugo (휴고)에서 자동으로 생성된 Scratch (스크래치)를 예로 들어 보겠습니다.

.Page.Scratch (점 페이지 점 스크래치)와 .Scratch (점 스크래치)는 동일한 기능을 갖습니다.

{{ .Scratch.Set "hey" "Hello" }} <!-- "hey"라는 키에 "Hello" 문자열 저장 (숫자나 슬라이스도 가능) -->
{{ .Scratch.Get "hey" }}         <!-- "hey" 키의 값 가져오기 -->
{{ .Scratch.Add "hey" "Welcome" }} <!-- "hey" 키의 값에 "Welcome" 추가 (문자열 연결, 숫자 덧셈, 배열 연결 등 Go 언어와 유사) -->
{{ .Scratch.GetSortedMapValues "hey" }} <!-- Get으로 맵을 가져오는 것 외에도 키로 정렬된 값을 반환할 수 있음 -->
{{ .Scratch.Delete "hey" }}      <!-- "hey" 키 삭제 -->

{{ .Scratch.SetInMap "hey" "Hello" "World" }} <!-- 맵 설정, 키:값은 Hello:World에 해당 -->
{{ .Scratch.SetInMap "hey" "Hey" "Andy" }}
{{ .Scratch.Get "hey" }} <!-- map[Hello:World Hey:Andy] 출력 -->



템플릿 디버깅

{{ printf "%#v" .Permalink }} (중괄호 두 개 프린트에프 쌍따옴표 퍼센트샵브이 쌍따옴표 점 퍼머링크 중괄호 두 개)를 통해 현재 변수 정보를 인쇄할 수 있습니다.

또한 페이지 레이아웃을 디버깅하려면 <head> (헤드)에 다음 내용을 추가하여 쉽게 볼 수 있습니다.

<style>
div {
  border: 1px solid black; /* 모든 div 요소에 검은색 1px 실선 테두리 적용 */
  background-color: LightSkyBlue; /* 모든 div 요소의 배경색을 LightSkyBlue로 설정 */
}
</style>



관련 글 (Related Articles)

Hugo (휴고)는 기본적으로 관련 글에 대한 Related Content (릴레이티드 콘텐츠) 구성을 제공하며, 기본적으로 키워드, 날짜 및 태그를 통해 관련성을 일치시킵니다.

모범 사례 (Best Practices)

최상위 디렉터리에는 archetypes (아키타입스), assets (애셋), content (콘텐츠), data (데이터), i18n (아이일팔엔), static (스태틱), layouts (레이아웃) 여러 디렉터리가 포함됩니다.

archetypes/ (아키타입스 슬래시): new (뉴) 하위 명령을 통해 새 글을 만들 때의 템플릿.


config/ (콘피그 슬래시): 기본적으로 hugo.[toml|yaml|json] (휴고 점 대괄호 티오엠엘 파이프 와이에이엠엘 파이프 제이슨 대괄호)이 구성으로 사용되며, 다음 디렉터리 방법을 사용할 수 있습니다.


_default/ (언더바디폴트 슬래시): 기본 구성.


production/ (프로덕션 슬래시): 전역 구성.


i18n/ (아이일팔엔 슬래시): 지역화.


themes/ (테마즈 슬래시):


halo/ (헤일로 슬래시): 해당 템플릿 이름.


assets/ (애셋 슬래시): 템플릿의 리소스 파일.


images/ (이미지즈 슬래시)


js/ (제이에스 슬래시): JavaScript (자바스크립트) 관련 스크립트, 자세한 내용은 footer/script-footer.html (푸터 슬래시 스크립트 대시 푸터 점 에이치티엠엘) 참조.


scss/ (에스씨에스에스 슬래시): SCSS (에스씨에스에스) 파일.


app.scss (앱 점 에스씨에스에스): 최상위 SCSS (에스씨에스에스) 파일, 다른 디렉터리의 파일을 포함하며, 자세한 내용은 head/head.html (헤드 슬래시 헤드 점 에이치티엠엘) 참조.


static/ (스태틱 슬래시): 정적 파일.


syntax.css (신택스 점 씨에스에스): 위 hugo gen chromastyles (휴고 젠 크로마스타일즈) 명령으로 생성된 CSS (씨에스에스) 파일, 자세한 내용은 head/head.html (헤드 슬래시 헤드 점 에이치티엠엘) 참조.


layouts/ (레이아웃 슬래시): 레이아웃 템플릿, 여기서 _default (언더바디폴트)는 기본값이고, partials (파셜즈)는 다른 템플릿의 참조입니다.


_default/ (언더바디폴트 슬래시)


blog/ (블로그 슬래시): blog (블로그) 섹션(Section) 템플릿에 해당.


docs/ (독스 슬래시): docs (독스) 섹션(Section) 템플릿에 해당.


partials/ (파셜즈 슬래시): 다른 템플릿의 참조.


resume/ (레쥬메 슬래시): resume (레쥬메) 섹션(Section) 템플릿에 해당.


baseof.html (베이스오브 점 에이치티엠엘): 렌더링을 위한 루트 페이지.


shortcodes/ (숏코즈 슬래시): 숏 코드.


slide/ (슬라이드 슬래시): slide (슬라이드) 섹션(Section) 템플릿에 해당.


404.html (사공사 점 에이치티엠엘): 404 페이지 생성.

CSS (씨에스에스) 관련 내용은 다음 파일에 따라 달라집니다.

syntax.css (신택스 점 씨에스에스): 구문 강조 표시, 압축만 필요합니다.


main.css (메인 점 씨에스에스): 핵심 사용자 정의 구성.

부트스트랩(bootstrap) 변수를 사용하기 위해 scss (에스씨에스에스) 템플릿에서도 참조되므로 bootstrap.min.css (부트스트랩 점 민 점 씨에스에스)를 별도로 도입할 필요가 없습니다.


fontawesome.min.css (폰트어썸 점 민 점 씨에스에스): 사용된 아이콘, Icons (아이콘즈)의 내용을 참조할 수 있습니다.


또한 Bootstrap (부트스트랩)의 관련 변수는 bootstrap/scss/_variables.scss (부트스트랩 슬래시 에스씨에스에스 슬래시 언더바변수 점 에스씨에스에스)에 저장됩니다.

태그 (Tags)

기본 태그 및 키워드 구성을 통해 글을 연결합니다.

이 중 키워드는 글 유형에 따라 추가되며, 태그에는 다음과 같은 일반적인 분류가 포함됩니다.

topic (토픽): 특별 주제 기사, 일부 기사를 중앙 집중적으로 정리하고 표시합니다.


language (랭귀지): 프로그래밍 관련, c/cpp (씨 슬래시 씨피피), lua (루아), bash (배시), rust (러스트), java (자바), python (파이썬), golang (고랭), web (웹), css (씨에스에스), html (에이치티엠엘) 등과 같은 특정 언어로 세분화됩니다.


database (데이터베이스): 데이터베이스 관련, mysql (마이에스큐엘) 등으로 세분화됩니다.


linux (리눅스): 운영 체제 관련, kvm (케이브이엠), network (네트워크), command (커맨드), vim (빔), ebpf (이비피에프) 등으로 세분화됩니다.


security (시큐리티): 보안 관련, ssh (에스에스에이치), tls/ssl (티엘에스 슬래시 에스에스엘) 등으로 세분화됩니다.


container (컨테이너): 컨테이너 관련 콘텐츠, docker (도커), k8s (케이에잇에스) 등으로 세분화됩니다.


warehouse (웨어하우스): 빅데이터 관련 콘텐츠, hudi (후디) 등으로 세분화됩니다.


devops (데브옵스): 운영 및 개발 관련 도구, git (깃) 등으로 세분화됩니다.


algorithm structure (알고리즘 스트럭처): 알고리즘 데이터 구조 관련.


example (이그잼플): 관련 예제 코드, 일반적으로 사용되는 명령줄을 정리하기 위한 치트시트(cheatsheet)를 포함하며, 소프트웨어는 명령줄보다 체계적입니다.


각 글 제목 아래의 태그 목록은 점프에 사용할 수 있습니다.

이때 템플릿의 layouts/_default/list.html (레이아웃 슬래시 언더바디폴트 슬래시 리스트 점 에이치티엠엘)을 통해 렌더링됩니다.