devbox-light-server (7). Dockerizing, MVP 마무리

도커라이징 영속성까지 추가했으므로 이제 서버를 하나의 실행 단위로 묶을 차례다. 지금까지는 로컬에서 Node.js를 설치하고, 의존성을 설치하고, TypeScript를 빌드한 다음 서버를 실행했다. 혼자 개발할 때는 큰 문제가 없지만, 이 서버를 다른 환경에서 실행하려면 매번 같은 준비 과정을 반복해야 한다. 도커라이징은 이 과정을 이미지 안에 고정하는 작업이다. 이 프로젝트에서는 Express 서버를 빌드하고, 실행에 필요한 파일만 담은 뒤, .data 디렉터리를 기준으로 데이터를 유지할 수 있도록 구성했다. Dockerfile 작성하기 Dockerfile은 두 단계로 나눴다. FROM node:24-alpine AS build WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY tsconfig.json tsconfig.build.json ./ COPY src ./src RUN npm run build 첫 번째 build 단계에서는 개발 의존성을 포함해서 설치하고 TypeScript를 빌드한다. npm run build를 실행하면 dist 디렉터리가 만들어진다. ...

August 10, 2026

devbox-light-server (6). Json 영속성

MVP의 마지막 기능으로 서버를 재시작해도 데이터가 사라지지 않도록 영속성을 추가했다. 이번 포스트에서는 devbox-light-server에 DB, Storage, Token Storage에서 영속성을 가진 저장 방식을 구현해서 in-memory 대신 사용할 수 있도록 만든다. 프로토타입이었던 dev-data-server에서는 시작부터 SQL 의존성을 가지고 시작했지만, devbox-light-server는 아주 얇은 in-memory 구현만 가지고 있다. MVP 마지막에 영속성을 넣는 이유는 서버를 구현할 때, 특정 구현에 휘둘리지 않기 위해서다. dev-data-server에서 SQL을 빠르게 들여와서, 결국 프로젝트가 SQL 래퍼가 된 느낌이 있다. 당연히 Service 레이어는 Repository의 인터페이스에만 의존하므로 어떤 방법을 쓰든 단순히 구현체만 갈아 끼우고, 의존성 생성, 연결 부분을 제외하고는 어떠한 코드에도 변화가 없어야 한다. ...

August 10, 2026

DevOps. AI 코딩 에이전트 구조적으로 설계하기

AI 에이전트에게 프로젝트를 설명하기 예전에는 LLM을 이용해 코드를 작성하려면 필요한 기능을 설명하고, 프로젝트의 구조나 현재 상황을 프롬프트로 설명해야 했다. 즉, 프로젝트와 LLM의 API가 사람이었다… 반면 Codex나 Claude Code 같은 코딩 에이전트는 프로젝트의 파일을 직접 탐색하고 기존 코드를 분석하면서 작업에 필요한 컨텍스트를 스스로 수집한다. 하지만 코드만으로 프로젝트의 모든 것을 알 수 있는 것은 아니다. 프로젝트의 규모가 작거나 코드에 충분한 단서가 없다면 의도를 추론하기 어렵고, 반대로 규모가 커질수록 필요한 정보를 찾기 위해 더 많은 코드를 탐색하고 컨텍스트로 사용해야 한다. ...

August 10, 2026

DevOps. 로컬 LLM을 VSCode와 Xcode에서 코딩 에이전트로 사용하기

로컬 LLM 모델을 설치하고 이어서 로컬 LLM 모델을 Xcode와 VSCode에 연동해보자. 우선 VSCode에 연결해보고 다음엔 Xcode의 ‘Chat’ 기능, 최종적으론 OpenCode와 Xcode를 ACP로 연동해서 로컬 LLM을 코딩 에이전트로 이용하려 한다. VSCode 연결 Ollama 익스텐션 설치 및 모델 연동 Ollama에서 공식적으로 VSCode 익스텐션을 제공한다. 단순히 설치만 하면된다. 로컬 LLM을 VS Code에서 사용하려면, 빌트인 되어있는 Copilot Chat 기능을 이용해야 한다. Copilot Chat의 UI와 코드 컨텍스트 수집 기능을 사용하고, 실제 응답을 생성하는 언어 모델은 Ollama에서 실행 중인 로컬 모델을 사용할 것이다. ...

August 9, 2026

devbox-light-server (5). Auth

Auth 설계하기 개발용 목서버에서 실제 서비스 수준의 인증 시스템을 구현하지 않고도, 클라이언트에서 사용하는 로그인과 인증 흐름을 테스트할 수 있도록 Auth 기능을 추가했다. 로그인 요청을 보낸다. access token을 발급받는다. Authorization 헤더에 token을 실어 요청한다. 현재 로그인된 유저를 확인한다. 로그아웃으로 token을 무효화한다. JWT, 비밀번호, OAuth, Refresh Token, 보안 같은 기능은 의도적으로 제외했다. 프로덕션 인증 로직을 구현하려는 글이 아니라, 개발용 Mock 서버에서 클라이언트의 로그인, 인증, 로그아웃 흐름을 확인하는 것이 목적이기 때문이다. 최소한의 Auth 구조 첫 단계에서는 DatabaseService를 그대로 사용했다. users 컬렉션을 만들어서 그 레코드 ID를 유저 ID로 사용해 로그인할 수 있도록 했다. ...

