Skip to content
Merged
21 changes: 11 additions & 10 deletions public/docs/get-started/get-docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,29 @@
>
> 대기업(직원 250명 이상 또는 연간 매출 1000만 달러 이상)에서 Docker Desktop을 상업적으로 사용하려면 [유료 구독](https://www.docker.com/pricing/?_gl=1*h2v28y*_gcl_au*MjczODgxODI4LjE3Mzg0NzA0NDI.*_ga*MjEyODM1MDY2OC4xNzIwMzEyNzQ5*_ga_XJWPQMJYHQ*MTczOTU2MjU3My42MS4xLjE3Mzk1NjI3NjMuNjAuMC4w)이 필요합니다.

<box-component
<div class="not-prose">
<card-component
imgsrc="/imgs/get-started/get-docker-logo/apple_48.svg"
title="Docker Desktop for Mac"
description="macOS 샌드박스 보안 모델을 사용하는 네이티브 애플리케이션으로, Mac에 모든 Docker 도구를 제공합니다."
href="https://docs.docker.com/desktop/setup/install/mac-install/"
></box-component>


<box-component
></card-component>
<card-component
imgsrc="/imgs/get-started/get-docker-logo/windows_48.svg"
title="Docker Desktop for Windows"
description="모든 Docker 도구를 Windows 컴퓨터에 제공하는 네이티브 Windows 애플리케이션입니다."
href="https://docs.docker.com/desktop/setup/install/windows-install/"
></box-component>


<box-component
></card-component>
<card-component
imgsrc="/imgs/get-started/get-docker-logo/linux_48.svg"
title="Docker Desktop for Linux"
description="모든 Docker 도구를 Linux 컴퓨터에 제공하는 네이티브 Linux 애플리케이션입니다."
href="https://docs.docker.com/desktop/setup/install/linux/"
></box-component>
></card-component>
</div>




> **Note**
>
Expand Down
81 changes: 80 additions & 1 deletion public/docs/get-started/introduction/whats-next.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,89 @@

컨테이너, 이미지, 레지스트리, Docker Compose의 핵심 개념을 배워보세요.

<div class="not-prose md:grid-cols-2 lg:grid-cols-3 grid grid-cols-1 gap-4 mb-6 auto-rows-fr">
<card-component
title="What is a container?"
description="첫 번째 컨테이너를 실행하는 방법을 배워보세요."
href="/#/get-started/docker-concepts/the-basics/what-is-a-container"
></card-component>
<card-component
title="What is an image?"
description="이미지 레이어의 기초를 배워보세요."
href="/#/get-started/docker-concepts/the-basics/what-is-an-image"
></card-component>
<card-component
title="What is a registry?"
description="컨테이너 레지스트리에 대해 알아보고, 레지스트리 간 상호 운용성을 살펴본 후, 실제로 레지스트리와 상호작용해 보세요."
href="/#/get-started/docker-concepts/the-basics/what-is-a-registry"
></card-component>
<card-component
title="What is Docker Compose?"
description="Docker Compose를 더 잘 이해해 보세요."
href="/#/get-started/docker-concepts/the-basics/what-is-docker-compose"
></card-component>
</div>

## Building images

Dockerfiles, 빌드 캐시 및 다단계 빌드를 사용하여 최적화된 컨테이너 이미지를 만들어보세요.

<div class="not-prose md:grid-cols-2 lg:grid-cols-3 grid grid-cols-1 gap-4 mb-6 auto-rows-fr">
<card-component
title="Understanding image layers"
description="컨테이너 이미지 레이어에 대해 배워보세요."
href="/#/get-started/docker-concepts/building-images/understanding-image-layers"
></card-component>
<card-component
title="Writing a Dockerfile"
description="Dockerfile을 사용하여 이미지를 생성하는 방법을 배워보세요."
href="/#/get-started/docker-concepts/building-images/writing-a-dockerfile"
></card-component>
<card-component
title="Build, tag and publish an image"
description="Docker Hub나 다른 레지스트리에 이미지를 빌드하고 태그한 뒤 게시하는 방법을 알아보세요."
href="/#/get-started/docker-concepts/building-images/build-tag-and-publish-an-image"
></card-component>
<card-component
title="Using the build cache"
description="빌드 캐시가 무엇인지, 어떤 변경이 캐시를 무효화하는지, 그리고 빌드 캐시를 효과과적으로 활용하는 방법을 배워보세요."
href="/#/get-started/docker-concepts/building-images/using-the-build-cache"
></card-component>
<card-component
title="Multi-stage builds"
description="멀티 스테이지 빌드와 그 이점에 대해 잘 이해해 보세요."
href="/#/get-started/docker-concepts/building-images/multi-stage-builds"
></card-component>
</div>

## Running containers

포트 노출, 기본값 재정의, 데이터 유지, 파일 공유, 멀티 컨테이너 애플리케이션 관리를 위한 필수 기술을 익혀보세요.
포트 노출, 기본값 재정의, 데이터 유지, 파일 공유, 멀티 컨테이너 애플리케이션 관리를 위한 필수 기술을 익혀보세요.

<div class="not-prose md:grid-cols-2 lg:grid-cols-3 grid grid-cols-1 gap-4 mb-6 auto-rows-fr">
<card-component
title="Publishing ports"
description="Docker에서 포트를 게시하고 노출하는 것의 중요성을 이해해 보세요"
href="/#/get-started/docker-concepts/running-containers/publishing-ports"
></card-component>
<card-component
title="Overriding container defaults"
description="<code>docker run</code> 명령어를 사용해 컨테이너의 기본 설정을 재정의하는 방법을 알아보세요."
href="/#/get-started/docker-concepts/running-containers/overriding-container-defaults"
></card-component>
<card-component
title="Persisting container data"
description="Docker에서 데이터 지속성이 왜 중요한지 알아보세요."
href="/#/get-started/docker-concepts/running-containers/persisting-container-data"
></card-component>
<card-component
title="Sharing local files with containers"
description="Docker에서 사용 가능한 다양한 스토리지 옵션과 사용법을 살펴보세요."
href="/#/get-started/docker-concepts/running-containers/sharing-local-files"
></card-component>
<card-component
title="Multi-container applications"
description="다중 컨테이너 애플리케이션의 중요성과 단일 컨테이너 애플리케이션과의 차이점을 알아보세요."
href="/#/get-started/docker-concepts/running-containers/multi-container-applications"
></card-component>
</div>
41 changes: 0 additions & 41 deletions src/scripts/components/box-component.ts

This file was deleted.

46 changes: 46 additions & 0 deletions src/scripts/components/card-component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
class CardComponent extends HTMLElement {
static get observedAttributes() {
return ['imgsrc', 'href', 'title', 'description'];
}

constructor() {
super();
}

attributeChangedCallback() {
this.render();
}

connectedCallback() {
this.render();
}

render() {
const imgSrc = this.getAttribute('imgsrc'); // 없으면 null
const href = this.getAttribute('href') || '#';
const title = this.getAttribute('title') || '';
const description = this.getAttribute('description') || '';

this.innerHTML = `
<div class="card">
<a href="${href}" class="card-link">
${
imgSrc
? `<div class="card-icon">
<img class="card-img" src="${imgSrc}" alt="${title}" />
</div>`
: ''
}
<div class="card-content">
<p class="card-description">
<strong class="card-title">${title}</strong><br />
${description}
</p>
</div>
</a>
</div>
`;
}
}

customElements.define('card-component', CardComponent);
2 changes: 1 addition & 1 deletion src/scripts/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import './footer-component';
import './header-component';
import './box-component';
import './card-component';
import './button-component';
62 changes: 53 additions & 9 deletions src/scripts/load_md.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,73 @@
import { marked } from 'marked';

// marked 옵션 설정 (브레이크, GFM 지원 등)
// marked 옵션 설정 (브레이크, GFM 지원 등)
marked.setOptions({
gfm: true,
breaks: true,
});

// card-component를 블록 태그 및 셀프 클로징 태그로 처리하는 커스텀 토크나이저 추가
// 템플릿 리터럴에서 역참조(\1) 사용 불가하므로 정규식 리터럴로 하드코딩
const blockTagRegex =
/^<(card-component)([\s\S]*?)(?:>([\s\S]*?)<\/card-component>|\s*\/)>/i;

const customBlockTokenizer = {
name: 'custom-block-tag',
level: 'block',
start(src: string) {
return src.match(blockTagRegex)?.index;
},
tokenizer(src: string) {
const match = blockTagRegex.exec(src);
if (match) {
return {
type: 'html',
raw: match[0],
text: match[0],
};
}
return;
},
} as const;

marked.use({ extensions: [customBlockTokenizer] });

/**
* mdText를 웹 컴포넌트 태그(<box-component>, <button-component>) 기준으로 분할하여
* 마크다운은 파싱하고, 웹 컴포넌트는 그대로 삽입하는 함수
* 커스텀 파서: <div ...>...</div> 블록을 마크다운 파싱 없이 그대로 삽입
* 나머지 마크다운만 기존 파서로 처리
*/
export async function renderMarkdownWithComponents(
mdText: string,
contentElement: HTMLElement
) {
const tokens = mdText
.split(/(<\/?box-component[^>]*>|<\/?button-component[^>]*>)/gi)
.filter(Boolean);
// <div ...>...</div> 블록 추출 (빈 줄 포함, 중첩 X)
const divBlockRegex = /(<div[\s\S]*?>[\s\S]*?<\/div>)/gi;
const tokens = mdText.split(divBlockRegex).filter(Boolean);

for (const token of tokens) {
if (/^<\/?(box-component|button-component)[^>]*>$/.test(token)) {
if (/^<div[\s\S]*?>[\s\S]*?<\/div>$/.test(token)) {
// div 블록은 그대로 삽입
contentElement.innerHTML += token;
} else if (token.trim()) {
const html = await marked.parse(token);
contentElement.innerHTML += html;
// 나머지는 기존 방식대로 웹 컴포넌트 분리 후 마크다운 파싱
const innerTokens = token
.split(
/(<card-component[\s\S]*?<\/card-component>|<card-component[\s\S]*?\/>|<button-component[\s\S]*?<\/button-component>|<button-component[\s\S]*?\/>)/gi
)
.filter(Boolean);
for (const innerToken of innerTokens) {
if (
/^<\/?(card-component|button-component)[^>]*?>.*?<\/(card-component|button-component)>$/.test(
innerToken
) ||
/^<(card-component|button-component)[^>]*?\/>$/.test(innerToken)
) {
contentElement.innerHTML += innerToken;
} else if (innerToken.trim()) {
const html = await marked.parse(innerToken);
contentElement.innerHTML += html;
}
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/scripts/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import '../styles/content_style.css';
import '../styles/not_found.css';
import '../styles/style.css';
import './load_md';
import './components/box-component';
import './components/card-component';
import { initializeMarkdownLoader } from './load_md';
import { initializeNavFn } from './nav';
import { initializeTableContents } from './table-contents';
Expand Down
63 changes: 63 additions & 0 deletions src/styles/style.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
@import 'tailwindcss';

@tailwind base;
@tailwind components;
@tailwind utilities;

/* Table 관련 기본 스타일 */
@layer base {
card-component {
@apply block;
}
table {
@apply w-3/4 table-auto;
}
Expand All @@ -14,3 +22,58 @@
@apply bg-gray-200;
}
}

/* 카드 컴포넌트 스타일 */
@layer components {
.card {
@apply mb-4 flex h-full min-w-0 flex-col rounded-md border border-gray-200 bg-white px-4 py-3 transition duration-200 hover:border-gray-300 hover:shadow;
}

.card-link {
@apply flex items-start gap-4 no-underline;
}

.card-icon {
@apply mt-1 flex-shrink-0;
}

.card-img {
@apply h-6 w-6;
}

.card-content {
@apply flex-1;
}

.card-description {
@apply text-sm leading-snug text-gray-500;
}

.card-title {
@apply text-base font-semibold text-gray-700;
}
}

/* 전역 스타일 */
body {
font-family: 'Noto Sans KR', Arial, sans-serif;
background: #f8fafc;
color: #222;
margin: 0;
padding: 0;
}

h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 700;
margin-top: 1.5em;
margin-bottom: 0.5em;
}

p {
margin: 0 0 1em 0;
}
Comment on lines +58 to +79
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 전역 스타일을 추가한 이유는 뭘까요?

전역 스타일이 필요없다는 건 아닌데, card-comonent랑은 목적이 다른 코드라는 생각이여서요

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아니다. 이건 들어가고 제가 좀 더 정리해야할 것 같아요. 머지하겠습니다.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

앗 넵!!

Loading