iOS. Demystify SwiftUI (3) - WWDC21

Dependencies: SwiftUI는 무엇이 바뀌었는지 어떻게 알까? 앞선 글에서는 SwiftUI가 View를 구분하는 방식인 Identity와, Identity가 유지되는 기간인 Lifetime을 정리했다. 이번에는 SwiftUI가 View를 업데이트하는 기준인 Dependencies를 살펴본다. 먼저 결론부터 말하면 SwiftUI의 업데이트 과정은 다음과 같다. Dependency 변경 ↓ 관련된 View 무효화 ↓ body 재평가 ↓ 새로운 View Value와 이전 Value 비교 ↓ 실제로 변경된 화면만 업데이트 Identity는 같은 View인지 판단하고, Lifetime은 상태를 유지하며, Dependency는 어떤 View를 다시 계산해야 하는지 결정한다. 이 세 가지를 함께 이해하면 단순히 API 사용법을 외우는 것보다 SwiftUI의 동작을 더 잘 예측할 수 있다. ...

July 22, 2026

TIL. Jul 21, 2026

키워드 Codeforces 가입 로컬 LLM opencode에 연결하고 ACP로 Xcode에 연동하기 SwiftUI WWDC 세션, 특히 View Value와 View Identity 내용 PS 풀기, Codeforces 가입 LeetCode에서만 문제를 푸는게 조금 시야가 좁아지나 싶어서, Codeforces에 가입했다. Swift 지원이 없지만, PS 문제를 풀 때 특정 언어에 종속되지 않으려고 꾸준히 Swift, Python, C++를 돌아가면서 풀고 있으니 큰 문제는 없다. 가장 풀이 수가 많은 문제 하나를 풀었다. 매일 LeetCode 오늘의 문제를 푸는 것이 루틴 중 하나인데, Codeforces, 삼성 SW Expert Academy 등 온라인 저지 사이트 여럿 돌아다니면서 풀어보려 한다. BOJ가 사라진 이후로 LeetCode 의존이 꽤 심해졌는데, 다양하게 풀어봐야겠다. ...

July 21, 2026

SwiftUI. Demystify SwiftUI (2) - WWDC21

Lifetime 1편에서는 SwiftUI가 View를 구분하는 방식인 Identity를 정리했다. 이번에는 Identity가 유지되는 시간인 Lifetime과, 그 안에서 State가 어떻게 보존되는지 살펴본다. View Value는 계속 새로 만들어질 수 있지만, Identity가 유지되는 동안에는 같은 View의 Lifetime 안에 있다고 볼 수 있다. 그리고 State와 StateObject는 이 Lifetime에 연결되어 있기 때문에 Identity가 바뀌면 함께 교체된다. 고양이가 하루 동안 이곳저곳 움직이더라도 우리는 계속 같은 고양이라고 생각한다. 이처럼 Identity는 시간에 따라 달라지는 여러 값을 하나의 안정적인 존재로 연결한다. 시간의 흐름 속에서 연속성을 만들어 주는 셈이다. ...

July 21, 2026

DevOps. 로컬 LLM 모델 설치하고 UI 붙여보기

Codex는 iOS 개발할 때만 사용하고, 다른 작업은 주로 무료 모델로 처리했다. dev-data-server-light를 개발할 때는 Cursor를 사용했는데, 개발 도중 사용량이 모두 소진돼 Antigravity로 옮겨야 했다. 그래서 로컬에서 직접 실행하는 LLM 환경을 찾았고, 생각보다는 쉽게 환경을 구축할 수 있었다., 맥미니에서 만족스럽게 사용하고 있다. 이번 글에서는 맥북 에어에도 같은 환경을 설치한 과정을 정리한다. 맥북 에어 사양 설치 ollama 설치하고 서버 켜기 맥에서는 Homebrew로 쉽게 설치할 수 있다. brew install ollama 설치가 끝났으면 Ollama 서버를 켜야 한다. Ollama는 단순히 실행하는 앱이 아니라, 서버 형태로 동작한다. ...

July 21, 2026

LeetCode 3499. Maximize Active Section With Trade I

문제 https://leetcode.com/problems/maximize-active-section-with-trade-i 풀이 '0'와 '1'로만 이루어진 문자열 s가 존재하고, 문제에서 주어진 연산을 최대 1번 적용하여 문자열에 있는 '1'의 개수를 최대로 만든 뒤 그 개수를 리턴하면 된다. 주어진 연산은 다음과 같다. (순서대로 둘 다 적용해야 한다.) 양 옆이 '0'로 둘러싸인 연속된 '1' 블록 하나를 선택해서 모두 '0'로 바꾼다. 양 옆이 '1'으로 둘러싸인 연속된 '0' 블록 하나를 선택해서 모두 '1'으로 바꾼다. 문제에서 s의 양 옆에 '1'을 붙이라 했는데, 이때 추가된 '1'은 최종 반환값에 포함되지 않는다. ...

July 21, 2026

Codeforces 1A. Theatre Square

