Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ src/content/
title: 제목
date: 2026-04-18
updatedAt: 2026-04-20 # 실질적으로 내용을 수정한 경우만 (선택)
project: unilink # unilink | ai-curator | site (선택)
project: wirestead # wirestead | ai-curator | site (선택)
kind: design # design | implementation | retrospective | study | note | devlog
tags: [ros2, c++]
description: 한 줄 요약
series: unilink-design # 연속 글일 때만 (선택)
series: wirestead-design # 연속 글일 때만 (선택)
seriesOrder: 1 # series가 있으면 필수
draft: false
---
Expand All @@ -62,7 +62,7 @@ draft: false

`series`가 있는 글은 `project` 유무와 무관하게 `/blog` 인덱스의 "Series" 섹션에 카드로 묶여서 노출된다.

- `series`에 연결된 `project`가 있으면(`unilink-design` → `unilink` 등) 카드는 해당 프로젝트 허브(`/projects/[slug]`)로 링크되고, 그 페이지의 "Series" 섹션에서 순서대로 볼 수 있다.
- `series`에 연결된 `project`가 있으면(`wirestead-design` → `wirestead` 등) 카드는 해당 프로젝트 허브(`/projects/[slug]`)로 링크되고, 그 페이지의 "Series" 섹션에서 순서대로 볼 수 있다.
- `project`가 없는 시리즈(예: `llm-core`, `llm-training`)는 전용 허브 페이지 `/blog/series/[series]`로 링크된다.

새 시리즈를 추가하려면 `src/data/taxonomy.json`의 `series` 배열에 항목을 추가하고 `config.yml`의 Series select 옵션도 함께 갱신한다 (다르면 `content:check`가 실패한다).
Expand Down Expand Up @@ -114,4 +114,4 @@ Node.js 22 이상 필요.
이 레포가 블로그까지 통합 운영. 나머지 서브패스는 별도 레포:

