PIPE #1/3

C, 파이썬, 펄, 루비, 자바등의 범용 프로그래밍 언어들은 표준입출력을 제공한다.

“표준입출력은 많이 들어봤는데, 나는 그거 안써” 라고 하는 분들을 위한 글이다.

프로그램은 시작과 끝이 있기 마련이고, 작동하는 중에 “내가 뭘 하고 있습니다” 라는 표시를 해야 사람이 그걸 보고 판단을 할 수 있게 된다.

물론 기능이 단순한 copy 같은 프로그램은 굳이 안보여줘도 되지만, 복잡한 기능을 가진 프로그램일 수록 지금 뭘하는지 보여주지 않으면 곤란한 상황이 많이 생긴다.

뻔한 얘기는 여기까지 하고.

표준입력 + 표준출력 + 표준에러 = 표준입출력

다르게 말해서 STDIN, STDOUT, STDERR 이다. 코드상에서는 이렇게 접하게 된다.

자바에서는 System.in, System.out, System.err 로 제공하고,
파이썬에서는 sys.stdin, sys.stdout, sys.stderr 로 제공한다.

자바는 Stream 객체이고, 파이썬에서는 file 오브젝트이지만 그건 중요치 않다.

각각이 뭘 주고 받는지 역할을 이해하는 것이 중요하다.

표준이라고 이름 붙인 것은 약속이기에

  • STDIN 은 프로그램의 입력
  • STDOUT 은 프로그램의 출력
  • STDERR 은 프로그램 오류나 경고등을 출력하기로 약속이 되어있다.

강제는 아니나 이를 지켰을 때 다른 프로그램과의 연동이 손쉬워 진다.

연동?

요즘은 주로 웹서비스나 모바일앱같은 GUI를 가진 프로그램을 작성하는 것이 큰 유행이기 때문에, 연동이라 함은

웹서비스 -> RESTful API
모바일앱 -> Custom URI Schema

등으로 연동을 하는 것이 상식일 것이다.

그런데 웹이나 모바일앱이 나오기 훨씬 이전부터 앱간의 연동의 필요성은 있었고,
이를 위해 표준입출력을 만든 것이다.

자주 쓰게 되는 명령어를 보자면…

ps -ef | grep java

ps 명령의 출력을 grep명령의 입력으로 전달( | )하고 있다. 그리고 grep의 출력이 화면에 나타난다.

요런 것이 OS에서 제공하는 앱간의 연동이자, 표준입출력간의 연결이자, IPC의 일종인 파이프 통신이다.
세가지 용어를 확 묶어버리니까 좀 마음이 편해졌다.

물론 프로그램끼리 통신하는 방법에는 파이프통신도 있고,

  • HTTP통신도 있고,
  • RPC도 있고,
  • COM(ActiveX)도 있고,
  • DB를 서로 뒤져보는 무식한 연동도 있고,
  • 공유메모리를 이용하는 방법도 있고,
  • 직접 실행시 인자를 집어넣어서 자식프로세스를 생성하는 것도 있겠다.

파이프통신은 쉽고, 유연하고, 편리하다

파이프 통신의 처리

파이썬으로만 살펴보겠다.

print("name?")
name = input()
print("Hello "+ name)

input 은 표준입력으로 글자를 받아들이는 역할을 한다.
print 는 표준출력으로 글자를 내보내는 역할을 한다.

잠깐, 아까 파이썬에는 sys.stdin 과 sys.stdout 으로 제공된다고 하지 않았나?
그것도 가능하고 이것도 가능하지만, 일단 엄청나게 자주 쓰이다 보니 쓰기 편한게 하나 더 있다고 생각하면 된다.
내부적으로는 같은 작동을 한다.

import sys
sys.stdout.write("name?\n")
name = sys.stdin.readline().rstrip()
sys.stdout.write("Hello "+name+"\n")
$ python3 hello.py
name?
sng2c
Hello sng2c
$ python3 hello_sys.py
name?
sng2c
Hello sng2c
$

나는 어릴때 C언어를 배울 때, 저것부터 시작했다. 표준입출력을 다루는 중요한 단계임에도 이게 얼마나 유용한 것인지 알지못했고, 초라한 프로그램이라고 생각했다.

name? 을 출력하고 멈춰있는 것을 볼수 있는데, 이게 표준입력을 read() 하기 위해 기다리고 있다. 이때에는 키보드를 타이핑하는 것이 표준입력이 된다.

이름을 써주면 “Hello “와 조합한 결과를 다시 표준출력으로 내보내게 된다.

echo 명령과 파이프로 연결해보자

echo 는 단순히 입력한 값을 “표준출력으로 내보낸다”.

$ echo 'KHS'
KHS

그리고 우리가 작성한 hello.py는 표준입력(아까는 키보드)를 한줄 받아서 인사를 하게 되어있다.
echo 의 출력을 | 로 연결을 해주면 hello.py 의 입력이 된다!!

$ echo 'KHS' | python3 hello.py
name?
Hello KHS
$

키보드 입력을 받기 위해 기다리지 않고,
표준입력으로 들어온 echo 의 ‘KHS’ 를 받아서 “Hello KHS”를 출력해냈다

첫번째(?) 파이프 통신을 축하한다.