일시정지된 사랑: 코루틴 로맨스

eggChopChop·2025년 3월 10일
1

Android

목록 보기
1/3
post-thumbnail

일시정지된 사랑: 코루틴 로맨스

1장: 기다림이 필요 없는 만남

오후 3시 27분. 내 맥북의 인텔리제이는 또다시 빨간 에러 메시지를 뱉어냈다. 콜백 지옥에 갇힌 코드를 보며 한숨이 나왔다. 그때 핸드폰이 짧게 진동했다.

유진: 안녕하세요, 김도현 씨? 옆 건물 마케팅팀 신유진이에요. 저번에 엘리베이터에서 뵀죠? 혹시 시간 되시면 회사 앞 카페에서 잠깐 이야기할 수 있을까요?

심장이 쿵 내려앉았다. 마케팅팀의 그 유진이라고? 첫눈에 반한 그 여자가 정말 연락해온 거야? 손가락이 떨렸다.

: 안녕하세요! 물론이죠. 언제가 편하세요?

메시지를 보내고 초조하게 기다렸다. 일은 손에 잡히지 않았다. 5분, 10분... 마치 스레드가 블로킹된 것처럼 다른 일을 할 수 없었다.

'이럴 때 코루틴이 있으면 얼마나 좋을까...'

개발자답게 이런 생각을 하고 있을 때, 핸드폰이 다시 울렸다.

유진: 내일은 발표 준비가 있어서... 금요일 저녁 7시는 어떠세요?

문득 깨달음이 왔다. 이건 딱 코루틴 같은 상황이다. 대화는 일시중단(suspend)됐다가 나중에 재개(resume)된다. 마치 내가 짜고 있는 코드처럼.

"대기 중인 스레드는 다른 작업을 할 수 없지만, 일시중단된 코루틴은 다른 작업을 수행할 수 있지..." 난 중얼거리며 IDE로 돌아가 코드를 새로 작성하기 시작했다.

suspend fun chatWithYujin() {
    val message = sendMessage("카페에서 만날래요?")
    // 답장을 기다리는 동안 다른 작업 가능
    doOtherTasks()
    val reply = awaitReply() // 유진의 답장이 오면 재개
    processReply(reply)
}

유진의 답장을 기다리는 동안 코드에 몰입했다. 어느새 콜백 지옥에서 벗어난 깔끔한 코루틴 코드가 완성되었다.

2장: 디스패처의 선택

금요일 오후, 회사에서의 마지막 회의가 끝나고 시계를 확인했다. 6시 15분. 데이트까지 45분밖에 남지 않았다.

"시간 관리가 필요해. 각 작업에 맞는 디스패처를 선택해야 해."

개발자의 습관이 일상에도 적용되기 시작했다. 급하게 메모를 끄적였다.

1. 옷 갈아입기, 머리 정리 - Dispatchers.Main (가장 중요, 최우선)
2. 꽃 사기 - Dispatchers.IO (시간 걸림, 기다림 필요)
3. 데이트 코스 계획 - Dispatchers.Default (계산 필요)

집에 도착한 나는 마치 코루틴 스코프를 만들듯 계획을 실행했다.

fun prepareForDate() = runBlocking {
    // UI 스레드처럼 중요한 준비
    launch(Dispatchers.Main) {
        changeClothes()
        fixHair()
    }
    
    // IO 작업처럼 시간 걸리는 일
    launch(Dispatchers.IO) {
        buyFlowers()
    }
    
    // 계산이 필요한 작업
    launch(Dispatchers.Default) {
        planOptimalDateRoute()
    }
}

놀랍게도 이 방식은 효과가 있었다. 6시 55분, 모든 준비를 마치고 카페 앞에 도착했다. 정확히 제 시간에.

3장: 첫 데이트, 또는 LaunchedEffect

카페 문을 열자 유진이 이미 와 있었다. 심장이 빠르게 뛰었다.

"안녕하세요, 도현 씨. 오래 기다리셨어요?" 유진이 미소지었다.

"아뇨, 방금 왔어요. 정확히 7시니까요." 내가 말했다.

"개발자답네요. 시간 정확하고." 유진이 웃었다.

데이트는 예상보다 훨씬 잘 풀렸다. 우리는 회사 이야기, 취미, 좋아하는 음악까지 모든 것에 대해 이야기했다. 시간이 훌쩍 지나갔다.

"저도 프로그래밍에 관심이 있어요. 요즘 디자이너들도 기본은 알아야 한다고 해서 공부 중이에요." 유진이 말했다.

