Node. Node.js 소개

Node.js는 브라우저 밖에서도 JavaScript를 실행할 수 있게 해주는 런타임이다. 구조 Node.js를 설치하면 JavaScript 런타임 하나만 설치되는 것이 아닌, 프로젝트 관리, 외부 라이브러리, 개발 도구를 실행하기 위한 여러 구성 요소가 함께 설치된다. Node JavaScript 실행 환경이다. 브라우저 외부에서 JS를 실행할 수 있게 해준다. 간단한 파일은 다음처럼 직접 실행할 수도 있다. (다른 언어들과 비슷하다.) node <FILE-NAME>.js npm(Node Package Manager) Node 프로젝트의 패키지 관리자이다. 외부 라이브러리를 설치하고, 제거하고, 프로젝트의 의존성을 관리한다. 외부 라이브러리를 설치할 때는 다음 명령을 사용한다. ...

October 5, 2025

SwiftUI 상태 관리

상태를 누가 소유하고 어떻게 전달해야 하는가 SwiftUI에서는 상태를 저장하거나 다른 뷰에 전달할 때 프로퍼티 래퍼를 사용한다. 이 상태를 현재 뷰가 직접 가지고 있는지, 부모 뷰에서 전달받는지, 아니면 별도의 객체가 관리하는지에 따라 사용하는 래퍼가 달라진다. 상위 뷰 → 하위 뷰 @State → @Binding 상위 뷰가 상태를 소유하고, 하위 뷰는 해당 상태를 수정할 수 있도록 @Binding으로 전달받는다. 뷰 모델 → 뷰 → 하위 뷰 ObservableObject 프로토콜을 채택한 뷰 모델에서는, 변경을 알려야 하는 값을 @Published 프로퍼티로 선언한다.(이 뷰 모델을 뷰에서 주입받아 사용할 때는 보통 @ObservedObject로 관찰함) ...

September 25, 2025

Swift Concurrency. Behind the Scenes - WWDC21

Threading model 뉴스 피드 리더 앱을 예로 들어보자. 앱의 상위 컴포넌트는 다음과 같이 나눌 수 있다. 사용자 인터페이스를 담당하는 메인 스레드 사용자가 구독한 뉴스 피드를 추적하는 데이터베이스 최신 콘텐츠를 가져오는 네트워킹 서브시스템 사용자가 최신 뉴스를 요청하면 다음과 같은 흐름으로 처리할 수 있다. 메인 스레드에서 이벤트 제스처 처리 데이터베이스 작업을 처리하는 직렬 큐로 요청을 비동기적으로 디스패치 작업을 다른 큐로 보내면 메인 스레드는 데이터베이스 작업을 기다리지 않고 사용자 입력에 계속 반응할 수 있다. 직렬 큐가 상호 배제를 보장하므로 데이터베이스 접근을 순서대로 처리할 수 있다. 데이터베이스 큐에선 사용자가 구독한 피드에 URLSession을 통해 콘텐츠를 다운로드하는 네트워크 요청을 스케줄링 결과가 도착하면 URLSession의 콜백이 Delegate Queue 위에서 호출되어서 각 결과의 Completion Handler가 동기적으로 데이터베이스를 업데이트한다. MainThread를 깨워서 UI를 리프레시한다. 보기에는 합리적인 방법이다. 메인 스레드를 블록하지 않으면서 네트워크 요청을 동시에 처리할 수 있기 때문이다. ...

August 25, 2025

Programmers. 미로 탈출 명령어