August 8, 2026

StackDay. 0. Concept

시작하기 애플 리마인더나 마이크로소프트 To do를 쓰면 매일 해야하는 일들을 관리할 수 있다. 나도 매일 LeetCode Daily를 풀고, Bing 출석체크를 하고, 매일 TIL 을 적으려고 한다. 하지만 기본적으로 Reminder, Todo 앱과 습관 형성 앱은 차이가 있다. 첫 번째로 기능 요구사항이 다르다. 애플 리마인더는 매일 반복해야 하는 태스크를 하지 않았을 경우에, 날짜가 새로 갱신되지 않고, 그 날짜에 계속 남아있는다. 마이크로소프트 To do는 하루를 빠뜨리면 그 태스크가 사라지지 않고 누적된다. 내가 원하는 습관 형성 앱은 리마인더의 방식, 마이크로소프트 투 두의 방식 등등을 포괄할 수 있는 앱이었다. ...

August 8, 2026

Swift Concurrency. Meet async/await in Swift (2) - WWDC21

1편에서는 async await를 어떻게 사용했는지 알아봤다면, 여기서는 테스트와 실제 앱 코드에서 async/await를 사용하는 법을 알아본다. 또한 기존에 존재하는 completion handler 기반 API를 continuation을 사용하여, async/await를 사용하는 async alternative로 변환하는 방법을 알아본다. 비동기 코드 테스트하기 async/await를 쓰면 비동기 코드도 동기 코드만큼 쉽게 테스트할 수 있다. XCTest는 async 테스트를 지원한다. 아래는 completion handler 방식의 비동기 코드를 테스트하는 코드이다. class MockViewModelSpec: XCTestCase { func testFetchThumbnails() throws { let expectation = XCTestExpectation(description: "mock thumbnails completion") self.mockViewModel.fetchThumbnail(for: mockID) { result, error in XCTAssertNil(error) expectation.fulfill() } wait(for: [expectation], timeout: 5.0) } } ifulfill fulfill()은 expectation을 충족된 상태로 표시하는 메소드다. 일반적으로 비동기 작업이 완료되었을 때 호출한다. 기존에는 XCTestExpectation을 만들고, API를 호출한 뒤 expectation을 fulfill 하고, 지정한 시간 동안 기다리도록 작성해야 했다. ...

August 3, 2026

Swift Concurrency. Meet async/await in Swift (1) - WWDC21

completion handler로 작성한 비동기 코드는 쉽게 장황해지고, 복잡해지고, 부정확해진다. Swift의 async/await는 비동기 코드를 일반 코드를 작성하는 것처럼 만들어 주고, 아이디어를 더 쉽게 반영하며, 더 안전하게 만든다. async/await는 단순한 비동기 표현 방식이 아니다. 이 세션에서는 async/await가 왜 기존 completion handler 방식보다 좋은지, 그리고 Swift의 컨셉에 왜 잘 맞는지를 계속해서 설명한다. Meet async/await in Swift Foundation 같은 Apple SDK에는 await할 수 있는 수백 개의 메소드가 존재한다. UIKit의 UIImage는 섬네일을 만드는 API를 동기 방식과 비동기 방식으로 모두 제공한다. ...

August 3, 2026

SwiftUI. Essentials - WWDC24

SwiftUI는 선언형 UI 프레임워크다. Rich Feature Set, 다양한 기능과 기기 고유의 이점을 활용할 수 있는 풍부한 기능 집합 Less Code, 더 적은 코드 Incremental adoption, 필요한 순간에 적절하게 사용 가능. 전체 앱이 반드시 SwiftUI일 필요는 없다. SwiftUI Essentials SwiftUI는 선언형 UI 프레임워크이기 때문에 UIKit 처럼 UIView 객체가 계속 메모리에 상주해있고, 그 객체를 직접 변화시키는게 아니라, View를 보고 SwiftUI가 그리는 방식이다. 즉, View는 그냥 UI 요소를 정의하는 설계도이다. (Demistify SwiftUI 세션에서도 한 말이다!) ...

July 27, 2026

SwiftUI. Discover Observation in SwiftUI - WWDC23

SwiftUI의 Observation은 모델의 프로퍼티 변화를 추적하고, 그 변화에 맞춰 UI를 업데이트하는 기능이다. @Observable 매크로를 사용하면 별도의 ObservableObject, @Published, @ObservedObject 없이도 일반 Swift 타입에 가까운 형태로 관찰 가능한 모델을 만들 수 있다. 핵심은 간단하다. View가 읽은 프로퍼티가 바뀌면, 그 View가 다시 계산된다. 이 글에서는 Observation의 동작 방식, @State, @Environment, @Bindable을 언제 써야 하는지, 그리고 기존 ObservableObject 기반 코드를 @Observable로 옮기는 방법을 정리한다. Observation @Observable은 Swift 매크로다. 타입에 이 매크로를 붙이면 컴파일러가 해당 타입을 관찰할 수 있도록 코드를 확장한다. ...

July 24, 2026