SwiftUI 데이터 흐름 정복: @StateObject부터 @EnvironmentObject까지 (Prop Drilling 해결법)
·
Notes/Swift
SwiftUI로 앱을 개발하다 보면 가장 먼저 마주치는 고민이 바로 "뷰(View) 간의 데이터 전달"이다. 처음에는 단순하게 부모에서 자식으로 넘겨주면 되지만, 뷰의 계층이 깊어질수록(A -> B -> C) 고민은 깊어진다. 오늘은 CalendarViewModel을 예시로, 올바른 데이터 주입 방식과 깊은 계층 구조에서의 해결책을 정리해 본다.1. 가장 흔한 실수: 뷰 모델의 중복 생성보통 처음에는 뷰마다 뷰 모델이 필요하니 아래와 같이 작성하기 쉽다.// ❌ 잘못된 방법struct HomeView: View { // 여기서 또 초기화(... = CalendarViewModel())를 하면 안 된다! @ObservedObject var calendarViewModel = CalendarVie..
<optgroup>으로 select 옵션 그룹화하기
·
Notes/HTML+CSS
태그select options들이 너무 많아서 검색할 수 있는 select 라이브러리를 찾던 중 options들을 optgroup 태그를 통해 options들을 그룹핑 할 수 있다는 걸 알았다. 사실 이번에 처음 안 사실이라 창피하지만 다음에도 사용하려고 글을 쓴다.설명는 HTML의 드롭다운 메뉴에서 옵션들을 그룹화할 때 사용하는 태그다.특징 요소들을 논리적으로 묶어서 구조화할 수 있다.기본 문법 옵션1 옵션2 주요 속성label (필수): 그룹의 제목을 지정한다disabled: 해당 그룹의 모든 옵션을 비활성화한다유의사항는 안에서만 사용 가능하다 안에 또 다른 를 중첩할 수 없다
iOS 개발: 실기기 CoreData 데이터를 시뮬레이터에서 사용하는 방법
·
Project/Swift
문제 상황아이패드 지원을 준비하고 앱스토어용 스크린샷을 촬영하면서 불편한 점을 발견했다. 앱 내 캘린더에 많은 기록들이 있는데 아직 기기간 동기화를 구현하지 않아서 이미 사용 중인 iPhone의 데이터를 iPad 시뮬레이터에 매번 수동으로 입력해야 하는 번거로움이 있었다.해결 방법: JSON을 활용한 CoreData ExportCoreData를 직접 export/import할 수는 없지만, JSON 형태로 변환하여 시뮬레이터 환경에서는 CoreData 대신 JSON을 사용하는 방향으로 문제를 해결했다.1단계: CoreData를 JSON으로 Export먼저 실기기에서 CoreData의 모든 데이터를 JSON 형태로 변환하는 함수를 작성했다:import CoreDatafunc exportCoreDataToJ..
PHP에서 부동소수점(Floating Point) 문제와 안전한 진행률 계산
·
Notes/Etc
문제 상황학생이 모든 수업을 완료했는데 진행률이 99%로 표시되는 이슈를 전달받았었다. 실제 데이터는 73/73였지만 계산값은 99로 99%로 표시되었다. 찾아본 결과 부동소수점이 원인이라는 것을 발견했다.부동소수점 문제란?컴퓨터는 실수를 2진수로 표현하기 때문에 미세한 오차가 발생한다.var_dump(0.1 + 0.2); // float(0.30000000000000004)원래 코드에서 오차가 발생하는 원인들나눗셈 연산 (/) - 73 / 73 = 1.0이어야 하지만 컴퓨터 내부에서는 0.9999999999999999 같은 값이 될 수 있음곱셈 연산 (* 100) - 이미 오차가 있는 값에 100을 곱하면 오차도 함께 증폭됨 (0.9999999999999999 * 100 = 99.999999999999..
멀티 테넌트 (Multi-Tenant) 탐구
·
Notes/Etc
현재 LMS를 유지보수하면서 흥미로운 구조를 발견했다. 여러 학교와 교육기관들이 동일한 서버에서 같은 프론트엔드 코드베이스를 공유하고 있는 방식이었다. 각 기관은 독립적인 교육 환경을 운영하지만 실제로는 하나의 시스템을 함께 사용하고 있었다. 이런 구조에 대한 정확한 용어가 무엇인지 궁금해서 찾아보다가 '멀티 테넌트 아키텍처'라는 개념을 알게 되었다.멀티 테넌트 아키텍처란?멀티 테넌트 아키텍처(Multi-Tenant Architecture) 또는 멀티 테넌시(Multi-Tenancy)는 하나의 소프트웨어 인스턴스가 여러 고객(테넌트, Tenant)을 동시에 서비스하는 구조다. A대학, B고등학교, C학원이 각각 독립적인 교육 시스템을 가진 것처럼 보이지만 실제로는 동일한 코드베이스와 인프라를 공유하는 방..
Admob 광고 안뜸 "No ad to show" - 에러 해결 방법 - IDFA 테스트 기기 등록으로 광고 표시 문제 해결하기
·
Project
문제 상황앱을 출시하고 3개월 정도가 지난 시점에서 애드몹 광고가 표시되지 않는 문제를 발견했다. 테스트 광고는 정상적으로 작동했지만 실제 광고 ID로 테스트해보니 다음과 같은 에러가 발생했다:Error Domain=com.google.admob Code=1 "Request Error: No ad to show." 며칠간 기다려봤지만 상황이 개선되지 않았다. AdMob 콘솔에서는 Request가 정상적으로 기록되고 있었지만 Impression은 계속 0을 유지하는 상태였다.초기 접근처음에는 단순히 "보여줄 광고가 없다"는 메시지 그대로 받아들여서 미디에이션을 추가해야 하나 고민했다. 하지만 현재 트래픽도 그리 많지 않은 상황에서 이런 현상이 며칠째 지속되는 게 이상했다. 레딧 글들과 다른 개발자 블로그들..
Git 실수로 다른 브랜치에 커밋했을 때 커밋을 새 브랜치로 옮기는 방법
·
Notes/Etc
작업 도중 브랜치를 잘못 선택한 채 커밋을 하는 실수를 하는 경우가 있다. develop 브랜치에서 새 브랜치를 만들어 작업해야 했는데 실수로 branch-a 브랜치에서 커밋을 했을 때의 해결 방법이다.상황 예시branch-a는 기존 작업이 있던 브랜치develop은 새로운 작업을 시작하려던 기준 브랜치실수로 branch-a에서 커밋을 진행함아직 git push는 하지 않은 상태목표현재 커밋을 develop 기반의 새 브랜치로 이동branch-a는 커밋 전 상태로 복원단계별 절차1. 최근 커밋 해시 확인git log --oneline가장 위에 있는 커밋 해시 값을 복사한다.예: abc12342. develop에서 새 브랜치 생성git checkout developgit checkout -b new-fea..
Astro SSG 블로그를 위한 마크다운 생성 유틸리티 개발기
·
Project/Astro(SSG)
최근에 Astro로 SSG(Static Site Generator) 블로그를 구축했다. 정적 사이트이다 보니 컨텐츠는 마크다운 파일로 관리하고 있는데 매번 새 글을 작성할 때마다 파일을 만들고 frontmatter를 작성하는 과정이 번거로웠다. 이런 불편함을 해소하기 위해 간단한 유틸리티 함수를 개발했다.유틸리티 함수 구현import fs from "fs";import path from "path";// 블로그 포스트 메타데이터 타입 정의interface Frontmatter { title: string; description?: string; pubDate: string; image?: string;}// 기본 템플릿 값const frontmatterTemplate: Frontmatter = {..
SwiftUI TextEditor에서 Placeholder 구현하기
·
Project/Swift
TextField와 달리 TextEditor는 기본적으로 placeholder 기능을 제공하지 않는다. ZStack을 활용하여 TextEditor에 placeholder를 추가하는 방법을 알아보겠다.문제점TextField는 다음과 같이 간단하게 placeholder를 설정할 수 있다:TextField("placeholder 텍스트", text: $input)여기에 더해 TextEditor는 기본적으로 테두리(border)도 제공하지 않아 시각적으로 입력 영역을 구분하기 위해서는 별도로 .overlay나 .border 수식어를 사용해야 한다. 이러한 기본 요소들의 부재는 개발자가 TextEditor를 사용할 때마다 추가 작업을 해야 하는 불편함을 초래한다.해결 방법: ZStack을 활용한 Placehold..
Javascript ES6 문법 간단 정리
·
Notes/Javascript
ES6는 JavaScript의 중요한 업데이트로, 개발 생산성을 높이고 코드를 더 간결하고 읽기 쉽게 만드는 다양한 기능을 도입했다.1. let과 constvar 대신 블록 스코프를 가지는 변수 선언 방식이다.let: 재할당 가능const: 재할당 불가능 (상수)let a = 10;a = 20; // 가능const b = 30;b = 40; // 오류: 상수에 재할당 불가2. 화살표 함수간결한 함수 표현식으로, this는 상위 스코프를 유지한다.// 일반 함수function sum(a, b) { return a + b;}// 화살표 함수const sum = (a, b) => a + b; // 단일 표현식에서 return 생략 가능// 매개변수가 하나라면 괄호 생략 가능const square = x =>..