본문으로 건너뛰기
버전: 4.6.1

구간 제어 통합

코드 기반 통합을 사용하여 NetFUNNEL Android 에이전트로 구간 제어를 구현하는 완전한 가이드입니다.

통합 방법

이것은 사용 가능한 두 가지 통합 방법 중 하나입니다. 통합 방법 개요를 참조하여 기본 제어와 비교하고 사용 사례에 가장 적합한 방법을 선택하세요.


작동 방식

사용자 경험:

  1. 사용자가 버튼을 클릭하거나 작업을 트리거합니다
  2. 현재 화면에 대기실이 나타납니다
  3. 진입이 허용되면 대기실이 닫히고 사용자가 활성 구간에 진입합니다
  4. 사용자는 구간 내에서 여러 화면을 탐색할 수 있습니다
  5. 사용자가 프로세스를 완료하면 키가 반환되고 다음 사용자가 진입할 수 있습니다

최적 용도:

  • 다단계 프로세스 (결제, 등록, 예약)
  • 특정 영역에서 고정된 동시 사용자 유지
  • 사용자 세션 관리
  • 제어된 동시 사용자 수가 필요한 리소스 집약적인 워크플로우

기본 제어와의 주요 차이점:

  • 기본 제어: 진입 속도를 제어합니다 (키가 빠르게 반환됨)
  • 구간 제어: 고정된 동시 사용자 수를 유지합니다 (구간 종료까지 키가 유지됨)

사전 요구사항

샘플 애플리케이션 예제

이 가이드는 샘플 애플리케이션을 사용하여 구간 제어 통합 패턴을 보여줍니다. 실제 애플리케이션 코드는 표시된 예제와 다를 수 있습니다. 통합 개념을 이해하고 패턴을 특정 코드베이스, 함수 이름, 비즈니스 로직에 맞게 조정하는 데 집중하세요.

💡 연습 템플릿: NetFUNNEL SDK 통합 연습을 위한 Android 애플리케이션 (Single Activity) 템플릿이 준비된 샘플 프로젝트를 확인하세요.


1단계: 세그먼트 생성

두 가지 제어 유형 모두 지원

코드 기반 통합은 기본 제어구간 제어를 모두 지원합니다. 이 가이드는 구간 제어를 사용합니다.

1.1 새 세그먼트 생성

  1. NetFUNNEL 콘솔 → 프로젝트세그먼트로 이동합니다
  2. + 버튼을 클릭하여 새 세그먼트를 생성합니다

Create segment button

1.2 제어 유형 선택

구간 제어를 선택하고 다음을 클릭합니다

Select Section Control

1.3 세그먼트 구성

세그먼트 이름: 설명적인 이름을 입력합니다 (예: "결제 프로세스", "등록 흐름", "예약 구간")

Enter section segment name

진입 상태:

  • 세그먼트 활성화 활성화됨
  • 진입 상태: 대기 (사용자를 대기실로 보냄)

Entry section segment status settings

대기실 적용:

  • 테스트를 위해 기본 설정 사용
  • 라이브 메시지는 비워 둡니다

Waiting room settings on section segment

진입 허용 수:

  • 테스트를 위해 0으로 설정 (아무도 허용되지 않음, 대기실이 항상 나타남)
  • 이것은 구간에서 동시에 활성화될 수 있는 사용자 수를 제어합니다

Limited inflow setting on section segment

1.4 세그먼트 생성

생성을 클릭하여 세그먼트를 완료합니다

Segment created of section segment


2단계: 키 발급 통합 지점 식별 (nfStartSection)

샘플 애플리케이션

다음 예제는 데모 목적으로 샘플 애플리케이션을 사용합니다. 실제 애플리케이션 코드는 여기에 표시된 것과 자연스럽게 다를 수 있습니다. 통합 패턴을 특정 코드 구조, 버튼 ID, 함수 이름, 비즈니스 로직에 맞게 조정하세요.

💡 연습 프로젝트가 필요하신가요? NetFUNNEL SDK 통합 연습을 위한 Android 애플리케이션 (Single Activity) 템플릿이 준비된 샘플 프로젝트를 확인하세요.

샘플 애플리케이션 이해:

NetFUNNEL 구간 보호가 적용되어야 하는 위치를 이해하기 위해 샘플 애플리케이션을 살펴보겠습니다:

2.1 레이아웃에서 대상 버튼 식별

<!-- fragment_main.xml -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_section_control_function"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
app:cardCornerRadius="12dp"
app:cardElevation="4dp"
app:rippleColor="?attr/colorSecondary"
app:strokeColor="?attr/colorSecondary"
app:strokeWidth="1dp">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/section_control_function"
android:textAppearance="?attr/textAppearanceTitleLarge"
android:textColor="?attr/colorSecondary" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="@string/section_control_function_desc"
android:textAppearance="?attr/textAppearanceBodyMedium" />

</LinearLayout>
</com.google.android.material.card.MaterialCardView>

이 샘플에 대한 가정:

  • "구간 제어 (코드 기반 통합)" 카드(card_section_control_function)는 다단계 프로세스를 나타냅니다
  • 이것은 결제 흐름, 등록 프로세스, 예약 워크플로우 또는 다단계 양식일 수 있습니다
  • 사용자는 여러 화면을 탐색합니다: Section1 → Section2 → End
  • 이 전체 흐름에서 동시에 있을 수 있는 사용자 수를 제어해야 합니다

2.2 이 버튼의 클릭 리스너 찾기

// MainFragment.kt
override fun setupViews() {
binding.cardBasicControlFunction.setOnClickListener {
Log.d("MainActivity", "Basic Control Function button clicked")
lifecycleScope.launch {
navigationManager.navigateWithDelay(
R.id.action_mainFragment_to_basicControlFragment
)
}
}

binding.cardSectionControlFunction.setOnClickListener {
Log.d("MainActivity", "Section Control Function button clicked")
lifecycleScope.launch {
navigationManager.navigateWithDelay(
R.id.action_mainFragment_to_sectionControlSection1Fragment
)
}
}
}

2.3 구간 흐름 검토

전체 구간 흐름:

  1. MainFragment: 사용자가 구간 제어 카드를 클릭합니다
  2. SectionControlSection1Fragment: 프로세스의 첫 번째 단계
  3. SectionControlSection2Fragment: 프로세스의 두 번째 단계
  4. SectionControlEndFragment: 최종 완료 단계

통합 전략:

  • 구간 진입: 네비게이션 전에 MainFragment에서 nfStartSection() 호출
  • 구간 활동: 사용자는 Section1 → Section2 → End 내에서 자유롭게 탐색할 수 있습니다
  • 구간 종료: 프로세스가 완료되면 SectionControlEndFragment에서 nfStopSection() 호출

2.4 통합 지점 식별

  1. 대상 카드: card_section_control_function (다단계 프로세스 진입)
  2. 클릭 리스너: setupViews() 메서드가 클릭 핸들러를 설정합니다
  3. 통합 위치: navigationManager.navigateWithDelay()가 호출되기 직전
  4. 여기서 하는 이유: 보호된 구간에 진입하기 직전의 정확한 시점입니다
  5. 보호 전략: 구간 진입 전에 NetFUNNEL 구간 큐를 추가합니다

전체 흐름 분석:

  1. Fragment 생성: onViewCreated()setupViews()를 호출합니다
  2. 버튼 설정: setupViews()가 각 카드의 클릭 리스너를 설정합니다
  3. 사용자 작업: 사용자가 "구간 제어 (코드 기반 통합)" 카드를 클릭합니다
  4. 현재 동작: navigationManager.navigateWithDelay()가 즉시 실행됩니다
  5. 구간 로드: 이것이 다단계 프로세스 진입을 트리거합니다

로직:

  • NetFUNNEL 없이: 카드 클릭 → 즉시 구간 진입 → 잠재적 동시 사용자 수 초과
  • NetFUNNEL 사용: 카드 클릭 → 큐 확인 → 제어된 구간 진입 → 동시 사용자 수 유지

3단계: 키 발급 함수 구현 (nfStartSection)

코드에 맞게 조정

아래 예제는 샘플 애플리케이션의 MainFragment 클릭 핸들러에 NetFUNNEL을 통합하는 방법을 보여줍니다. 이 패턴을 실제 코드 구조에 맞게 조정하세요 - 보호가 필요한 다른 함수 이름, 이벤트 핸들러 또는 비즈니스 로직이 있을 수 있습니다.

3.1 키 가져오기

먼저 콘솔에서 프로젝트 키와 세그먼트 키를 찾으세요:

  1. NetFUNNEL 콘솔 → 프로젝트세그먼트로 이동합니다
  2. 세그먼트를 클릭합니다
  3. 프로젝트 키세그먼트 키를 복사합니다

Project and segment keys of section control

3.2 nfStartSection 함수 이해

nfStartSection 함수는 다음과 같은 기본 구조를 가집니다:

Netfunnel.nfStartSection(
projectKey = "your_project_key", // 콘솔에서 가져옴
segmentKey = "your_segment_key", // 콘솔에서 가져옴
callback = yourCallback, // 응답을 처리하기 위한 콜백
activity = this // 현재 activity 컨텍스트
)

Java 동등 코드:

Netfunnel.INSTANCE.nfStartSection(
"your_project_key", // 콘솔에서 가져옴
"your_segment_key", // 콘솔에서 가져옴
yourCallback, // 응답을 처리하기 위한 콜백
this // 현재 activity 컨텍스트
);
API 참조

nfStartSection 매개변수, 콜백 처리 및 응답 형식에 대한 자세한 내용은 API 참조를 참조하세요.

3.3 현재 코드로 시작

현재 구현:

// MainFragment.kt
override fun setupViews() {
binding.cardSectionControlFunction.setOnClickListener {
Log.d("MainActivity", "Section Control Function button clicked")
lifecycleScope.launch {
navigationManager.navigateWithDelay(
R.id.action_mainFragment_to_sectionControlSection1Fragment
)
}
}
}

핵심 개념:

  • 비즈니스 로직: navigationManager.navigateWithDelay()는 다단계 구간 진입을 나타냅니다
  • 통합 지점: 이 구간 진입을 NetFUNNEL 보호로 감싸야 합니다
  • 감싸기 전략: 다단계 프로세스가 시작되기 전에 nfStartSection()을 사용하여 동시 사용자 수를 제어합니다

여기서 감싸는 이유:

  • 이것은 구간 진입이 시작되기 직전의 정확한 시점입니다
  • 여기서 감싸면 전체 다단계 구간을 동시 사용자 수 초과로부터 보호합니다
  • 비즈니스 로직은 변경되지 않습니다 - 동시 사용자 수 제어 레이어만 추가합니다

3.4 필수 import 추가

NetFUNNEL을 구현하기 전에 Fragment에 필요한 import를 추가하세요:

// MainFragment.kt
import com.nf4.Netfunnel
import com.nf4.NetfunnelCallback