문제 https://codeforces.com/problemset/problem/1/A 풀이 Codeforces에서 푼 첫 문제. $n \times m$ 크기의 직사각형 도시가 있고, 그 도시를 $a \times a$ 크기의 타일로 뒤덮는 문제이다. 타일은 도시 경계를 넘어가도 되지만, 잘라선 안되고 겹쳐도 안된다. 즉, 필요한 타일의 개수는 가로/세로 각각을 $a$로 나눈 값을 올림하여 곱하면 된다. 문제에 간단한 함정이 하나 있는데, n, m, a의 범위가 최대 $10^9$이라 곱셈 결과가 int 범위를 넘어갈 수 있으므로 long long을 사용을 사용해야 한다. 코드 #include <iostream> #include <cmath> int main() { long long n, m, a; std::cin >> n >> m >> a; std::cout << ((n + a - 1) / a) * ((m + a - 1) / a) << std::endl; return 0; }

July 21, 2026

TIL. Jul 20, 2026

키워드 단조 스택 Hugo Flat Post -> Page Bundle 블로그 스크립트는 어떤 언어로? Xcode 프로젝트명 바꾸기 SwiftUI Identity 내용 LeetCode 1081, Substring, Subsequence, Monotonic Stack LeetCode 1081 PS 문제를 풀면서, 처음에 Medium 문제인데 좀 해맸다, LCS 두 개를 하면서 Substring이랑 Subsequence 차이를 분명히 알았는데, Substring으로 생각하고 풀어서 스택을 써야 할 곳에 투 포인터를 썼다. 단조 스택(Monotonic Stack) 문제인데, 사실 이런 스택이 있는지 오늘 처음 알았다. 그냥 스택은 스택으로 생각했으니까, 마치 Binary Search와 Parametric Search같은 느낌인가. ...

July 20, 2026

SwiftUI. Demystify SwiftUI (1) - WWDC21

i시작하기 전에 Identity는 화면에 띄워지는 UI 요소들이 같은 요소인지, 다른 요소인지 구분하는 방식이다. 이 WWDC 세션에서 가장 중요한건, View 프로토콜을 채택하여 작성하는 View Structure가 실제 화면에 보이는 요소가 아니라 그냥 그 요소의 설계도일 뿐이라는 것이다. (UIKit과 많이 다르다) Swift에서 ‘Value Type은 Immutablity를 가진다.’ 이라는 말이 가장 크게 체감되는 부분이기도 한데, SwiftUI에서 코드로 작성한 View도 Value Type이고 당연히 Immutable하다. 따라서 한 번 생성된 값은 변하지 않아야 한다. 만약 내부의 값이 변해야 하면 UIKit의 View Controller 처럼 은근슬쩍 내부 프로퍼티만 바꾸지 않고, Value 전체를 새로 만든다. ...

July 20, 2026

LeetCode 1260. Shift 2D Grid

문제 https://leetcode.com/problems/shift-2d-grid 풀이 $m \times n$ 2d 그리드에 있는 원소들을 오른쪽으로 k번 민 결과를 리턴하면 된다. grid[row][n - 1] → grid[row + 1][0] : 마지막 열의 원소는 다음 행의 첫 번째 열로 이동 grid[m - 1][n - 1] → grid[0][0] : 마지막 행의 마지막 열 원소는 첫 번째 행의 첫 번째 열로 이동 k번 직접 반복하는 대신, 그리드를 1차원으로 평탄화하면 shift 연산이 단순한 배열 회전으로 바뀐다. 평탄화한 배열을 오른쪽으로 k칸 회전시킨 뒤, 다시 $m \times n$ 2차원 배열로 복원하면 된다. 단, k가 배열 길이 $m \times n$ 보다 클 수 있으므로 모듈러 연산으로 정규화한다. ...

July 20, 2026

LeetCode 1081. Smallest Subsequence of Distinct Characters

문제 https://leetcode.com/problems/smallest-subsequence-of-distinct-characters 풀이 문자열 s에 있는 모든 개별 문자를 정확히 한 번씩 포함하는 부분수열 중, 사전순으로 가장 작은 것을 리턴하면 된다. 처음에 투 포인터를 생각했는데, 원소가 굳이 쭉 이어질 필요가 없으니 스택을 활용했다. 처음에 전처리로 각 문자의 마지막 등장 인덱스를 구해둔다. 스택 top의 마지막 인덱스가 현재 인덱스보다 크면 뒤에 또 나온다는 뜻이므로 제거할 수 있다. 스택에 문자를 추가하기 전, 아래 세 조건을 모두 만족할 때 top을 pop하면 된다. 스택이 비어있지 않다 스택 top이 현재 문자보다 크다 (사전순으로 뒤에 있다) 스택 top 문자가 뒤에 또 등장한다 (lastIndice[stack[-1]] > idx) 코드 class Solution: def smallestSubsequence(self, s: str) -> str: stack = [] lastIndice = {} for idx, c in enumerate(s): lastIndice[c] = idx for idx, c in enumerate(s): if c in stack: continue while stack and c < stack[-1] and lastIndice[stack[-1]] > idx: stack.pop() stack.append(c) return "".join(stack)

July 20, 2026