SniffMEET. Interactor가 인프라를 직접 알아도 될까

Interactor에서 직접 매니저 호출하지 않기 매니저가 변하면 인터랙터를 직접 변경해야한다. 매니저와 인터랙터 간의 의존성을 줄이고, 인터랙터는 “비즈니스 로직”만, 그리고 비즈니스 로직의 구현체인 유즈케이스에서 네트워크 요청이나 데이터 관리와 같은 인프라 로직을 담당하는 것이 좋다고 생각한다. 또한 싱글톤 객체여도 현재 주입하는 방식으로 사용중인데, 인터랙터에서 사용하면 직접 매니저의 싱글톤 객체를 호출해서 사용해야 한다: func sendWalkRequest(message: String, latitude: Double, longtitude: Double, location: String) { Task { do { let myInfo = try loadUserInfoUseCase.execute() let id = try SessionManager.shared.userID.get() ... try await requestWalkUseCase.execute(walkNoti: walkNoti) } catch { ... } } presenter?.didSendWalkRequest() } 위 코드에서 id를 얻기 위해 SessionManager의 싱글톤 객체를 호출해야 한다. 싱글톤 객체 호출 자체는 크게 문제가 되지 않을 수 있지만, 다음과 같이 생각해볼 주제가 있다. ...

February 10, 2025

SniffMEET. AuthManager와 SessionManager의 책임 분리하기

작업 배경 AuthManager와 SessionManager는 서로 매우 밀접하게 연관된 작업을 한다. AuthManager는 사용자의 계정 인증을 담당하고 세션을 받아오며, SessionManager는 그 세션을 관리한다. 하지만 기존 코드에서는 세션 관리를 포함한 대부분의 작업을 AuthManager가 처리하고, SessionManager는 세션을 소유하는 역할만 하고 있었다. 역할 분리 기존에는 AuthManager에서 세션 갱신, 복원, 저장, 로드 작업을 처리하고 있었고, SessionManager는 세션의 만료 여부 확인과 세션 객체를 소유하는 역할만 맡고 있었다. // AuthManager 인터페이스 프로토콜 protocol AuthManager { static var shared: AuthManager { get } var authStateSubject: PassthroughSubject<AuthState, Never> { get set } func signInAnonymously() async throws func restoreSession() async throws func refreshSession() async throws func loadTokens() throws } // SessionManager 클래스 final class SessionManager { static let shared = SessionManager() var session: SupabaseSession? var isExpired: Bool { guard let session else { return true } // 세션 만료를 파악할 때는 30초의 여유시간을 줍니다. return Date(timeIntervalSince1970: TimeInterval(session.expiresAt + 30)) < Date() } private init() {} } 그래서 세션 관리는 SessionManager, 인증은 AuthManager가 맡도록 기능을 다시 정의했다. ...

February 10, 2025

SniffMEET. ISP로 Supabase 요청 빌더 역할 나누기

들어가며 Supabase REST API를 직접 감싸서 사용하다 보니, 유즈케이스 레이어에서 eq., in., gte. 같은 쿼리 문자열을 직접 조립하는 코드가 늘어났다. 처음에는 단순했지만, 요청이 많아질수록 오타 가능성이 커지고 Supabase의 세부 문법이 상위 레이어로 새어 나오는 문제가 있었다. 이번 글은 이 쿼리 구성 책임을 Supabase DB Layer 안으로 옮기기 위해 요청 빌더와 쿼리 파라미터 래퍼를 도입한 과정을 정리한다. 기본 구조 SNMNetwork의 동작을 간단하게 설명하면, SNMRequestConvertible을 채택하는 객체의 정보로 네트워크 요청을 생성하고, 통신한 다음, 응답을 반환하는 방식으로 동작한다. ...

February 6, 2025

Network. NAT(Network Address Translation)

