수십~수백 기가바이트에 달하는 데이터를 복사하거나 이동해 본 적이 있나요? 그렇다면 그동안 시스템 반응 속도가 눈에 띄게 느려지는 현상을 경험했을 것입니다. 리눅스에서는 ionice 명령어를 활용하면 이러한 문제를 피할 수 있습니다.
I/O 우선순위란 무엇인가?
I/O는 입력/출력(Input/Output)의 약자입니다. I/O 장치에는 여러 종류가 있지만, 여기서는 저장 장치(디스크)를 기준으로 설명합니다.
이런 장치에 데이터를 읽거나 쓰려는 각 프로세스에는 스케줄링 클래스와 우선순위 번호(일명 "nice" 값)가 할당됩니다. 이는 리눅스의 ext4 같은 파일시스템에 적용되며, ZFS처럼 디스크 읽기/쓰기 작업을 조금 다른 방식으로 스케줄링하는 파일시스템도 있습니다. 또한 이 기능이 정상적으로 동작하려면 CFQ 스케줄러가 활성화되어 있어야 합니다. 다음 명령으로 확인할 수 있습니다.
cat /sys/block/*/queue/scheduler
nice 값이 높은 프로세스일수록 우선순위는 낮아집니다. 숫자가 클수록 다른 프로세스에게 더 "친절(nice)"하다는 논리 때문입니다.
I/O 우선순위는 어떻게 동작하는가?
저장 장치는 초당 처리할 수 있는 I/O 연산 횟수(IOPS)가 분명히 제한적입니다. 따라서 두 프로세스가 동시에 읽기/쓰기를 원하면 각각 IOPS를 나눠 갖게 되며, 우선순위가 같다면 대략 50%씩 배분받습니다.

다만 IOPS는 다소 추상적이고 어렵게 느껴질 수 있습니다. 이해를 돕기 위해 최종 결과물인 읽기/쓰기 속도로 단순화해 보겠습니다. 디스크의 최대 쓰기 속도가 100MB/s라고 가정해 봅시다. 프로세스 A가 쓰기 작업을 시작하면 100MB/s로 디스크에 기록합니다. 이때 프로세스 B가 같은 디스크에 쓰기를 시도하면 약 50MB/s로 기록하게 되고, 프로세스 A의 속도 역시 50MB/s로 떨어집니다. 만약 프로세스 B에 더 높은 I/O nice 값을 부여하면 B는 20MB/s로, A는 80MB/s로 기록하게 됩니다. A의 작업이 끝나면 B는 다시 100MB/s로 기록할 수 있습니다.
이 예시는 많은 사람들이 혼동할 수 있는 부분을 이해하는 데 도움이 됩니다. 프로세스의 우선순위가 매우 낮다(nice 값이 높다)고 해서 항상 느리게 동작하는 것은 아닙니다. 디스크를 사용하는 유일한 프로세스라면 최대 속도로 읽기/쓰기를 수행합니다. 하지만 다른 프로세스가 디스크를 필요로 하면 잠시 자리를 비켜주어 더 많은 디스크 대역폭을 양보합니다. 완료까지 몇 시간이 걸릴 수 있는 복사/쓰기 작업이라면, 그동안 컴퓨터를 계속 사용하고 싶다면 낮은 우선순위를 부여하는 것이 좋습니다.
ionice 명령어 사용법
명령어의 일반적인 문법은 다음과 같습니다.
ionice -c scheduling_class -n priority_nice_value command
ionice 스케줄링 클래스
Idle(유휴, 클래스 3): 이 클래스의 프로세스는 다른 프로그램이 디스크 접근을 필요로 하지 않을 때만 읽기/쓰기를 수행합니다. 경쟁 상대가 없을 때는 최대 속도로 동작하지만, 다른 프로그램이 디스크를 사용하기 시작하면 남은 자원만으로 작업을 진행합니다. 100MB/s로 쓰던 프로세스가 일시적으로 5MB/s로 떨어졌다가, 다른 프로그램의 작업이 끝나면 다시 100MB/s로 복귀하는 식입니다. 시스템 속도 저하 없이 오래 실행해야 하는 작업에 가장 적합한 클래스이며, 별도의 우선순위 지정이 필요 없습니다.
예제 명령:
ionice -c 3 cp /home/user/largefile /Backups
Best-effort(최선 노력, 클래스 2): 0부터 7 사이의 우선순위(nice) 값을 사용합니다. 숫자가 작을수록 우선순위가 높다는 점을 기억하세요. 두 개 이상의 프로세스에 디스크 사용 시간을 세밀하게 조정하고 싶을 때 유용합니다.
예를 들어 백업을 빨리 끝내고 싶어 nice 값 0을 부여하고, 여섯 편의 영화를 다른 디스크로 옮기는 작업은 급하지 않으니 nice 값 7을 부여하는 식입니다.
예제 명령:
ionice -c 2 -n 0 backup_command

Realtime(실시간, 클래스 1): 어떤 프로그램의 방해도 받지 않고 최대한 빨리 쓰기 작업을 완료해야 하는 특수한 경우에만 사용해야 합니다. 대부분의 사용자는 이 클래스가 필요 없으며, 특별한 경우가 아니라면 사용을 피하는 것이 좋습니다. 마찬가지로 0~7 사이의 nice 값을 지원하며, root 권한이 필요하므로 보통 sudo를 붙여 실행합니다. 주의할 점은, 우선순위 0의 realtime 프로세스가 다른 프로세스의 자원을 고갈시킬 수 있다는 것입니다. 실제로는 다른 프로그램이 몇 MB의 데이터를 읽고 쓰는 데 수 분, 심하면 수 시간을 기다려야 할 수도 있습니다. 반드시 필요하다고 확신할 때만 신중하게 사용하세요. 클래스 2나 3의 중요한 프로세스가 디스크 접근을 필요로 하는 상황이라면, realtime 프로세스의 작업이 끝날 때까지 시스템이 멈춘 것처럼 보일 수 있습니다.
예제 명령:
sudo ionice -c 1 -n 7 bash
유용한 ionice 활용 예시
마지막 예제에서는 복사/이동 명령 대신 셸(Bash)을 실행했습니다. 이렇게 하면 이후 그 셸에서 입력하는 모든 명령이 해당 I/O 스케줄링 클래스와 우선순위를 상속받습니다. GUI 환경에서도 같은 방법을 쓸 수 있습니다.
ionice -c 3 pcmanfm
위 명령은 LXDE 데스크톱 환경의 파일 탐색기를 실행합니다. 자신이 사용하는 데스크톱 환경의 파일 탐색기 이름으로 "pcmanfm"을 바꿔 실행하면, 이후 그 탐색기에서 시작하는 모든 디스크 작업이 idle I/O 스케줄링 클래스로 수행됩니다.
반대로 이미 복사/이동 작업이 진행 중인 경우에는 ionice를 다른 방식으로 사용할 수 있습니다.
ionice -c 3 -p 4910
이 명령은 프로세스 ID(PID) 4910으로 실행 중인 프로그램의 우선순위 클래스를 변경합니다. PID는 작업 관리자나 pgrep 같은 명령으로 확인할 수 있습니다.

결론
ionice는 대용량 파일을 복사/이동하는 동안에도 데스크톱이 느려지지 않게 하는 데 유용합니다. 하지만 서버 환경에서는 그 활용 가치가 더욱 큽니다. 전체 백업을 수행하는 동안 호스팅 중인 웹사이트가 방문자에게 느리게 반응하는 상황은 누구도 원하지 않을 것입니다.