Java 동등 코드:

// MainFragment.java
import com.nf4.Netfunnel;
import com.nf4.NetfunnelCallback;

핵심 import:

  • com.nf4.Netfunnel - NetFUNNEL 메인 클래스
  • com.nf4.NetfunnelCallback - 응답을 위한 콜백 인터페이스

3.5 기본 NetFUNNEL 보호 추가 (성공만)

비즈니스 로직 감싸기:

// MainFragment.kt
import com.nf4.Netfunnel
import com.nf4.NetfunnelCallback

override fun setupViews() {
binding.cardBasicControlFunction.setOnClickListener {
Log.d("MainActivity", "Basic Control Function button clicked")
lifecycleScope.launch {
navigationManager.navigateWithDelay(
R.id.action_mainFragment_to_basicControlFragment
)
}
}

binding.cardSectionControlFunction.setOnClickListener {
Log.d("MainActivity", "Section Control Function button clicked")
startSectionControl()
}
}

private fun startSectionControl() {
Netfunnel.nfStartSection(
projectKey = "your_project_key",
segmentKey = "your_segment_key",
callback = sectionControlCallback,
activity = requireActivity()
)
}

private val sectionControlCallback = object : NetfunnelCallback() {
override fun onSuccess(statusCode: Int, message: String) {
// 사용자가 진행할 수 있음 - 원래 로직 실행
Log.d("NetFUNNEL", "onSuccess(statusCode=$statusCode, message='$message')")
lifecycleScope.launch {
navigationManager.navigateWithDelay(
R.id.action_mainFragment_to_sectionControlSection1Fragment
)
}
}

override fun onBlock(statusCode: Int, message: String) {
Log.d("NetFUNNEL", "onBlock(statusCode=$statusCode, message='$message')")
}

override fun onClose(statusCode: Int, message: String) {
Log.d("NetFUNNEL", "onClose(statusCode=$statusCode, message='$message')")
}

override fun onContinue(
statusCode: Int,
message: String,
aheadWait: Int,
behindWait: Int,
waitTime: String,
progressRate: Int
) {
Log.d("NetFUNNEL", "onContinue(statusCode=$statusCode, message='$message', aheadWait=$aheadWait, behindWait=$behindWait, waitTime='$waitTime', progressRate=$progressRate)")
}

override fun onError(statusCode: Int, message: String) {
Log.d("NetFUNNEL", "onError(statusCode=$statusCode, message='$message')")
}

override fun onNetworkError(statusCode: Int, message: String) {
Log.d("NetFUNNEL", "onNetworkError(statusCode=$statusCode, message='$message')")
}
}

변경 사항:

  • 감쌈: navigationManager.navigateWithDelay()가 이제 onSuccess 콜백 내부에 있습니다
  • 조건부: 특정 카드만 NetFUNNEL 보호를 받습니다
  • 성공만: NetFUNNEL이 진입을 허용할 때만 구간 진입이 발생합니다
  • 완전한 인터페이스: 모든 필수 콜백 메서드가 적절한 로깅과 함께 구현됩니다
Android 인터페이스 요구사항

Android에서 NetfunnelCallback은 모든 메서드를 구현해야 하는 인터페이스입니다. onSuccess만 구현할 수 없습니다 - 모든 콜백 메서드에 대한 구현을 제공해야 합니다. 이 구현은 모든 응답 유형에 대한 적절한 로깅과 함께 완전한 콜백 처리를 제공합니다.

이제 구현이 올바르게 작동하는지 테스트해보겠습니다.

앱을 실행하고 "구간 제어 (코드 기반 통합)" 카드를 클릭합니다. 화면에 대기실 WebView가 나타나야 합니다. 모든 것이 올바르게 작동하는지 확인하려면 Logcat에서 NetFUNNEL 로그를 확인하세요.

대기실이 나타나지 않는 경우

대기실이 보이지 않으면 세그먼트 구성 단계에서 진입 허용 수를 0으로 설정했는지 확인하세요. 이 설정은 사용자를 대기실로 보낼지 직접 진행할 수 있게 할지를 제어합니다.

더 나은 디버깅을 위한 NetFUNNEL 로깅 활성화:

Application 클래스에서 printLog = true를 설정하여 디버그 로깅을 활성화한 다음, Logcat에서 package:mine NetFUNNEL로 필터링합니다. 자세한 설정 지침은 NetFUNNEL 초기화 테스트) 섹션을 참조하세요.

확인할 사항:

진입 허용 수 = 0으로 구간 제어 카드를 클릭하면 다음과 같은 로그가 보여야 합니다:

2025-09-15 17:10:41.744  6881-6881  NetFUNNEL               com...ample_android_single_activity  D  [NF4] Initialization successful. NetFUNNEL Version: 4.3.3-onprem
2025-09-15 17:10:47.409 6881-6897 NetFUNNEL com...ample_android_single_activity D [NF4] Initial entry detected. Request(5101), Work(projectKey=service_1, segmentKey=segKey_2548), Control(SECTION)
2025-09-15 17:10:47.461 6881-6899 NetFUNNEL com...ample_android_single_activity D [NF4] Sending 5101 request. https://nf4-onprem-demo-4525.stclab.com/ts.wseq?opcode=5101&sid=service_1&aid=segKey_2548
2025-09-15 17:10:48.907 6881-6897 NetFUNNEL com...ample_android_single_activity D [NF4] Received 5101 response. Response(timestamp=1757923849180, code=201, msg=null, key=72D5F5FB98C3C27813CF5B7106D11EDDFB3008B12E6BFFA493E027A749A853E1BE450D9D849A0A717DD25BEC75DE40A3BCFD08B8F833299D4D743DBF3C84B6D4359F81879079494C2A0482939478A897347B786360D662C7FD9BAB75A3C285D32C312C302C302C302C302C30, nwait=0, nnext=0, tps=0.0, ttl=1, ip=nf4-onprem-demo-4525.stclab.com, port=443, vwrHtml=https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html, vwrType=wait, preBeginTs=null, preEndTs=null, postBeginTs=null, postEndTs=null, sticky=nf1, liveMessage=null, chkEnterCnt=0)
2025-09-15 17:10:48.915 6881-6897 NetFUNNEL com...ample_android_single_activity D [NF4] Loading the virtual room. Work(projectKey=service_1, segmentKey=segKey_2548), Status(WAIT)
2025-09-15 17:10:49.850 6881-6897 NetFUNNEL com...ample_android_single_activity D [NF4] Fetching HTML content from following URL. https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html
2025-09-15 17:10:50.510 6881-6989 NetFUNNEL com...ample_android_single_activity D [NF4] Sending 5002 request. https://nf4-onprem-demo-4525.stclab.com/ts.wseq?opcode=5002&key=72D5F5FB98C3C27813CF5B7106D11EDDFB3008B12E6BFFA493E027A749A853E1BE450D9D849A0A717DD25BEC75DE40A3BCFD08B8F833299D4D743DBF3C84B6D4359F81879079494C2A0482939478A897347B786360D662C7FD9BAB75A3C285D32C312C302C302C302C302C30&sticky=nf1
2025-09-15 17:10:50.666 6881-6988 NetFUNNEL com...ample_android_single_activity D [NF4] Received 5002 response. Response(timestamp=1757923851681, code=201, msg=null, key=72D5F5FB98C3C27813CF5B7106D11EDDF35A5F6A6BE9A186341F85B4481E24B2EB67CFE5013835FCED7D49E3D8A34875BCFD08B8F833299D4D743DBF3C84B6D4359F81879079494C2A0482939478A897347B786360D662C7FD9BAB75A3C285D3302C312C302C302C302C302C30, nwait=0, nnext=0, tps=0.0, ttl=1, ip=nf4-onprem-demo-4525.stclab.com, port=443, vwrHtml=https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html, vwrType=wait, preBeginTs=null, preEndTs=null, postBeginTs=null, postEndTs=null, sticky=nf1, liveMessage=null, chkEnterCnt=0)
2025-09-15 17:10:51.694 6881-6988 NetFUNNEL com...ample_android_single_activity D [NF4] Sending 5002 request. https://nf4-onprem-demo-4525.stclab.com/ts.wseq?opcode=5002&key=72D5F5FB98C3C27813CF5B7106D11EDDF35A5F6A6BE9A186341F85B4481E24B2EB67CFE5013835FCED7D49E3D8A34875BCFD08B8F833299D4D743DBF3C84B6D4359F81879079494C2A0482939478A897347B786360D662C7FD9BAB75A3C285D3302C312C302C302C302C302C30&sticky=nf1
2025-09-15 17:10:51.732 6881-6986 NetFUNNEL com...ample_android_single_activity D [NF4] Received 5002 response. Response(timestamp=1757923852822, code=201, msg=null, key=72D5F5FB98C3C27813CF5B7106D11EDDAE345D62D157667B59776AA8C70B32D3B0D23D1D5FE2FD80B12E5F3FCB932C3BBCFD08B8F833299D4D743DBF3C84B6D4359F81879079494C2A0482939478A897C379CCB8ED96A113D843D4FC24D7341C2C312C302C302C302C302C30, nwait=0, nnext=0, tps=0.0, ttl=1, ip=nf4-onprem-demo-4525.stclab.com, port=443, vwrHtml=https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html, vwrType=wait, preBeginTs=null, preEndTs=null, postBeginTs=null, postEndTs=null, sticky=nf1, liveMessage=null, chkEnterCnt=0)

모든 것이 작동하고 있음을 나타내는 핵심 지표:

로그 메시지의미상태
[NF4] Initialization successfulNetFUNNEL 에이전트가 올바르게 로드됨✅ 정상
[NF4] Initial entry detectednfStartSection()가 성공적으로 호출됨✅ 정상
[NF4] Sending 5101 requestNetFUNNEL 서버로 요청 전송됨✅ 정상
[NF4] Received 5101 response with code=201서버가 WAIT 상태로 응답함✅ 정상
[NF4] Loading the virtual room대기실 WebView가 로드 중✅ 정상
[NF4] Fetching HTML content대기실 HTML이 로드 중✅ 정상
[NF4] Sending 5002 request주기적인 재진입 요청 (폴링)✅ 정상
[NF4] Received 5002 response with code=201서버가 WAIT 상태로 응답함✅ 정상

응답 확인:

  • 로그에서 ts.wseq?opcode=5002 요청을 찾으세요
  • 응답이 code=201 (WAIT)을 표시하는지 확인하세요
  • 201 = WAIT, 200 = PASS (진입 허용)
  • 여기서는 진입 허용 수가 0 (동시 사용자 수 = 0)이므로 올바른 응답은 201입니다

문제가 발생하는 경우:

  • 로그가 나타나지 않음: 초기화에서 printLog = true가 설정되어 있는지 확인
  • 대기실이 나타나지 않음: 콘솔에서 진입 허용 수가 0으로 설정되어 있는지 확인
  • 앱 크래시: 모든 콜백 메서드가 올바르게 구현되어 있는지 확인
  • 네트워크 오류: clientId 및 네트워크 연결 확인

