노트북으로 홈서버 구축하기 - 직접 만든 컨테이너 대시보드 (Spring Boot + React + SSE) (12편)

왜 직접 만들었나 Portainer가 있는데 굳이 만든 이유는 단순하다. 그냥 만들어보고 싶었다. Portainer는 기능이 너무 많다. 나는 컨테이너 목록 확인, 시작/중지/재시작, 로그 보기 딱 세 가지만 필요했다. 이 정도면 직접 만들 수 있겠다 싶어서 Spring Boot 백엔드 + React 프론트엔드로 구성했다. 완성 화면 컨테이너 목록을 카드 UI로 표시 (상태별 색상 배지) Start / Stop / Restart 원클릭 제어 Logs 버튼으로 실시간 로그 스트리밍 (SSE) 5초 주기 자동 갱신 ...

April 3, 2026 · 5 min · 978 words · Chanyeol

Spring AI 프로젝트 마무리: 로컬 LLM 챗봇의 한계와 향후 발전 로드맵 (7편)

[Dev-Fortune] 시리즈 다시보기 1편: 기획부터 스택 선정까지 2편: 로컬 LLM Ollama 연동 3편: RAG와 Vector Store 구축 4편: 프롬프트 엔지니어링 실전 5편: 스트리밍 API 구현 6편: 전체 워크플로우 분석 1. 서론: 프로젝트를 마무리하며 시니컬한 개발자 챗봇 ‘Dev-Fortune’을 통해 Spring AI와 RAG의 가능성을 엿보았습니다. 마지막으로 이 프로젝트의 한계를 짚어보고 고도화 로드맵을 그려봅니다. 2. 미래 고도화 로드맵 (AS-IS vs TO-BE) 현재의 메모리 기반 구조에서 영구 저장소와 맥락 인지 능력을 갖춘 시스템으로의 진화 방향입니다. ...

March 23, 2026 · 1 min · 164 words · Chanyeol

Spring AI RAG 워크플로우 분석: 사용자 질문부터 AI 답변까지의 여정 (6편)

[Dev-Fortune] 시리즈 다시보기 1편: 기획부터 스택 선정까지 2편: 로컬 LLM Ollama 연동 3편: RAG와 Vector Store 구축 4편: 프롬프트 엔지니어링 실전 5편: 스트리밍 API 구현 1. 서론: 조각난 퍼즐을 하나로 합치기 데이터의 이동이 일어나는 찰나의 순간, 서버 내부에서 일어나는 유기적인 상호작용을 파헤쳐 보겠습니다. 2. 전체 워크플로우 시퀀스 (Deep-Dive) 사용자의 엔터 키 한 번이 답변으로 돌아오기까지의 7단계 여정입니다. sequenceDiagram autonumber User->>Controller: 고민 입력 (JSON) Controller->>Service: 사주 분석 요청 Service->>VectorStore: 고민 기반 유사도 검색 VectorStore-->>Service: 관련 사주 데이터 반환 Service->>AI: 프롬프트 조합 후 전달 (System+User) AI-->>Controller: 스트리밍 답변 생성 (Flux) Controller-->>User: SSE 응답 (실시간 텍스트) 3. 데이터 흐름의 5단계 요청 수신: JSON 고민 데이터 접수. 의미 검색: 사주 데이터 조각 탐색. 프롬프트 조합: 페르소나 + 지식 + 질문 결합. 추론 및 생성: AI의 인격이 투영된 답변 생성. 스트리밍 응답: 차가운 조언의 실시간 전달. 결국 데이터가 지능을 만들고, 프롬프트가 성격을 만듭니다. ...

March 22, 2026 · 1 min · 146 words · Chanyeol

Spring WebFlux와 SSE로 구현하는 AI 스트리밍 API: 실시간 대화 경험 (5편)