NAT NAT: Network Address Translation 패킷이 라우팅 장치를 통해 전송되는 동안 패킷의 IP 주소 정보를 수정하여 IP 주소를 다른 주소로 매핑하는 방법, 공인 IP와 사설 IP로 나눠서 처리한다. 동작 원리 NAT는 라우터에서 동작하며, 내부 네트워크의 사설 IP 주소를 외부에서 사용할 수 있는 공인 IP 주소로 변환한다. 이를 통해 여러 장치가 하나의 공인 IP 주소를 공유하면서 인터넷에 접속할 수 있다. 동작 방식 출발지 주소 변환 (SNAT: Source NAT) 내부 네트워크의 컴퓨터가 외부에 패킷을 전송할 때 사설 IP주소를 공인 IP주소로 변환 목적지 주소 변환 (DNAT: Destination NAT) 외부에서 내부로 네트워크로 들어오는 패킷의 목적지 IP를 공인 IP에서 내부 네트워크의 사설 IP로 변환 포트 주소 변환 (PAT: Port Address Translation) 여러 내부 IP들이 하나의 공인 IP를 공유하기 때문에, 포트 번호로 이들을 구별한다. 하나의 공인 IP 주소를 여러 장치가 함께 사용할 수 있도록 포트 번호를 함께 변환하여 구분한다. 예를 들어 다음과 같이 서로 다른 내부 장치가 하나의 공인 IP를 사용할 수 있다. ...

February 5, 2025

OS. Stack, Heap 메모리 관리

Date: February 2, 2025 Multi-select: Memory 스택 메모리 LIFO 구조로, 함수 호출 시 생성되는 스택 프레임(로컬 변수, 파라미터, 반환 주소 등)을 저장한다. 함수가 호출 될 때 마다 새로운 스택 프레임이 쌓이고, 함수가 종료되면 스택 프레임 제거된다. 특징 빠른 메모리 할당/해제: 스택은 메모리가 자동으로 관리되어서 함수가 끝나면 알아서 메모리가 반환됨 고정 크기: 스택 메모리는 크기가 제한적이라서 너무 많은 데이터를 저장하면 스택 오버플로우 위험이 있음 호출 상태 저장: 함수의 매개변수와 지역 값 일부가 스택 프레임에 저장될 수 있음. 실제 저장 위치는 ABI와 컴파일러 최적화에 따라 레지스터나 다른 영역이 될 수도 있음 스레드별 스택: 각 스레드는 별도의 호출 스택을 가지지만, 이것만으로 함수나 데이터 전체가 thread-safe해지는 것은 아님. 스택에 있는 참조가 공유 객체를 가리킬 수도 있음 스택 오버플로우 프로그램이 스택 메모리를 초과할 때 발생하는 오류, 함수 호출 시마다 생성되는 스택 프레임이 쌓이면서 스택 공간을 사용하게 되고, 이 제한된 스택 공간을 초과해서 스택 프레임이 쌓일 경우 발생한다. ...

February 2, 2025

Network. 쿠키, 세션

개요 웹 애플리케이션에서 사용자 정보를 저장하고 관리하는 방식, HTTP는 statelessness이기 때문에, 이전 요청에 대한 정보를 기억하지 않는다. 따라서 이 문제를 해결하기 위해 쿠키와 세션이 필요하다. 쿠키 클라이언트에 저장되는 작은 데이터 파일, 서버가 클라이언트에게 데이터를 저장하도록 지시하면, 해당 데이터를 전송하게 됨 용도 사용자 인증 정보 저장 (로그인 상태 유지) 웹사이트 설정 저장 사용자 행동 추적 특징 주기적 전송: 사용자가 특정 사이트에 다시 방문하면 브라우저가 자동으로 쿠키를 서버로 전송함 수명: 유효 기간을 설정할 수 있고, 만료되면 삭제됨, 유효기간이 없으면 브라우저 세션이 종료될 때 삭제 용량: 한 도메인당 쿠키는 4KB 정도로 제한 보안 사용자의 브라우저에 저장되기 때문에 클라이언트에서 조작할 수 있다. 따라서 민감한 데이터는 쿠키에 저장하면 안됨 ...

February 2, 2025

Network. 프록시