대기실과 로그가 보이면 기본 구현이 작동 중입니다! 이제 더 나은 오류 관리를 위해 콜백 처리를 향상시킬 수 있습니다. 진입을 테스트하려면 콘솔에서 진입 허용 수를 1 (동시 사용자 수 = 1)로 변경하세요.

3.6 완전한 콜백 처리 추가

이제 더 나은 오류 관리 및 사용자 경험을 위해 콜백 처리를 개선하겠습니다:

이전 단계에서 모든 콜백 메서드를 기본 로깅과 함께 구현했습니다. 이제 프로덕션 환경에서 견고한 서비스 가용성과 최적의 사용자 경험을 보장하기 위해 오류 처리를 향상시키겠습니다.

완전한 콜백 처리가 필수인 이유:

  • 사용자 경험: 다양한 응답 유형에 적절한 사용자 피드백이 필요합니다
  • 서비스 안정성: 오류 상태가 사용자의 워크플로우를 중단하지 않아야 합니다
  • 디버깅: 포괄적인 로깅이 문제를 빠르게 식별하는 데 도움이 됩니다
  • 비즈니스 연속성: NetFUNNEL에 문제가 발생해도 서비스가 계속되어야 합니다

견고한 오류 처리로 sectionControlCallback 향상:

// MainFragment.kt - 완전한 처리를 포함한 sectionControlCallback 업데이트
private val sectionControlCallback = object : NetfunnelCallback() {
override fun onSuccess(statusCode: Int, message: String) {
// 사용자가 진행할 수 있음 - 원래 로직 실행
Log.d("NetFUNNEL", "onSuccess(statusCode=$statusCode, message='$message')")
lifecycleScope.launch {
navigationManager.navigateWithDelay(
R.id.action_mainFragment_to_sectionControlSection1Fragment
)
}
}

override fun onError(statusCode: Int, message: String) {
// 시스템 오류 발생 - 서비스 가용성을 유지하기 위해 원래 로직 진행
Log.d("NetFUNNEL", "onError(statusCode=$statusCode, message='$message')")
lifecycleScope.launch {
navigationManager.navigateWithDelay(
R.id.action_mainFragment_to_sectionControlSection1Fragment
)
}
}

override fun onNetworkError(statusCode: Int, message: String) {
// 네트워크 오류 발생 - 디버깅을 위해 로깅만 수행, 비즈니스 로직은 실행하지 않음
Log.d("NetFUNNEL", "onNetworkError(statusCode=$statusCode, message='$message')")
// 참고: 여기서는 비즈니스 로직을 실행하지 않음 - 아래 설명 참조
}

override fun onBlock(statusCode: Int, message: String) {
// 사용자가 차단됨 - 적절한 메시지 표시
Log.d("NetFUNNEL", "onBlock(statusCode=$statusCode, message='$message')")
}

override fun onClose(statusCode: Int, message: String) {
// 사용자가 대기실을 닫음 - 적절히 처리
Log.d("NetFUNNEL", "onClose(statusCode=$statusCode, message='$message')")
// 메인 Fragment에 머물기 - 사용자가 취소함
}

override fun onContinue(
statusCode: Int,
message: String,
aheadWait: Int,
behindWait: Int,
waitTime: String,
progressRate: Int
) {
Log.d("NetFUNNEL", "onContinue(statusCode=$statusCode, message='$message', aheadWait=$aheadWait, behindWait=$behindWait, waitTime='$waitTime', progressRate=$progressRate)")
}
}

응답 처리 전략:

응답 유형동작비즈니스 로직
Success실행✅ 예
Error실행✅ 예
NetworkError로깅만❌ 아니오
Block로깅만❌ 아니오
Close로깅만❌ 아니오
Continue로깅만❌ 아니오

onError는 비즈니스 로직을 실행하지만 onNetworkError는 실행하지 않는 이유:

onError (상태 코드 500) - 서버 오류:

  • 시나리오: NetFUNNEL 서버가 내부 오류를 만남
  • 전략: 서비스 가용성을 유지하기 위해 비즈니스 로직 실행
  • 근거: 서버 오류는 일반적으로 일시적이며 사용자 액세스를 차단하지 않아야 함
  • 결과: NetFUNNEL에 문제가 있어도 계속되는 견고한 서비스

onNetworkError (상태 코드 1001, 1002) - 네트워크 문제:

  • 시나리오: 네트워크 연결 문제 (오프라인, 타임아웃)
  • 전략: 로깅만 수행, 비즈니스 로직 실행 안 함
  • 근거: 자동 네트워크 복구를 위해 useNetworkRecoveryMode = true 사용
  • 결과: 네트워크 문제 중 사용자가 대기실에 머물고 연결이 복구되면 자동 재개

네트워크 복구 모드 구성:

최적의 네트워크 오류 처리를 위해 Application 클래스에서 네트워크 복구를 활성화합니다:

// SampleApplication.kt
Netfunnel.initialize(
clientId = "{{CLIENT_ID}}",
useNetworkRecoveryMode = true // 자동 네트워크 복구 활성화
)

변경 사항:

  • 견고한 오류 처리: onError는 최대 서비스 가용성을 위해 비즈니스 로직을 진행합니다
  • 스마트 네트워크 처리: onNetworkError는 수동 처리 대신 네트워크 복구 모드에 의존합니다
  • 개선된 사용자 경험: 다양한 응답 상태에 대한 더 나은 처리
  • 프로덕션 준비: 견고한 오류 처리는 NetFUNNEL에 문제가 발생해도 서비스가 계속되도록 보장합니다
  • 포괄적인 로깅: 모든 응답 유형 및 디버깅에 대한 상세한 콘솔 메시지
완전한 API 참조

모든 콜백 응답 유형, 상태 코드, 응답 객체 구조 및 고급 콜백 패턴에 대한 자세한 정보는 API 참조를 참조하세요.

3.7 주요 구현 포인트

  1. 프로젝트/세그먼트 키: NetFUNNEL 콘솔에서 정확한 키를 사용합니다
  2. 필수 import: com.nf4.Netfunnelcom.nf4.NetfunnelCallback import를 추가합니다
  3. 콜백 구현: 모든 콜백 메서드를 구현합니다 (Android 인터페이스 요구사항)
  4. 견고한 오류 처리:
    • onSuccessonError는 서비스 가용성을 위해 비즈니스 로직을 실행합니다
    • onNetworkError는 로깅만 수행합니다 (자동 복구를 위해 useNetworkRecoveryMode = true 사용)
  5. Activity 컨텍스트: 항상 현재 activity 컨텍스트를 nfStartSection()에 전달합니다
  6. 포괄적인 로깅: 디버깅을 위해 모든 콜백 응답을 로깅합니다

4단계: 키 반환 통합 지점 식별 (nfStopSection)

샘플 애플리케이션

다음 예제는 데모 목적으로 샘플 애플리케이션을 사용합니다. 실제 애플리케이션 코드는 여기에 표시된 것과 자연스럽게 다를 수 있습니다. 통합 패턴을 특정 코드 구조, 비즈니스 로직 완료 지점, 키 반환 요구사항에 맞게 조정하세요.

💡 연습 프로젝트가 필요하신가요? NetFUNNEL SDK 통합 연습을 위한 Android 애플리케이션 (Single Activity) 템플릿이 준비된 샘플 프로젝트를 확인하세요.

샘플 애플리케이션 이해:

NetFUNNEL 키를 반환하기 위해 nfStopSection을 호출해야 하는 위치를 이해하기 위해 샘플 애플리케이션을 살펴보겠습니다.

4.1 구간 완료 지점 식별

nfStartSection 성공 후 현재 흐름:

// 3단계에서 - nfStartSection이 성공할 때
override fun onSuccess(statusCode: Int, message: String) {
Log.d("NetFUNNEL", "onSuccess(statusCode=$statusCode, message='$message')")
lifecycleScope.launch {
navigationManager.navigateWithDelay(
R.id.action_mainFragment_to_sectionControlSection1Fragment
)
}
}

다음에 발생하는 일:

  1. 사용자가 SectionControlSection1Fragment로 이동 - 프로세스의 첫 번째 단계
  2. 사용자가 SectionControlSection2Fragment로 이동 - 프로세스의 두 번째 단계
  3. 사용자가 SectionControlEndFragment로 이동 - 최종 완료 단계
  4. 사용자의 구간 세션이 완료됨 - 여기서 키를 반환해야 합니다
  5. 키를 반환해야 함 - 대기열의 다음 사용자가 구간에 진입할 수 있도록 합니다

nfStopSection 구현에 대한 중요 참고사항: nfStopSectionnfStartSection이 먼저 호출될 필요 없이 독립적으로 호출할 수 있습니다. nfStartSection이 호출되지 않은 경우, NetFUNNEL은 필요시 키 해제를 자동으로 처리하거나 키가 없으면 아무 작업도 수행하지 않습니다. 이로 인해 조건부 확인 없이 어떤 시나리오에서도 nfStopSection을 안전하게 호출할 수 있어 구현이 단순해집니다.

4.2 키 반환을 위한 통합 지점 식별

통합 지점 옵션:

통합 지점사용 시기장점
구간 종료 Fragment다단계 완료 흐름명확한 완료 지점, 대부분의 경우에 작동합니다
비즈니스 로직 완료복잡한 작업 (API 호출, 처리)정밀한 제어, 실제 작업 후 키 반환
사용자 작업 완료사용자 시작 완료사용자가 작업을 완료할 때 키 반환

4.3 적절한 통합 지점 선택

샘플 애플리케이션의 경우:

현재 비즈니스 흐름: 다단계 네비게이션 프로세스

  • 수행하는 작업: 사용자가 Section1 → Section2 → End를 거칩니다
  • 완료 시점: SectionControlEndFragment가 성공적으로 로드될 때
  • 최적 통합 지점: Fragment 생명주기 이벤트 (onViewCreated, setupViews)

통합 전략:

  1. 구간 완료: SectionControlEndFragment가 완전히 로드될 때 키 반환
  2. 간단하고 신뢰할 수 있음: 네비게이션 기반 구간 흐름에 작동합니다
  3. 사용자 경험: 사용자가 전체 구간을 완료했을 때 키가 반환됩니다

4.4 통합 지점 로직 검증

전체 흐름 분석:

  1. 사용자가 버튼 클릭nfStartSection() 호출됨
  2. 대기실 나타남 → 사용자가 대기열에서 대기
  3. 진입 허용됨onSuccess 콜백 발생
  4. 구간 네비게이션 시작 → 사용자가 Section1 → Section2 → End를 진행합니다
  5. SectionControlEndFragment 로드됨 → 사용자가 구간을 완료했습니다
  6. 키 반환 필요nfStopSection()을 호출하여 구간 슬롯 해제