문제 https://school.programmers.co.kr/learn/courses/30/lessons/150365 풀이 분명히 배열(문자열)의 원소를 하나씩 채워나가야 하는 DFS 완전 탐색 스타일의 문제인데 k의 최대값이 2,500으로 너무 크다. 하지만 문제에서 주어진 조건들을 읽어보면 프루닝을 통해 백트래킹 문제로 만들 수 있다. 현재 위치와 종료 위치 사이의 맨하탄 거리가 남은 이동 횟수보다 적으면, 더 이상 탐색할 필요가 없다. 목표에 도달하지 못하는 분기이기 때문에, 분기를 버려야 한다. 남은 이동 횟수와 현재 위치와 종료 위치 사이의 맨하탄 거리의 차가 홀수인 경우에도 더 이상 탐색할 필요가 없다. 이동 횟수는 고정이고, 두 위치의 거리보다 크다면 이동 횟수를 어딘가에서 소모해야한다. 그런데 다른 위치로 갔다가, 다시 현재 위치로 돌아올때 소모하는 값은 2이므로, 홀수인 경우에는 목적지에 절대 도달할 수 없게 된다. 마지막으로, 탐색 순서를 잘 정했다면 처음으로 성공한 케이스가 곧 사전순에서 가장 앞선 순서가 된다. 한 번만 성공하게 되면 그 뒤의 모든 분기는 의미가 없어진다. 이렇게 프루닝을 하면 완전 탐색으로 절대로 해결 불가능한 문제를 풀 수 있게 된다. ...

August 23, 2025

The Swift Programming Language. Macro (2)

Macro Expansion 매크로를 사용한 Swift 코드를 빌드 할 때, 코드를 확장하기 위해 매크로의 구현을 불러오게 된다. 구체적으로 Swift는 다음과 같은 방법으로 매크로를 확장한다: 컴파일러가 코드를 읽어, 구문의 in-memory 표현을 만든다. 컴파일러가 이 in-memory 표현의 일부를 매크로를 확장시키는 매크로 구현부에 보낸다. 컴파일러가 매크로 호출을 확장된 형태로 대체한다. 컴파일러가 확장된 소스 코드를 사용하여 컴파일을 계속 진행한다. 구체적인 단계들을 살펴보기 위해, 다음을 생각해보자: let magicNumber = #fourCharacterCode("ABCD") #fourCharacterCode 매크로는 4개의 캐릭터로 구성된 문자열을 받아, 그 문자열의 ASCII 값들을 이어 붙인 32비트 언사인드 인티저를 리턴한다. 일부 파일 포맷은 데이터를 식별하기 위해 이런 형태의 인티저를 사용하는데, 컴팩트 하면서도 디버거에서 읽을 수 있기 때문이다. 아래의 Implementing a Macro 섹션에서 이 매크로를 구현하는 방법을 보여준다. ...

August 15, 2025

Programmers. 합승 택시 요금

문제 https://school.programmers.co.kr/learn/courses/30/lessons/72413 풀이 문제를 간단히 하는 것이 중요하다. 이 문제에서 원하는 것은 S에서 시작해서 A와 B 노드로 가야하는데, 그 최단 거리를 요구하고 있다. 그러면 둘이 헤어지는 지점이 존재할 것이고, 이 헤어지는 지점은 S일 수도 있다(문제에서 주어진 내용이다). 그러면 헤어지는 지점을 M이라고 했을때, 우리가 구해야 하는 것은 S → M, M → A, M → B의 최단거리들의 합이다. 문제가 최단거리를 구하는 문제로 단순화 되었다. 음수 사이클이 존재하지 않으므로, 다익스트라 알고리즘이나 플로이드 워셜 알고리즘을 사용하면 된다. 만약 다익스트라를 사용한다면 M을 우리가 모르므로 모든 노드에 대해서 다익스트라 알고리즘을 적용해보고 M을 찾아야 한다. 플로이드 워셜은 모든 노드 상호간의 최단거리를 알 수 있고, 노드의 개수도 200개가 상한이기 때문에 플로이드 워셜을 쓰는 것이 훨씬 간단하게 풀 수 있다. ...

August 14, 2025

Programmers. 표 편집