프록시 클라이언트와 서버 사이에 중간 역할을 하는 시스템, 클라이언트의 요청을 대신 처리하고 서버로부터 받은 응답을 클라이언트에 전달하는 방식으로 작동 프록시는 클라이언트와 서버 사이에서 요청과 응답을 대신 전달하는 중개 서버이다. 특징 익명성 제공 클라이언트의 실제 IP 주소를 숨기고, 프록시 서버의 IP 주소 사용 캐싱 자주 요청되는 데이터를 미리 저장해두고, 클라이언트의 요청이 있을 떄 빠르게 응답 보안 프록시 서버는 클라이언트와 서버 사이에 존재, 보안 및 필터링 기능 제공 트래픽 제어 리소스 보호를 위해 트래픽 필터링 종류 포워드 프록시 클라이언트가 외부 서버에 접근할 때 중개 역할을 하는 프록시 ...

February 1, 2025

Network. REST(Representational State Transfer)

REST REST: Representational State Transfer RESTful API: REST를 기반으로 한 API REST 아키텍처 스타일의 설계 원칙을 준수하는 API Note. REST는 HTTP와 동일한 개념이 아니다. REST는 웹 API를 설계하기 위한 아키텍처 스타일이며, HTTP는 REST를 구현할 때 가장 많이 사용하는 프로토콜이다. 설계 원칙 Uniform interface 동일한 리소스에 대한 모든 API 요청은 동일하게 표시되어야 한다(리소스는 단일 URL을 통해 식별할 수 있도록 고유해야 한다). 서버는 표준 형식으로 정보를 전송하고, 형식이 지정된 리소스를 REST에서는 표현(Represent)라고 한다. ...

February 1, 2025

Network. Load Balancing

로드 밸런싱 가용성, 성능, 확장성을 높이기 위해 여러 서버에 네트워크 트래픽을 분산하는 방법이다. 특징 서버와 클라이언트 간의 트래픽을 지시하고 제어하여 가용성, 확장성, 보안 및 성능이 향상됨 가용성 여러 서버에 트래픽을 분배하여 한 서버가 다운되었을 때, 사용 가능한 서버로 트래픽을 리다이렉션한다. 애플리케이션 가동 중지 없이 서버 유지 관리 및 업그레이드 가능 성능 여러 서버에 요청을 분배하여, 네트워크 지연 시간을 줄임 물리적으로 더 가까운 서버로 리다이렉션 하여 지연 시간 단축 보안 트래픽 모니터링 공격 트래픽을 여러 서버로 리다이렉션 하여 영향 최소화 확장성 서버 수를 동적으로 추가하거나 제거하여 트래픽 변화에 유연하게 대응 가능 수평 확장(서버 추가), 수직 확장(성능 향상) 둘 다 가능 동작 원리 L4 로드 밸런싱 전송 계층에서 수행하는 로드 밸런싱, 패킷 헤더에 포함된 정보를 기반으로 TCP나 UDP 패킷을 기준으로 트래픽을 분배한다. ...

February 1, 2025

Network. DNS(Domain Name System)

DNS DNS: Domain Name System 도메인 이름을 IP 주소로 변환하는 시스템, 웹 사이트 주소를 IP주소로 변환해주는 역할 동작 방식 DNS는 계층 구조를 가지며, 요청을 처리하는 과정에서 필요한 DNS 서버를 순차적으로 탐색한다. 한 번 조회한 결과는 캐시에 저장되어 이후에는 같은 과정을 반복하지 않을 수 있다. 사용자가 google.com을 입력했다고 하면, 맥이 자동으로 로컬 DNS 서버에 요청을 보냄 → 만약 로컬 DNS 서버가 정보를 가지고 있지 않다면, 상위 DNS 서버로 요청을 보냄 1. 맥 → 로컬 캐시 확인 2. 로컬 DNS 서버(ISP DNS 서버) → 로컬 캐시 확인 3. 로컬 DNS 서버 → 재귀 DNS 서버에 요청 4. 재귀 DNS 서버 → 루트 DNS 서버 → TLD DNS 서버 → 권한 있는 네임서버 5. 권한 있는 네임서버 → IP 주소 반환 6. 재귀 DNS 서버 → 로컬 DNS 서버 → IP 주소 전달 7. 로컬 DNS 서버 → 맥에 최종 IP 주소 전달 8. 맥 → 구글 접속 재귀 DNS 서버(Recursive DNS Server)는 클라이언트를 대신하여 필요한 DNS 서버를 차례대로 조회하고 최종 결과를 반환하는 역할을 한다. ...

February 1, 2025