[Dev-Fortune] 시리즈 다시보기 1편: 기획부터 스택 선정까지 2편: 로컬 LLM Ollama 연동 3편: RAG와 Vector Store 구축 4편: 프롬프트 엔지니어링 실전 1. 서론: AI 답변, 왜 기다리게 하나요? 사용자 경험(UX)을 위해 한 글자씩 타이핑하듯 보여주는 스트리밍 방식은 필수적입니다. 우리 프로젝트는 WebFlux와 **SSE(Server-Sent Events)**를 활용했습니다. 2. 스트리밍 시퀀스 다이어그램 서버와 클라이언트 간의 끊임없는 데이터 흐름을 살펴보세요. sequenceDiagram participant U as User participant S as Spring Server (Flux) participant A as AI Model (Ollama) U->>S: POST /chat (Request) Note over S,A: Connection Stay Open A-->>S: "오늘의" (Token 1) S-->>U: data: "오늘의" A-->>S: " 사주는" (Token 2) S-->>U: data: " 사주는" Note right of U: 사용자는 실시간으로 글자가 보임 3. Flux와 SSE MediaType.TEXT_EVENT_STREAM_VALUE를 사용하여 AI가 단어(Token)를 생성할 때마다 즉시 클라이언트로 전송합니다. 비차단(Non-blocking) 방식인 WebFlux는 답변을 기다리는 동안 쓰레드를 점유하지 않아 성능적으로도 우수합니다. ...

March 21, 2026 · 1 min · 154 words · Chanyeol

프롬프트 엔지니어링 실전: AI에게 시니컬한 개발자 페르소나 주입하기 (4편)

[Dev-Fortune] 시리즈 다시보기 1편: 기획부터 스택 선정까지 2편: 로컬 LLM Ollama 연동 3편: RAG와 Vector Store 구축 1. 서론: AI의 ‘인격’은 어디서 오는가? 지식만 있는 AI는 백과사전일 뿐입니다. 우리가 원하는 “시니컬한 시니어 개발자” 인격을 형성하고 답변 형식을 강제하는 프롬프트 엔지니어링을 살펴보겠습니다. 2. 프롬프트 조합 구조 시스템 지침(Persona)과 검색된 데이터, 사용자의 질문이 하나로 섞이는 과정입니다. graph TD A[Persona: 실리콘밸리 개발자] + B[Rules: 반말/두문장] --> E[System Message] C[Retrieved Saju Data] + D[User Message] --> F[User Message with Context] E & F --> G((AI Model)) G --> H[Final Response] 3. 시스템 프롬프트(System Prompt) 설계 apiContext를 통해 페르소나를 정의하고, 건조하고 시니컬한 반말 말투를 강제합니다. 특히 출력 형식을 엄격하게 통제하여 UI 일관성을 유지합니다. ...

March 20, 2026 · 1 min · 171 words · Chanyeol

Spring AI RAG 구현하기: SimpleVectorStore로 전문 지식 데이터 주입 (3편)

[Dev-Fortune] 시리즈 다시보기 1편: 기획부터 스택 선정까지 2편: 로컬 LLM Ollama 연동 1. 서론: AI는 어떻게 사주를 ‘공부’하는가? AI에게 새로운 지식을 가르치는 방법 중 가장 경제적이고 정확한 RAG(Retrieval-Augmented Generation) 방식을 살펴봅니다. 질문이 들어올 때마다 관련 내용을 찾아서 읽어주며 답변하게 하는 원리입니다. 2. 데이터 주입 프로세스 (Data Ingestion) JSON 파일이 어떻게 벡터화되어 메모리에 저장되는지 그 흐름을 도식화했습니다. flowchart LR A[(sajuAPI.json)] --> B[DataLoader] B --> C[Text 정제: Key-Value형식] C --> D[Embedding Model] D --> E{SimpleVectorStore} E --> F[RAM Memory] style F fill:#f96,stroke:#333,stroke-width:2px 3. SimpleVectorStore와 DataLoader 우리 프로젝트는 별도의 DB 없이 메모리 기반의 SimpleVectorStore를 사용합니다. UnidocuDataLoader는 서버 기동 시점에 JSON 데이터를 읽어 벡터로 변환하여 주입합니다. ...

March 19, 2026 · 1 min · 149 words · Chanyeol

로컬 LLM Ollama와 Spring Boot 연동하기: 서버 설정과 성능 최적화 (2편)

