📚 CS/운영체제

[CS] 멀티스레딩 & 멀티프로세싱 (feat: 멀티스레딩 예시 코드)

수댕ʕت̫͡ʔ 2025. 3. 10. 15:10

오늘은 멀티스레딩과 멀티프로세싱이 뭔지 알아보자!

면접 질문에 많이 나오는 CS 지식 중에 하나인데 아직 정확하게 알고 있지 않은 것 같아서 이참에 정리해보려고한다.

 

그 전에 프로세스와 스레싱에 대해 생각해본다면 다음과 같다.

1️⃣ 프로세스 VS 스레드

1) 프로세스 : 프로세스는 프로그램이 운영체제에 의해 실행 중인 인스턴스를 의미한다. 즉, 실행 중인 프로그램을 의미한다. 프로세스는 독립적인 메모리 영역을 가지고 있다.

 

2) 스레드 : 스레드는 프로세스 안에서 실행되는 작업의 흐름이다. 포로세스와는 별개로 하나의 프로세스 안에 여러 개의 스레드가 존재할 수 있다. 이 스레드는 스택 영역만 독립적이며 코드, 데이터 힙 메모리를 공유한다.

2️⃣ 멀티 프로세스 vs 멀티 스레딩

1) 멀티 프로세스 : 프로세스가 여러 개 실행 중인 경우를 의미한다. 프로세스는 각각 독립적인 메모리 공간이 있기 때문에 서로 메모리 영역을 공유하지 않는다. 그렇기 때문에 하나의 프로세스가 죽더라도 다른 프로세스에 영향을 주지 않는다. 

 

2) 멀티 스레딩 : 멀티 스레딩은 이런 스레딩이 여러 개 동시에 실행되고 있는 것을 말한다. 여기서 주의할 점은 멀티 프로세스와 다르게 메로리를 공유하기 때문에 데이터 전달이 빠르고 간편하다는 것이다. 하지만 메모리를 공유하기 때문에 한 스레드의 오류가 전체 프로세스의 영향을 줄 수 있다.

3️⃣ 최종 비교

1) 멀티 프로세싱 사용하는 경우

- CPU의 집약적인 작업을 해야 하는 경우

- 프로세스 간의 독립성이 중요한 경우

- 메모리 충돌을 피하고 싶을 떄

 

2) 멀티스레딩을 사용해야하는 경우

- I/O 작업이 많아 대기 시간이 긴 경우

- 메모리를 효율적으로 사용해야할 때

 

4️⃣ 멀티 스레딩 코드

멀티 스레딩의 예시를 보자. 

밑에 코드는 구현 중인 '당신의 안식' 서버 부분 중 하나이다. 내가 원했던 기능은 다음과 같다. 

나는 로그인을 안한지 1년 지난 회원에 대해 soft delete 처리를 하고 싶다. 즉, 1년 동안 로그인을 안하면 user 테이블에 deleted_at에 표시를 해줄 것이다.

 

이걸 구현하기 위해서는 어떻게 해야할까? 당연히 매일 자정마다 DB 검사를 해야한다. 모든 user를 확인하면서 마지막 로그인 시간을 확인해야하는 것이다. 하지만 만약 그 때 API 호출이 들어오면 당연히 해당 API 호출을 처리해줘야한다! 이때 사용할 것이 멀티 스레딩이다. 

 

package com.beyoureyes.beyoureyes

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.scheduling.annotation.EnableScheduling

@SpringBootApplication
@EnableScheduling
class BeyoureyesApplication

fun main(args: Array<String>) {
	runApplication<BeyoureyesApplication>(*args)
}

 

@Scheduled(cron = "0 0 0 * * *", zone = "Asia/Seoul")
    fun deactivateInactiveUsers() {
        val affectedRows = userMapper.deactivateInactiveUsers()
        println("1년 이상 로그인하지 않은 사용자 $affectedRows 명 비활성화 되었습니다.")
    }

 

여기서 API 요청은 서블릿 스레드가 처리하고, Cron 작업은 스케줄러 스레드가 처리한다. 이렇게 한 프로세스 내에 여러 개의 스레드가 존재하고 이것을 멀티 스레드라고 하는 것이다!