- `/ai-curator/` — AI 큐레이션 ([jwsung91/ai-curator](https://github.com/jwsung91/ai-curator), Astro)
- `/unilink/` — 라이브러리 문서 ([jwsung91/unilink](https://github.com/jwsung91/unilink), Doxygen)
- `/wirestead/` — 라이브러리 문서 ([jwsung91/wirestead](https://github.com/jwsung91/wirestead), Doxygen)
30 changes: 30 additions & 0 deletions astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,39 @@ function remarkMermaid() {
};
}

// unilink -> wirestead 리네임으로 바뀐 구 URL을 유지하기 위한 리다이렉트.
// 정적 빌드에서는 meta refresh 페이지로 생성된다.
const renamedSlugs = [
'2026-05-31-unilink-builder-api-설계',
'2026-05-31-unilink-unified-api-설계',
'2026-05-31-unilink-설계-배경',
'2026-06-02-unilink-channel-추상화-설계',
'2026-06-02-unilink-channelfactory-설계',
'2026-06-02-unilink-transport-계층-설계',
'2026-06-02-unilink-wrapper-계층-설계',
'2026-06-03-unilink-backpressure-설계',
'2026-06-03-unilink-framer-계층-설계',
'2026-06-03-unilink-memory-buffer-설계',
'2026-06-03-unilink-runtimestats와-diagnostics-설계',
'2026-06-03-unilink-설계-회고',
'2026-07-02-unilink-tcp-nodelay-트러블슈팅',
'2026-07-02-unilink-udp-backpressure-데드락-트러블슈팅',
];

const legacyRedirects = {
'/projects/unilink': '/projects/wirestead',
...Object.fromEntries(
renamedSlugs.map((slug) => [
`/blog/${slug}`,
`/blog/${slug.replace('unilink', 'wirestead')}`,
]),
),
};

export default defineConfig({
site: 'https://jwsung91.github.io',
integrations: [sitemap()],
redirects: legacyRedirects,
markdown: {
processor: unified({
remarkPlugins: [remarkMath, remarkMermaid],
Expand Down
4 changes: 2 additions & 2 deletions docs/cms-writing-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

프로젝트와 직접 관련된 글이면 선택합니다.

- `unilink`: unilink 설계/구현/릴리즈 기록
- `wirestead`: wirestead 설계/구현/릴리즈 기록
- `ai-curator`: AI Curator 파이프라인/운영 기록
- `site`: 이 블로그, Sveltia CMS, Astro 운영 기록

Expand Down Expand Up @@ -60,7 +60,7 @@ Reliable / BestEffort 채널에서 send(), queue pressure, drop 정책, backpres
연속 글이라면 아래 필드를 함께 입력한다.

```yaml
series: unilink-design
series: wirestead-design
seriesOrder: 1
```

Expand Down
4 changes: 2 additions & 2 deletions public/admin/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ collections:
required: false
hint: "프로젝트와 직접 관련 없는 개인 공부 글이면 비워둡니다."
options:
- { label: "unilink", value: "unilink" }
- { label: "wirestead", value: "wirestead" }
- { label: "AI Curator", value: "ai-curator" }
- { label: "Site", value: "site" }

Expand Down Expand Up @@ -118,7 +118,7 @@ collections:
required: false
hint: "연속 글이 아니라면 비워둡니다."
options:
- { label: "unilink 설계 노트", value: "unilink-design" }
- { label: "wirestead 설계 노트", value: "wirestead-design" }
- {
label: "AI Curator 파이프라인 구축기",
value: "ai-curator-pipeline",
Expand Down
2 changes: 1 addition & 1 deletion src/content/about.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: About

# About

로보틱스 플랫폼에서 7년 이상 소프트웨어를 설계해 온 엔지니어입니다. 복잡도가 높은 시스템을 구조적으로 풀어내는 과정에서 소프트웨어 아키텍처의 중요성을 체감해 왔고, 도메인 전문가를 넘어 시스템 전체를 설계하는 아키텍트로 성장하는 것을 목표로 하고 있습니다.
2018년부터 로보틱스 플랫폼에서 소프트웨어를 설계해 온 엔지니어입니다. 복잡도가 높은 시스템을 구조적으로 풀어내는 과정에서 소프트웨어 아키텍처의 중요성을 체감해 왔고, 도메인 전문가를 넘어 시스템 전체를 설계하는 아키텍트로 성장하는 것을 목표로 하고 있습니다.

모듈 간 의존성을 분리하고 인터페이스를 일관되게 추상화하여 시스템 복잡도를 낮추는 것을 중요하게 생각합니다. 로우레벨 비동기 I/O부터 고수준 임무 관리까지, 확장 가능하고 일관된 소프트웨어 구조를 설계해 왔습니다.

Expand Down
5 changes: 4 additions & 1 deletion src/content/blog/2026-04-18-hello.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ title: '사이트 오픈'
date: 2026-04-18
project: site
kind: note
tags: ['meta']
tags:
- meta
- astro
- site
description: 'Jekyll 기반 블로그에서 Astro 허브 사이트로 전환한 배경과 개인 플랫폼의 초기 방향을 정리했다.'
---

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ kind: note
tags:
- markdown
- sveltia
- site
description: Sveltia CMS raw Markdown 모드에서 frontmatter, 코드 블록, 표, Mermaid 다이어그램 작성 예시를 정리했다.
draft: false
---
Expand Down
31 changes: 17 additions & 14 deletions src/content/blog/2026-04-21-stl-priority-queue.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,26 @@ title: 'Priority queue'
date: 2026-04-21
kind: study
tags:
- cpp
- stl
- c++
- 자료구조
description: C++ std::priority_queue의 동작 방식, 최대 힙과 최소 힙 사용법, 사용자 정의 비교 함수 예제를 정리합니다.
- data-structure
description: C++ std::priority_queue의 동작 방식, 최대 힙과 최소 힙 사용법, 사용자 정의 비교 함수 예제를 정리했다.
draft: true
---

## 정의

우선순위가 가장 높은(혹은 낮은) 데이터를 가장 먼저 도출되는 형태의 자료구조
우선순위가 가장 높은(혹은 낮은) 데이터가 가장 먼저 나오는 자료구조

- C++에서는 `std::priority_queue`가 기본적으로 제공
- 내부적으로 \*\*최대 힙(Max Heap)\*\*을 사용해서 구현되어 있음
- 정렬이 필요없는 **우선순위 기반의 데어터 처리**에 적합
- 내부적으로 **최대 힙**(Max Heap)을 사용해서 구현되어 있음
- 정렬이 필요 없는 **우선순위 기반의 데이터 처리**에 적합

### 구조

- C++의 `std::priority_queue`는 기본적으로 힙(Heap) 자료구조를 기반으로 동작
- 내부적으로 `std::vector`를 사용하며, 힙 연산을 활용하여 정렬
- 내부적으로 `std::vector`를 사용하며, 힙 연산으로 힙 순서(heap order)를 유지한다
- 컨테이너 전체가 정렬되어 있는 것은 아니다. `top()`이 항상 최우선 원소를 가리키도록 유지할 뿐이다
- `std::make_heap`, `std::push_heap`, `std::pop_heap`

### 시간복잡도
Expand All @@ -31,7 +32,7 @@ draft: true

### 템플릿 정의

```c
```cpp
template <class T, class Container = std::vector<T>, class Compare = std::less<T>>
class priority_queue;
```
Expand All @@ -50,7 +51,7 @@ class priority_queue;

- 기본적으로 최대 힙으로 적용되어 있음

```c
```cpp
#include <iostream>
#include <queue>

Expand Down Expand Up @@ -79,7 +80,7 @@ int main() {

`std::priority_queue`를 선언할 때 `std::greater<>` 추가

```c
```cpp
#include <iostream>
#include <queue>
#include <vector>
Expand Down Expand Up @@ -107,13 +108,14 @@ int main() {

## 사용자 정의 구조체 적용

특정 기준으로 정렬하고 싶다면, `operator`를 오버로딩하거나 `compare` 함수를 지정
특정 기준으로 정렬하고 싶다면, `operator<`를 오버로딩하거나 `compare` 함수를 지정

### operator 오버로딩

```c
```cpp
#include <iostream>
#include <queue>
#include <string>

struct Task {
int score;
Expand Down Expand Up @@ -148,9 +150,10 @@ High Medium Low

### compare 함수 이용

```c
```cpp
#include <iostream>
#include <queue>
#include <string>
#include <vector>

struct Task {
Expand Down Expand Up @@ -180,7 +183,7 @@ int main() {
}
```

priority 기준 오름차순으로 정리됨
priority 기준 오름차순으로 출력됨

```text
Low Medium High
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,58 +6,56 @@ kind: design
tags:
- ai-curator
- astro
description: 'Astro와 GitHub Actions를 활용해 서버리스 정적 큐레이션 시스템의 초기 아키텍처와 운영 원칙을 정리합니다.'
- architecture
description: Astro와 GitHub Actions를 활용해 서버리스 정적 큐레이션 시스템의 초기 아키텍처와 운영 원칙을 정리했다.
series: 'ai-curator-pipeline'
seriesOrder: 1
draft: false
---

> 업데이트: 이후 Weekly 리포트와 별도 아카이브가 추가되었다.
> 현재 구조는 ai-curator README와 repository 구현을 기준으로 한다.
> 이 글은 구축 **이전**에 작성한 초기 설계 방안이다.
> 아래 클래스 구조, 소스 목록, 저장 경로는 실제 구현에서 상당 부분 달라졌다.
> 현재 동작하는 구조는 [파이프라인 구축기 — 실제 구현](/blog/2026-04-25-ai-curator-파이프라인-구축기-—-실제-구현)을 참고할 것.

## 1. 시스템 개요

별도의 백엔드 서버나 동적 데이터베이스 없이 동작하는 완전 자동화 큐레이션 파이프라인입니다. 정보 수집부터 AI 요약, 웹사이트 배포까지의 전 과정이 단일 리포지토리 내에서 처리되는 서버리스(Serverless) 및 정적 사이트 생성(SSG) 기반 아키텍처를 채택했습니다.
별도의 백엔드 서버나 동적 데이터베이스 없이 동작하는 완전 자동화 큐레이션 파이프라인이다. 정보 수집부터 AI 요약, 웹사이트 배포까지의 전 과정이 단일 리포지토리 내에서 처리되는 서버리스(Serverless) 및 정적 사이트 생성(SSG) 기반 아키텍처를 채택했다.

### 주요 설계 원칙

- **비용 통제:** 클라이언트(브라우저) 사이드에서의 API 호출을 원천 배제하여 악의적인 트래픽 공격에 따른 비용 과금을 방어합니다.
- **유지보수 효율화:** 프론트엔드 코드와 데이터 파이프라인(Python 스크립트)을 단일 저장소에서 관리하되, 모듈을 명확히 분리합니다.
- **정적 데이터 관리:** RDBMS 대신 마크다운(`.md`) 파일과 Git 커밋 히스토리를 시계열 데이터베이스처럼 활용합니다.
- **비용 통제:** 클라이언트(브라우저) 사이드에서의 API 호출을 원천 배제하여 악의적인 트래픽 공격에 따른 비용 과금을 방어한다.
- **유지보수 효율화:** 프론트엔드 코드와 데이터 파이프라인(Python 스크립트)을 단일 저장소에서 관리하되, 모듈을 명확히 분리한다.
- **정적 데이터 관리:** RDBMS 대신 마크다운(`.md`) 파일과 Git 커밋 히스토리를 시계열 데이터베이스처럼 활용한다.

---

## 2. 시스템 아키텍처 및 워크플로우

전체 시스템은 크게 데이터 수집 및 가공을 담당하는 **파이프라인 모듈(Python)**과 정적 렌더링을 담당하는 **프론트엔드 모듈(Astro)**로 분리되어 동작합니다.
전체 시스템은 크게 데이터 수집 및 가공을 담당하는 **파이프라인 모듈**(Python)과 정적 렌더링을 담당하는 **프론트엔드 모듈**(Astro)로 분리되어 동작한다.

### 2.1. 컴포넌트 아키텍처 (Component Architecture)

시스템을 구성하는 주요 모듈 간의 논리적 의존성 및 데이터 흐름입니다.
시스템을 구성하는 주요 모듈 간의 논리적 의존성 및 데이터 흐름이다.

```mermaid
graph TD
subgraph CI["GitHub Actions (CI/CD Environment)"]
Cron([Schedule Trigger])
Runner[Ubuntu Runner]
end

subgraph Pipeline["Data Pipeline (Python)"]
Fetcher["Fetcher Module<br/>(RSS/API Parser)"]
Processor["Processor Module<br/>(Prompt & LLM)"]
Formatter["Formatter Module<br/>(Markdown Generator)"]
end

subgraph External["External Services & APIs"]
Sources[("Data Sources<br/>(ArXiv, ROS2 Discourse, Hacker News)")]
Gemini{"Gemini API"}
end

subgraph Frontend["Astro Frontend (SSG)"]
Collection[("Content Collections<br/>(src/content/curation/)")]
Builder["Astro Build Engine"]
Pages(["Static HTML Pages"])
end

%% Flow
Cron --> Runner
Expand All @@ -75,7 +73,7 @@ graph TD

### 2.2. 아키텍처 워크플로우 (Sequence Diagram)

파이프라인이 실행되는 하루 주기의 데이터 흐름 명세입니다.
파이프라인이 실행되는 하루 주기의 데이터 흐름 명세다.

```mermaid
sequenceDiagram
Expand All @@ -89,37 +87,31 @@ sequenceDiagram
Cron->>Fetcher: 지정된 시간에 파이프라인 실행
activate Fetcher

rect rgb(30, 30, 30)
Note over Fetcher, LLM: 1. 데이터 수집 및 가공
Fetcher->>Fetcher: 타겟 소스(RSS, API) 스크래핑
Fetcher->>LLM: 텍스트 데이터 및 프롬프트 전송
activate LLM
LLM-->>Fetcher: 요약 및 인사이트 데이터 반환
deactivate LLM
end

rect rgb(40, 40, 40)
Note over Fetcher, Repo: 2. 데이터 저장
Fetcher->>Repo: Frontmatter 포함 YYYY-MM-DD.md 생성
Fetcher->>Repo: src/content/curation/ 경로에 Commit & Push
end
deactivate Fetcher

rect rgb(30, 30, 30)
Note over Repo, Astro: 3. 빌드 및 배포
Repo->>Astro: Commit 발생 시 배포 Action 트리거
activate Astro
Astro->>Astro: SSG 빌드 (Markdown -> HTML)
Astro-->>Repo: gh-pages 브랜치로 배포 완료
deactivate Astro
end
```

---

## 3. 파이프라인 모듈 설계 (Class Diagram)

Python 기반의 데이터 수집기(`scripts/`) 내부의 객체 지향적 구조와 역할 명세입니다. 외부 소스 확장을 고려하여 인터페이스를 분리했습니다.
Python 기반의 데이터 수집기(`scripts/`) 내부의 객체 지향적 구조와 역할 명세다. 외부 소스 확장을 고려하여 인터페이스를 분리했다.

```mermaid
classDiagram
Expand Down Expand Up @@ -173,11 +165,11 @@ classDiagram

### 모듈별 책임 (Responsibility)

- **`PipelineController`**: 배치 작업의 전체 생명주기 관리. 설정된 소스 목록을 순회하며 프로세스를 순차 제어합니다.
- **`DataSource` (인터페이스/구현체)**: 외부 데이터를 읽어와 시스템 내부 규격인 `Article` 객체로 정규화합니다.
- **`PipelineController`**: 배치 작업의 전체 생명주기 관리. 설정된 소스 목록을 순회하며 프로세스를 순차 제어한다.
- **`DataSource` (인터페이스/구현체)**: 외부 데이터를 읽어와 시스템 내부 규격인 `Article` 객체로 정규화한다.
- **`Article`**: 데이터 전송 객체(DTO).
- **`LLMClient`**: 정규화된 리스트를 바탕으로 프롬프트를 구성하고 Gemini API와 통신하여 텍스트를 반환합니다.
- **`MarkdownBuilder`**: LLM 응답과 메타데이터를 결합하여 Astro 프레임워크 규격에 맞는 마크다운 파일을 시스템에 기록합니다.
- **`LLMClient`**: 정규화된 리스트를 바탕으로 프롬프트를 구성하고 Gemini API와 통신하여 텍스트를 반환한다.
- **`MarkdownBuilder`**: LLM 응답과 메타데이터를 결합하여 Astro 프레임워크 규격에 맞는 마크다운 파일을 시스템에 기록한다.

---

Expand Down Expand Up @@ -211,4 +203,4 @@ sources: ['ArXiv', 'ROS Discourse']

- **렌더링 방식:** 정적 사이트 생성(SSG).
- **데이터 연동:** Astro의 Content Collections API를 사용하여 빌드 타임에 마크다운을 HTML로 변환.
- **호스팅:** 빌드된 정적 에셋은 GitHub Pages(`gh-pages` 브랜치)를 통해 무료 서빙.
- **호스팅:** 빌드된 정적 에셋은 GitHub Pages(`gh-pages` 브랜치)를 통해 무료 서빙한다.
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ project: ai-curator
kind: implementation
tags:
- ai-curator
description: 'GitHub Actions와 Gemini API를 활용해 기술 뉴스를 자동 수집·요약하고 Astro 정적 사이트로 배포하는 과정을 정리합니다.'
- github-actions
- astro
description: GitHub Actions와 Gemini API를 활용해 기술 뉴스를 자동 수집·요약하고 Astro 정적 사이트로 배포하는 과정을 정리했다.
series: 'ai-curator-pipeline'
seriesOrder: 2
draft: false
---

> 이 글은 2026-04-23에 작성한 설계 방안 포스트의 실제 구현 버전입니다.
> 이 글은 [파이프라인 구축 방안](/blog/2026-04-23-ai-curator-파이프라인-구축-방안)의 실제 구현 버전이다.
> 설계 단계와 달라진 부분을 포함해 현재 작동 중인 상태를 기록합니다.

## 결과물
Expand Down
Loading