[Dev-Fortune] 시리즈 다시보기 1편: 기획부터 스택 선정까지 1. 서론: 왜 유료 API 대신 로컬 LLM인가? 이번 2편에서는 본격적인 구현의 첫 단추인 AI 모델 환경 구축을 다룹니다. 우리는 비용 제로, 데이터 보안, 완전한 통제를 위해 Ollama를 활용한 로컬 LLM 방식을 선택했습니다. 2. 로컬 AI 서버 연동 구조 Spring Boot가 로컬에서 실행 중인 Ollama와 통신하는 물리적 구조입니다. graph LR subgraph "Local PC" A[Spring Boot App] -- "HTTP Post (11434)" --> B[Ollama Server] B -- "Model Load" --> C[qwen2.5:3b] subgraph "Application.properties" D[Base-URL] E[Temperature: 0.4] F[Model Name] end D -.-> A E -.-> A end 3. Spring Boot 프로젝트 설정: application.properties application.properties 파일에 담긴 설정값들을 하나씩 뜯어보며 그 의미를 파헤쳐 보겠습니다. ...

March 18, 2026 · 1 min · 167 words · Chanyeol

Spring Boot 예외 처리 통일하기 — @ControllerAdvice와 @ExceptionHandler

1. 서론: 왜 예외 처리를 통일해야 하는가? API를 개발하다 보면 다양한 예외 상황이 발생합니다. 데이터가 없는 경우, 입력값이 잘못된 경우, 서버 내부 로직 오류 등이 대표적입니다. 이때 각 컨트롤러에서 try-catch로 예외를 개별 처리하면 다음과 같은 문제가 발생합니다. 코드 중복: 비슷한 예외 처리 로직이 여러 컨트롤러에 반복됩니다. 응답 일관성 부족: 어떤 API는 JSON으로 에러를 주는데, 어떤 API는 HTML 에러 페이지를 주는 등 응답 형식이 제각각이 됩니다. 비즈니스 로직 집중도 저하: 예외 처리 코드가 섞여 있어 핵심 로직을 파악하기 힘듭니다. Spring은 이를 우아하게 해결할 수 있도록 @ControllerAdvice와 @ExceptionHandler를 제공합니다. ...

March 17, 2026 · 2 min · 401 words · Chanyeol

Spring AI와 Ollama로 만드는 AI 개발자 사주 챗봇: 기획부터 스택 선정까지 (1편)

1. 프롤로그: 왜 ‘AI 개발자’ 사주인가? 전통적인 사주 풀이는 어렵고 따분합니다. “올해는 물의 기운이 강하니…” 같은 말은 현대의 개발자들에게는 다소 와닿지 않죠. 하지만 만약 **“실리콘밸리 출신의 천재 개발자”**가 당신의 인생을 코드로 보고 ‘디버깅’해준다면 어떨까요? 이 프로젝트는 바로 그 엉뚱한 상상에서 시작되었습니다. 감정 섞인 위로 대신, 건조하고 시니컬한 말투로 당신의 사주를 “안티 패턴"과 “배드 해빗(Bad Habit)“으로 분석해 주는 챗봇, **‘Dev-Fortune’**입니다. 2. 프로젝트 시스템 구조도 전체적인 데이터 흐름과 기술 스택을 한눈에 살펴보겠습니다. ...

March 17, 2026 · 1 min · 192 words · Chanyeol

Prometheus와 Grafana를 활용한 서버 메트릭 모니터링 구축하기: 안정적인 서비스를 위한 시각화 전략

1. 서론: 왜 단순 로그만으로는 부족한가? 시스템을 운영하다 보면 에러 로그만으로는 원인을 파악하기 힘든 상황에 직면합니다. “갑자기 왜 느려졌지?”, “메모리가 부족한 건 아닐까?”, “현재 동시 접속자 수는 얼마인가?“와 같은 질문에 답하기 위해 필요한 것이 바로 메트릭(Metric) 모니터링입니다. 로그가 **사건(Event)**에 대한 기록이라면, 메트릭은 **상태(State)**에 대한 수치적 기록입니다. 이번 포스트에서는 수치 데이터를 수집하는 Prometheus와 이를 대시보드로 시각화하는 Grafana의 조합을 통해 서비스의 생애 주기를 추적하는 방법을 상세히 알아보겠습니다. 2. 모니터링 스택의 작동 원리 전형적인 모니터링 스택은 Pull 방식을 기반으로 합니다. ...

March 6, 2026 · 2 min · 379 words · Chanyeol
1