문제 https://school.programmers.co.kr/learn/courses/30/lessons/81303 풀이 이 문제에서 핵심은 삭제된 칸을 건너 뛰면서 칸을 옮기는 것이다. 칸을 옮기는 횟수가 최대 1,000,000 번이라고 제한되어 있지만, 명령의 개수도 200,000 개 이므로 칸을 단순히 부울리언 값으로 켜고 끄면서 이동하는 것은 최악의 경우에 굉장히 많은 시간이 걸릴 것이다. 여기서 생각해야할 점은 이 문제에서는 ‘랜덤 액세스’를 요구하지 않는다는 것이다. 문제에서 삭제된 칸을 복구할때 커서를 옮기지 않는다고 했으므로, 랜덤 액세스가 들어갈 부분은 처음 커서 위치를 지정하는 부분밖에 없다. 또한 중간에 있는 칸을 삭제하고 복구하는 작업들이 있으므로, 컨테이너 중간에서 삭제/삽입 연산이 쉬운 자료구조를 생각해야 하고, 바로 링크드 리스트가 떠올랐다. ...

August 14, 2025

The Swift Programming Language. Macro (1)

매크로는 컴파일할 때 소스 코드를 변환하여, 반복적인 코드를 직접 작성하지 않게 해준다. 컴파일하는 동안, Swift는 평상시처럼 코드를 빌드하기 전에 매크로들을 확장한다. 매크로를 확장하는 것은 항상 추가하는(additive) 작업이다: 매크로는 새로운 코드를 더하지만, 기존에 존재하는 코드를 삭제하거나 수정하지 않는다. 매크로 입력과, 매크로 확장의 출력 둘 다 구문적으로 유효한 Swift 코드인지 체크된다. 마찬가지로, 매크로에 전달되는 값과 매크로로 생성된 코드 안의 값이 정확한 타입인지 검사된다. 추가적으로, 매크로를 확장할 때 구현부에서 에러를 마주치면, 컴파일러는 이를 컴파일 에러로 처리한다. 이러한 보장은 매크로를 사용하는 코드를 더 쉽게 이해하게 해주고, 매크로를 잘못 사용하거나 매크로의 구현에 버그가 있는 이슈들을 더 쉽게 알아차리게 해준다. ...

August 14, 2025

Programmers. 인사고과

문제 https://school.programmers.co.kr/learn/courses/30/lessons/152995 풀이 정렬 문제다. 두 개의 수를 가진 튜플(혹은 배열)이 있고, 두 수의 합이 아닌, 각 수를 개별적으로 두 값이 모두 작거나 큰지 판단해야 하는 경우에는 첫 번째 기준이 되는 값은 오름차순, 그리고 두 번째 기준이 되는 값은 내림차순으로 정렬하는 것이 일반적이다. 반대도 가능하고, 이 문제에서도 첫 번째 기준이 되는 값을 내림차순, 두 번째 기준이 되는 값을 오름차순으로 정렬하는 것이 더 편하다. 순위를 셀 때도 조금은 최적화할 수 있다. 제거해야할 원소들을 제거하고 새로운 배열을 만드는 것이 아닌, 그냥 배열을 순회하면서, 기준이 되는 원소보다 큰 수를 카운트 하면 된다. ...

August 6, 2025

Programmers. 풍선 터트리기

문제 https://school.programmers.co.kr/learn/courses/30/lessons/68646 풀이 문제의 조건은 쉬운데, 풀이 과정은 쉽지 않아보인다. 하지만 문제를 최대한 단순화해보자. 기본적으로, 인접한 두 풍선을 고를 수 있고 두 풍선중 번호가 더 큰 풍선을 터트려야 한다. 하지만 1회에 한정에서 번호가 더 작은 풍선을 터트릴 수 있다. 일단 기본적으로 마지막까지 남을 수 있는 풍선의 개수를 세야 하므로 모든 풍선에 대해 확인해봐야 한다. 그리고 마지막까지 남을 수 있는 풍선이라고 했으므로, 항상 마지막에 고르는 두 풍선들 중 하나는 현재 내가 확인하고 싶은 풍선일 것이다. ...

August 5, 2025