이 통합 지점이 합리적인 이유:

  • 사용자 경험: 사용자가 전체 구간을 완료했을 때 키가 반환됩니다
  • 동시 사용자 수 관리: 현재 사용자가 구간을 완료하자마자 다음 사용자가 진입할 수 있습니다
  • 리소스 효율성: 불필요한 동시 사용자 수 차단을 방지합니다
  • 구현 단순성: 구현 및 유지 관리가 쉽습니다

핵심 통찰: nfStopSection 통합 지점은 사용자의 의도한 구간 작업이 실제로 완료되고 대기한 구간 사용을 마친 위치여야 합니다.

구간 제어 vs 기본 제어 키 관리

진입 후 키가 빠르게 반환되는 기본 제어와 달리, 구간 제어는 전체 구간이 완료될 때까지 키를 유지합니다. 이 근본적인 차이는 nfStopSection()을 언제 어디서 호출해야 하는지에 영향을 줍니다:

  • 기본 제어: 진입 직후 키 반환 (예: Fragment 로드 후)
  • 구간 제어: 전체 구간 동안 키 유지 (예: Section1 → Section2 → End)

5단계: 키 반환 함수 구현 (nfStopSection)

애플리케이션에 맞게 조정

아래 예제는 구간이 완료될 때 키를 반환하는 다양한 접근 방식을 보여줍니다. 애플리케이션 아키텍처에 가장 적합한 접근 방식을 선택하세요 - Fragment 네비게이션, API 호출 또는 기타 비즈니스 로직 완료 후 키를 반환해야 하는지 여부에 따라 다릅니다.

5.1 nfStopSection 함수 이해

nfStopSection 함수는 다음과 같은 기본 구조를 가집니다:

Netfunnel.nfStopSection(
projectKey = "your_project_key", // nfStartSection 키와 정확히 일치해야 함
segmentKey = "your_segment_key", // nfStartSection 키와 정확히 일치해야 함
completeCallback = yourCompleteCallback // 완료를 처리하기 위한 콜백
)

Java 동등 코드:

Netfunnel.INSTANCE.nfStopSection(
"your_project_key", // nfStartSection 키와 정확히 일치해야 함
"your_segment_key", // nfStartSection 키와 정확히 일치해야 함
yourCompleteCallback // 완료를 처리하기 위한 콜백
);

핵심 요구사항:

  • 정확한 키 일치: 키는 nfStartSection()에서 사용된 것과 동일해야 합니다
  • 타이밍: nfStartSection() 직후가 아니라 구간이 완료된 후에 호출합니다
  • 콜백: 완료 응답을 처리하기 위해 NetfunnelCompleteCallback을 사용합니다

5.2 필수 import 추가

nfStopSection을 구현하기 전에 Fragment에 필요한 import를 추가합니다:

// SectionControlEndFragment.kt
import com.nf4.Netfunnel
import com.nf4.NetfunnelCompleteCallback

핵심 Import:

  • com.nf4.Netfunnel - 메인 NetFUNNEL 클래스 (nfStartSection에 이미 import됨)
  • com.nf4.NetfunnelCompleteCallback - 키 반환 완료를 위한 콜백 인터페이스

5.3 구간 키 반환 추가 (Fragment 생명주기)

SectionControlEndFragment가 로드될 때 키 반환:

// SectionControlEndFragment.kt
import com.nf4.Netfunnel
import com.nf4.NetfunnelCompleteCallback

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

// 구간 종료 Fragment가 완전히 로드될 때 키 반환
Netfunnel.nfStopSection(
projectKey = "your_project_key",
segmentKey = "your_segment_key",
completeCallback = completeCallback
)
}

private val completeCallback = object : NetfunnelCompleteCallback() {
override fun onComplete(statusCode: Int, message: String) {
Log.d("NetFUNNEL", "Section key returned: $message")
}
}

변경 사항:

  • 구간 생명주기: SectionControlEndFragment가 완전히 로드될 때 키 반환
  • 구간 완료: 다단계 구간 시나리오에 작동
  • 직접 호출: NetFUNNEL이 초기화되고 사용 가능하다고 가정

이제 키 반환 구현을 테스트하여 모든 것이 올바르게 작동하는지 확인하세요.

앱을 실행하고 다음 테스트 시퀀스를 따르세요:

  1. "구간 제어 (코드 기반 통합)" 카드를 클릭합니다 - 대기실이 나타나는 것을 볼 수 있습니다
  2. NetFUNNEL 콘솔에서 진입 허용 수를 0에서 1로 변경합니다 - 이것은 진입을 허용합니다
  3. 대기실이 닫히는 것을 관찰합니다 - 대기실이 사라지고 SectionControlSection1Fragment로 이동해야 합니다
  4. Section1 → Section2 → End를 통해 탐색합니다 - 구간 흐름을 완료합니다
  5. Logcat에서 키 타임아웃 연장 로그를 확인합니다 - 구간 중에 5003 요청 로그가 보여야 합니다
  6. Logcat에서 키 반환 로그를 확인합니다 - 구간이 완료될 때 5004 요청 로그가 보여야 합니다

더 나은 디버깅을 위해 NetFUNNEL 로깅 활성화:

Application 클래스에서 printLog = true를 설정하여 디버그 로깅을 활성화한 다음 Logcat을 package:mine NetFUNNEL로 필터링하세요. 자세한 설정 지침은 NetFUNNEL 초기화 테스트) 섹션을 참조하세요.

확인할 사항:

구간 흐름을 완료하면 (Section1 → Section2 → End) 다음과 같은 로그가 표시됩니다:

2025-09-15 17:30:24.506  7138-7138  NetFUNNEL               com...ample_android_single_activity  D  [NF4] Initialization successful. NetFUNNEL Version: 4.3.3-onprem
2025-09-15 17:30:27.647 7138-7158 NetFUNNEL com...ample_android_single_activity D [NF4] Initial entry detected. Request(5002), Work(projectKey=service_1, segmentKey=segKey_2548), Control(SECTION)
2025-09-15 17:30:27.696 7138-7156 NetFUNNEL com...ample_android_single_activity D [NF4] Sending 5002 request. https://nf4-onprem-demo-4525.stclab.com/ts.wseq?opcode=5002&key=72D5F5FB98C3C27813CF5B7106D11EDD7796632DC8DA328ACD21E27878B567DD43DDCFCA79225210E75F65F358703A67BCFD08B8F833299D4D743DBF3C84B6D4359F81879079494C2A0482939478A89794D7C8E4BEA05A019FF78476D2CEAF2F2C312C302C302C302C302C30&sticky=nf1
2025-09-15 17:30:29.267 7138-7156 NetFUNNEL com...ample_android_single_activity D [NF4] Received 5002 response. Response(timestamp=1757925029406, code=201, msg=null, key=B04303FD454C5CA18924C54783F2BC494399438D1C0EE7AA0512477FC651CDA8D0C0F1928FD7C09AB18E7593EAE92B7FBCFD08B8F833299D4D743DBF3C84B6D4359F81879079494C2A0482939478A897BD882ABDAC46FAEC31605E83E9F49CD72C312C312C302C302C302C30, nwait=1, nnext=0, tps=0.0, ttl=1, ip=nf4-onprem-demo-4525.stclab.com, port=443, vwrHtml=https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html, vwrType=wait, preBeginTs=null, preEndTs=null, postBeginTs=null, postEndTs=null, sticky=nf1, liveMessage=null, chkEnterCnt=0)
2025-09-15 17:30:29.274 7138-7156 NetFUNNEL com...ample_android_single_activity D [NF4] Loading the virtual room. Work(projectKey=service_1, segmentKey=segKey_2548), Status(WAIT)
2025-09-15 17:30:30.007 7138-7156 NetFUNNEL com...ample_android_single_activity D [NF4] Fetching HTML content from following URL. https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html
2025-09-15 17:30:30.396 7138-7230 NetFUNNEL com...ample_android_single_activity D [NF4] Sending 5002 request. https://nf4-onprem-demo-4525.stclab.com/ts.wseq?opcode=5002&key=B04303FD454C5CA18924C54783F2BC494399438D1C0EE7AA0512477FC651CDA8D0C0F1928FD7C09AB18E7593EAE92B7FBCFD08B8F833299D4D743DBF3C84B6D4359F81879079494C2A0482939478A897BD882ABDAC46FAEC31605E83E9F49CD72C312C312C302C302C302C30&sticky=nf1
2025-09-15 17:30:30.462 7138-7157 NetFUNNEL com...ample_android_single_activity D [NF4] Received 5002 response. Response(timestamp=1757925031536, code=201, msg=null, key=B04303FD454C5CA18924C54783F2BC496041E95666117EA3413E1FA1CF7D93C83F3BBCFCE4DDF36303B4D29BAB59285BBCFD08B8F833299D4D743DBF3C84B6D4359F81879079494C2A0482939478A89724B5E2DCE14558567E22635B848476732C312C302C302C302C302C30, nwait=0, nnext=0, tps=0.0, ttl=1, ip=nf4-onprem-demo-4525.stclab.com, port=443, vwrHtml=https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html, vwrType=wait, preBeginTs=null, preEndTs=null, postBeginTs=null, postEndTs=null, sticky=nf1, liveMessage=null, chkEnterCnt=0)
2025-09-15 17:30:36.726 7138-7182 NetFUNNEL com...ample_android_single_activity D [NF4] Received 5002 response. Response(timestamp=1757925037810, code=200, msg=null, key=B04303FD454C5CA18924C54783F2BC49C0C7D49B86899E082C565EED4F443625926DA265156909BA64B87F00F7C565325F6C6B5A1410BD25FF45AAF2D0FCF38570442F1BB67CC53F28D02A19B48CDEE2902D1EA62CCD2C8E006BBC45D5A080019F32F0077492B7D5F8DB92356655AFF1302C302C30, nwait=0, nnext=0, tps=0.0, ttl=0, ip=nf4-onprem-demo-4525.stclab.com, port=443, vwrHtml=https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html, vwrType=null, preBeginTs=null, preEndTs=null, postBeginTs=null, postEndTs=null, sticky=nf1, liveMessage=null, chkEnterCnt=1)
2025-09-15 17:30:36.740 7138-7182 NetFUNNEL com...ample_android_single_activity D [NF4] "Success" response from NetFUNNEL Server.
2025-09-15 17:30:36.740 7138-7182 NetFUNNEL com...ample_android_single_activity D onSuccess(statusCode=200, message='Success')
2025-09-15 17:30:36.750 7138-7182 NetFUNNEL com...ample_android_single_activity D [NF4] Key refresh attempt detected. Work(projectKey=service_1, segmentKey=segKey_2548), Control(SECTION)
2025-09-15 17:30:36.758 7138-7182 NetFUNNEL com...ample_android_single_activity D [NF4] Sending 5003 request. https://nf4-onprem-demo-4525.stclab.com/ts.wseq?opcode=5003&key=B04303FD454C5CA18924C54783F2BC49C0C7D49B86899E082C565EED4F443625926DA265156909BA64B87F00F7C565325F6C6B5A1410BD25FF45AAF2D0FCF38570442F1BB67CC53F28D02A19B48CDEE2902D1EA62CCD2C8E006BBC45D5A080019F32F0077492B7D5F8DB92356655AFF1302C302C30&sticky=nf1
2025-09-15 17:30:36.808 7138-7157 NetFUNNEL com...ample_android_single_activity D [NF4] Received 5003 response. Response(timestamp=1757925037885, code=201, msg=null, key=B04303FD454C5CA18924C54783F2BC49C0C7D49B86899E082C565EED4F443625926DA265156909BA64B87F00F7C565325F6C6B5A1410BD25FF45AAF2D0FCF38570442F1BB67CC53F28D02A19B48CDEE2902D1EA62CCD2C8E006BBC45D5A080019F32F0077492B7D5F8DB92356655AFF1312C302C30, nwait=0, nnext=0, tps=0.0, ttl=5, ip=nf4-onprem-demo-4525.stclab.com, port=443, vwrHtml=https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html, vwrType=null, preBeginTs=null, preEndTs=null, postBeginTs=null, postEndTs=null, sticky=nf1, liveMessage=null, chkEnterCnt=1)
2025-09-15 17:30:37.725 7138-7138 VRI[NetfunnelWebView] com...ample_android_single_activity D visibilityChanged oldVisibility=true newVisibility=false
2025-09-15 17:30:41.817 7138-7230 NetFUNNEL com...ample_android_single_activity D [NF4] Sending 5003 request. https://nf4-onprem-demo-4525.stclab.com/ts.wseq?opcode=5003&key=B04303FD454C5CA18924C54783F2BC49C0C7D49B86899E082C565EED4F443625926DA265156909BA64B87F00F7C565325F6C6B5A1410BD25FF45AAF2D0FCF38570442F1BB67CC53F28D02A19B48CDEE2902D1EA62CCD2C8E006BBC45D5A080019F32F0077492B7D5F8DB92356655AFF1312C302C30&sticky=nf1
2025-09-15 17:30:41.849 7138-7231 NetFUNNEL com...ample_android_single_activity D [NF4] Received 5003 response. Response(timestamp=1757925042935, code=201, msg=null, key=B04303FD454C5CA18924C54783F2BC49C3E3247A56D8C04F7F9FA55FB70138558B8260BDD3FAE86F40C4139CBCBD20FB5F6C6B5A1410BD25FF45AAF2D0FCF38570442F1BB67CC53F28D02A19B48CDEE2902D1EA62CCD2C8E006BBC45D5A08001715A51C76F286957F8DE56D6092043B1312C302C30, nwait=0, nnext=0, tps=0.0, ttl=5, ip=nf4-onprem-demo-4525.stclab.com, port=443, vwrHtml=https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html, vwrType=null, preBeginTs=null, preEndTs=null, postBeginTs=null, postEndTs=null, sticky=nf1, liveMessage=null, chkEnterCnt=1)
2025-09-15 17:30:59.015 7138-7158 NetFUNNEL com...ample_android_single_activity D [NF4] Key return attempt detected. Work(projectKey=service_1, segmentKey=segKey_2548), Control(SECTION)
2025-09-15 17:30:59.019 7138-7158 NetFUNNEL com...ample_android_single_activity D [NF4] Sending 5004 request. https://nf4-onprem-demo-4525.stclab.com/ts.wseq?opcode=5004&key=B04303FD454C5CA18924C54783F2BC49951551C40A5E72EE425E8BBE7154D8917EDEA09F96A8542EE989BA43DF1619125F6C6B5A1410BD25FF45AAF2D0FCF38570442F1BB67CC53F28D02A19B48CDEE2902D1EA62CCD2C8E006BBC45D5A080018D551F84A0705E2E596EA1998D395695312C302C30&sticky=nf1
2025-09-15 17:30:59.062 7138-7158 NetFUNNEL com...ample_android_single_activity D [NF4] Received 5004 response. Response(timestamp=1757925060140, code=200, msg=null, key=B04303FD454C5CA18924C54783F2BC49951551C40A5E72EE425E8BBE7154D8917EDEA09F96A8542EE989BA43DF1619125F6C6B5A1410BD25FF45AAF2D0FCF38570442F1BB67CC53F28D02A19B48CDEE2902D1EA62CCD2C8E006BBC45D5A080018D551F84A0705E2E596EA1998D395695312C302C30, nwait=0, nnext=0, tps=0.0, ttl=5, ip=nf4-onprem-demo-4525.stclab.com, port=443, vwrHtml=https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html, vwrType=null, preBeginTs=null, postEndTs=null, postBeginTs=null, postEndTs=null, sticky=nf1, liveMessage=null, chkEnterCnt=1)
2025-09-15 17:30:59.062 7138-7158 NetFUNNEL com...ample_android_single_activity D [NF4] "Success" response from NetFUNNEL Server.
2025-09-15 17:30:59.063 7138-7158 NetFUNNEL com...ample_android_single_activity D Section key returned: Key Return Successful

