ViewModel을 사용할 때 Factory를 사용하는 경우와 사용하지 않는 경우에는 큰 차이가 있다. 이 차이를 이해하면, ViewModel의 인스턴스 생성 방식의존성 주입(DI) 활용 방법을 더욱 효과적으로 설계할 수 있다.

1. 기본적인 ViewModel 사용 (Factory 없이)

특징

  • ViewModel이 기본 생성자만 가진 경우 Factory 없이 사용 가능.
  • ViewModelProvider를 사용하여 Activity 또는 Fragment에 간단히 연결 가능.
  • 인수가 필요 없는 ViewModel에 적합.

예제 코드

class MainViewModel : ViewModel() {
    val message = MutableLiveData<String>()
    fun updateMessage(newMessage: String) {
        message.value = newMessage
    }
}

 

class MainFragment : Fragment() {
    private val viewModel: MainViewModel by viewModels()
}

장점

  • 간단하고 구현이 쉬움 (by viewModels() 또는 ViewModelProvider 사용 가능).
  • 생명주기를 고려하여 자동으로 관리됨.

단점

  • 생성자에서 파라미터를 받을 수 없음 (Repository, UseCase 같은 객체를 직접 주입할 수 없음).
  • 의존성 주입(DI)이 어렵고, ViewModel 내부에서 객체를 직접 생성해야 함 (유지보수 어려움).

2. Factory를 사용하는 ViewModel

특징

  • ViewModel 생성자에서 파라미터를 받는 경우 반드시 Factory가 필요함.
  • 보통 Repository, UseCase, API 서비스 등의 객체를 ViewModel에 주입할 때 사용.
  • DI(Dependency Injection) 환경 (예: Hilt, Dagger)에서 활용하기 좋음.

예제 코드

① ViewModel이 생성자를 가지는 경우

class MainViewModel(private val repository: DataRepository) : ViewModel() {
    val data: LiveData<String> = repository.getData()
}

② Custom ViewModelFactory 구현

class MainViewModelFactory(private val repository: DataRepository) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(MainViewModel::class.java)) {
            @Suppress("UNCHECKED_CAST")
            return MainViewModel(repository) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

③ Factory를 이용한 ViewModel 생성

class MainFragment : Fragment() {
    private val repository = DataRepository()
    private val viewModel: MainViewModel by viewModels {
        MainViewModelFactory(repository)
    }
}

장점

  • ViewModel의 생성자를 통해 의존성을 주입할 수 있음 (Repository, UseCase 등).
  • DI를 활용하여 테스트가 용이하고 유지보수가 쉬움.

단점