내 눈이 빛났다. "정말요? 혹시 어떤 언어 배우세요?"

"자바스크립트요. 근데 너무 어려워요. 특히 비동기 프로그래밍이라는 게..."

"아! 제가 요즘 비동기 프로그래밍 중에서도 코루틴이라는 개념을 공부하는데, 이게 정말 혁명적이에요."

유진이 호기심 어린 눈으로 물었다. "코루틴이요? 그게 뭔가요?"

이 순간을 위해 태어난 것처럼, 나는 자연스럽게 설명을 시작했다.

"당신이 인스타그램을 보고 있다고 생각해보세요. 피드를 스크롤하다가 사진을 클릭하면, 사진이 로딩되는 동안 앱이 멈추지 않죠? 그런데 예전 앱들은 로딩할 때 아무것도 할 수 없었어요."

"아, 맞아요! 예전엔 앱이 자주 멈췄었죠."

"코루틴은 마치... 우리의 대화와 같아요. 내가 질문하면 당신이 생각하는 동안, 난 커피를 마시거나 주변을 둘러볼 수 있잖아요. 답변을 기다리는 동안 완전히 정지하지 않는 거죠."

유진의 눈이 반짝였다. "오, 그거 정말 똑똑한 방식이네요!"

"맞아요. 그리고 Compose에선 LaunchedEffect라는 게 있는데... 이건 마치..."

"잠깐만요," 유진이 재미있다는 듯 웃었다. "당신 지금 첫 데이트에서 코딩 이야기하고 있는 거 알아요?"

내 얼굴이 빨개졌다. "아, 죄송해요. 너무 몰입했네요."

"아니에요, 재밌어요. 계속해요. LaunchedEffect가 뭔데요?"

"음, 이건... 특별한 상황이 시작될 때 자동으로 실행되는 행동이에요. 마치..." 잠시 생각하다 말했다. "마치 내가 당신을 볼 때마다 자동으로 웃게 되는 것처럼요."

이제 유진의 얼굴이 빨개질 차례였다.

4장: 취소된 약속과 예외 처리

우리의 데이트는 정기적으로 이어졌다. 두 번째, 세 번째... 그리고 한 달이 지났다. 금요일마다 우리는 만났고, 내 인생은 마치 잘 설계된 코루틴 시스템처럼 효율적이고 행복하게 돌아갔다.

그러던 어느 금요일 오후, 핸드폰에 메시지가 왔다.

유진: 도현 씨, 정말 미안해요. 갑자기 급한 일이 생겼어요. 오늘 약속 취소해야 할 것 같아요. 정말 죄송해요. 다음에 꼭 보상할게요.

예상치 못한 취소. 마치 코루틴이 갑자기 취소된 것 같은 상황이었다. 실망스러웠지만, 코루틴을 다루듯 예외 처리가 필요했다.

fun datePlanning() = runBlocking {
    val dateJob = launch {
        try {
            prepareForDate()
            meetYujin()
            haveGreatTime()
        } catch (e: CancellationException) {
            // 취소 처리 로직
            handleDisappointment()
            rescheduleDate()
        } finally {
            // 항상 실행되어야 하는 정리 작업
            sendUnderstandingMessage()
        }
    }
}

유진에게 메시지를 보냈다.

: 괜찮아요. 급한 일 먼저 처리하세요. 다음에 봐요. 화이팅!

어차피 인생은 취소 예외로 가득한 법. 중요한 건 예외 처리를 어떻게 하느냐였다.

5장: async/await 고백

우리의 관계는 점점 깊어졌다. 7번째 데이트 날, 나는 결심했다. 내 마음을 고백하기로.

하지만 완벽한 고백을 위해선 철저한 준비가 필요했다. 마치 async/await 패턴처럼 여러 작업을 병렬로 준비하기로 했다.

그날 아침, 내 코드는 이렇게 돌아갔다:

suspend fun prepareConfession() = coroutineScope {
    val flowers = async { buySpecialFlowers() }
    val restaurant = async { bookFancyRestaurant() }
    val letter = async { writeHeartfeltLetter() }
    
    // 모든 준비가 완료될 때까지 기다림
    val fullPreparation = awaitAll(flowers, restaurant, letter)
    
    // 모든 준비가 끝나면 고백
    confess(fullPreparation)
}

저녁 8시, 한강이 내려다보이는 레스토랑에서 유진과 마주 앉았다. 꽃다발은 테이블 옆에, 편지는 주머니에 있었다.

"오늘 뭔가 특별한 일 있어요?" 유진이 물었다.