모든 것이 작동 중임을 나타내는 핵심 지표:

로그 메시지의미상태
[NF4] Initial entry detectednfStartSection()가 성공적으로 호출됨✅ 좋음
[NF4] Loading the virtual room대기실 WebView가 로드 중임✅ 좋음
[NF4] Sending 5002 request (반복)주기적 재진입 요청 (폴링)✅ 좋음
[NF4] Received 5002 response with code=200진입 허용됨 - 대기실이 닫혀야 함✅ 좋음
onSuccess(statusCode=200, message='Success')성공 콜백 발생✅ 좋음
[NF4] Key refresh attempt detected구간 제어: 자동 반환 방지를 위한 키 타임아웃 연장✅ 좋음
[NF4] Sending 5003 request구간 제어: 키 타임아웃 연장 요청 (기본 20초)✅ 좋음
[NF4] Received 5003 response with code=201구간 제어: 키 타임아웃이 성공적으로 연장됨✅ 좋음
visibilityChanged oldVisibility=true newVisibility=false대기실 WebView가 닫힘✅ 좋음
[NF4] Key return attempt detectednfStopSection()가 호출됨✅ 좋음
[NF4] Sending 5004 request키 반환 요청이 서버로 전송됨✅ 좋음
[NF4] Received 5004 response with code=200키 반환 성공✅ 좋음
Section key returned: Key Return Successful완료 콜백 발생✅ 좋음

테스트 시퀀스:

  1. 진입 허용 수 = 0으로 시작: 대기실이 나타나고 5002 요청이 반복됨
  2. 진입 허용 수를 1로 변경: 5002 응답이 code=200으로 변경되고 대기실이 닫힘
  3. 구간 진입: onSuccess 콜백이 발생하고 사용자가 구간에 진입함
  4. 키 타임아웃 연장: 구간 제어가 자동 반환을 방지하기 위해 키 타임아웃을 자동으로 연장함 (5003 요청)
  5. 구간 네비게이션: 사용자가 Section1 → Section2 → End를 통해 진행함
  6. 구간 완료: SectionControlEndFragment onViewCreated()nfStopSection()을 호출함
  7. 키 반환: 5004 요청/응답이 키 반환을 확인함
구간 제어 키 관리

구간 제어는 기본 제어와 비교하여 고유한 키 관리 동작을 가집니다:

  • 키 타임아웃 연장 (5003): 구간 중 자동 반환을 방지하기 위해 키 타임아웃을 자동으로 연장함 (기본 20초)
  • 타임아웃 구성: NetFUNNEL 콘솔 → 세그먼트 → 고급 설정 → 타임아웃에서 타임아웃 구성
  • 동시 사용자 수 유지: 명시적 완료까지 구간에서 고정된 동시 사용자 수를 유지함
  • 자동 관리: NetFUNNEL이 타임아웃 연장을 자동으로 처리함 - 수동 개입 불필요
  • 수동 반환: nfStopSection()이 명시적으로 호출될 때만 키가 반환됨

문제가 발생하는 경우:

  • 5004 로그가 없음: SectionControlEndFragment에서 nfStopSection()이 호출되는지 확인
  • 키 반환 실패: nfStartSection()nfStopSection() 간의 프로젝트/세그먼트 키가 정확히 일치하는지 확인
  • 구간이 완료되지 않음: 구간 네비게이션 흐름이 올바르게 작동하는지 확인
  • 대기실이 닫히지 않음: 콘솔에서 진입 허용 수가 1로 설정되었는지 확인
  • 키가 자동 반환됨: NetFUNNEL 콘솔 → 세그먼트 → 고급 설정 → 타임아웃에서 타임아웃이 너무 짧은지 확인
  • 5003 로그가 없음: 구간 지속 시간이 타임아웃 기간(기본 20초)을 초과하는지 확인

대기실 → 진입 → 구간 네비게이션 → 구간 완료 → 키 반환의 전체 흐름이 보이면 구현이 올바르게 작동 중입니다! 이제 오류 처리를 향상시키고 더 견고한 콜백 관리를 추가할 수 있습니다.

5.4 주요 구현 포인트

모범 사례: 키를 즉시 반환

구간이 완료되면 NetFUNNEL 키를 반환하세요. NetFUNNEL은 타임아웃 후(기본 20초) 자동으로 키를 반환하지만, 수동 반환은 더 나은 사용자 경험과 동시 사용자 수 관리 효율성을 제공합니다.

키 반환 규칙:

  • 항상: 구간이 완료된 후 키를 반환합니다 (성공 또는 실패)
  • ⚠️ 자동 타임아웃: NetFUNNEL은 타임아웃 기간 후 자동으로 키를 반환합니다 (콘솔에서 구성 가능)
  • 타임아웃 연장: NetFUNNEL은 구간 중 자동 반환을 방지하기 위해 타임아웃을 자동으로 연장합니다 (5003 요청)
  • 타이밍: nfStartSection() 직후가 아니라 구간이 완료된 후에 호출합니다

구현 체크리스트:

  1. 정확한 키 일치: nfStopSection()의 키가 nfStartSection()과 정확히 일치해야 함
  2. 구간 생명주기: 키 반환 타이밍에 onViewCreated() 사용
  3. 완전한 콜백: 완료 처리를 위해 항상 NetfunnelCompleteCallback 구현
  4. 일관된 키: 구간 흐름 전체에서 동일한 프로젝트/세그먼트 키 사용
완전한 API 참조

nfStopSection 매개변수, 응답 처리 및 고급 키 반환 패턴에 대한 자세한 정보는 API 참조를 참조하세요.


6단계: 대기실 테스트 (진입 허용 수 = 0)

애플리케이션으로 테스트

