Swift 공부 노트: mutating 요구사항 프로토콜을 class가 채택할 때의 컴파일 동작
·
Swift
왜 이 내용을 정리하나프로토콜을 설계할 때 값을 바꾸는 메서드를 요구하는 경우가 많다. 이때 struct와 class가 같은 프로토콜을 채택하면 결과가 다르게 나온다. 어떤 타입은 아무 문제 없이 통과하고, 어떤 타입은 컴파일 에러가 나므로 채택하기 전에 차이를 알아 둘 필요가 있다. 특히 struct 위주로 작성하던 코드를 class로 옮기려고 할 때 이 차이를 모르면 에러 메시지 앞에서 당황하게 된다. 이 노트에서는 mutating 요구사항을 class가 채택할 때 무슨 일이 생기는지 정리해 본다.개념 설명프로토콜에 mutating func를 요구하면, 그 메서드를 구현하는 타입은 값 자체를 바꿀 수 있어야 한다. struct와 enum은 값 타입이라 mutating을 붙인 메서드 안에서 프로퍼티를 ..
Swift 딕셔너리 subscript로 꺼낸 struct 값 수정과 원본 반영 과정 검증
·
Swift
왜 이 내용을 정리하나Swift에서 딕셔너리에 struct 값을 담아 두고 필요한 항목만 꺼내 고치는 코드는 자주 나온다. 설정 값, 사용자 정보, 캐시 항목처럼 키로 묶인 데이터를 다룰 때 이런 작업이 반복된다. 이때 꺼낸 값을 변수에 담아 수정했는데 딕셔너리 안의 값은 그대로인 경우가 생기면 원인을 찾기 어렵다. struct가 값 타입이라는 점을 정확히 알아야 이 혼란이 풀린다. 이 노트에서는 subscript로 꺼낸 struct 값을 수정해도 원본이 바뀌지 않는 이유를 확인하고, subscript에 다시 대입해야 딕셔너리에 반영되는 과정을 print로 검증해 본다.개념 설명Swift의 struct는 값 타입이다. 값 타입은 대입하거나 함수에 넘길 때 내용이 복사된다. 따라서 딕셔너리의 subscri..
React.memo 자식에 인라인 객체 props를 넘기면 부모가 리렌더링될 때마다 자식도 다시 렌더링되는지 console.count로 확인하기
·
React
왜 이 내용을 정리하나React.memo로 감싼 자식 컴포넌트는 props가 이전과 같으면 렌더링을 건너뛴다. 그래서 자식 컴포넌트 최적화를 하려고 React.memo를 붙여 두었는데도 성능이 개선되지 않는 경우가 생긴다. 이때 원인 중 하나가 부모 컴포넌트 안에서 객체 리터럴을 매번 새로 만들어 props로 넘기는 습관이다. 이 노트에서는 인라인 객체 props가 실제로 자식의 리렌더링을 유발하는지 console.count로 세어 확인하는 방법을 정리해 본다.개념 설명JavaScript에서 객체는 참조 타입이다. 내용이 똑같은 두 객체라도 {a: 1}과 {a: 1}은 서로 다른 메모리 위치를 가리키므로 === 비교에서 false가 나온다. React.memo는 props를 얕은 비교(shallow co..
Dart compute 함수에 클로저를 넘길 때 생기는 오류 확인하기
·
Flutter
왜 이 내용을 정리하나Flutter 앱에서 무거운 계산을 메인 Isolate 밖으로 빼려면 compute 함수를 쓴다. 파일 파싱, JSON 디코딩, 이미지 처리처럼 UI가 멈추면 안 되는 작업이 여기에 해당한다. 그런데 compute에 넘기는 함수를 아무 곳에서나 만들다 보면 어느 순간 런타임 오류가 난다. 빌드는 되는데 실행하면 깨지는 종류라서 처음 보면 원인을 찾기 어렵다. 이 노트에서는 compute에 넘긴 함수가 최상위 함수가 아니라 클로저일 때 어떤 오류가 나는지 코드로 확인하고, 왜 그런지 정리해 본다.개념 설명compute 함수는 내부에서 새 Isolate를 만들고, 그 Isolate에 함수와 인자를 보낸 뒤 결과를 받아 돌려준다. Isolate는 메모리를 공유하지 않는 독립된 실행 단위다..
데코레이터 래퍼 안의 ValueError가 호출 지점까지 전파되는지 try/except로 확인하기
·
Python
왜 이 내용을 정리하나데코레이터는 함수를 감싸서 로깅, 인자 검사, 재시도, 권한 확인 같은 공통 로직을 끼워 넣을 때 자주 쓰인다. 이때 래퍼 내부에서 발생한 예외가 원래 함수를 호출한 지점까지 그대로 올라오는지, 중간에서 사라지거나 다른 예외로 바뀌지는 않는지 알아두어야 한다. 특히 래퍼가 try/except로 예외를 잡고 있다면 어디서 잡고 어디서 다시 던지는지에 따라 호출자가 받는 결과가 달라진다. 이 노트에서는 데코레이터 래퍼에서 발생한 ValueError가 호출 지점까지 전파되는 과정을 try/except로 직접 확인해 본다.개념 설명파이썬에서 예외는 발생한 지점에서 호출 스택을 따라 위로 전파된다. 함수 A가 함수 B를 호출하고 B가 예외를 일으키면, B에 처리 구문이 없을 경우 예외는 A로..
useReducer에서 정의되지 않은 액션을 dispatch했을 때 default 분기와 상태 유지 확인
·
React
왜 이 내용을 정리하나useReducer를 쓰다 보면 액션 타입 문자열을 오타로 잘못 보내거나, 새로 추가한 액션을 reducer에 반영하지 않은 채 dispatch하는 경우가 생긴다. 이때 reducer가 어떤 경로로 빠지는지, 상태가 바뀌는지 그대로 유지되는지 모르면 버그의 원인을 찾기 어렵다. 그래서 정의되지 않은 액션을 실제로 보냈을 때 default 분기가 실행되고 상태 객체가 그대로 남는지 콘솔 로그로 직접 확인해 본다. 이 노트에서는 default 분기의 동작과 상태 참조 비교 방법을 정리해 본다.개념 설명useReducer의 reducer 함수는 현재 상태와 액션 객체를 받아 다음 상태를 반환한다. 이 함수는 switch 문으로 action.type을 분기하는 것이 일반적이다. 어떤 cas..
Swift 클로저 캡처 리스트 [x]로 struct 값이 캡처 시점에 고정되는지 print로 확인하기
·
Swift
왜 이 내용을 정리하나Swift에서 클로저는 바깥 변수를 자연스럽게 참조한다. 콜백, 지연 실행, 여러 번 호출되는 핸들러를 만들다 보면 클로저가 실행되는 시점의 값을 읽을지, 클로저를 만든 시점의 값을 가질지 헷갈리는 경우가 많다. 특히 값 타입인 struct는 참조 타입인 class와 다르게 동작하기 때문에, 같은 코드라도 결과가 달라질 수 있다. 버튼을 여러 개 만들면서 루프 안에서 클로저를 등록하거나, 설정값을 담은 struct를 비동기 작업에 넘기는 상황에서 이 차이가 실제 버그로 이어진다.이 노트에서는 캡처 리스트 [x]를 썼을 때 struct 값이 클로저 생성 시점에 고정되는지를 print로 직접 확인해 본다. 그리고 캡처 리스트가 없을 때와 비교해 차이를 정리해 본다.개념 설명클로저는 자신..
React 상태 복사 후 중첩 객체 갱신 시 형제 필드가 유지되는지 console.log로 확인하기
·
React
왜 이 내용을 정리하나React에서는 상태 객체를 직접 수정하면 안 되고 새 객체를 만들어 setState에 넘겨야 한다. 폼 입력처럼 여러 필드를 하나의 객체로 관리하는 경우, 특정 필드만 바꾸려다 다른 필드가 사라지는 실수가 자주 나온다. 특히 객체 안에 또 객체가 들어 있는 중첩 구조에서는 얕은 복사만으로 충분한지 헷갈리기 쉽다. 이런 상황에서 스프레드 연산자로 복사한 뒤 형제 필드가 실제로 유지되는지 콘솔 출력으로 확인해 보면 원리를 빠르게 이해할 수 있다.이 노트에서는 스프레드로 상태를 복사하고 중첩 객체 필드를 갱신할 때 형제 필드가 어떻게 되는지 console.log로 확인하는 과정을 정리해 본다.개념 설명스프레드 연산자(...)는 객체의 모든 자기 속성을 새 객체에 펼쳐 넣는다. 최상위 속..
Dart 클로저의 루프 변수 캡처: for문과 for-in문 비교
·
Flutter
왜 이 내용을 정리하나Flutter 앱에서 버튼 목록이나 리스트 항목을 반복문으로 만들면서 각 항목마다 콜백 함수를 붙이는 경우가 많다. 이때 콜백이 반복문 바깥의 변수를 캡처하는데, 루프 변수가 매 반복마다 새로 만들어지는지 아니면 하나를 계속 공유하는지에 따라 모든 버튼이 같은 값을 출력할 수도, 각자 다른 값을 출력할 수도 있다. 이 차이를 모르면 버튼을 눌렀을 때 엉뚱한 항목이 처리되는 버그를 만나게 된다. 특히 for문과 for-in문은 겉보기에 비슷해도 루프 변수의 생명주기가 다르게 동작하므로 코드로 직접 확인해 둘 필요가 있다.이 노트에서는 Dart에서 클로저가 루프 변수를 캡처할 때 두 종류의 반복문이 어떻게 다르게 동작하는지 코드로 확인하는 방법을 정리해 본다.개념 설명클로저는 함수가 선..
collections.deque에 maxlen을 지정했을 때 append와 appendleft는 어느 쪽 원소를 밀어내는가
·
Python
왜 이 내용을 정리하나파이썬으로 최근 기록만 유지해야 하는 상황은 자주 생긴다. 로그의 마지막 100줄만 보관하거나, 센서 값의 최근 10개만 평균 내거나, 명령 히스토리를 일정 개수로 자르는 작업이 대표적이다. 이때 list를 직접 관리하면 길이를 확인하고 앞이나 뒤를 잘라내는 코드를 매번 써야 한다. collections.deque는 양쪽 끝에서 원소를 넣고 뺄 수 있는 자료형이며, maxlen 인자를 주면 길이가 넘칠 때 반대쪽 원소를 자동으로 밀어낸다. 그런데 append와 appendleft가 각각 어느 쪽 원소를 밀어내는지는 직관과 어긋나기 쉽다. 이 노트에서는 실제 출력을 보면서 두 메서드의 동작 차이를 정리해 본다.개념 설명deque는 double-ended queue의 줄임말이다. 리스트..