전체 글 68

remember vs rememberSaveable

jetpack compose에서 ui 상태를 효율적으로 관리하는 핵심인 remember와 rememberSaveable의 내부 동작 원리를 파헤쳐 보자. 1. remember와 rememberSaveable의 차이점재구성시 상태를 유지하기 위해 jetpack compose는 remember와 rememberSaveable이라는 두 가지 필수 도구를 제공한다.공통점: 두 API 모두 Compose 런타임 메모리에 값을 캐시하여, 상태가 없는 함수 내에서 지속성을 제공하는 것처럼 보이게 한다.차이점: remember: 프로세스가 살아있는 동안에만 값을 메모리에 저장한다. 앱 프로세스가 종료되면 (예: 백그라운드에서 시스템에 의해 회수될 때) 상태가 손실된다.rememberSaveable: 상태를 Bundle..

CORS, CSRF, SOP

1. CORS (Cross-Origin Resource Sharing) 란?CORS는 크로스 오리진 리소스 공유의 약자로, 한 사이트에서 주소가 다른 서버로 요청을 보낼 때 발생하는 문제이며, 이는 브라우저가 보안상의 이유로 다른 출처 간의 리소스 공유를 기본적으로 차단하는 '동일 출처 정책(SOP)' 때문에 발생즉, 요청은 브라우저가 보내지만, 응답을 브라우저가 읽을 수 있는지는 서버의 CORS 설정에 따라 달라짐 2. SOP (Same-Origin Policy, 동일 출처 정책)브라우저 보안 정책 중 하나로, **서로 다른 출처(origin)**의 리소스 간 스크립트 접근을 제한악의적인 사이트가 사용자의 인증 정보를 도용하거나 민감한 데이터에 접근하지 못하게 막기 위함. 3. CSRF (Cross-S..

개발 지식 2025.05.26

세션 방식 vs JWT 토큰 방식

먼저 들어가기에 앞서 인증(authentication) 과 인가(authorization) 의 차이점에 대해서 설명하겠습니다. 인증(authentication)은 로그인 과정이며, 사용자가 특정 서비스에 회원임을 아이디와 패스워드로 확인하는 절차이다 .인가(authorization)는 인증 후 사용자에게 서비스 내에서 다양한 기능 접근을 허가하는 과정으로, 로그인 상태에서의 활동을 관리한다 1. 📜 세션 방식의 로그인 과정 설명사용자가 로그인에 성공하면 서버는 세션 표잡지를 생성하여 사용자의 브라우저로 전송한다 .생성된 세션 표잡지는 영화관 티켓처럼 반으로 찢어서 사용자의 브라우저와 서버 메모리에 각각 저장된다 .서버 메모리는 작업의 속도에 따라 책상(메모리), 서랍(디스크), 창고(DB)에 비유되..

개발 지식 2025.05.25

git submodule 등록 방법

일단 git submodule을 알아보게 된 이유에 대해서 말해보려고 합니다.  여러가지 Repository 에서 공용으로 사용할 Repository 가 필요한 상황이 발생했을 때 어떻게 해야할지 고민을 하면서 알아보게 됐습니다. 단적인 예로 여러가지 앱이 각각의 Repository로 있을 때 공통의 디자인 시스템을 사용해야 한다면 디자인 시스템 관련 Repository는 각각의 앱에서 참조해서 사용해야 합니다. 1. 서브 모듈 추가 (public repository 기준으로 작성했습니다. private 은 SSH 인증을 추가 해야합니다.) git submodule add  이렇게 생성하고 나면 .gitmodules 에 path 와 url 이 저장되게 됩니다. 2. 서브 모듈 업데이트 (특정 브랜치로도..

형상관리 2025.01.30

안드로이드 PIP 모드 커스텀 버튼 추가

안드로이드 PIP 모드에서 커스텀 버튼을 추가하는 방법 1. PendingIntent.getActivity 를 이용해 onNewIntent 에서 action 에 대해 기능 정의 방법 예제 코드private fun enterPipModeWithActions() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val aspectRatio = Rational(16, 9) // PIP 모드에서 사용할 액션 버튼 정의 val intent = Intent(this, PipActivity::class.java).apply { action = "ACTION_DO_SOME..

안드로이드 PIP 모드 설정

안드로이드에서 Picture-In-Picture 모드로 현재 화면과 독립적으로 움직일 수 있는 Activity 를 띄울 수 있습니다.코드 중심으로 설명을 하겠습니다.1. PIP 모드를 사용할 Activity 클래스 생성package im.metrex.oa.features.sendbirdimport android.app.PictureInPictureParamsimport android.content.res.Configurationimport android.net.Uriimport android.os.Bundleimport android.util.Rationalimport androidx.activity.ComponentActivityimport androidx.activity.OnBackPressedCal..

[Chapter 6] CoroutineContext

CoroutineContext 란?코루틴을 실행하는 실행 환경을 설정하고 관리하는 인터페이스이다.CoroutineName, CoroutineDispatcher, Job, CoroutineExceptionHandler 를 조합해 코루틴의 실행 환경을 설정한다. 1. CoroutineContext 구성 키값CoroutineName 키CoroutineName 객체CoroutineDispatcher 키CoroutineDispatcher 객체Job 키Job 객체CoroutineExceptionHandler 키CoroutineExceptionHandler 객체 각 구성요소는 고유한 키를 가지며, 키에 대해 중복된 값은 허용되지 않는다. 코드 예제)import kotlinx.coroutines.*import kotl..

[Chapter 5] async와 Deferred

launch 코루틴 빌더를 통해 생성되는 코루틴은 기본적으로 작업 실행 후 결과를 반환하지 않는다. 하지만 우리가 코루틴을 다룰 때는 코루틴으로부터 결과를 수신해야 하는 경우가 빈번하다!비동기 작업으로부터 결과를 수신해야 하는 경우를 위해 async 코루틴 빌더를 통해 코루틴으로부터 결과값을 수신받을 수 있다.launch 를 사용하면 결과값이 없는 Job 객체가 반환되는 것과 다르게 async 함수를 사용하면 결과값이 있는 Deferred 객체가 반환이 된다!1. async 를 사용해 Deferred 만들기 (await 를 사용해 결과값을 수신 해보기)예시 코드를 보자import kotlinx.coroutines.*fun main() = runBlocking { val networkDeferred: D..

Closure(클로저)

정의람다를 실행 시점에 표현하는 데이터 구조는 람다에서 시작하는 모든 참조가 포함된 닫힌(closed) 객체 그래프를 람다 코드와 함께 저장해야 한다.그런 데이터 구조를 클로저(closure)라고 부른다.(출처: Kotlin in Action) 정의를 보고 무슨말인가 싶은데 아래 코드를 보자.fun View.throttleClick( interval: Long = 1500L, onClick: () -> Unit) { var lastClickTime = 0L // 로컬 변수 this.setOnClickListener { val currentTime = SystemClock.elapsedRealtime() if (currentTime - lastClickTime..

[백준 11650번] 좌표 정렬하기

단순하게 문제를 봤을 땐 중첩 for 문을 이용하면 쉽게 풀릴 수 있다고 생각할 수 있다. 하지만 100000 × 100000 은 이미 1초를 넘어가게 된다. 그러므로 중첩 for 문을 이용하는 것은 사용할 수 없다. 코틀린에서는 sortedWith 를 사용하면 O(nlogN) 의 시간 복잡도를 가지고 정렬을 할 수 있다. chatGpt 설명 : 기본적으로 TimSort 알고리즘을 사용합니다. TimSort는 합병 정렬(Merge Sort)과 삽입 정렬(Insertion Sort)을 결합한 알고리즘으로, 최선의 경우, 평균적인 경우, 최악의 경우 모두 O(n log n)의 시간복잡도를 가집니다.  코드) import java.io.BufferedReaderimport java.io.InputStreamR..