아래 테스트 단계는 샘플 애플리케이션을 기반으로 합니다. 테스트 프로세스를 실제 애플리케이션에 맞게 조정하세요 - 버튼 이름, Fragment 네비게이션 및 확인 단계를 특정 구현에 맞게 교체하세요.

6.1 작업 트리거

  1. Logcat 로그 지우기 (깨끗한 상태에서 관찰하려는 경우)

    • Android Studio에서 Logcat의 휴지통 아이콘을 클릭하여 이전 로그를 지웁니다
    • 또는 명령어 사용: adb logcat -c
  2. 보호된 버튼 클릭 (예: "구간 제어 (코드 기반 통합)" 카드)

예상 결과: 현재 화면에 대기실 WebView가 나타납니다

Android main screen before clicking Android waiting room WebView of Section Control

6.2 대기실 표시 확인

다음 요소들이 올바르게 표시되는지 확인하세요:

진입 허용 수가 0으로 설정되고 한 명의 사용자만 연결된 경우, 다음을 확인하세요:

  • 나의 대기 순서: 1
  • 예상 대기 시간: 표시되지 않음 (구간 제어만)
  • 내 뒤의 대기자 수: 0
구간 제어 vs 기본 제어 대기실

구간 제어는 이미 구간에 있는 사용자들의 완료 시간이 다양하고 예측하기 어렵기 때문에 예상 대기 시간을 표시하지 않습니다. 진입이 빠르고 예측 가능한 기본 제어와 달리, 구간 제어 사용자는 다단계 프로세스를 완료하는 데 다양한 시간을 소비할 수 있습니다.

Android waiting room WebView of Section Control

6.3 Logcat 활동 확인

NetFUNNEL 로그 확인:

Application 클래스에서 printLog = true를 설정하여 디버그 로깅을 활성화한 다음, Logcat에서 package:mine NetFUNNEL로 필터링합니다. 다음과 같은 로그가 보여야 합니다:

2025-09-15 17:30:24.506  7138-7138  NetFUNNEL               com...ample_android_single_activity  D  [NF4] Initialization successful. NetFUNNEL Version: 4.3.3-onprem
2025-09-15 17:30:27.647 7138-7158 NetFUNNEL com...ample_android_single_activity D [NF4] Initial entry detected. Request(5002), Work(projectKey=service_1, segmentKey=segKey_2548), Control(SECTION)
2025-09-15 17:30:27.696 7138-7156 NetFUNNEL com...ample_android_single_activity D [NF4] Sending 5002 request. https://nf4-onprem-demo-4525.stclab.com/ts.wseq?opcode=5002&key=72D5F5FB98C3C27813CF5B7106D11EDD7796632DC8DA328ACD21E27878B567DD43DDCFCA79225210E75F65F358703A67BCFD08B8F833299D4D743DBF3C84B6D4359F81879079494C2A0482939478A89794D7C8E4BEA05A019FF78476D2CEAF2F2C312C302C302C302C302C30&sticky=nf1
2025-09-15 17:30:29.267 7138-7156 NetFUNNEL com...ample_android_single_activity D [NF4] Received 5002 response. Response(timestamp=1757925029406, code=201, msg=null, key=B04303FD454C5CA18924C54783F2BC494399438D1C0EE7AA0512477FC651CDA8D0C0F1928FD7C09AB18E7593EAE92B7FBCFD08B8F833299D4D743DBF3C84B6D4359F81879079494C2A0482939478A897BD882ABDAC46FAEC31605E83E9F49CD72C312C312C302C302C302C30, nwait=1, nnext=0, tps=0.0, ttl=1, ip=nf4-onprem-demo-4525.stclab.com, port=443, vwrHtml=https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html, vwrType=wait, preBeginTs=null, preEndTs=null, postBeginTs=null, postEndTs=null, sticky=nf1, liveMessage=null, chkEnterCnt=0)
2025-09-15 17:30:29.274 7138-7156 NetFUNNEL com...ample_android_single_activity D [NF4] Loading the virtual room. Work(projectKey=service_1, segmentKey=segKey_2548), Status(WAIT)
2025-09-15 17:30:30.007 7138-7156 NetFUNNEL com...ample_android_single_activity D [NF4] Fetching HTML content from following URL. https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html
2025-09-15 17:30:30.396 7138-7230 NetFUNNEL com...ample_android_single_activity D [NF4] Sending 5002 request. https://nf4-onprem-demo-4525.stclab.com/ts.wseq?opcode=5002&key=B04303FD454C5CA18924C54783F2BC494399438D1C0EE7AA0512477FC651CDA8D0C0F1928FD7C09AB18E7593EAE92B7FBCFD08B8F833299D4D743DBF3C84B6D4359F81879079494C2A0482939478A897BD882ABDAC46FAEC31605E83E9F49CD72C312C312C302C302C302C30&sticky=nf1
2025-09-15 17:30:30.462 7138-7157 NetFUNNEL com...ample_android_single_activity D [NF4] Received 5002 response. Response(timestamp=1757925031536, code=201, msg=null, key=B04303FD454C5CA18924C54783F2BC496041E95666117EA3413E1FA1CF7D93C83F3BBCFCE4DDF36303B4D29BAB59285BBCFD08B8F833299D4D743DBF3C84B6D4359F81879079494C2A0482939478A89724B5E2DCE14558567E22635B848476732C312C302C302C302C302C30, nwait=0, nnext=0, tps=0.0, ttl=1, ip=nf4-onprem-demo-4525.stclab.com, port=443, vwrHtml=https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html, vwrType=wait, preBeginTs=null, preEndTs=null, postBeginTs=null, postEndTs=null, sticky=nf1, liveMessage=null, chkEnterCnt=0)

모든 것이 작동하고 있음을 나타내는 핵심 지표:

로그 메시지의미상태
[NF4] Initialization successfulNetFUNNEL 에이전트가 올바르게 로드됨✅ 정상
[NF4] Initial entry detectednfStartSection()가 성공적으로 호출됨✅ 정상
[NF4] Sending 5002 requestNetFUNNEL 서버로 요청 전송됨✅ 정상
[NF4] Received 5002 response with code=201서버가 WAIT 상태로 응답함✅ 정상
[NF4] Loading the virtual room대기실 WebView가 로드 중✅ 정상
[NF4] Fetching HTML content대기실 HTML이 로드 중✅ 정상
[NF4] Sending 5002 request주기적인 재진입 요청 (폴링)✅ 정상
[NF4] Received 5002 response with code=201서버가 WAIT 상태로 응답함✅ 정상

응답 확인:

  • 로그에서 ts.wseq?opcode=5002 요청을 찾으세요
  • 응답이 code=201 (WAIT)을 표시하는지 확인하세요
  • 201 = WAIT, 200 = PASS (진입 허용)
  • 여기서는 진입 허용 수가 0이므로 올바른 응답은 201입니다

7단계: 구간 진입 테스트 (진입 허용 수 = 1)

7.1 세그먼트 설정 업데이트

  1. NetFUNNEL 콘솔로 돌아갑니다
  2. 세그먼트의 수정 버튼을 클릭하여 편집 화면을 엽니다

NetFUNNEL console edit segment button of section control

  1. 진입 허용 수0에서 1로 변경합니다
  2. 하단의 확인을 클릭합니다

Update limited inflow of section control Confirm changes of section control

즉시 효과

확인을 클릭하자마자 대기실이 사라지고 즉시 SectionControlSection1Fragment로 이동합니다. 이 순간을 관찰하려면 대기실이 현재 표시된 다른 화면을 열어 두세요.

7.2 구간 진입 확인

예상 결과: 대기실이 즉시 사라지고 SectionControlSection1Fragment로 이동합니다

Android section entry successful - Section 1

진입 확인을 위해 Logcat을 확인하세요:

다음과 같은 로그가 보여야 합니다:

2025-09-15 17:30:36.726  7138-7182  NetFUNNEL               com...ample_android_single_activity  D  [NF4] Received 5002 response. Response(timestamp=1757925037810, code=200, msg=null, key=B04303FD454C5CA18924C54783F2BC49C0C7D49B86899E082C565EED4F443625926DA265156909BA64B87F00F7C565325F6C6B5A1410BD25FF45AAF2D0FCF38570442F1BB67CC53F28D02A19B48CDEE2902D1EA62CCD2C8E006BBC45D5A080019F32F0077492B7D5F8DB92356655AFF1302C302C30, nwait=0, nnext=0, tps=0.0, ttl=0, ip=nf4-onprem-demo-4525.stclab.com, port=443, vwrHtml=https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html, vwrType=null, preBeginTs=null, preEndTs=null, postBeginTs=null, postEndTs=null, sticky=nf1, liveMessage=null, chkEnterCnt=1)
2025-09-15 17:30:36.740 7138-7182 NetFUNNEL com...ample_android_single_activity D [NF4] "Success" response from NetFUNNEL Server.
2025-09-15 17:30:36.740 7138-7182 NetFUNNEL com...ample_android_single_activity D onSuccess(statusCode=200, message='Success')
2025-09-15 17:30:36.750 7138-7182 NetFUNNEL com...ample_android_single_activity D [NF4] Key refresh attempt detected. Work(projectKey=service_1, segmentKey=segKey_2548), Control(SECTION)
2025-09-15 17:30:36.758 7138-7182 NetFUNNEL com...ample_android_single_activity D [NF4] Sending 5003 request. https://nf4-onprem-demo-4525.stclab.com/ts.wseq?opcode=5003&key=B04303FD454C5CA18924C54783F2BC49C0C7D49B86899E082C565EED4F443625926DA265156909BA64B87F00F7C565325F6C6B5A1410BD25FF45AAF2D0FCF38570442F1BB67CC53F28D02A19B48CDEE2902D1EA62CCD2C8E006BBC45D5A080019F32F0077492B7D5F8DB92356655AFF1302C302C30&sticky=nf1
2025-09-15 17:30:36.808 7138-7157 NetFUNNEL com...ample_android_single_activity D [NF4] Received 5003 response. Response(timestamp=1757925037885, code=201, msg=null, key=B04303FD454C5CA18924C54783F2BC49C0C7D49B86899E082C565EED4F443625926DA265156909BA64B87F00F7C565325F6C6B5A1410BD25FF45AAF2D0FCF38570442F1BB67CC53F28D02A19B48CDEE2902D1EA62CCD2C8E006BBC45D5A080019F32F0077492B7D5F8DB92356655AFF1312C302C30, nwait=0, nnext=0, tps=0.0, ttl=5, ip=nf4-onprem-demo-4525.stclab.com, port=443, vwrHtml=https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html, vwrType=null, preBeginTs=null, postEndTs=null, postBeginTs=null, postEndTs=null, sticky=nf1, liveMessage=null, chkEnterCnt=1)
2025-09-15 17:30:37.725 7138-7138 VRI[NetfunnelWebView] com...ample_android_single_activity D visibilityChanged oldVisibility=true newVisibility=false