심호흡을 한 후 편지를 꺼냈다. "사실... 당신에게 하고 싶은 말이 있어요."

"저도요." 유진이 갑자기 말했다.

"네?" 내가 놀라서 물었다.

"저도 도현 씨에게 하고 싶은 말이 있어요." 유진의 뺨이 붉어졌다. "먼저 해도 될까요?"

이건 예상치 못한 상황이었다. 마치 두 개의 async 블록이 서로 기다리는 데드락 같았다.

"둘 다 동시에 말해요. 1, 2, 3 하면." 유진이 제안했다.

"좋아요."

"하나, 둘, 셋!"

"당신을 좋아해요!" 우리가 동시에 외쳤다.

잠시 침묵이 흐른 후, 우리는 함께 웃음을 터뜨렸다. 이건 완벽한 async/await 시나리오였다. 두 개의 비동기 작업이 정확히 동시에 완료된 것이다.

6장: 구조화된 관계

6개월이 지났다. 우리의 관계는 이제 단순한 데이트를 넘어 진지한 연애로 발전했다. 주말엔 함께 시간을 보내고, 평일엔 각자의 일에 집중하면서도 꾸준히 연락했다.

"우리 관계가 정말 안정적이고 체계적이네요." 유진이 어느 날 말했다.

"그렇죠? 마치 구조화된 동시성(Structured Concurrency) 같아요."

유진이 눈을 굴렸다. "또 코딩 용어요? 설명해보세요, 개발자 씨."

"구조화된 동시성은 코루틴이 부모-자식 관계로 구성되는 것을 의미해요. 부모 코루틴이 취소되면 모든 자식 코루틴도 자동으로 취소돼요. 이렇게 하면 리소스 누수를 방지할 수 있죠."

유진이 생각에 잠겼다. "그러니까... 우리의 주요 관계가 부모 코루틴이고, 우리가 함께하는 다양한 활동들이 자식 코루틴들인 거네요?"

"바로 그거예요!" 내가 흥분해서 말했다. "당신 정말 빨리 배우네요!"

"그럼 우리 관계가 끝나면..." 유진이 장난스럽게 물었다.

"모든 자식 활동들도 자연스럽게 종료되겠죠." 내가 웃으며 말했다. "하지만 걱정 마세요. 우리의 부모 코루틴은 무기한 실행 중이니까요."

"그렇군요. 하지만..." 유진이 미소지었다. "가끔은 withTimeout도 필요하지 않을까요? 예를 들어, 당신이 30분 안에 도착하지 않으면 데이트 취소 같은?"

나는 놀라서 유진을 바라봤다. "당신... 코루틴 공부했어요?"

유진이 뿌듯한 표정을 지었다. "조금요. 개발자 남자친구를 이해하려면 필요하더라고요."

그 순간 나는 유진이 이전의 어떤 여자보다 완벽하다고 느꼈다.

에필로그: SideEffect와 미래

1년 후, 우리는 작은 아파트에 함께 살고 있었다. 유진은 UI/UX 디자이너로 성장했고, 나는 시니어 안드로이드 개발자가 되었다.

"여보, 이거 봐요. 내가 디자인한 앱이에요." 유진이 태블릿을 내밀었다.

화면을 살펴보니 놀랍게도 코루틴 개념을 시각화한 앱이었다. 시작, 일시중단, 재개 등의 개념을 아름다운 애니메이션으로 표현했다.

"와, 이거 정말 대단해요!" 내가 감탄했다.

"SideEffect 같은 거죠." 유진이 웃었다. "당신이 나에게 코루틴을 가르쳤고, 그 영향으로 내가 이런 앱을 디자인하게 된 거니까요."

"그러고 보니 우리의 만남 자체가 일종의 SideEffect였네요. 내가 코루틴을 공부하지 않았다면, 그날 엘리베이터에서 당신에게 코루틴 설명하려고 시도하지 않았을 테니까."

유진이 내 어깨에 머리를 기대며 말했다. "프로그래밍 용어로 따지면, 우리의 관계는 무엇일까요?"

잠시 생각한 후 대답했다. "runBlocking { forever { love() } } 아닐까요? 영원히 멈추지 않는 사랑의 코루틴이요."

"오글거리네요." 유진이 웃으며 말했다. "하지만 맘에 들어요."

그리고 우리의 코루틴은 계속해서 실행 중이다. 때로는 일시중단되기도 하고, 가끔은 다른 디스패처로 전환되기도 하지만, 결코 취소되지 않는 영원한 프로세스로.

  • 끝 -
profile
Hi, I'm an App Developer. I will archive the minor details.

0개의 댓글