  • Factory 클래스를 따로 구현해야 하므로 코드가 길어질 수 있음.
  • Factory를 생성할 때 ViewModel을 명시적으로 매핑해야 하는 과정이 필요함.

3. Factory를 사용하지 않는 경우 vs Factory를 사용하는 경우 비교

항목Factory 사용 X (by viewModels())Factory 사용 O (Factory 필요)

사용 가능 조건ViewModel에 생성자 파라미터 없음ViewModel에 생성자 파라미터 필요
ViewModel 생성 방식by viewModels() 또는 ViewModelProviderViewModelProvider.Factory를 통해 생성
의존성 주입(DI)불가능 (ViewModel 내부에서 직접 객체 생성)가능 (Repository, UseCase 등 주입 가능)
테스트 용이성어려움 (ViewModel 내부에서 직접 객체 생성)쉬움 (의존성을 모킹(Mock)할 수 있음)
코드의 복잡성단순하고 짧음Factory 클래스를 추가해야 함

4. ViewModelFactory를 활용하는 고급 예제

(1) ViewModel에 여러 개의 의존성을 주입하는 경우

class MainViewModel(
    private val repository: DataRepository,
    private val analyticsTracker: AnalyticsTracker
) : ViewModel() {
    fun logEvent(event: String) {
        analyticsTracker.trackEvent(event)
    }
}

(2) Factory에서 여러 개의 파라미터를 전달

class MainViewModelFactory(
    private val repository: DataRepository,
    private val analyticsTracker: AnalyticsTracker
) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(MainViewModel::class.java)) {
            @Suppress("UNCHECKED_CAST")
            return MainViewModel(repository, analyticsTracker) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

(3) Fragment에서 Factory를 활용한 ViewModel 생성

class MainFragment : Fragment() {
    private val repository = DataRepository()
    private val analyticsTracker = AnalyticsTracker()

    private val viewModel: MainViewModel by viewModels {
        MainViewModelFactory(repository, analyticsTracker)
    }
}

5. Hilt를 이용한 ViewModel Factory 대체 방법

최근에는 DI 라이브러리(Hilt, Dagger)를 사용하면 Factory를 직접 구현할 필요 없음.

(1) Hilt를 활용한 ViewModel 생성

① ViewModel에 @HiltViewModel 추가

@HiltViewModel
class MainViewModel @Inject constructor(private val repository: DataRepository) : ViewModel() {
    val data: LiveData<String> = repository.getData()
}

② Repository에 @Inject 추가

class DataRepository @Inject constructor() {
    fun getData(): LiveData<String> {
        return MutableLiveData("Hello from Repository")
    }
}

③ Fragment에서 간단하게 ViewModel 생성

@AndroidEntryPoint
class MainFragment : Fragment() {
    private val viewModel: MainViewModel by viewModels()
}
  • Hilt를 사용하면 Factory 클래스를 직접 만들 필요 없이, 의존성이 자동으로 주입됨.
  • 이 방식이 현재 Android 개발의 표준적인 접근법.

6. 결론

  • ViewModel에 생성자 파라미터가 필요 없다면 Factory 없이 by viewModels() 사용.
  • ViewModel에 생성자 파라미터가 필요하면 반드시 Factory를 사용해야 함.
  • DI 라이브러리(Hilt, Dagger)를 활용하면 Factory 없이도 자동으로 의존성 주입 가능.
  • 테스트 가능성과 유지보수를 고려하면 Factory 또는 Hilt를 사용하는 것이 권장됨.

📌 정리:

간단한 ViewModel → by viewModels()
의존성이 있는 ViewModel → Factory 사용 or Hilt 활용

'Android Programming' 카테고리의 다른 글

Modern Anroid Application의 UI 구조 이해  (0) 2025.03.18
Modern Anroid Application의 구조 이해  (1) 2025.03.11
Waydroid 설정하기  (0) 2022.04.15

들어가며..

앞에서 이야기 했던 것[1]과 같이 기존에 개발 중이던 Android Application 과제에 참여하게 되면서 작성된 내용을 이해해야 하는 상황이 되었다. 여기서는 앞에서 언급한 UI 및 네비게이션 흐름 분석 중에서 FragmentTransaction, ViewModel, LiveData의 동작 방식 확인하기 위한 상세 내용에 대해서 살펴 본다.

 

Modern Anroid 구조

(1) Fragment 중심 설계 (Modern Android Architecture)

✅ 장점

  1. 단일 Activity 구조 가능 (Single Activity Architecture)
    • 대부분의 UI를 하나의 Activity에서 관리하고 Fragment를 동적으로 교체.
    • Navigation Component를 활용하면 자연스러운 화면 이동 가능.
  2. 유지보수 및 확장성 용이
    • 같은 Activity 내에서 Fragment만 바꾸면 되므로 화면 재사용성이 높음.
    • 대규모 앱 개발 시 구성 요소를 분리하여 관리하기 용이.
  3. 반응형 UI (Adaptive UI) 지원
    • 태블릿과 스마트폰에 따라 레이아웃을 유연하게 조정 가능.
    • 예: 태블릿에서는 좌측 리스트 + 우측 상세보기, 스마트폰에서는 화면 전환.
  4. Activity 간 전환 비용 감소
    • Activity 간 전환 시 onCreate() → onDestroy() 호출이 발생하여 리소스 소모가 큼.
    • Fragment 전환은 비용이 상대적으로 적고, BackStack을 관리하면 자연스럽게 복귀 가능.
  5. ViewModel과 LifecycleOwner 활용 가능
    • Activity 단위에서 ViewModel을 공유하면 Fragment 간 데이터 유지 가능.
    • viewLifecycleOwner를 활용하면 Fragment의 라이프사이클을 안전하게 관리.

❌ 단점

  1. Fragment의 생명주기 관리가 복잡
    • Activity보다 복잡한 생명주기를 가짐 (onAttach(), onCreateView(), onDestroyView() 등).
    • BackStack을 적절히 관리하지 않으면 메모리 누수 발생 가능.
  2. FragmentTransaction 관리 필요
    • Fragment 간 전환 시 FragmentTransaction을 직접 관리해야 함.
    • commit(), commitNow(), addToBackStack() 등 사용법을 숙지해야 함.
  3. Navigation Component 도입 필요
    • 기존 방식 (FragmentTransaction) 대신 Navigation Component를 사용하는 것이 권장됨.
    • Safe Args 같은 추가적인 학습이 필요할 수 있음.

Fragment vs Activity 사용 비교

Fragment 기반 (Single Activity) - 동적인 화면 변경이 많은 경우
- 데이터 공유가 필요한 경우 (ViewModel 활용)
- 태블릿/멀티-윈도우 지원이 필요한 경우
- Navigation Component를 활용하는 경우
Activity 기반 (Multiple Activity) - 독립적인 기능의 화면이 많고, 서로 연결이 필요 없는 경우
- 단순한 앱(로그인 화면, 설정 화면)에서 사용
- 백스택 관리를 자동으로 하고 싶은 경우

 

Fragment, ViewModel, LiveData 분석 방법

(1) FragmentTransaction 분석

① Fragment 변경 방식 확인

  • replace(), add(), remove(), show(), hide() 사용 여부 확인.
  • commit(), commitNow()의 사용 방식이 적절한지 확인.
  • addToBackStack() 사용 여부 및 Fragment 백스택 관리 방식 파악.

② Fragment 생명주기 확인

  • onCreate(), onCreateView(), onResume(), onPause()의 호출 순서를 Logcat으로 확인.
  • Fragment 간 전환 시 ViewModel이 정상적으로 재사용되는지 확인.

③ Fragment 간 데이터 전달 방식 분석

  • arguments를 통해 전달하는지, ViewModel을 사용하는지 확인.
  • FragmentResultListener 또는 LiveData로 데이터 전달하는지 분석.

(2) ViewModel 분석

① ViewModel 인스턴스 범위 확인

  • Activity 범위인지 Fragment 범위인지 확인 (ViewModelProvider의 owner 확인).
  • Fragment 재생성 시 ViewModel이 유지되는지 확인.

② ViewModel 내부 데이터 흐름 확인

  • LiveData 또는 StateFlow를 사용하여 데이터를 관리하는지 분석.
  • Transformations.map(), Transformations.switchMap()이 적절히 활용되는지 확인.

③ ViewModel의 Clear 시점 분석

  • Fragment가 사라질 때 ViewModel이 정상적으로 유지되는지 또는 제거되는지 확인.

(3) LiveData 동작 분석

① LiveData의 구독 방식 확인

  • observe()가 어디에서 호출되는지 확인 (Activity vs Fragment).
  • viewLifecycleOwner를 사용하고 있는지 확인 (viewLifecycleOwner.lifecycleScope.launchWhenStarted).

② LiveData의 이벤트 처리 방식 확인

  • SingleLiveEvent(일회성 이벤트) vs 일반 MutableLiveData 사용 방식 검토.
  • observeForever()가 사용되었는지 확인 (메모리 누수 가능성 체크).

③ LiveData의 Thread 처리 확인

  • MediatorLiveData 사용 여부 확인 (여러 LiveData 조합 처리 확인).
  • viewModelScope.launch 등을 사용하여 백그라운드에서 처리되는지 확인.

 

마무리

Modern Android Application 구조가 Fragement 기반의 구조로 변경되면서 기존 Android Application을 이해하는 방법도 바뀌었다고 할 수 있다. 즉, Application -> Activity 기반의 구조 이해에서 Fragment, ViewModel, LiveData로 연결되는 구조를 이해를 먼저 해야 한다. 

 

Fragment에서는 변경 방식, 생명주기, 데이터 전달 방식을 이해한 후에, ViewModle 인스턴스 범위 확인, 내부 데이터 흐름 확인 그리고 Clear 시점 분석을 한다. LiveData의 동작 분석에서는 구독 방식, 이벤트 처리 방식, Thread 처리를 확인한다.

 

참고 문헌

[1] Modern Android Application 구조의 이해, https://technical-leader.tistory.com/174

 

'Android Programming' 카테고리의 다른 글

ViewModel에서 Factory 사용 여부 비교  (0) 2025.03.25
Modern Anroid Application의 구조 이해  (1) 2025.03.11
Waydroid 설정하기  (0) 2022.04.15

들어가며..

기존에 개발 중이던 Android Application 과제에 참여하게 되면서 작성된 내용을 이해해야 하는 상황이 되었다. 일반적으로는 빌드를 해보고, 실행을 해보는 "모의 설치" [1]와 비슷한 절차를 해보았다. 개발 환경을 구축하고 소스를 받아서 빌드를 해보, 소스 코드를 살펴 보았다. 예전에 알고 있던 Android Application과 구조도 많이 달라져 정리해 본다. 특히, LLM과 분석에 대해서 이야기 해볼 때, 여러가지 힌트를 얻어서 기존 Android Application Project를 이해하는데 도움이 될 것으로 보여 정리해 본다.

 

분석 절차

1. 런타임 동작 분석

  • 로그 분석: Logcat을 활용하여 주요 이벤트와 동작 흐름을 분석.
  • 트레이스 프로파일링: Android Profiler를 사용하여 CPU, 메모리, 네트워크 사용 패턴을 확인.
  • StrictMode 활성화: 백그라운드에서 발생하는 블로킹 작업이나 리소스 누수를 감지.

2. 의존성 및 모듈 구조 분석

  • Gradle의 dependencies 확인 (./gradlew dependencies 실행).
  • Android Studio의 Project Structure를 이용하여 모듈 간의 의존성 파악.
  • Dagger/Hilt, Koin 등의 의존성 주입(Dependency Injection) 구조가 있다면 플로우 확인.

3. UI 및 네비게이션 흐름 분석

  • Navigation Component를 사용하고 있다면 nav_graph.xml 분석.
  • Espresso 또는 UI Automator를 이용하여 주요 UI 플로우 자동화 테스트 실행.
  • FragmentTransaction, ViewModel, LiveData의 동작 방식 확인.

4. 네트워크 통신 분석

  • OkHttp 로그 인터셉터 추가하여 API 호출 확인.
  • Charles, Postman, Wireshark를 사용해 실제 API 요청과 응답을 캡처.
  • Retrofit, Volley, Ktor 등의 네트워크 라이브러리 사용 여부 확인.

5. 데이터 저장 방식 분석

  • Room, SharedPreferences, DataStore, Realm 등의 사용 여부 확인.
  • adb shell 명령어를 통해 DB 상태 확인 (adb shell sqlite3 /data/data/your.package.name/databases/your_db_name.db).

6. 멀티스레딩 및 백그라운드 작업 확인

  • WorkManager, JobScheduler, RxJava, Kotlin Coroutines 사용 여부 분석.
  • 주요 백그라운드 태스크 실행 여부와 성능 영향 파악.

7. 앱 보안 및 권한 점검

  • AndroidManifest.xml에서 불필요한 권한이 있는지 확인.
  • 앱의 내부 데이터 보호 방식 (EncrytedSharedPreferences, SQLCipher 등) 점검.
  • ProGuard 또는 R8 난독화 설정 확인.

8. 빌드 및 배포 프로세스 확인

  • CI/CD 파이프라인 (GitHub Actions, Jenkins, Bitrise) 연동 여부 분석.
  • Fastlane 또는 Gradle Task를 활용한 빌드 자동화 방식 점검.

 

정리

위 항목들을 실행하면서 애플리케이션의 구조적 특징과 문제점을 파악할 수 있을 것이다. 특히, 1차적으로 1, 2번은 쉽게 진행하였고 3번을 통해서 전체 프로젝트의 파일들과 역할들을 이해하게 되면서 전체적인 구조의 그림이 보이기 시작했다. 항후 진행 하면서 관련된 배경 지식등을 학습하게 된 내용도 추가 정리해 보자. 

 

참고 문헌

[1] 객체 지향 리엔지니어링 패턴: 3장 첫 번째 접근, https://technical-leader.tistory.com/139

 

 

'Android Programming' 카테고리의 다른 글

ViewModel에서 Factory 사용 여부 비교  (0) 2025.03.25
Modern Anroid Application의 UI 구조 이해  (0) 2025.03.18
Waydroid 설정하기  (0) 2022.04.15

고성능 브라우저 네트워킹: 무선 네트워크 개요

유비쿼터스 환경이 급성장하며, 언제 어디서나 온라인 서비스를 이용할 수 있는 시대가 되었다. 이에 따라 무선 네트워크의 중요성도 커졌으며, 현재 사용되는 무선 기술만 해도 WiFi, Bluetooth, ZigBee, NFC, WiMAX, LTE, HSPA, 위성 서비스 등 다양하다.

 

무선 네트워크의 기본 원리와 성능 결정 요소

 

무선 네트워크는 유선 네트워크와는 다르게 공유 매체(전파)* 사용하며, 다음과 같은 요소들에 의해 성능이 결정된다. 

  1. 대역폭(Bandwidth): 주파수 범위가 넓을수록 전송 속도가 증가한다. 예를 들어, WiFi 802.11n은 40MHz 대역폭을 사용하여 더 빠른 속도를 구현했다.
  2. 신호 대 잡음비(SNR): 신호의 세기와 잡음의 비율로, 방해 전파가 많을수록 성능이 저하된다.
  3. 변조(Modulation): 디지털 데이터를 아날로그 신호로 변환하는 방법으로, SNR과 기기의 처리 능력에 영향을 받는다.

특히, 샤논의 법칙은 정보 전송량이 대역폭과 신호 대 잡음 비로 결정된다는 것을 보여 준다. 특히, 변조에 따른 정보 효율이 달라 질 수 있다.

 

무선 네트워크의 종류와 사용처

  • PAN (Personal Area Network): Bluetooth, ZigBee, NFC를 사용하여 개인 기기간 연결.
  • LAN (Local Area Network): WiFi를 사용해 건물 내 네트워크 확장.
  • MAN (Metropolitan Area Network): WiMAX 등으로 도시 네트워크 연결.
  • WAN (Wide Area Network): LTE, 위성 서비스 등을 통해 전 세계 연결.

 

무선 통신 성능 최적화의 중요성

무선 네트워크는 공유 매체 특성상 방해 전파의 영향을 많이 받고, 전송 전력, 변조 방식, 송수신 거리 등 여러 요소에 의해 성능이 좌우된다.

  • 셀 호흡(Cell-breathing): 주변 방해 신호가 많을수록 통신 가능 거리가 줄어든다.
  • 근거리/원거리 문제(Near-far Problem): 강한 신호가 약한 신호를 밀어내는 현상.

 

실제 무선 네트워크 성능 측정과 고려사항

 

무선 네트워크의 성능은 위치, 방해 전파, 송수신 거리 등에 따라 변화무쌍하다.

  • 이상적인 환경: 최대 대역폭, 낮은 잡음, 효율적인 변조 방식 사용 시 최적의 성능.
  • 실제 환경: 사용자의 위치와 주변 환경에 따라 성능이 크게 달라집니다.

 

결론 및 전망

무선 네트워크는 편리성이동성을 제공하지만, 잡음, 방해 신호, 대역폭 한계 등 여러 제약이 존재합니다. 앞으로 더 빠르고 안정적인 무선 통신을 위해 5G, WiFi 6 등 차세대 기술이 도입될 것이다.

 

참고 자료

[1] 일리아 그리고릭, "구글 엔지니어에게 듣는 네트워킹과 웹 성능 최적화 기법", 정해권, 오현주 공역, 인사이트(insight)

들어가며

논어에는 "배우고 때때로 익히면 또한 기쁘지 아니한가?" (學而時習之, 不亦說乎?)라는 말이 있다. 옛날 사람의 이야기이지만 우리가 현재 학교에서 교과서를 통해서 배우는 것과 같은 명시지(Explicit Knowledge)도 실천을 바탕으로 해야 한다는 것으로 알 수 있다. 우리는 우리가 학습 한 것 혹은 전문성을 바탕으로 하는 직업에서도 학습이 일어나고 수행(peform)하기도 한다. 그렇다면, 우리가 이해하는 지식의 모습은 어떨까? 이러한 지식을 얻기 위한 학습을 어떻게 얻을 수 있을까? 이런 이해를 바탕으로 한다면 어떻게 학습하는 것이 좋을까? 그리고 이러학 학습을 통해 생겨난 나의 지식은 어떻게 관리하는 것이 좋을까? 단편적일 수 있지만, AC2에서 학습한 근거 있는 방법들과 개인적으로 알게된 도구들을 포함하여 살펴 보자.

우리가 이해하는 지식의 모습.

지식을 이야기 하면 우리가 배운 것을 기억하고 있는 것이라고 간단히 이야기 할 수 있을 것이다. 기억은 보통 단기 기억(Short-term Memory)/작업 기억(Working Memory)와 장기 기억(Long-term Memory)로 이야기를 많이 한다. 암기 한다는 것이 결국은 우리 뇌에 그 기억을 심고 시간이 오래 지나도 그것을 잘 꺼내는 것이 필요하다. 우리는 경험 상으로 이렇게 더는 것이 쉽지 앓다는 것을 안다. 그리고, 이렇게 되기 위해 반복과 시간이 걸리는 경우가 많다는 것도 경험 상이나 이론으로도 알려져 있다. 어릴 때 부터 자주 꺼내어 쓰는 구구단이나 조선왕 순서가 이렇게 단기 메모리를 장기 메모리로 잘 옮겨 둔 사례가 될 수 있겠다.

그렇다면, 운동이나 작업과 같은 것들은 어떨까? 연구자들은 이러한 부분도 연구를 했다. 많은 전문성 연구에서 이를 다루고 있는데, 이와 관련된 한 가지 모델이 절차적 지식 혹은 기억(Procedural Memory)이라고 한다. 앞에서도 이야기했듯이, 단기 기억 혹은 작업 기억 에서 중요한 것은 기억을 인출하는 것이다. 앤더스 에릭슨과 월터 킨치[1]는 "장기 작업 기억(Long-Term Working Memory)"이라는 개념을 도입하여 일상적인 작업과 관련된 정보에 원활하게 접근할 수 있는 장기 기억의 "인출 구조(retrieval structure)"집합으로 정의하여 설명하고 있다. 이런 방식으로 장기 기억의 일부는 효과적으로 작업 기억으로 동작한다고 설명하고 있다. 다시 이야기 하자면, 우리가 하고자 하는 작업 같은 경우도 전문가의 지식 혹은 행동으로 가지고 싶은 지식의 경우 명시화 해서 시간을 들여 반복하는 것이 필요하다. 즉, 학습, 훈련하는 것이 필요한 것이다.

내가 사용하는 배우고 익히는 방법

기존에 방식은 책을 보고 배우고, 프로그래밍과 같은 실습이 필요한 것은 코드를 입력하고 돌려보고 프로젝트를 해보는 것으로 알고 있었다. 물론 영어와 같은 언어는 여러 메타학습적인 부분이 있어서 학습법도 찾아 보고 시도해 보면서 영어로 생각하고, 표현하는 훈련이 필요하다와 같은 내가 지금 사용하는 방법을 찾아 적용하기도 했다.

AC2에 참여 하고 나서 학습하는 방식이 추가 되고 바뀌었다. 특히, 김창준님의 "야생학습" 패치(AC2 Patch)를 듣고 나서는 기존의 책 읽는 방법 그리고 실행하는 것을 훈련하는 방식도 변하고 있는 상황이다. 여기서 이야기하는 것들은 여러 곳에서 배운 것들을 나에게 적용하고 있는 과정 중인 것이다. 그렇기 때문에 v1.x 라고 부르기보다는 보다는 v0.1 혹은 v0.x와 같은 진행형이라는 부분을 이야기하고 싶다.

내가 생각하기에 기존의 내가 쓰던 방식과 다른 것은 "협력적"으로 학습하는 것, "절차적 지식"을 위한 학습, 그리고 "형성 평가적"인 요소의 도입을 하는 것이다.

협력적인 학습의 경우는 김창준님이 Mental Representation관련해서 알려 주실 때 공유받았던 논문[2]에  나오는 내용으로 "그룹이 개인이 독립적으로 수행할 때 발생하지 않는 추상적인 표현을 창발(Emergence)한다는" 주장이다. 이러한 것이 의미있는 지식으로 발전할 수 있다. 그래서, 소그룹의 논의와 이를 공유하는 작업은 학습에서도 중요한 의미를 지닌다고 볼 수 있겠다. 책을 읽는 것도 혼자서 읽고 이야기 하는 것이 아니라 같은 책 혹은 다른 책을 읽는 모임에서도 서로가 책을 읽은 것을 가지고 이야기를 공유하는 것이 혼자 하는 것과는 다른 결과를 만들어 낸다. 나는 정기적인 독서 모임이 일주일 특히 주말에 2회가 있다. 특별한 사정이 있지 않으면 참석을 한다. 하나는 다른 책 혹은 같은 책의 다른 부분을 읽고 이야기하고, 다른 하나는 하나의 책을 정해 놓고 처음 부터 끝까지 같이 읽는다. 다른 형식임에도 공통적인 것은 내가 생각하지 못했던 것을 다른 사람들에게 배우는 것이다.

절차적 지식 학습을 위해 최근에 가장 많이 사용한 방법은 Outcome Observable Question (OOQ)를 이용한 Action Planning이었다. 내 개인적인 생각으로는 이것이 의도적인 수련(Deliberate Practice)과 의도적인 수행(Deliberate Performance)을 적용하는 것이라 생각한다. 이 방식은 AC2를 할 때, 김창준님의 Essense of Agility를 연습하는 방법이었지만, 이 방식은 행동으로 옮길 프레임워크가 있다면 적용이 가능하다. 예를 살펴보자, 예전에 변신철님이 알려 주신 책이었는데 "헤라클리이토스"의 "같은 강에 두 번 발을 담글 수 없다."라는 경구를 실천해 보자고 한다고 하자. 이 문장을 지나간 일은 어쩔 수 없으니, 앞으로 일어날 일에 집중하자고 해보자. 이를 중요한 Outcome으로 보고 이를 관찰할 수 있는 질문으로 바꾸어 "지나간 일 보다는 지금 혹은 곧 발생할 중요한 일은 무엇인가? 그것에 집중하고 있는가?"를 사용해 볼 수 있다. 그렇다면, 이를 기반으로 지금/오늘 나에게 중요한 문제에 대해서 적용해 볼 수 있다. "지나간 부분에 대해서 어쩔 수 없으니 지금 중요한 "임원 보고"에 대해서 준비하고 대응하자."와 같은 Action Plan을 짤 수 있다. 이러한 작업이 의도적 수련이 될 수 있고, 이를 기반으로 실재 실행과도 연결할 수 있다. 이 OOQ 기반 Action Plan을 여러 사람들과 피드백 받아서 한다면 더욱 효과가 좋다. 나는 매일 루틴 처럼 아침에 어제 Action Plan에 대해서 회고를 하고 새로운 Action Plan을 수행하면서 피드백을 받아 반복해서 진행되도록 했었다.

AC2를 하면서 알게된 한가지 효과적인 학습 방법은 형성 평가(Formative Assessment)를 사용하는 것이다. 우리에게 익숙한 학습의 평가는 배우고 난 것을 평가하는 총괄평가(Summative Assessment)를 하는 것이다. 즉, 수업 등의 진도가 나간 후에 마지막에 시험을 봐서 학습자가 얼마나 이해했는지를 평가하는 것이다. 형성 평가는 이와는 달리 중간에 학습자가 얼마나 이해하는지 보여 주게 하면서 학습의 효과를 높이는 것이라고 할 수 있다. 예를 들자면, 학습자들이 몇몇이 모여서 이해하고 있는 곳들을 나누고 함께 모여서 그것들을 나누면서 자신이 알고 있는 것을 확인하고 다른 사람들을 통해서 이해도를 높일 수 있다. 연구자들의 측면의 근거로서 흥미로운 것은 구글 Scholar를 검색해 보는 것이다. 2025년 2월 말에 검색 했을 때에는 형성 학습 관련한 논문이 총괄 평가와 관련된 논문의 약 7배가 많다는 것을 알 수 있다. 하지만, 아직도 현실에서는 총괄 평가가 많은 상황이다. 이러한 상황에서 사용 가능한 전략을 AC2에서 소개 받은 바가 있다. 총괄 평가 시스템이어서 바꾸기 어렵다면 중간 중간에 형성 평가 구간을 두는 것이 한 방법이다. 회사의 분기별 안전 교육에서도 문제 풀이를 중간에 보여주도록 바뀐 적이 있는데 이러한 모습을 반영한 것이라고 할 수 있다. 우리가 형성 평가 기준으로 학습하고 있을 때, 중간에 총괄 평가에해당 하는 시험 혹은 모의 시험들을 넣어서 피드백을 받는 것도 의미가 있다. 좀 더 구체적인 예를 드다면, 내가 영어를 잘 하기 위해서 평생 공부를 하지만, TOEIC, OPiC등 시험을 중간 중간 넣어서 피드백을 받아 성적을 살펴 보는 것이 이러한 방법이 될 수 있다.
 

내가 사용하는 나의 개인 지식 관리

또다른 학습의 과정은 알고 있는 것의 인출(Retrieval)이다. 다시 말해 알게 된 것, 알고 있는 것을 계속 끄집어 내는 것도 좋은 학습 중 하나이다. 이 부분은 나의 뇌에서 지식을 꺼내는 것도 있지만, 지식 관리 시스템에서 내용을 다시 보고 내 기억을 강화 하거나 지식 관리 시스템에 내용을 보강하는 것이. 이를 활용하게 하는 대표적인 것이 워크샵을 하거나 공유회를 하는 것이 될 수 있다. 여기에서는 일반적인 강의만 하는 것이 아니고 AC2의 워크샵 처럼 수련, 연습, 실행을 포함하는 것이 더 좋은 것이 보인다. 최근에는 동기 면담과 관련한 주제에 대해서 작게 공유회를 하였다. 이 때, 동기 면담의 중요한 기술 중의 하나인 반영(Refrelction)에 대해서 이야기도 하고, 이를 위한 간단한 연습을 포함하였다. 이러한 방식은 사람들에게 지식을 전달하는 과정이 포함되어 있지만 나한테는 또다른 학습이기도 한 것이다.

머리 속에 모든 것을 담아 둘 수 없기 때문에 두번 째 뇌라고 할 수 있는 메모앱은 지식 관리 시스템의 뼈대가 된다고 생각한다. 기존에 사용하던 메모앱은 Evernote, Google Keep 그리고 OneNote로 넘어가 사용하고 있었다. AC2를 하면서 다른 분들이 소개하는 것을 듣고는 OneNote에서 Obsidian으로 옮기기 시작했다. 하지만, 오래 사용한 OneNote의 모든 내용을 옮기는 작업은 하지 않고, 지속적으로 업데이트하는 문서를 짧게 먼저 옮기고 사용을 시작했다. 중간에 다시 OneNote에서 많이 참고하는 문서의 복사본을 만들어 옮겨 사용하였다. 현재 OneNote는 거의 열어 보고 있지 않다.

Obsidian은 Text 문서에 Markdown 형식으로 문서를 작성하면 이를 포매팅해서 보여 준다. 이는  단순하지만 불릿 포인트 같은 문서 포맷팅 뿐 아니라, 수학 수식도 작성이 가능하다. 무엇 보다도 문서간의 Link를 활용해서 제텔 카스텐을 지원한다. 처음에 강의 등으로 들은 내용이고, 내가 사용하는 방법은 아직도 어설프지만 나름 흉내 내보려고 하고있는 실정이다. 예를 들어 관련 있는 문서들이 처음에는 파편화 되어 생겨 난다. 그리고, 연결 될 대 문서 제목으로 링크를 만들어 연결 시키서 탐색이나 검색이 용이하게 이뤄진다.

Obsidian을 이용하고 나서 알게된 PARA 룰의 적용도 유용하다. PARA는 Project, Area, Resource, Archive 의 약자로 메모를 카테고리화 해서관리한다. 이와 관련된 YouTube와 온라인 교육을 들은 적이 있다. 교육에서 제안받은 데로 Inbox를 포함하여 5개의 큰 카테고리로 나눠어 메모를 분류하고 활용해서 급하게 만든 문서는 Inbox에 만들어 넣고, 간략하게 정리되면 Project 혹은 관련된 다른 폴더로 이동하게 된다. 물론 다른 폴더에 있는 것들도 완료되거나 하면 Archive등으로 이동하기도 한다. 회사의 메일을 정리하는 방법도 PARA 형태로 바꾸면서 모든 이메일을 백업하는 일은 포기한 상황이기도 하다.

블로깅은 AC2를 하기 전 부터 학습하던 것을 기록하는 도구로서 사용하였다. 특히, 메모 등으로 조각 난 정보들 중에서 이와 같은 글을 쓰거나 학습한 내용 중 다른 분들과도 공유하고 싶은 내용들을 위주로 정리해서 올리고 있다. 이 글도 블로그에 올라갈 것으로 기대한다. 블로깅의 중요한 축은 사람들의 피드백을 살펴 볼 수 있는 부분이다. 다른 블로깅 채널을 뚫어 볼까도 생각하고 있지만, 아직은 시도하기 전이기는 하다.

Anki가 지금까지 마지막으로 활용하게 된 도구이다. Anki는 암기(暗記)의 일본 발음으로 Flashcard 형태의 정보를 간격 반복(Spaced Repetition) 학습을 하게 도와주는 도구 이다. 이는 인출의 연습을 하게 도와 주는 도구로 이제 영어 단어 혹은 자격증 시험에 많이 활용하는 것을 볼 수 있다. 나도 영어로 시작해서 자격증 시험이나 기억하고 싶은 이론 등에 대해서 정리해 두고 살펴 보는 도구로 사용하기 시작했다. Obsidian과 연계하기 시작하면서 새로운 지식을 Obsidian에 정리하고 Anki의 Flashcard로 만들어 기억하고 싶은 것들을 더 자주 들여다 보면서 간격 반복 학습을 하도록 시도하고 있다. 이 부분에 대해서는 배휘동님의 가이드도 참고 하고 있다[3].

정리하며

여기서는 AC2를 하면서 여러 가지를 배우고 얻었지만, 기존에 내가 학습하던 방법과는 다르게 근거가 있는 도구나 방법들을 많이 배웠다. 그래서, 지식이라는 것에 대한 이해도 조금 더 가지게 되었고, 이러한 이해를 바탕으로 학습하는 벙법 및 도구를 얻게 되었다. 이를 기반으로 실용적인 지식 관리 도구들도 가지고 적용하게 되었다. 이 부분은 상당히 개인적인 경험이나 근거들을 기반으로 한 것으로 다른 분들도 이러한 참고하여 자신에게 맞는 방법을 찾아서 튜닝해서 사용할 수 있을 것이라 기대한다.

참고 문헌

[1]  K. Anders Ericsson and Walter Kintsch, "Long-Term Working Memory", https://kantor.comminfo.rutgers.edu/t/MLIS/551/public_dump/morris_a_11.html
[2] D. L. Schwartz "The emergence of abstract representations in dyad problem solving", The journal of the learning sciences, 1995
[3] 배휘동, "[GeekNight 2024] 인지과학 연구로 증명된 학습 보조 도구 Anki: 10배 더 효과적으로 활용하는 방법", https://www.stdy.blog/10x-effective-way-to-use-anki/

 

개요

MVA (Minimum Viable Architecture)는 시스템의 필수적인 아키텍처만을 구현하여 빠르고 효율적으로 제품을 시장에 출시하고 사용자 피드백을 받는 접근 방식이다[1]. 이는 효과적인 아키텍처 실험과 밀접하게 연결된다. MVA를 통해 각 실험은 원자성(Atomic), 시기적절함(Timely), 명확성(Unambigous)한 특징을 유지하면서, 최소한의 아키텍처로 실험을 진행하여, 더 큰 아키텍처 변경 전에 필요한 피드백을 신속하게 얻을 수 있다. 이러한 접근 방식은 리스크를 최소화하고, 결과의 해석을 간단하게 하며, 전체 개발 과정을 더욱 효과적으로 관리할 수 있도록 돕는다.

 

효과적인 아키텍처 실험의 특징

특징설명

원자성 한 번에 하나의 질문에 집중하여 혼란을 방지하고 결과를 명확하게 한다.
시기 적절함 위험을 작고 관리 가능한 단위로 나누어 빠르게 피드백을 얻고 결과 해석을 간소화한다.
명확성 명확한 성공 기준과 측정 가능한 결과를 가지고 있어 실험이 성공했는지 판단할 수 있다.

 

효과적인 아키텍처 실험을 위한 질문

아래 표는 기사에서 설명하는 효과적인 아키텍처 실험을 수행하는 핵심 원칙을 요약하고, 이러한 실험을 계획하고 실행하기 위한 구조적 접근 방식을 제공한다.

가설 설정
(A clear hypothesis)
우리가 테스트하는 구체적인 가설은 무엇이며, 어떤 결과가 가설이 유효하다는 것을 나타낼까?
측정 가능성
(An explicit and measurable goal or target)
성공을 어떻게 측정할 것이며, 어떤 메트릭을 사용할까?
구현
(A method for running the experiment and mechanisms for measuring its success or failure)
실험을 수행하기 위해 어떤 단계를 밟을 것이며, 결과를 어떻게 문서화할까?
대체 계획
(A plan for rollback if the experiment fails)
실험이 실패할 경우, 우리의 롤백 계획은 무엇인가?
시간
(An explicit timeline for the experiment)
이 실험을 완료해야 하는 시간 프레임은 무엇이며, 우리의 목표와 어떻게 일치해야 하는가?

 

참고 문서

[1] Pierre Pureur and Kurt Bittner, "Software Architecture and the Art of Experimentation", Dec 17, 2024, https://www.infoq.com/articles/architecture-experimentation/?utm_source=infoqEmail&utm_medium=editorial&utm_campaign=ArchitectNL&utm_content=01312025

TLS의 개념 및 역할

  • TLS(Transport Layer Security)는 데이터 암호화, 인증, 무결성을 제공하여 안전한 통신 환경을 조성.
  • 초기 SSL 프로토콜에서 발전된 것으로, TCP 위에서 작동하여 HTTP, 이메일 등 애플리케이션의 보안을 강화.

TLS의 작동 원리

  • 핸드셰이크 과정: 클라이언트와 서버가 암호화 방식과 키를 협상하여 안전한 터널을 생성.
  • 암호화: 대칭키 암호화를 통해 효율적이고 안전한 데이터 전송.
  • 인증: 신뢰 사슬을 기반으로 클라이언트와 서버의 신원을 확인.

 

최적화 기법

  • 세션 재개: TLS 핸드셰이크 과정에서 발생하는 레이턴시를 줄이기 위해 세션 캐시나 세션 티켓을 활용.
  • TLS 레코드 크기 조정: 레코드 크기를 TCP MSS(Maximum Segment Size)에 맞춰 설정해 효율적 데이터 전송.
  • 조기 종료: CDN(콘텐츠 전송 네트워크)나 프록시 서버를 활용해 클라이언트와 가까운 서버에서 세션을 종료해 레이턴시 최소화.
  • 압축 비활성화: TLS 레벨에서의 압축은 보안 문제(CRIME 공격) 및 이중 압축 문제로 인해 비활성화 권장.

 

TLS 관련 최신 기술

  • ALPN (Application-Layer Protocol Negotiation): 핸드셰이크 과정에서 애플리케이션 프로토콜 협상을 포함시켜 추가 레이턴시를 줄임.
  • SNI(Server Name Indication): 하나의 서버에서 여러 도메인을 운영할 때 필요한 확장.

 

실무에서의 TLS 활용

  • 최신 OpenSSL 및 TLS 버전 사용으로 성능 최적화.
  • 인증서 길이 최소화 및 중간 인증서 포함으로 불필요한 레이턴시 방지.
  • TLS를 지원하지 않는 구형 클라이언트를 고려해 세션 캐시와 세션 티켓을 병행 사용하는 것이 권장됨.

 

참고 자료

[1] 일리아 그리고릭, "구글 엔지니어에게 듣는 네트워킹과 웹 성능 최적화 기법", 정해권, 오현주 공역, 인사이트(insight)

UDP의 특성 및 역할

  • UDP는 단순하고 신뢰성을 제공하지 않는 프로토콜로, 데이터그램 방식으로 작동하며 TCP와 달리 연결 상태를 유지하지 않는다.
  • 빠르고 효율적인 데이터 전송을 위해 설계되었지만, 재전송, 흐름 제어, 오류 검출 등의 기능은 지원하지 않는다.

 

 

UDP의 주요 활용 사례:

  • DNS와 같은 간단한 데이터 전송 프로세스에 사용되며, WebRTC와 같은 실시간 통신에서 필수적으로 활용된다.
  • UDP는 음성 및 화상 통화, P2P 통신 등 지연 시간이 중요한 애플리케이션에서 적합하다.

NAT(Network Address Translation):

NAT는 IPv4 주소의 부족 문제를 해결하기 위해 개발된 기술로, 로컬 네트워크의 사설 IP 주소를 공용 IP 주소로 변환하여 인터넷 통신이 가능하도록 한다. 이 기술은 특히 라우터에서 사용되며, 내부 네트워크와 외부 네트워크 간의 트래픽을 중계하고 IP 주소를 변환한다.

동작 방식: NAT 기기는 내부 네트워크의 사설 IP 주소와 포트를 외부의 공용 IP 주소와 포트로 변환하여 인터넷에 데이터를 전송하고, 반대로 외부에서 들어오는 패킷의 공용 IP와 포트를 내부의 사설 IP와 포트로 변환한다.
예시: 내부 클라이언트 192.168.0.1:1337이 공용 IP 50.76.44.114:31454로 변환되어 인터넷과 통신. NAT는 IP 주소 부족 문제를 완화하고 내부 네트워크를 외부로부터 보호하는 데 기여했으나, 이로 인해 외부에서 기기가 보이지 않는 것과 같은 새로운 문제들이 발생한다.

 

NAT 문제 해결:

  • UDP와 NAT 간의 문제는 STUN, TURN, ICE 등의 기술을 통해 해결할 수 있다.
  • STUN은 공용 IP와 포트를 확인하고, TURN은 UDP가 차단될 때 TCP로 전환하며, ICE는 가장 효율적인 경로를 찾아 연결다.

STUN(Session Traversal Utilities for NAT), TURN(Traversal Using Relays around NAT), ICE(Interactive Connectivity Establishment)의 특징과 역할을 기반으로 표를 정리하면 다음과 같다:

기술 정의 및 역할 특징 장점 단점
STUN NAT 뒤에 있는 클라이언트의 공용 IP 주소와 포트를 알아내기 위한 프로토콜 - 클라이언트가 자신의 공용 IP와 포트를 확인
- 제3의 STUN 서버 필요
- 간단한 NAT 탐지 및 설정
- NAT 테이블에 라우팅 값 생성 가능
- 일부 NAT 환경에서는 제대로 작동하지 않음
TURN NAT를 통과할 수 없을 때 데이터를 중계 서버를 통해 전달하는 프로토콜 - 데이터를 중계 서버를 통해 전송
- 모든 데이터를 양방향으로 중계
- STUN 실패 시 대안으로 사용
- 안정적인 데이터 전송 보장
- NAT 및 방화벽이 막힌 상황에서도 작동
- 중계 서버 부하 증가
- 데이터 지연 발생 가능
ICE NAT 및 방화벽을 통과하기 위해 가장 적합한 경로를 선택하는 프로토콜 - STUN과 TURN을 결합하여 사용
- 직접 연결, STUN, TURN을 모두 시도
- 네트워크 환경에 따라 최적 경로 선택
- P2P 연결 가능성 극대화
- 복잡한 설정 필요
- 프로토콜 구현 및 설정 과정이 다소 까다로움

주요 활용 시나리오

  • STUN: 클라이언트가 NAT 뒤에 있을 때 공용 IP와 포트 정보를 알아내는 데 사용.
  • TURN: STUN을 사용할 수 없거나 NAT 및 방화벽이 UDP를 차단하는 경우 데이터 중계.
  • ICE: P2P 애플리케이션에서 최적의 연결 경로를 찾기 위해 STUN, TURN을 조합.

STUN

 

TURN

 

ICE

UDP 최적화 및 권장 사항:

  • UDP 기반 애플리케이션은 데이터 전송률 조절, 혼잡 제어, 패킷 재전송 등의 메커니즘을 별도로 구현해야 한다.
  • RFC 5405에 따르면, UDP 애플리케이션은 인터넷 경로 상황에 유연하게 대응하고, 최소한의 연결 유지 기능을 설계해야 한다.

이 글을 통해 UDP의 기본 개념과 특징, 그리고 이를 최적화하고 활용하는 방법에 대해 이해할 수 있다. UDP는 단순하지만 강력한 전송 프로토콜로, 효율적인 네트워킹과 실시간 데이터 전송에 적합한 선택지가 될 수 있다.

 

참고문헌

[1] 일리아 그리고릭, "구글 엔지니어에게 듣는 네트워킹과 웹 성능 최적화 기법", 정해권, 오현주 공역, 인사이트(insight)

[2] https://docs.google.com/presentation/d/1ZgF4MQ-7BBS92Zlz3mB52APRmyoSyaXprwltw5y3VJg/edit#slide=id.p9

TCP와 IP의 개요

  • 인터넷의 중심은 TCP(전송 제어 프로토콜)와 IP(인터넷 프로토콜)로 이루어진다.
  • TCP는 신뢰성을 보장하며, 데이터 전송 순서 확인, 데이터 재전송 등을 처리한다.
  • TCP는 HTTP 표준의 기본 전송 프로토콜로 활용된다.

 

TCP의 핵심 메커니즘

 

3-Way 핸드셰이크:

  • 연결 성립 전 클라이언트와 서버 간 초기화 절차.
  • 왕복 레이턴시가 연결 성능에 영향을 미친다

느린 시작(Slow-Start):

  • 새로운 연결에서 데이터 전송 속도를 점진적으로 증가시킨다.
  • 초기 처리량이 제한되며, 대규모 데이터를 처리하는 경우 더 큰 영향을 미친다.


TCP Fast Open
:

  • 구글이 개발한 최적화 기법으로 초기 핸드셰이크 레이턴시를 줄인다.
  • SYN 패킷에서 데이터 전송 가능
  • HTTP 트랜잭션 속도를 약 10~40%까지 개선.

 

혼잡 제어(Congestion Control) vs 흐름 제어(Flow Control):

항목 혼잡 제어 흐름 제어
정의 네트워크의 혼잡 상태를 완화하고 패킷 손실을 방지하기 위한 메커니즘. 수신자의 처리 용량을 초과하는 데이터 전송을 방지하기 위한 메커니즘.
목적 네트워크 전반의 안정성을 유지하고 혼잡으로 인한 성능 저하를 줄이는 것. 송신자가 수신자의 버퍼 용량을 초과하는 데이터를 보내지 않도록 보장.
초점 네트워크의 상태에 따라 전송 속도를 조절. 수신자의 상태에 따라 전송 속도를 조절.
작동 원리 - 패킷 손실을 혼잡의 신호로 판단. - 리시브 윈도(rwnd) 를 기준으로 송신량을 조절.
- 혼잡 윈도 크기(cwnd)를 조정하여 전송 속도 감소 및 회복. - 송신자와 수신자가 TCP 핸드셰이크 중에 초기 리시브 윈도(rwnd) 를 설정하고, 이후 ACK 패킷을 통해 업데이트.
주요 알고리즘 - 느린 시작(Slow-Start): 작은 윈도 크기로 시작해 점진적으로 증가. - 수신자가 버퍼가 포화 상태에 가까워지면 리시브 윈도(rwnd) 를 줄여 송신자에게 알림.
- 혼잡 회피(Congestion Avoidance): 패킷 손실 발생 시 혼잡 윈도를 줄여 네트워크 부담 감소. - 리시브 윈도(rwnd) 가 0이면 송신자는 수신 버퍼가 비워질 때까지 대기.
병목 원인 네트워크 경로 내의 혼잡(라우터, 스위치 등)에서 발생. 수신자의 버퍼 용량 부족으로 인해 발생.
주요 지표 - 혼잡 윈도(cwnd): 송신자가 전송할 수 있는 데이터의 양. - 리시브 윈도(rwnd): 수신자가 처리할 수 있는 데이터의 양.
주된 영향 - 네트워크 경로에서 데이터 처리량이 줄어들거나 지연이 발생. - 송신자가 데이터를 전송하지 못하거나 속도가 제한됨.
활용 사례 네트워크 전송 속도가 다양한 상황(혼잡, 정체 등)에서 효율적으로 조절되어야 하는 경우. 데이터 처리 용량이 한정된 IoT 기기, 모바일 기기 등에서 송신 속도를 조절해야 하는 경우.

 

혼잡 회피(Congestion Avoidance) 

  • 패킷 손실을 피드백으로 사용하여 혼잡 윈도를 패킷 손실이 발생할 때까지 증사 시킴
  • 알고리즘 종류
    • TCP Tahoe and Reno (original implementations) (AIMD)
    • TCP Vegas
    • TCP New Reno
    • TCP BIC
    • TCP CUBIC (default on Linux) or Compound TCP (default on Windows)

웹 성능 최적화 방법

  1. 서버 설정 최적화:
    • 최신 커널 업데이트 및 초기 혼잡 윈도 크기를 10으로 설정.
    • 느린 시작 재시작 기능 비활성화.
  2. 네트워크 환경 개선:
    • 서버를 사용자와 가까운 위치에 배치.
    • 기존 TCP 연결을 최대한 재사용.
  3. 데이터 전송 최적화:
    • 불필요한 데이터 전송 제거.
    • 전송 데이터를 압축하여 처리량 개선.

 

결론

 

TCP는 안정적이고 신뢰할 수 있는 프로토콜로 설계되었지만, 레이턴시가 주요 병목 요인이 될 수 있다. 이를 해결하기 위해 애플리케이션 설계와 서버 설정을 최적화하는 것이 중요하다.

 

참고 문헌

[1] 일리아 그리고릭, "구글 엔지니어에게 듣는 네트워킹과 웹 성능 최적화 기법", 정해권, 오현주 공역, 인사이트(insight)

[2] https://docs.google.com/presentation/d/1ZgF4MQ-7BBS92Zlz3mB52APRmyoSyaXprwltw5y3VJg/edit#slide=id.p9

[1]은 웹 성능 최적화에 이야기 하고 있지만, 네트워크를 사용한 성능과 관련된 이론적인 부분을 많이 다루고, 여러 프로토콜에 대해 설명도 잘 되어 있어, 살펴 보고자 한다. 네트워크 성능에 가장 기본적인 지연시간(Latency)와 대역폭(bandwidth, 혹은 troughput)에 대해 이야기 한다.

레이턴시와 대역폭:

레이턴시는 데이터가 출발지에서 도착지까지 이동하는 데 걸리는 시간이다. 대역폭은 네트워크 경로에서 전송 가능한 최대 데이터 용량을 나타낸다. 이 두 요소는 웹 성능 최적화의 핵심 요소로, 서로 상호작용하며 웹 애플리케이션의 속도에 영향을 미친다. 아래 그림에서 볼 수 있듯이 레이턴시는 송신단과 수신단의 거리, 대역폭은 가장 성능이 낮은 링크의 영향이 큰 것을 예상할 수 있다. 

 

 

레이턴시의 구성 요소:

  • 전파 지연: 신호가 전송 매체를 통해 이동하는 데 걸리는 시간. 예를 들어 광섬유를 거치는 경우 빛의 속도.
  • 전송 지연: 패킷이 링크를 통해 전송되는 시간. 전송할 데이터양과 연결하는 링크의 처리량에 따라 달라진다.
  • 프로세싱 지연: 라우터 등이 패킷을 처리하는 데 걸리는 시간. 패킷 헤더의 정보를 처리하는데 필요한 시간.
  • 큐잉 지연: 패킷이 처리 대기열에서 기다리는 시간. 

이러한 것들이 합쳐져 전체 지연 시간이 된다.

 

광섬유와 네트워크 속도:

광섬유는 네트워크의 핵심 전송 매체로, 높은 대역폭을 제공하며 장거리 데이터 전송에서 중요한 역할을 한다.
빛의 속도가 빠르지만, 현실적 제약으로 인해 이상적인 속도에 도달하기 어렵다. 네트워크는 기술 발전으로 대역폭은 점차 증가하고 있으나, 레이턴시는 물리적 한계로 인해 큰 개선이 어려운 상황이다. 이를 극복하기 위해 프로토콜 최적화 및 캐싱, 프리페칭 등의 기술을 활용해야 한다. 대표적으로 이러한 상황에서 최적화 전략으로 Content Delivery Network(CDN)와 같은 기술을 활용해 데이터 전송 거리와 레이턴시를 줄이는 방법을 사용하고 있다. 

 

라스트 마일

인터넷 트래픽의 대부분의 레이턴시는 대륙이나 바다를 건너는 메인 네트워크 구간이 아니라, 집이나 사무실에서 인터넷 서비스 프로바이더(ISP) 네트워크로 연결되는 마지막 구간(최종 몇 킬로미터)에서 발생한다. ISP의 연결 방식, 네트워크 토폴로지, 기술적 제한으로 인해 이 구간에서 지연이 크며, 네트워크 성능의 병목 현상이 자주 발생한다.



참고문서

[1] 일리아 그리고릭, "구글 엔지니어에게 듣는 네트워킹과 웹 성능 최적화 기법", 정해권, 오현주 공역, 인사이트(insight)

[2] https://docs.google.com/presentation/d/1ZgF4MQ-7BBS92Zlz3mB52APRmyoSyaXprwltw5y3VJg/edit#slide=id.p9

+ Recent posts