성공적인 구간 진입의 핵심 지표:

로그 메시지의미상태
[NF4] Received 5002 response with code=200진입 허용됨 - 대기실이 닫혀야 함✅ 정상
[NF4] "Success" response from NetFUNNEL Server성공 응답 수신됨✅ 정상
onSuccess(statusCode=200, message='Success')성공 콜백 발생✅ 정상
[NF4] Key refresh attempt detected구간 제어: 키 타임아웃 연장 시작됨✅ 정상
[NF4] Sending 5003 request구간 제어: 키 타임아웃 연장 요청 전송됨✅ 정상
visibilityChanged oldVisibility=true newVisibility=false대기실 WebView 닫힘✅ 정상

7.3 구간 네비게이션 테스트

구간 흐름을 통해 탐색:

  1. Section1 → Section2 → End: 다단계 구간 프로세스 완료
  2. 각 단계가 올바르게 작동하는지 확인: Fragment 간의 원활한 네비게이션 보장
  3. 타임아웃 연장 로그 확인: 구간 중 주기적인 5003 요청 찾기
Android section navigation - Section 2

예상 동작:

  • 사용자는 구간 내에서 자유롭게 탐색할 수 있습니다 (Section1 → Section2 → End)
  • NetFUNNEL은 구간 중에 키 타임아웃을 자동으로 연장합니다 (5003 요청)
  • 명시적 완료까지 동시 사용자 수가 유지됩니다

7.4 키 반환 확인

성공적인 키 반환 확인:

Android section completion - End

End fragment에 도달했을 때 Logcat에서 다음 로그를 찾으세요:

2025-09-15 17:30:59.015  7138-7158  NetFUNNEL               com...ample_android_single_activity  D  [NF4] Key return attempt detected. Work(projectKey=service_1, segmentKey=segKey_2548), Control(SECTION)
2025-09-15 17:30:59.019 7138-7158 NetFUNNEL com...ample_android_single_activity D [NF4] Sending 5004 request. https://nf4-onprem-demo-4525.stclab.com/ts.wseq?opcode=5004&key=B04303FD454C5CA18924C54783F2BC49951551C40A5E72EE425E8BBE7154D8917EDEA09F96A8542EE989BA43DF1619125F6C6B5A1410BD25FF45AAF2D0FCF38570442F1BB67CC53F28D02A19B48CDEE2902D1EA62CCD2C8E006BBC45D5A080018D551F84A0705E2E596EA1998D395695312C302C30&sticky=nf1
2025-09-15 17:30:59.062 7138-7158 NetFUNNEL com...ample_android_single_activity D [NF4] Received 5004 response. Response(timestamp=1757925060140, code=200, msg=null, key=B04303FD454C5CA18924C54783F2BC49951551C40A5E72EE425E8BBE7154D8917EDEA09F96A8542EE989BA43DF1619125F6C6B5A1410BD25FF45AAF2D0FCF38570442F1BB67CC53F28D02A19B48CDEE2902D1EA62CCD2C8E006BBC45D5A080018D551F84A0705E2E596EA1998D395695312C302C30, nwait=0, nnext=0, tps=0.0, ttl=5, ip=nf4-onprem-demo-4525.stclab.com, port=443, vwrHtml=https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html, vwrType=null, preBeginTs=null, postEndTs=null, postBeginTs=null, postEndTs=null, sticky=nf1, liveMessage=null, chkEnterCnt=1)
2025-09-15 17:30:59.062 7138-7158 NetFUNNEL com...ample_android_single_activity D [NF4] "Success" response from NetFUNNEL Server.
2025-09-15 17:30:59.063 7138-7158 NetFUNNEL com...ample_android_single_activity D Section key returned: Key Return Successful

성공적인 키 반환의 핵심 지표:

로그 메시지의미상태
[NF4] Key return attempt detectednfStopSection()이 호출됨✅ 정상
[NF4] Sending 5004 request키 반환 요청이 서버로 전송됨✅ 정상
[NF4] Received 5004 response with code=200키 반환 성공✅ 정상
Section key returned: Key Return Successful완료 콜백 발생✅ 정상

요약

필수 사항 (반드시 수행)

설정:

  • 설치 및 초기화를 완료하고 NetFUNNEL 에이전트가 올바르게 로드되는지 확인합니다
  • 콘솔에서 구간 제어로 세그먼트를 생성합니다
  • 콘솔에서 프로젝트 키와 세그먼트 키를 가져옵니다
  • 테스트를 위해 진입 허용 수를 0으로 설정하고, 프로덕션에서는 1 이상으로 설정합니다

통합:

  • 필수 import 추가: com.nf4.Netfunnel, com.nf4.NetfunnelCallback, com.nf4.NetfunnelCompleteCallback
  • 모든 콜백 메서드를 구현합니다 (Android 인터페이스 요구사항)
  • 클릭 핸들러에서 구간 진입을 Netfunnel.nfStartSection()로 감쌉니다
  • 구간 진입 로직을 실행하기 위해 onSuccess 콜백을 처리합니다
  • 구간이 완료된 후 Netfunnel.nfStopSection()을 호출합니다
  • nfStartSection()nfStopSection() 모두에서 동일한 키를 사용합니다

에러 처리:

  • onError를 처리하여 구간 진입을 계속 진행합니다 (서비스 가용성 유지)
  • onNetworkError는 로깅만 수행합니다 (useNetworkRecoveryMode = true 사용)
  • onBlock을 처리하여 적절한 사용자 메시지를 표시합니다
  • onClose를 처리하여 현재 Fragment에 머뭅니다 (사용자가 취소함)
  • 모든 콜백 응답에 대한 포괄적인 로깅을 구현합니다

테스트:

  • 진입 허용 수 = 0일 때 대기실이 나타나는지 테스트합니다
  • 진입 허용 수 = 1 이상일 때 진입이 작동하는지 테스트합니다
  • 구간 완료 후 키 반환이 발생하는지 확인합니다
  • package:mine NetFUNNEL 필터로 Logcat에서 NetFUNNEL 로그를 확인합니다

선택 사항 (있으면 좋음)

에러 처리 강화:

  • 기본 로깅 대신 사용자 친화적인 에러 메시지를 추가합니다
  • 다양한 응답 유형에 대한 사용자 정의 에러 처리 전략을 구현합니다
  • NetFUNNEL 이벤트에 대한 분석 추적을 추가합니다

코드 구성:

  • 중앙화된 구성 상수를 생성합니다
  • 재사용 가능한 NetFUNNEL 래퍼 함수를 구축합니다
  • 여러 Fragment에 걸쳐 모듈식 통합 패턴을 구현합니다

모범 사례

필수 import

import com.nf4.Netfunnel
import com.nf4.NetfunnelCallback
import com.nf4.NetfunnelCompleteCallback

이러한 import가 중요한 이유:

  • NetFUNNEL 통합에 필수적입니다
  • NetFUNNEL을 사용하는 모든 Fragment/Activity에 추가해야 합니다
  • nfStartSection()nfStopSection() 함수 모두에 필요합니다

완전한 콜백 구현

private val sectionControlCallback = object : NetfunnelCallback() {
override fun onSuccess(statusCode: Int, message: String) {
// 진입이 허용되면 구간 진입 로직 실행
Log.d("NetFUNNEL", "onSuccess(statusCode=$statusCode, message='$message')")
lifecycleScope.launch {
navigationManager.navigateWithDelay(
R.id.action_mainFragment_to_sectionControlSection1Fragment
)
}
}

override fun onError(statusCode: Int, message: String) {
// 시스템 에러 - 서비스 가용성을 유지하기 위해 계속 진행
Log.d("NetFUNNEL", "onError(statusCode=$statusCode, message='$message')")
lifecycleScope.launch {
navigationManager.navigateWithDelay(
R.id.action_mainFragment_to_sectionControlSection1Fragment
)
}
}

override fun onNetworkError(statusCode: Int, message: String) {
// 네트워크 오류 - 로깅만 수행, 네트워크 복구 모드에 의존
Log.d("NetFUNNEL", "onNetworkError(statusCode=$statusCode, message='$message')")
// 여기서는 비즈니스 로직을 실행하지 않음 - 아래 설명 참조
}

override fun onBlock(statusCode: Int, message: String) {
// 사용자가 차단됨 - 적절한 메시지 표시
Log.d("NetFUNNEL", "onBlock(statusCode=$statusCode, message='$message')")
}

override fun onClose(statusCode: Int, message: String) {
// 사용자가 대기실을 닫음 - 적절히 처리
Log.d("NetFUNNEL", "onClose(statusCode=$statusCode, message='$message')")
// 메인 Fragment에 머물기 - 사용자가 취소함
}

override fun onContinue(
statusCode: Int,
message: String,
aheadWait: Int,
behindWait: Int,
waitTime: String,
progressRate: Int
) {
Log.d("NetFUNNEL", "onContinue(statusCode=$statusCode, message='$message', aheadWait=$aheadWait, behindWait=$behindWait, waitTime='$waitTime', progressRate=$progressRate)")
}
}

핵심 원칙: 항상 모든 콜백 메서드를 구현합니다 - Android 인터페이스 요구사항입니다.

중앙화된 구성

// 키를 한 곳에 저장
companion object {
private const val PROJECT_KEY = "your_project_key"
private const val SEGMENT_KEY = "your_segment_key"
}

// 모든 곳에서 동일한 구성 사용
Netfunnel.nfStartSection(
projectKey = PROJECT_KEY,
segmentKey = SEGMENT_KEY,
callback = sectionControlCallback,
activity = requireActivity()
)

Netfunnel.nfStopSection(
projectKey = PROJECT_KEY,
segmentKey = SEGMENT_KEY,
completeCallback = completeCallback
)

장점:

  • 전체 앱에서 키를 쉽게 업데이트할 수 있음
  • 복사-붙여넣기 오류 감소
  • 구성의 단일 소스

견고한 오류 처리 전략

// onError는 비즈니스 로직을 실행하지만 onNetworkError는 실행하지 않는 이유:

// onError (상태 코드 500) - 서버 오류
override fun onError(statusCode: Int, message: String) {
// 시나리오: NetFUNNEL 서버가 내부 오류를 만남
// 전략: 서비스 가용성을 유지하기 위해 비즈니스 로직 실행
// 근거: 서버 오류는 일반적으로 일시적이며 사용자 액세스를 차단하지 않아야 함
// 결과: NetFUNNEL에 문제가 있어도 계속되는 견고한 서비스
sectionEntryLogic()
}

// onNetworkError (상태 코드 1001, 1002) - 네트워크 문제
override fun onNetworkError(statusCode: Int, message: String) {
// 시나리오: 네트워크 연결 문제 (오프라인, 타임아웃)
// 전략: 로깅만 수행하고 비즈니스 로직을 실행하지 않음
// 근거: 자동 네트워크 복구를 위해 useNetworkRecoveryMode = true 사용
// 결과: 네트워크 문제 중 사용자가 대기실에 머물고 연결이 복구되면 자동 재개
Log.d("NetFUNNEL", "onNetworkError(statusCode=$statusCode, message='$message')")
}

핵심 원칙: 서비스 가용성을 유지하기 위해 시스템 오류에서 항상 비즈니스 로직을 진행하세요.

네트워크 복구 모드 구성

// SampleApplication.kt
Netfunnel.initialize(
clientId = "{{CLIENT_ID}}",
useNetworkRecoveryMode = true // 자동 네트워크 복구 활성화
)

장점:

  • 네트워크 연결 문제의 자동 처리
  • 네트워크가 복구되면 사용자가 자동으로 재개됨
  • 수동 네트워크 오류 처리 복잡성 감소

항상 키 반환

// 구간 완료 후 키 반환
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

// 구간 종료에 도달하면 키 반환
Netfunnel.nfStopSection(
projectKey = PROJECT_KEY,
segmentKey = SEGMENT_KEY,
completeCallback = completeCallback
)
}

private val completeCallback = object : NetfunnelCompleteCallback() {
override fun onComplete(statusCode: Int, message: String) {
Log.d("NetFUNNEL", "Section key returned: $message")
}
}

키를 반환할 때:

  • 구간이 완료된 후 (Section1 → Section2 → End)
  • 다단계 프로세스가 완료된 후
  • 비즈니스 작업이 완료된 후
  • 작업이 실패한 경우에도

키 일치

// 시작과 중지가 동일한 키를 사용해야 함
const val PROJECT_KEY = "your_project_key"
const val SEGMENT_KEY = "your_segment_key"

Netfunnel.nfStartSection(
projectKey = PROJECT_KEY,
segmentKey = SEGMENT_KEY,
callback = callback,
activity = requireActivity()
)

Netfunnel.nfStopSection(
projectKey = PROJECT_KEY, // 정확히 일치해야 함
segmentKey = SEGMENT_KEY, // 정확히 일치해야 함
completeCallback = completeCallback
)

포괄적인 로깅

// Application 클래스에서 디버그 로깅 활성화
Netfunnel.initialize(
clientId = "{{CLIENT_ID}}",
printLog = true // 상세 로깅 활성화
)

// Logcat 필터링: package:mine NetFUNNEL

로깅의 장점:

  • NetFUNNEL 통합 문제의 쉬운 디버깅
  • 요청/응답 흐름 추적
  • 키 반환 작업 모니터링
  • 네트워크 연결 문제 식별

일반적인 문제 및 문제 해결

대기실이 나타나지 않음

증상: 버튼 클릭은 정상적으로 작동하지만 대기실이 나타나지 않습니다

디버그 단계:

  1. Android 에러를 위해 Logcat 확인: adb logcat | grep -i error
  2. Application 클래스에서 NetFUNNEL 초기화 확인
  3. 콘솔에서 세그먼트가 활성화되어 있는지 확인 (비활성화되지 않음)
  4. 테스트를 위해 진입 허용 수가 0으로 설정되어 있는지 확인
  5. 프로젝트 키와 세그먼트 키가 콘솔과 정확히 일치하는지 확인 (대소문자 구분)

콜백이 발생하지 않음

증상: nfStartSection()가 호출되었지만 응답을 받지 못함

디버그 단계:

  1. NetFUNNEL 로그를 위해 Logcat 확인: adb logcat | grep NetFUNNEL
  2. NetFUNNEL 서버에 대한 네트워크 연결 확인
  3. 세그먼트가 활성화되어 있는지 확인 (비활성화되지 않음)
  4. 대기실을 강제로 표시하기 위해 진입 허용 수 = 0으로 시도
  5. 모든 콜백 메서드가 구현되어 있는지 확인 (Android 요구사항)

사용자가 대기열에 갇힘

증상: 첫 번째 사용자는 진입하지만 두 번째 사용자는 절대 통과하지 못함

디버그 단계:

  1. 구간이 완료된 후 nfStopSection()이 호출되는지 확인
  2. nfStopSection()의 키가 nfStartSection()와 정확히 일치하는지 확인
  3. nfStopSection() 실행을 방해하는 Android 에러 찾기
  4. Logcat에서 [NF4] Key return attempt detected 로그 확인
  5. 로그에 [NF4] Sending 5004 request가 나타나는지 확인

대기실이 표시되지만 진입을 허용하지 않음

증상: 대기실이 나타나지만 진입 허용 수 = 1이어도 사용자가 절대 통과하지 못함

디버그 단계:

  1. 콘솔에서 세그먼트 상태 확인 - "차단" 모드가 아닌지 확인
  2. 진입 허용 수가 1 이상으로 설정되어 있는지 확인
  3. Logcat에서 [NF4] Sending 5002 request 확인 (재진입 요청)
  4. NetFUNNEL 로그에서 에러 응답 찾기
  5. NetFUNNEL 서버에 대한 네트워크 연결 확인

NetFUNNEL 호출 시 앱 크래시

증상: nfStartSection() 또는 nfStopSection() 호출 시 앱이 크래시됨

디버그 단계:

  1. 필수 import가 추가되었는지 확인: com.nf4.Netfunnel, com.nf4.NetfunnelCallback, com.nf4.NetfunnelCompleteCallback
  2. Application 클래스에서 NetFUNNEL이 초기화되었는지 확인
  3. 모든 콜백 메서드가 구현되어 있는지 확인 (Android 인터페이스 요구사항)
  4. nfStartSection()에 activity context가 올바르게 전달되는지 확인
  5. NetFUNNEL 에이전트가 올바르게 설치되었는지 확인

키 반환 실패

증상: nfStopSection()이 호출되었지만 키가 반환되지 않음

디버그 단계:

  1. nfStopSection()의 키가 nfStartSection()와 정확히 일치하는지 확인 (대소문자 구분)
  2. Logcat에서 [NF4] Key return attempt detected 메시지 확인
  3. 로그에서 [NF4] Sending 5004 request 찾기
  4. [NF4] Received 5004 responsecode=200인지 확인
  5. NetfunnelCompleteCallback이 구현되어 있는지 확인

구간 타임아웃 문제

증상: 구간 완료 전에 키가 자동으로 반환됨

디버그 단계:

  1. NetFUNNEL 콘솔 → 세그먼트 → 고급 설정 → 타임아웃에서 타임아웃 설정 확인
  2. 구간 지속 시간이 타임아웃 기간을 초과하는지 확인 (기본값 20초)
  3. [NF4] Sending 5003 request 로그 찾기 (키 타임아웃 연장)
  4. 타임아웃이 만료되기 전에 nfStopSection()이 호출되는지 확인
  5. 구간 네비게이션 흐름이 타임아웃 기간 내에 완료되는지 확인

네트워크 복구 문제

증상: 네트워크 연결 문제 중에 사용자가 갇힘

디버그 단계:

  1. Application 초기화에서 useNetworkRecoveryMode = true 확인
  2. NetFUNNEL 서버에 대한 네트워크 연결 확인
  3. 네트워크 문제를 시뮬레이션하기 위해 비행기 모드 켜기/끄기로 테스트
  4. Logcat에서 onNetworkError 콜백 호출 모니터링
  5. onNetworkError가 비즈니스 로직을 실행하지 않는지 확인 (복구 모드에 의존)

QA 체크리스트

구현 전 검증

  • 프로젝트 키 / 세그먼트 키가 콘솔과 정확히 일치함 (콘솔에서 재확인)
  • Application 클래스에서 NetFUNNEL 에이전트가 올바르게 초기화됨
  • 필수 import 추가됨: com.nf4.Netfunnel, com.nf4.NetfunnelCallback, com.nf4.NetfunnelCompleteCallback
  • 모든 콜백 메서드 구현됨 (Android 인터페이스 요구사항)

대기실 테스트 (진입 허용 수 = 0)

  • 진입 허용 수 = 0일 때 대기실 WebView가 올바르게 표시됨
  • 대기실이 올바른 세부 정보를 표시함:
    • 나의 대기 순서: 1
    • 예상 대기 시간: 표시되지 않음 (구간 제어만)
    • 내 뒤의 대기자 수: 0
  • 대기 중에 Logcat에 **[NF4] Sending 5002 request**가 주기적으로 나타남
  • **[NF4] Received 5002 response**가 **code=201 (WAIT)**을 표시함

구간 진입 테스트 (진입 허용 수 = 1)

  • 진입 허용 수를 1로 변경할 때 onSuccess 콜백이 발생함
  • onSuccess 콜백이 원래 구간 진입 로직을 실행함
  • 진입 시 대기실이 즉시 사라짐
  • SectionControlSection1Fragment로의 네비게이션이 성공적으로 발생함

구간 네비게이션 테스트

  • 구간 네비게이션이 올바르게 작동함 (Section1 → Section2 → End)
  • 키 타임아웃 연장이 자동으로 발생함 (5003 요청)
  • 구간 중에 **[NF4] Sending 5003 request**가 주기적으로 나타남
  • **[NF4] Received 5003 response**가 **code=201**을 표시함
  • 명시적 완료까지 동시 사용자 수가 유지됨

키 반환 검증

  • 구간 완료 지점에서 키 반환이 올바르게 작동함
  • Logcat에 **[NF4] Key return attempt detected**가 나타남
  • **[NF4] Sending 5004 request**가 HTTP 200으로 발생함
  • **[NF4] Received 5004 response**가 **code=200**을 표시함
  • 키 반환이 nfStartSection 호출당 정확히 한 번 발생함
  • 키 반환이 구간 완료 에 발생함

에러 처리

  • 콜백 분기가 모든 필수 상태에 대해 구현됨:
    • onSuccess - 원래 로직 실행
    • onError - 시스템 에러를 적절히 처리함 (구간 진입 진행)
    • onNetworkError - 네트워크 문제를 적절히 처리함 (로깅만 수행)
    • onBlock - 차단 상태를 적절히 처리함
    • onClose - 사용자 취소를 적절히 처리함
    • onContinue - 대기 진행 상황을 적절히 처리함
  • Application 초기화에서 네트워크 복구 모드 활성화됨
  • 키 일치 - nfStartSectionnfStopSection에서 projectKey/segmentKey가 동일함
  • 모든 콜백 응답에 대한 포괄적인 로깅 구현됨

Logcat 검증

  • package:mine NetFUNNEL 필터로 NetFUNNEL 로그가 보임
  • 초기화 성공 메시지가 나타남
  • 버튼 클릭 시 초기 진입 감지 메시지가 나타남
  • 가상 대기실 로드 메시지가 나타남
  • 키 새로고침 시도 감지 메시지가 나타남 (구간 제어 전용)
  • 키 반환 시도 감지 메시지가 나타남
  • 완료 콜백에 구간 키 반환 성공 메시지가 나타남