2019년 4월 28일 일요일

데이터과학 입문(Doing Data Science)

'데이터과학 입문(Doing Data Science)'은 지난주에 구입한 책의 제목이다. 토요일 아침 자동차 검사소에 가서 정기검사가 끝나기를 기다리면서 전체를 찬찬히 훑어보았다. O'Reilly사의 웹사이트를 방문하면 영문으로 된 소개와 목차를 볼 수 있다(링크). 연초에 학회에서 주최했던 하루짜리 머신러닝 교육에 참석했던 것이 기본적인 개념을 잡는데 도움을 주었다. 감염성 병원체의 유전체학 관련 연구를 하는 생명과학자인 나에게는 제12장 역학(Epidemiology)가 특히 중요하다.


빅데이터와 데이터과학의 현재 문제점은 무엇일까? 28쪽에서 다음과 같은 내용을 발견할 수 있다.
  1. 기본적인 용어에 대한 정의가 없다.
  2. 오랫동안 이런 대상을 연구해온 학계와 산업체 연구소 연구자들이 이상하게 존경을 받지 못한다.
  3. 열풍이 너무 지나치다.
  4. 통계학자들은 이미 자신들이 '데이터의 과학'을 연구하거나 수행하고 있으며, 그것이 자신의 직업적 일상이라고 느낀다...어쩌면 통계학자들은 여러분이 정체성을 도둑맞았을 떄 드는 느낌을 갖고 있을 것이다.
  5. '자신을 과학이라고 불러야 하는 어떤 것도 과학이 아니다'라는 말이 있다. (과학이 아니라 기예craft에 가깝다는 뜻도 된다)
데이터과학은 현 시점에서 정의가 구체화되어 가는 매우 새로운 학문이다. 현재의 정의에 완벽하게 만족하는 사람은 아직 적겠지만. '데이터화'가 매우 중요한 활동의 하나임은 부인할 수 없다.
일단 대상을 데이터화하면, 우리는 그것의 사용 목적을 바꾸고 그 정보를 새로운 형식의 가치로 전환할 수 있다(32쪽).
여기에서 '우리'는 사람들이 어떤 것을 구매하게 함으로써 돈을 버는 모형 개발가와 사업가들이고, '가치'는 자동화를 통해서 향상된  효율성과 같은 것을 의미한다. 데이터 도사geek가 갖춘 매력적인 기술은 통계학·데이터 변환·시각화이다.

저자 중 하나인 캐시 오닐은 어딘가 모르게 낯이 익다. 아, 그렇다! '대량살상 수학무기'를 쓴 수학자이다(독후감). 알고리즘이니 데이터 모형이니 하는 것이 인간의 삶에서 더 많은 부분을 좌지우지하는 것을 경고하는 이 책은 미국에서 2016년에 출판되었다. 그러면 캐시 오닐은 '데이터 사이언스 입문'을 언제 출간하였을까? 이보다 앞선 2013년이었다. '대량살상 수학무기'라는 책을 이보나 나중에 냈다고 해서 캐시 오닐이 데이터 사이언스 자체에 회의적으로 바뀌었다고 볼 수는 없다. 칼이 사람을 찔렀다고 해서 주방에서 칼을 몰아낼 수는 없는 노릇 아니겠는가? 가치 중립적인 도구의 장단점을 제대로 파악하고 좋은 의도에서 이를 활용하려는 마음가짐을 갖고 있는 한 지나치게 우려를 할 필요는 없을 것이다.

2019년 상반기의 목표는 이 책을 통독하고 실습을 위해 필요한 수준으로 R 활용 능력을 향상시키는 것이다. 정확히 자리를 잡지 못하고 뇌세포 사이를 떠돌던 핵심 개념들도 제 자리를 잡게 될 것으로 믿는다

300B 싱글 앰프

진공관 앰프를 사랑하는 사람이라면 누구나 최종 목적지로 도착한다는 직열 삼극관 300B 싱글 앰프. 인터넷을 통해서만 보았던 300B 싱글 앰프를 어제 제이앨범 정기 모임에서 처음으로 만나보았다(모임 소식). 오디오 니르바나의 풀레인지 스피커를 쾅쾅 울려주던...


PSVANE의 300B. 흔히 '푸스반느'라고 읽는데 맞는지는 모르겠다.
위키피디아의 설명에 의하면 300B는 1938년 미국의 웨스턴 일렉트릭에 의해 처음 만들어진 삼극관으로, 전화 선로의 신호를 증폭하기 위한 목적으로 개발된 것이다. 그런데 1980년대에 일본의 오디오파일에 의해서 가정용 오디오 앰프 자작용으로 인기를 끌게 되었다. 이때의 열풍이 결코 합리적인 것은 아니었다는 평도 없지는 않다.

웨스턴 일렉트릭은 이제 잊혀진 회사가 되었고 지금은 작은 회사에 의해서 브랜드가 유지되고 있다. 현재 몇 회사에서 300B가 만들어지고 있는데, 2018년 웨스턴 일렉트릭의 원래 이름을 달고 재발매가 되었다고 한다(링크). Matched pair는 무려 1499 달러!

'내 평생 이것 하나는 만들어 보겠다'는 목표가 이제 조금씩 생겨나려고 한다. 집에 두고 온 앰프를 이곳 숙소로 가져오는 것부터 먼저 시도하고 볼 일이다.

2019년 4월 25일 목요일

CentOS 7 업그레이드 후 docker 설치 및 docker pull 실행에 성공하다

모든 문제는 SSL 인증서로 귀결된다. 회사 프록시 서버가 중간 과정에서 인증서를 건드리면서 Somansa라는 '비공인' 인증기관의 것으로 바꾸어서 내부 클라이언트로 전달하고, 응용프로그램에서는 이를 인정하지 못하겠다며 거부한다. 자체 인증서에 대한 CA bundle 위치를 제시하려 해도 응용 프로그램마다 그 방법이 전부 제각각이라는 것이 문제이다.

지난번 글 회사 프록시 서버 뒤에서 docker pull을 실행하지 못하는 문제에 도전해 보자는 결국 성공하지 못했다. 인증서 문제가 발생하지 않는 컴퓨터(예를 들어 윈도우에 설치한 docker)에서 이미지를 받은 뒤 이를 리눅스 서버로 옮겨서 docker run을 하는 우회 방법도 시도하였지만 만족스럽지 않았다. 그래서 CentOS 7으로 업그레이드를 하는 것에서 모든 것을 다시 시작하기로 했다. CentOS 6에서 설치 가능한 docker는 너무 옛날 것이고, 인터넷에서 찾아낸 사용자 지정 CA bundle 설치법도 잘 먹히질 않았다.

Docker 자체를 설치하는 것으로부터 시작해 본다. 다음의 docker 공식 문서 사이트를 참조하였다.

Get Docker CE for CentOS

시작부터 순탄하지 않다. https://로 시작되는 주소에 있는 repo 파일을 가져오는 것부터가 문제다.

# yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
Loaded plugins: fastestmirror, langpacks
adding repo from: https://download.docker.com/linux/centos/docker-ce.repo
grabbing file https://download.docker.com/linux/centos/docker-ce.repo to /etc/yum.repos.d/docker-ce.repo
Could not fetch/save url https://download.docker.com/linux/centos/docker-ce.repo to file /etc/yum.repos.d/docker-ce.repo: [Errno 14] curl#60 - "Peer's certificate issuer has been marked as not trusted by the user.

wget(--no-check-certificate)으로 repo 파일을 받은 다음, 각 엔트리에 대해서 sslverity=0을 삽입한다. 이렇게 수정한 파일을 가지고 다시 yum-config-manager를 실행하라. 그리고 이후 과정을 통해서 docker 관련 패키지를 설치한 다음에 최초의 docker pull 명령을 실행하면 익숙한 에러 메시지가 나온다('x509: certificate signed by unknown authority').

# yum-config-manager --add-repo docker-ce.repo
# yum install docker-ce docker-ce-cli containerd.io
# systemctl start docker
# docker pull hello-world
Using default tag: latest
Error response from daemon: Get https://registry-1.docker.io/v2/: x509: certificate signed by unknown authority

이제부터는 방법을 잘 알고 있다. CentOS 6 시절에 너무나 여러번 반복을 했기 때문이다. 물론 실패했지만... 하지만 CentOS 7에 깨끗한 docker CE를 설치했다면 이야기는 달라진다.

# cp _path_to_/Somansa_ROOT_CA.cer /etc/pki/ca-trust/source/anchors/
# update-ca-trust force-enable
# update-ca-trust extract
# systemctl restart docker
# docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

만약 내가 전산망 보안이 까다로운 회사로 오지 않았더라면 프록시 서버로 보호받는(?) 내부에서 SSL 인증서와 엮인 어려움을 전혀 알지 못했을 것이고, CentOS 7 업그레이드도 적어도 반년 뒤에나 시도했을 것이다. 어려움은 도전을 낳고 많은 경우에 해결이 된다. 속이 다 시원하다!

2019년 4월 24일 수요일

회사 프록시 서버는 DFAST의 reference database 다운로드도 어렵게 한다

비슷한 제목의 글을 연일 작성하게 되었다.
회사 프록시 서버는 ....을 어렵게 한다.
https://로 시작하는 곳을 접속하여 파일을 가져오는 것을 어렵게 하는 문제를 4월 초부터 하나씩 해결을 해 나갔다. 이제는 거의 다 해결을 했다고 생각했는데, 파이썬 코드 안에서 urllib 모듈을 사용하여 파일을 다운로드하는 request 메소드의 실행에서 문제가 벌어졌다. 라이브러리, 모듈, 함수, 메소드에 대한 정확한 정의는 일단 무시하도록 하자. 나는 파이썬 코드를 직접 쓰는 사람이 아니고 파이썬 응용프로그램을 설치하고 사용만 하는 사람이므로.

미생물 유전체 주석화 파이프라인의 대명사인 prokka와 병행하여 사용할 다른 프로그램을 검토 및 테스트하는 중에 벌어진 일이다. 일본에서 개발한 DFAST의 참조 데이터베이스를 설치하는 과정에서 또다시 SSL 인증 불가 문제가 드러난 것이다. wget/curl/pip를 실행하는 과정에서 SSL 인증을 건너뛰는 방법은 이제 충분히 알아낸 상태이지만, 코드 내에서 실행되는 함수 수준에서 벌어지는 에러라면 어떻게 할 것인가?

# python scripts/file_downloader.py --protein dfast
No handlers could be found for logger "dfc.utils.path_util"
Downloading DFAST reference. Files will be written into '/usr/local/apps/dfast_core/db/protein'
Traceback (most recent call last):
  File "scripts/file_downloader.py", line 169, in <module>
    retrieved_file = retrieve_dfast_reference(db_name, out_dir)
  File "scripts/file_downloader.py", line 74, in retrieve_dfast_reference
    request.urlretrieve(target_url, output_file)
  File "/usr/lib64/python2.7/urllib.py", line 94, in urlretrieve
    return _urlopener.retrieve(url, filename, reporthook, data)
  File "/usr/lib64/python2.7/urllib.py", line 240, in retrieve
    fp = self.open(url, data)
  File "/usr/lib64/python2.7/urllib.py", line 208, in open
    return getattr(self, name)(url)
  File "/usr/lib64/python2.7/urllib.py", line 437, in open_https
    h.endheaders(data)
  File "/usr/lib64/python2.7/httplib.py", line 1037, in endheaders
    self._send_output(message_body)
  File "/usr/lib64/python2.7/httplib.py", line 881, in _send_output
    self.send(msg)
  File "/usr/lib64/python2.7/httplib.py", line 843, in send
    self.connect()
  File "/usr/lib64/python2.7/httplib.py", line 1260, in connect
    server_hostname=sni_hostname)
  File "/usr/lib64/python2.7/ssl.py", line 348, in wrap_socket
    _context=self)
  File "/usr/lib64/python2.7/ssl.py", line 609, in __init__
    self.do_handshake()
  File "/usr/lib64/python2.7/ssl.py", line 831, in do_handshake
    self._sslobj.do_handshake()
IOError: [Errno socket error] [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:618)

문제가 되는 것은 file_downloader.py 스크립트의 다음 줄이다.

    from urllib import request
    ...
    request.urlretrieve(target_url, output_file)

SSL verification 여부를 함수의 인자에 줄 수 있는 것 같지는 않다. pip 말고 파이썬 자체가 참조하는 인증서 번들 위치를 찾아서 Somansa의 루트 인증서 파일을 넣어도 될 것이다. 그런데 어디인지를 잘 모르겠다. 인증서 번들이라 해도 중간 단계 인증서는 없으므로 소만사에서 발급한 것 하나면 충분하다.

문제 해결 답안의 보물창고인 StackOverflow에서 힌트를 발견하였다. PYTHONHTTPSVERIFY 환경변수를 0으로 놓으면 된다.

urllib and "SSL: CERTIFICATE_VERIFY_FAILED" Error

# PYTHONHTTPSVERIFY=0 python scripts/file_downloader.py --protein dfast

환경변수 설정과 명령어를 한 줄에 놓는 것은 처음에는 매우 어색하게 느껴졌었다. 그러나 지금은 매우 익숙해졌다. 여기에서 PYTHONHTTPSVERIFY는 환경변수인가 쉘변수인가? 여기여기를 방문하여 잠깐 생각해 보도록 하자.

2019일 4월 25일 업데이트

HMMer와 RPS-BLAST 데이터베이스를 다운로드하는 과정에서 또다시 문제가 발생하였다.

# python scripts/file_downloader.py --cdd Cog --hmm TIGR

다운로드한 파일의 압축을 풀고 hmmpress를 실시하는 등의 후처리가 돌아가야 이 작업이 완료된다. 그런데 다운로드 자체가 원활하지 않아서 파일을 받다가 만 상태로 다음 과정으로 진행하는 것이다. 그래서 소스 코드를 참조하여 완전한 형태의 두 파일을 wget으로 미리 받은 다음(중간에 접속이 끊겨도 재전송이 가능), 다운로드 명령을 무력화한 소스 코드를 재실행하는 것으로 마무리하였다. 파이썬을 잘 알지 못하는 상태에서 소스를 고친다는 것이 대단히 부담스러웠다. 한 일이라고는 '#'를 소스 내 두 줄의 시작 부분에 삽입한 것이 전부였지만.

2019년 4월 23일 화요일

회사 프록시 서버는 R 라이브러리 패키지 설치도 어렵게 한다

epel 저장소 정보 파일의 주소 정보(baseurl) 라인을 활성화하여 CentOS 7에서 R rpm 패키지가 설치되도록 만들고 나서 일반 사용자 권한으로 필요한 R 라이브러리를 설치하려 하였더니 또 SSL 인증서와 관련한 에러가 발생하였다. 이젠 정말 지긋지긋하다!

> install.packages("BiocManager")
‘/home/hyjeong/R/x86_64-redhat-linux-gnu-library/3.5’의 위치에 패키지(들)을 설치합니다.
(왜냐하면 ‘lib’가 지정되지 않았기 때문입니다)
--- 현재 세션에서 사용할 CRAN 미러를 선택해 주세요 ---
경고: failed to download mirrors file (URL 'https://cran.r-project.org/CRAN_mirrors.csv'를 열 수 없습니다); using local file '/usr/share/doc/R-3.5.2/CRAN_mirrors.csv'
경고: 저장소 https://cran.ism.ac.jp/src/contrib에 대한 인덱스에 접근할 수 없습니다:
  URL 'https://cran.ism.ac.jp/src/contrib/PACKAGES'를 열 수 없습니다
경고메시지(들): 
1: In download.file(url, destfile = f, quiet = TRUE) :
  URL 'https://cran.r-project.org/CRAN_mirrors.csv': status was 'Peer certificate cannot be authenticated with given CA certificates'
2: 패키지 ‘BiocManager’(들)이 사용가능하지 않습니다 (그 이유는 for R version 3.5.2 입니다) 

Somansa의 Root 인증서 위치를 지정하는 옵션이 어딘가에 있을 것이라 생각하고 구글을 검색해 보았다. 홈 디렉토리의 .Renviron 파일에 이를 넣으면 된다고 한다. 힌트는 [StackOverflow] R Server: install.packages() certificate error에서 얻었다.

$ cat .Renviron 
CURL_CA_BUNDLE=.cert/Somansa_ROOT_CA.cer

다음은 bioconductor를 설치한 뒤의 모습이다.

> library(BiocManager)
Bioconductor version 3.8 (BiocManager 1.30.4), ?BiocManager::install for help

Somansa가 가로채기(?)를 하여 만들어 놓은 '자체 인증서' 문제는 앞으로 또 무슨 프로그램의 설치 작업에서 불거져 나올지 자못 궁금하다.

[CentOS 7] yum으로 R을 설치하지 못하던 문제를 해결하다(epel-repo)

epel(Extra Packages for Enterprise Linux)-release를 설치한 다음 R을 yum으로 깔려고만 하면 "One of the configured repositories failed"메시지가 나타나는 현상에 직면하였다. epel 저장소에 분명히 문제가 있는 것 같은데 구글을 뒤져보아도 마땅한 해결 방법을 찾기가 어려웠다. 그래서 conda base environment에 우선 설치를 해 놓은 다음, yum을 이용한 방법에 다시 도전하였다.

다음의 글에서 힌트를 얻었다.

[SOLVED] One of the configured repositories failed (Unknown)

/etc/yum.repos.d/epel.repo 파일을 열어서 baseurl= 앞의 '#'를 제거하고, metalink= 줄은 주석 처리를 하였다. 아마도 metalink 주소에 문제가 있는 것 같다. epel-repo 파일을 수정한 다음 yum install R을 실행하니 245개나 되는 패키지를 시원스럽게 다운로드하여 설치가 완료되었다.


[epel]
name=Extra Packages for Enterprise Linux 7 - $basearch
baseurl=http://download.fedoraproject.org/pub/epel/7/$basearch
#metalink=https://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$basearch
failovermethod=priority
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7

의존성이 있는 프로그램을 한방에 설치해 주는 데에는 conda만한 것이 없다. Qiime 2 정도가 되면 bioconda의 힘을 빌리지 않고 설치하는 것은 정말 고통스러울 것이다(실제로 공식 문서 사이트에서는 소개하고 있지도 않다). 그러나 구체적인 애플리케이션에 대하여 너무 개별적으로 환경을 만들어 주는 것은 그렇게 바람직하다고 생각하지 않는다. 가능하다면 다소 수고스럽더라도 의존성을 해결해 가면서 하나씩 해결을 하려는 노력을 아끼지 않는 것이 중요하다고 본다. Prokka나 Roary 정도라면 직접 설치를 할만하다. 그리고 bioconda라고 해서 의존성 있는 프로그램/라이브러리를 전부 자동으로 설치해 주는 것은 아님에 유의해야 한다. 따라서 설치법 문서를 주의 깊게 읽어야 한다.

그럼에도 불구하고 Sanger Institute의 Artemis는 bioconda를 이용하여 설치하였다. 왜냐하면 수작업으로 설치할 때 필요한 Apache Maven을 아직 잘 이해하지 못했기 때문이다.

어제는 집에서 사용하는 노트북 컴퓨터에 자바 런타임을 설치하려고 다운로드 사이트에 갔더니 오라클에 유저 등록을 하라는 메시지를 접하게 되었다. 예전에는 라이선스에 동의하는 것만으로도 설치 파일을 내려받을 수 있었는데... 돈이 드는 것은 아니지만 그동안 편리하게 사용한 것에 대해 이 정도의 수고는 감수해야 할 것이다.

2019년 4월 22일 월요일

도대체 내가 Perl 사용자 자격이 있는가?

오랫동안 Perl을 사용해 왔고, 가끔 초보 수준의 스크립트를 짜면서 '아무리 지저분해도 어쨌든 돌아가면 된다(혹은 한 가지 목적을 달성하는 방법은 여러 가지가 있다)'는 순진한 생각이 Perl의 기본 정신과 맞닿아 있다는 안이한 생각에 빠져 있었다. 그런데 이번에 CentOS 7을 새롭게 설치한 뒤 Perl module을 하나씩 재설치하면서 기본이 없어도 너무 없다는 생각을 갖게 되었다. 아무리 경험이 많아도 정확한 지식을 기반으로 한 것이 아니라면 사상누각과 같지 않겠는가?

일반 사용자 권한으로 Perl -MCPAN -e shell(혹은 명령행에서 cpan 실행)을 처음으로 실시하면 다음과 같은 질문을 던진다. 펄 라이브러리 디렉토리에 쓰기 권한이 없으니 어떻게 할 것이냐는 뜻이 되겠다.

Warning: You do not have write permission for Perl library directories.

To install modules, you need to configure a local Perl library directory or
escalate your privileges.  CPAN can help you by bootstrapping the local::lib
module or by configuring itself to use 'sudo' (if available).  You may also
resolve this problem manually if you need to customize your setup.

What approach do you want?  (Choose 'local::lib', 'sudo' or 'manual')
 [local::lib] 

관리자 권한으로 이 명령을 불러냈음에도 불구하고 왜 local::lib을 쓴다고 했는지 모르겠다. 그러니 .bashrc에 일반 사용자는 접근할 수 없는 위치로PERL_LOCAL_LIB_ROOT PERL_LOCAL_LIB_ROOT PERL_LOCAL_LIB_ROOT PERL_LOCAL_LIB_ROOT 등의 변수가 줄줄이 선언되어서 root를 제외하고는 접근을 하지 못하게 된 것 아니던가.

어떤 펄 모듈의 설치 위치를 알고 싶다면 'perl -I 모듈명'을 입력하면 된다. 다음의 결과를 보라. 빨간색 디렉토리는 local::lib을 쓰겠다고 하는 바람에 root 디렉토리 아래의 위치로 설정된 환경변수를 나타낸다. 상황이 이러하니 BioPerl을 설치했다고 믿었음에도 불구하고 일반 사용자로는 이를 쓸 수 없었던 것이다.

# perldoc -l Bio::Perl
/root/perl5/lib/perl5/Bio/Perl.pm
# perl -e 'print join "\n", @INC; print "\n"'
/root/perl5/lib/perl5/5.16.3/x86_64-linux-thread-multi
/root/perl5/lib/perl5/5.16.3
/root/perl5/lib/perl5/x86_64-linux-thread-multi
/root/perl5/lib/perl5
/usr/local/lib64/perl5
/usr/local/share/perl5
/usr/lib64/perl5/vendor_perl
/usr/share/perl5/vendor_perl
/usr/lib64/perl5
/usr/share/perl5
.

/root/.cpan/CPAN/MyConfig.pm을 삭제한 다음, BioPerl installation 문서에 나온 방법을 이용하여 다시 BioPerl을 설치하였다. 이번에는 /usr/local/share/perl5 아래에 제대로 펄 모듈들이 위치하였다.

App::cpanminus

cpan은 기본적으로 말이 많다. 그것이 성가시다면 cpanminus를 쓰면 된다. Perl이 설치된 시스템에 cpan은 자동적으로 따라오지만, cpanminus는 그렇지 않으니 추가적으로 깔아야 한다. cpan과 마찬가지로 App::cpanminus는 cpanm이라는 스크립트를 통해서 실행된다. 

많은 펄 모듈이 rpm 패키지로도 제공됨을 기억하면 좋다. 즉, cpan 혹은 cpanm 명령이 아닌 yum 명령으로 설치할 수도 있다는 것이다. 내가 App::cpanminus의 rpm 패키지를 설치했던가? 패키지의 이름은 약간 다르므로 주의해야 한다.

$ rpm -qa | grep perl-App-cpanminus
perl-App-cpanminus-1.6922-2.el7.noarch

설치가 된 상태였다. 이를 지우고 관리자로 전환한 다음 cpan에서 App::cpanminus를 실행해 보았다. 앗, 왜 다시 root 디렉토리에 설치를 하는 것인가?

Running make install
Manifying 1 pod document
Manifying 2 pod documents
Installing /root/perl5/lib/perl5/App/cpanminus.pm
Installing /root/perl5/lib/perl5/App/cpanminus/fatscript.pm
Installing /root/perl5/man/man1/cpanm.1
Installing /root/perl5/man/man3/App::cpanminus::fatscript.3pm
Installing /root/perl5/man/man3/App::cpanminus.3pm
Installing /root/perl5/bin/cpanm
Appending installation info to /root/perl5/lib/perl5/x86_64-linux-thread-multi/perllocal.pod
  MIYAGAWA/App-cpanminus-1.7044.tar.gz
  /usr/bin/make install  -- OK

생각을 해 보니 조금 전에 .bashrc에서 Perl 관련 환경변수를 삭제한 뒤에 다시 로그인을 하지 않아서 그런 것이었다. /root/perl5 디렉토리를 제거하고 로그아웃 후 다시 들어와서 cpan을 실행한 다음 'install App::cpanminus'를 실행하여 보았다. 예상한대로 /usr/local/share/perl5 아래에 제대로 설치가 되었고, 명령 프롬프트에서 cpanm을 실행해도 문제가 없다. cpanm 스크립트의 위치(/usr/local/bin/cpanm)은 yum으로 perl-App-cpanminus를 설치했을 때와는 다르다(/usr/bin/cpanm).

Perl의 패키지 관리 시스템은 허술해 보이기도 하지만 또 그런대로 유연하다. Perl package manger(PPM)은 파이썬으로 치자면 pip에 해당하는 것인가? 하지만 펄 라이브러리 설치 위치만 잘 기억하고 있으면 cpan(m)만으로도 충분하다고 생각한다. 몇 개의 환경변수, 그리고 @INC를 잊지 말자.

네이버 그린팩토리 방문

경기도 성남시 분당구 정자동에 위치한 네이버 신사옥 건물을 그린팩토리라고 부른다. 1층및 2층에 있는 도서관은 일반에게 개방이 되어 있다고 하여 무작정 가 보기로 하였다. 개인적으로 네이버를 별로 좋아하지는 않는데 네이버가 제공하는 대중 시설을 이용하는 것은 과연 옳은 일인가? 변절인가?

Do the right thing.

내가 스스로에게 부여한 좌우명에 해당하는 말이다. 나는 이를 '옳은 일을 해라' 정도로 생각하고 있다. 그런데 스파이크 리 감독의 1989년 영화의 제목 역시 Do the right thing('똑바로 살아라'로 번역)이다. '똑바로 살아라!'라고 하면 약간의 권위의식을 가지고 나무라는 것 같아서 별로 마음에 들지 않는다.

내가 현재 살고 있는 곳에서 산보 삼아 걸어서 네이버 그린 팩토리 도서관에 갈 수 있다는 것은 대단히 즐거운 일임에는 틀림이 없다. 잡지를 볼 수 있는 1층 공간은 회원 가입을 하지 않아도 자유롭게 출입이 가능하다. 이용 시간은 저녁 7시 반까지이다. 상당히 많은 잡지가 있어서 놀랐고, 그러한 반면 국내 잡지는 찾기가 쉽지 않았다. 영문 잡지명 기준으로 분류가 되어 있어서 그런것인지, 아니면 국내 잡지가 적어서 그런 것인지는 잘 모르겠다. 만약 네이처의 책장을 넘기면서 보고 싶다면 이곳을 찾으면 되겠다. 그렇다면 네이처 제네틱스는? 네이처 리뷰스 마이크로바이올로지는? 자매지까지 총망라하고 있는 것은 아니다. 스카이&텔레스코프를 여기서 볼 수 있어서 참 새로웠다.

비즈니스 관련 국내 잡지 몇 권을 읽으면서 머릿속이 새로운 생각으로 차오르는 느낌이 들었다. 그렇다. 잡지를 읽는다는 것이 바로 이런 것이로구나! 내가 종사하는 분야의 최신 논문을 늘 옆에 끼고 읽지 못하고 있다는 죄책감에 시달릴 필요가 없었다. 세상을 돌아가게 하는 큰 흐름을 읽는 것이 더 중요하다는 생각이 문들 들었다. 수첩을 들고 가지 못한 것이 너무 아쉬었다.
성공은 계획되지 않는다. 나중에 설명될 뿐이다.
어차피 도와줄 것이라면 특별한 도움이라는 것을 넌지시 알려주면 흔쾌히 도와주는 게 좋다.
(사내)정치란 관계의 정립이다. 자기 주변의 관계를 다음과 같이 정립하라.

오래 고민을 하고 궁리할수록 좋은 답이 나온다는 것이 나의 신념이었다. 그러나 판단은 빨리 내려야 한다. 판단과 이에 따르는 실행을 뒤로 미루기 위해 궁리를 계속 하고 있다면 그것은 옳은 일이 아니다. 특히 CEO는 70% 정도의 확신이 들 때 빨리 실행에 옮기고, 만약 잘못된 길을 가고 있다는 생각이 들면 빨리 고쳐나가는 것이 더 옳다는 글을 보고 많은 생각을 하였다. 당장 실행에 옮기는 것이 중요하다고 해서 날을 세우지 않은 톱으로 나무를 자를 수는 없는 노릇 아닌가. 빠른 결정과 실행이 곧 준비가 부족해도 됨을 의미하는 것은 아닐 것이다. 그럼에도 불구하고 모든 것을 미리 다 계획하여 단 하나의 예외도 발생하지 않을 것을 기대하고 추진을 하는 것은 너무 아름답지 못하다.


오늘 네이버 그린팩토리 방문은 계획한 일이 전혀 아니었다. 물론 아내가 같이 가자고 계속 얼마 전부터 권하기는 했었지만. 실패의 가능성까지 염두에 두고 일단 실행해 보는 것. 그것이 내게 필요한 자세이다.







2019년 4월 21일 일요일

Windows 7 지원의 종료가 멀지 않았다

사무실에서 사용하는 PC는 아직도 Windows 7을 고집하고 있었다. 2020년 1월 14자로 이것의 지원이 종료된다고 하니 익숙한 인터페이스에 작별을 고할 때가 멀지 않았다.

https://support.microsoft.com/ko-kr/help/4057281/windows-7-support-will-end-on-january-14-2020

내가 원래의 근무지에서 일하고 있었다면 설치매체를 대여하여 업그레이드를 한 다음 라이선스를 적용하면 모든 것이 해결된다. 그러나 지금은 장비를 반출하여 파견 근무지에 와 있으니 절차를 까다롭게 생각해 봐야 한다. 파견 근무지의 사이트 라이선스 계약을 파악하기 전에 내가 들고 온 PC에 파견지에서 제공하는 윈도우10을 설치할 수는 없을 것이다. 최악의 경우, PC를 들고 대전으로 출장을 가서 업그레이드를 한 다음 다시 가져와야 할지도 모른다.

윈도우 7이 출시된 것이 2009년 10월 22일이었다고 한다. 윈도우10의 공식 발매는 2015년 7월 29일. 10년 동안 소프트웨어 제품을 유지했다면 충분히 오랜 기간 노력을 한 것이다. 얼마 전에 아직 쓸만한 진공청소기의 부품(공기 배출구쪽의 필터)를 사러 갔더니 더 이상 보유하고 있지 않다고 하였다. 비록 먼지봉투는 여러 기종에서 공통으로 쓰이므로 아직 원활하게 구입을 할 수 있었다. 부품 보유 여부가 매우 중요하게 작용하는 자동차의 경우 부품 보유 기간은 생산 중단 시점으로부터 8년이라고 한다.

산업과 경제를 생각한다면 오래된 것은 가급적 버리고 새 것을 사는 것이 좋다. 어제 국립현대미술관 서울관에서 보았던 아스거 욘(Asger Jorn)의 설치작품 '삼면 축구'을 재현해 놓은 것에 이런 말이 적혀 있었다. '미래는 과거를 잊고 파괴하는 일에서 시작된다(정확하게 기억하는 것은 아님)'는...




환경을 생각한다면 낡은 것도 되도록 고쳐서 쓰는 것이 좋다. 그렇다면 손에 잡히지 않는 생각은 어떠한가?

2019년 4월 18일 목요일

CentOS 7로 업그레이드하기

연말까지는 되도록 업그레이드를 하지 않고 CentOS 6.10로 버티려고 했었으나 땜질 처방만으로 유지하는 것에는 한계가 있다고 생각하여 단호하게 업그레이드를 하기로 결심하고 즉시 실행에 옮겼다. 업무용(대부분 생명정보 분석용) 프로그램의 설치가 쉬운 Ubuntu 16.04로 갈아타는 문제도 한참을 고민하였지만 공용 서버로서 안정적이고 보수적인 운영을 원한다면 CentOS 7이 나을 것으로 최종 결정을 하였다.

언제나 그렇듯이 한 번의 시도에 흡족할 수준으로 설치가 되지는 않았다. 리눅스를 설치할 때마다 늘 혼동스러운 것은 하드디스크의 파티션 과정이다. 완전 자동으로 파티션을 하도록 만든 다음 설치를 마치고 났더니 /은 겨우 50 GB에 불과하고 나머지를 전부 /home으로 만든 것이 아닌가. 추가로 설치할 응용 프로그램이 상당히 많은데 이를 전부 심볼릭 링크로 만들 수는 없는 노릇이다. 다시 설치를 시도하였다. 요즘도 swap 파티션이 꼭 필요한 것인가하는 생각이 들기도 하고... 자동으로 생성한 파티션에서 swap 크기가 이 얼마였는지 확인을 해 보지 않고 재설치를 하고 말았다. df 명령으로는 swap 파티션이 보이지 않으므로 swapon -s 명령을 써야 한다(오늘 알게 된 사실).

'Swap 파티션의 크기는 대략 메모리의 두 배'라는 옛날의 기준을 수백 기가 바이트의 메모리가 장착된 요즘의 컴퓨터에도 적용해야 할까? 그렇지는 않으리라. 내 컴퓨터의 메모리는 256 GB이다.

Red Hat Enterprise Linux 권장 swap 크기는 어떻게 되나요?

16 GB면 충분한 것을, 무려 100 GB나 잡아 놓았다!!

CentOS 7로 업그레이드를 하니 예전에 즐겨 사용하던 palimpsest 디스크 유틸리티는 보이지 않고 거의 비슷한 외관의 gnome-disk-utility가 있다. 100 GB나 되는 공간이 swap으로 떡하니 자리를 차지하고 있는 것을 보니 안타깝다. 그놈 디스크 유틸리티(혹은 gparted)에서 구동 중인 하드디스크의 파티션을 조정하는 것이 가능한 것 같다(참고). 다만 바뀐 UUID를 수동으로 다시 맞추어 주어야 한다.

OS를 새로 설치하니 UID와 GID가 바뀌어서 NFS로 물린 시놀로지 NAS의 자료를 고치기가 어렵게 되었다. 계정명은 동일하지만 ID는 501에서 1001로 바뀌었으니 디렉토리와 파일이 주인을 잃은 상태가 되었다. 같은 시스템 안에 있던 RAID 공간에 있던 것들은 chown 명령으로 복구를 하였지만 NFS로 물린 것은 이렇게 고쳐지지 않는다. usermod 혹은 groupmod 명령어를 쓰는 것은 별로 권장할 일이 아닌 것 같다. 왜냐하면 홈 디렉토리 이외의 것에 대해서는 자동으로 고쳐지지 않기 때문이다. 또한 여기에 새로 만드는 파일 및 디렉토리의 권한은 777이 된 상태이다. NAS쪽에서 설정을 바꾸어야 하는 것일까? 보안과 squash 필드의 의미를 정확히 아는 것이 필요하다.

로컬 네트워크(NFS) 내에서 Synology NAS의 파일에 액세스하는 방법

아직도 해결할 일이 많이 남았다.

2019년 4월 21일 업데이트

새로 OS를 설치하는 것이니만큼 Perl 모듈도 깨끗하게 깔고자 하였으나 원하는대로 잘 되지는 않았다. 관리자 권한으로 perl -MCAPN -e shell 명령을 사용하여 BioPerl 설치 진행을 하였더니 루트의 홈 디렉토리에 펄 base directory가 지정되는 별로 바람직하지 않은 결과가 되었다. 여기에다가 필요에 의해 rpm 및 conda environment로 설치한 모듈까지 뒤죽박죽이 되고 말았다. prokka나 roary처럼 Perl 모듈에 대한 의존도가 높은 프로그램을 설치할 때 특히 주의를 해야 하는데 그렇게 하지를 못했다.

만약 내가 사용하려는 프로그램이 XML::Simple을 필요로 한다고 치자. perl -MCPAN -e shell 명령으로 설치를 했다 하더라도 yum install perl-XML-Simple 명령을 내리면 이미 시스템에 존재하는지를 확인하지 않고 중복하여 설치하는 것 같다. bioconda 패키지의 설치 역시 그런 것 같다.

앞으로 conda 환경이 아닌 시스템에서 직접 Perl 모듈을 설치할 때에는 CPANMinus(또는 CPANM) 유틸리티를 사용하는 것이 좋을 것이다. 그러려면 CPANM 자체를 설치하는 방법도 알아야 한다. App::cpanminus를 직접 설치하거나, 아니면 perl-App-cpanm rpm 패키지를 yum으로 설치하는 방법이 있다.

NAS의 최상위 디렉토리에서 파일이나 디렉토리를 만들면 777 권한이 되지만, 새로 만든 디렉토리의 권한을 적당히 바꾼 뒤 그 하위에 새로운 파일 또는 디렉토리를 만들면 umask에서 원래 설정한대로 되는 것을 확인하였다. Synology NAS쪽에서는 소유자가 잘못된 파일 등을 웹으로 접속하여 지우는 것 정도로만 마무리를 하였다.

2019년 4월 11일 목요일

회사 프록시 서버 뒤에서 docker pull을 실행하지 못하는 문제에 도전해 보자

프록시(proxy) 서버란 네트워크 서비스의 중계 역할을 하는 장비를 일컫는다. 과거에는 IP 주소를 세탁하고 접속이 차단된 곳을 둘러서 연결하게 만드는 뭔가 음험한 물건으로만 생각했었다. 원래 이 장비는 네트워크 트래픽을 줄이기 위한 목적으로 쓰는 것이라 하였다. 즉, 한번 접속해서 가져왔던 정보를 프록시 서버의 캐시에 저장해 둔 뒤, 같은 내용을 클라이언트에서 요청하는 경우 캐시의 것을 재전송함으로써 다시 원격 서버에 연결을 할 필요가 없게 만드는 것이다.

도대체 프록시 서버가 나와 무슨 관계가 있을까? 집에서 편히 앉아서 고속 인터넷망으로 접속을 하는 경우라면 프록시 서버의 존재에 신경을 쓸 필요가 없다. 그러나 회사 내 전산망이라면 사정은 다르다. 업무와 무관한 웹사이트의 접속을 차단하고, 중요 내부 정보의 유출을 막기 위한 보안 차원에서 프록시 서버를 사용하는 경우가 많다고 한다.

과연 나는 프록시 서버를 통해서 외부에 접속하는 것일까? Am I behind a proxy? 사이트에 접속을 하면 프록시 서버가 있는지를 알 수 있다고는 하지만, 이러한 서비스가 항상 프록시 서버의 존재 여부를 정확하게 검출하는 것은 아니다. 

기업의 입장에서 프록시 서버를 도입하여 운용하는 것을 뭐라고 할 수는 없다. 다만 HTTPS 트래픽을 복호화하여 필요한 '차단' 혹은 '기록(이것을 실제로 하는지는 잘 모른다)' 조치를 취한 다음 다시 암호화하여 내부로 돌려보내는 암호화 트래픽 복호화·가시성 장비(예: 소만사 HTTPS프록시)가 그렇게 만족스럽게 작동하지는 않는다는 것이다. SSL 가시성이라고 좋게 표현하지만, TLS(Transport Layer Security, SSL과 거의 같은 의미) interception이라고 써 놓으면 왠지 마뜩찮아 보인다.
보이지 않는 것은 보호할 수 없다.
멋진 말이기는 한데, 한편으로는 찝찝하다. 예를 들어 내가 소유한 은밀한 사진들을 비밀스런 사설 금고에 보관하고 싶은데, 이를 맡아주는 사람은 그 사진을 투명한 비닐백에 넣어 오지 않으면 안된다고 하는 것과 무엇이 다른가. '공공의 이익에 부합되지 않은 것을 보관해 줄 수는 없으니 금고지기는 내용물을 꼭 보아야 되겠다'라는 논리와 비슷하다. 물론 이 짧은 글을 통해서 이에 대한 논쟁을 확대하고 싶지는 않다.

어찌되었든 내가 앉아있는 책상 위의 컴퓨터에서 외부 세계로 HTTPS 접속을 한 뒤 인증서 정보를 열어보면 Somansa가 Root CA인 것으로 바뀌어서 나온다. 물론 소만사는 최상위 인증기관이 아니다. 소만사의 '공인되지 아니한' 루트 인증서는 업무용 컴퓨터(윈도우)를 세팅하는 과정에서 웹 브라우저에 설치가 되었다. 전산 담당자가 해 준 것인가, 저절로 한 것인가? 그건 잘 모르겠다. 변경(변조?)된 루트 인증서 정보에 보이는 Somansa라는 회사명으로 짐작하건대 아마도 이 회사의 프록시 서버가 변경을 했을 것이다. 이러한 루트 인증서 변경이 일어진다는 것을 안 것은 며칠 되지 않았다. 구글을 검색해 보면 이는 이미 잘 알려진 일이다.

[StackOverflow] Can proxy change SSL certificate? - 네, 그렇습니다!

문제는 리눅스 서버를 사용할 때이다. conda, curl, docker 등 https://(433번 포트)를 사용하는 서비스마다 연결이 제대로 되지 않아서 무척 애를 먹었다. 앞의 두 개는 각 프로그램의 고유한 설정 파일에 Somansa 루트 인증서를 넣어서 해결을 하였으나 docker는 도무지 해결이 되지 않았다.

$ docker pull ubuntu:16.04
Pulling repository ubuntu
Get https://index.docker.io/v1/repositories/library/ubuntu/images: x509: certificate signed by unknown authority

[StackOverflow] Docker : Get https://registry-1.docker.io/v2/: x509: certificate signed by unknown authority를 비롯한 많은 글에서 이에 대한 질문과 답변을 볼 수 있었다.
We have also a proxy. For monitoring our https connection to avoid malwares, our proxy creates a certificate on the fly for the secured connection between a station and the proxy. Then another secured connection is done between the proxy and the website. The message indicates that the certificate produced by the proxy was signed by an unknown authority: the "fake authority" which generates the certificates.
CentOS 6의 경우 소만사의 루트 인증서 파일을 받아다가 /etc/pki/ca-trust/source/anchors/ 아래에 복사한 다음 update-ca-trust force-enable와 update-ca-trust extract 명령을 차례로 실행한 뒤 docker 서비스를 재시동하면 된다는데 도무지 성공의 기미가 없다.
(인증서 파일을 받으려면 웹브라우저에서 내보내기를 하거나 openssl 프로그램을 쓰는 방법이 있다.)
남은 방법은 어떻게 해서든 docker image를 받아서(프록시 서버 영향을 받지 않는 다른 장비에서 docker pull 사용) 파일로 만든 뒤 이를 작업하고자 하는 리눅스 서버로 전송하여 docker load -f tar_file을 하는 것뿐이다. 네트워크를 거치는 docker pull만 아니라면, 일단 받은 이미지 파일을 docker run으로 올리는 데에는 문제가 없다. 혹은 docker pull 명령어를 쓰지 않고 이미지를 다운로드하는 유틸리티인 docker-drag(python 2.7 필요)을 쓰는 방법도 가능하다고 한다. 이는 검색에 검색을 거듭하여 겨우 알아낸 것인데([StackOverflow] How do I download docker images without using the pull command?), 아직 절반의 성공일 뿐이다. 왜냐하면 ubuntu:14.04 및 ubuntu:16.04를 다운로드하여 docker run을 하는 것은 성공하였지만...

$ python docker_pull.py ubuntu:14.04
Creating image structure in: tmp_ubuntu_14.04
e082d4499130: Pull complete [67148830]
371450624c9e: Pull complete [72650]
c8a555b3a57c: Pull complete [363]
1456d810d42e: Pull complete [162]
Docker image pulled: library_ubuntu.tar
$ docker load -i library_ubuntu.tar 
$ docker images
REPOSITORY                      TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu                          14.04               7dc2e660bb0c        4 weeks ago         188.1 MB
hello-world                     latest              c72cc8666399        3 months ago        1.84 kB
anvio_jeong180710_cog           latest              bf09cd455d01        9 months ago        3.936 GB
... 중간 생략...
phacnml/plasmidprofiler_0_1_6   latest              ae30d10d24fc        2 years ago         6.564 GB
$ docker run --rm -it ubuntu:14.04 /bin/bash
root@d604c684d26c:/# df -h
Filesystem                                                                                         Size  Used Avail Use% Mounted on
/dev/mapper/docker-8:19-12583470-d604c684d26c2cfaf0f3e234dd867535d306734b37c4c35884bfa7673fe489ea  9.8G  219M  9.1G   3% /
tmpfs                                                                                              127G     0  127G   0% /dev
shm                                                                                                 64M     0   64M   0% /dev/shm
/dev/sdb3                                                                                          5.3T  1.9T  3.2T  37% /etc/hosts

qiime2/core:2018.11을 다운로드할 때에는 'IOError: Not a gzipped file'이라는 에러 메시지가 나면서 실패를 했기 때문이다.

같은 링크에서 소개한 download-frozen-image-v2.sh는 golang, jq 등 생소한 것들을 같이 설치해야 하는 문제로 테스트에 시간이 걸리고 있다. 이에 대해서는 나중에 기록할 예정이다. 이 두 가지 유틸리티 외에도 Downloading Docker Images from Docker Hub without using Docker를 살펴보면 좋은 아이디어가 많으니 참고해 보도록 한다.

download-frozen-image-v2.sh의 활용법(아직은 실패)

위에서 소개한 URL에서 스크립트를 다운로드한다. 추가적으로 jqgo가 필요하다. 두 프로그램 전부 리눅스용 바이너리로 배포되는 것을 받아서 사용하였다. 

curl은 anaconda2 base environment에서 재설치하였고, 문제의 Somansa 루트 인증서는 /opt/anaconda3/ssl/에 설치하였다. 인증서 재설치에 관해서는 curl에 신뢰하는 인증서 추가하기를 참조하였다. 그러나 qiime2은커녕 docker-drag로 받아서 잘 돌아가던 ubuntu 이미지조차 잘 실행되지 않는다.


$ ./download-frozen-image-v2.sh temp_download ubuntu:16.04
Downloading 'library/ubuntu:16.04@16.04' (4 layers)...
#######################################################

Download of images into 'temp_download' complete.
Use something like the following to load the result into a Docker daemon:
  tar -cC 'temp_download' . | docker load
$ tar -cC 'temp_download' . | docker load
Error response from daemon: could not find image: Prefix can't be empty

에혀~ 나도 모르겠다. 동료가 윈도우 Hiper-V 환경에서 받은 도커 이미지를 제공해 주어서 이것을 리눅스 서버로 갖고 들어와서 사용해 보았다. qiime2만 생각한다면 bioconda로 설치를 해 두었으니 실행을 하는 데에는 무리가 없다. 그러나 앞으로의 확장 가능성을 생각한다면 docker를 피해나갈 수는 없을 것이다.

2019년 4월 16일 업데이트

CentOS의 버전이 너무 오래된 것이 문제라는 생각이 든다. 현재의 docker 설치 안내문서(Get Docker CE for CentOS)를 읽어보면 다음과 같이 기재되어 있다.

OS requirements
To install Docker CE, you need a maintained version of CentOS 7. Archived versions aren’t supported or tested.

이제 진지하게 CentOS 6을 버리고 7로 업그레이드하는 것을 생각해 보도록 하자.

2019년 4월 9일 화요일

아직 끝나지 않은 HTTPS/SSL 문제

Conda 활용에서 걸림될이 되는 SSL 인증 관련 문제는 대충 해결이 되었다. 하지만 docker와 git는 아직 해결이 되지 않은 상태이다. git 명령의 경우 아쉬운대로 직접 압축파일(.ZIP)을 받아다가 수동 설치하는 것으로 땜질 처방을 하였다.

pip까지도 불만을 토해낸다. 무슨 파이썬 패키지가 설치되었는지를 알고 싶어서 pip list를 하면 다음과 같은 성가신 메시지가 나온다.

$ pip list
Package    Version  
---------- ---------
biopython  1.72     
certifi    2018.8.24
ls-bsr     dev      
numpy      1.15.2   
pip        18.0     
setuptools 40.4.3   
wheel      0.32.0   
Could not fetch URL https://pypi.org/simple/pip/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/pip/ (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:719)'),)) - skipping
(py35) [hyjeong@tube LS-BSR-master]$ pip list --trusted-host pypi.org --trusted-host files.pythonhosted.org

팁 - 파이썬 패키지 설치할 때 SSL 인증 오류 해제 방법에서 힌트를 얻었다. 홈 디렉토리의 .pip/pip.conf에 다음의 내용을 추가하거나,


[global]
trusted-host = pypi.org
               files.pythonhosted.org

혹은 pip install 혹은 pip list 명령을 수행할 때 --trusted-host pypi.org --trusted-host files.pythonhosted.org 옵션을 주면 된다.


오후에 쓴 업데이트

직원의 도움으로 git 문제는 해결을 하였다. conda base environment에서 curl과 git를 업데이트한 다음, 인증서를 수동 설치하였다. git의 인증서 관련 설정을 변경하는 방법은 git에서 https repository 연결시 SSL 인증서 오류 해결법을 참조하였다.

인증서 체인이니 번들이니 하는 것의 개념을 아직 완벽하게 이해한 것이 절대로 아니다! 앞으로도 갈 길이 멀다. 다음의 사이트가 매우 유용하므로 이를 참조하자.

Get your certificate chain right

2019년 4월 5일 금요일

사람 헷갈리게 만드는 conda 환경 설정

Conda의 공식 문서 사이트의 사용자 가이드와 Anaconda 웹사이트의 Conda 4.6 Release 문서가 미묘하게 달라서 혼동을 유발하고 있다. conda init 명령이 바로 그것이다. 공식 문서 사이트에는 이에 대한 언급이 거의 없다.

Anaconda를 설치할 때, 로그인 스크립트에 conda 환경을 만들어 주는 코드(설치 디렉토리 하위의 /etc/profile.d/conda.sh)를 삽입할 것인지를 묻는다. 그렇지 않은 경우에는 PATH 환경변수의 맨 앞에 anaconda의 bin 디렉토리를 추가하라고 지시한다.
[참고] conda.sh를 로그인 스크립트에서 시동하면 잘 되지만, 명령행에서 source (PATH)/conda.sh를 쳐서 실행하면 잘 되지 않는다. 그러한 경우 environment 이름 없이 그냥 conda activate라고만 치면 된다(How do I activate a conda environment in my .bashrc?).
그런데 몇 가지 environment와 프로그램을 업데이트하고 conda 자체도 업데이트하였더니, 어느 순간에서부터 conda init SHELL_NAME을 실행하라는 메시지가 나오는 것이다. 이는 Anaconda의 Conda 4.6 Release의 맨 앞에 잘 설명이 되어 있다. 이 명령을 실행하면 .bashrc의 뒷부분에 다음과 같은 짤막한 코드를 삽입하게 된다.

# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/opt/anaconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
else
    if [ -f "/opt/anaconda3/etc/profile.d/conda.sh" ]; then
        . "/opt/anaconda3/etc/profile.d/conda.sh"
    else
        export PATH="/opt/anaconda3/bin:$PATH"
    fi
fi
unset __conda_setup
# <<< conda initialize <<<

또 다른 문제는 .condarc 설정 파일에 관한 문제이다. Conda 공식 문서를 보면 conda config 명령을 처음 실행할 때 홈 디렉토리에 이 파일이 생성되며, root environment에 있는 .condarc는 홈 디렉토리의 것에 우선하여 작동한다고 하였다.

The conda configuration file, .condarc, is an optional runtime configuration file that allows advanced users to configure various aspects of conda, such as which channels it searches for packages, proxy settings and environment directories.
The .condarc file is not included by default, but it is automatically created in your home directory the first time you run the conda config command.
.condarc file may also be located in the root environment, in which case it overrides any in the home directory.
anaconda2에서는 여기에 소개한 그대로 잘 작동하는 것 같았다. 그런데 anaconda3를 설치하고 몇 가지 작업을 하였더니 또 어느 순간부터는(아마도 conda 자체를 업데이트한 다음이 아닐까?) root environment에 무엇이 있든 상관이 없이 홈 디렉토리의 .condarc가 적용되는 것이다. 여기에서 root environment란  conda를 설치한 최상위 디렉토리를 의미한다. 즉 설치 과정에서 PREFIX=/opt/anaconda2로 정의되는 위치이다. <= 밑줄을 친 부분은 나중에 확인해보기 바란다. conda 버전에 따라서도 약간 다른 것 같다.

혹시 착각이 아니었을까? 확인을 위하여 anaconda2로 들어간 다음, anaconda 설치 root environment의 .condarc 파일을 수정하였다. 그러고나서 conda config --show를 했더니 바뀐 내용이 출력된다. 그런데 최신 (ana)conda에서는 오로지 홈 디렉토리에 있는 .condarc가 최우선이다.

Root environment라는 용어도 약간의 혼동을 초래한다. 이것은 conda를 설치하는 디렉토리를 말하는가, 혹은 conda create -n MYENV라고 실행하여 만들어내는 environment 부류 중에서 가장 기본이 되는 환경을 의미하는가? 후자에서 '기본 환경'이라 함은 최초로 conda create -n을 실행하기 전, 처음으로 anaconda를 설치했을 때의 환경을 말한다. Conda의 어떤 버전 문서에서는 root environment라고 부르다가, 최근 문서에서는 base environment라고 불리는 것 같다.

별 일이 아니라 생각했었는데 의외로 고려할 사항이 많다.

2019년 4월 7일 업데이트

Conda 공식 문서의 Troubleshooting 섹션에 SSL connection errors[1]에 대처하는 방법이 나온다. 이는 지난 며칠 동안 나를 괴롭혔던 문제(SSL과 관련한 conda 설치 에러)에 대한 직접적인 해결책이기도 하다. 내가 접한 에러 메시지를 그대로 복사하여 구글에서 검색을 하였을 때 이 페이지가 나오지 않았기 때문에 해결책을 알아내느라 고생을 한 것이다. 다음은 [1]에서 인용한 것이다. System-wide configuration file인 .condarc는 위에서 인용한 것과 같이 root environment에 있는 것인가?

When using conda config, the user's conda configuration file at ~/.condarc is used by default. The flag --system will instead write to the system configuration file for all users at /.condarc. The flag --env will instead write to the active conda environment's configuration file at/.condarc. If --env is used and no environment is active, the user configuration file is used.

2019년 4월 4일 목요일

13,495원을 내고 SSL 인증서를 구입하다

Hostinger에서 호스팅하는 내 위키 사이트를 더욱 안전하게 이용하기 위해 SSL 인증서를 구입하여 설치하였다. 한번 13,495원을 지불하고 평생 유지된다고 하니 투자해서 아까울 것은 없다.

실제 위키 사이트는 genoglobe.kr의 서브도메인에 있다.

이 사이트는 꽤 많은 정보를 계속하여 기록함은 물론 로그인 정보를 보내야 하기 때문에 SSL 인증서를 설치하여 https://로 시작하는 주소로 접속하게 하는 것이 매우 바람직하다. 그러나 나의 공식 홈페이지에 해당하는 http://genoglobe.com/은 로그인 기능이 없고 포함하는 정보도 매우 적으므로 그대로 두기로 하였다. 이 사이트에는 나에게 이메일을 보내는 폼이 있지만 설마 누가 여기에다가 국가 기밀이나 영업 기밀을 적어서 보내겠는가?

아직 남은 과제는 http://로 내 위키 사이트를 접속해도 강제로 https://...로 보내는 것이다. 이것은 hostinger tutorial을 참조하여 .htaccess를 편집하면 된다.

How to Force HTTPS

이 튜토리얼의 내용을 요약하자면 내 웹사이트로 들어오는 모든 요청이 https://로 강제로 보내지게 하려면 최상위 .htaccess 파일에 다음의 세 줄을 넣어 저장한 뒤 웹브라우저의 캐쉬를 지우고 재접속을 하면 된다. 주의할 것은 'RewriteEngine On' 라인이 .htaccess 파일 안에 단 한번만 존재해야 한다는 점.

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

.htaccess 파일을 잘못 건드리면 웹사이트가 아예 접속이 되지 않으므로 매우 주의를 기울여야만 한다. Hostinger 파일 관리자에서 수정을 완료한 다음 웹브라우저에 내 도메인 정보를 넣으니 저절로 https://로 접속이 된다.

hostinger.kr의 억지스런 우리말 번역을 보면 웃음이 날 지경이다.

'수색'이나 '시작하다' 정도면 그래도 준수하다.

'확인해 봐' 네, 네... 알겠습니다.


2019년 4월 3일 수요일

SSL과 관련한 conda 설치 에러 - anaconda3 [해결]

(2019년 4월 10일: 아무래도 정확하지 않은 정보를 가지고 섣불리 글을 쓴 것은 아닌지 걱정이 된다. 기본 개념부터 다시금 되짚어 보아야 하겠다. 본문은 2019년 4월 11일 최종 수정되었다.)

공공연구기관에서는 멀쩡히 작동하던 서버가 왜 기업 전산망 내부에서는 몽니를 부리는가? 4년 3개월 동안 아무런 장애 없이 나와 동고동락하던 서버를 정식으로 반출허가를 받아서 파견지로 힘들게 들고 나왔는데 왜 이런 일이 벌어지는 것일까? 달라진 것이라고는 네트워크 설정을 바꾸고 그리드 엔진을 삭제한 것뿐이다.

그동안 잘 사용해 오던 anaconda2 환경에 새로운 bioconda 패키지를 설치하려는데 도무지 되질 않는다. anaconda3을 새로 설치한 다음 conda 자체를 업데이트하고자 시도하였으나 다음과 같은 에러 메시지가 나왔다. Firefox에서 http 사이트를 연결하면 (다 그런 것은 아니지만) 안전한 연결이 아니라고 하면서 화면이 뜨지 않는다.

# conda install conda
Solving environment: failed

CondaHTTPError: HTTP 000 CONNECTION FAILED for url 
Elapsed: -

An HTTP error occurred when trying to retrieve this URL.
HTTP errors are often intermittent, and a simple retry will get you on your way.

If your current network has https://www.anaconda.com blocked, please file
a support request with your network engineering team.

SSLError(MaxRetryError('HTTPSConnectionPool(host=\'repo.anaconda.com\', port=443): Max retries exceeded with url: /pkgs/r/noarch/repodata.json.bz2 (Caused by SSLError(SSLError("bad handshake: Error([(\'SSL routines\', \'tls_process_server_certificate\', \'certificate verify failed\')])")))'))
처음에는 그저 사내 전산망을 보호하는 방화벽에서 443번 포트가 막혀서 그런가 보다하고 관리자에게 이를 풀어줄 것을 요청하면 될 것이라 생각했었다. 그런데 구글에서 내가 해결할 방안이 없을지 검색을 거듭한 결과 이는 SSL(Secure Socket Layer) 인증서와 연관된 문제라는 생각이 들었다. 나와 비슷한 문제를 겪는 사람이 의외로 많이 있었다. 이번에야말로 SSL 인증서가 무엇이고 왜 중요한지를 알아볼 수 있는 마지막 기회라고 생각하고 공부를 하기로 마음을 먹었다. 그렇지 않으면 영원히 초보 리눅서를 벗어날 수 없다! CD-ROM으로 슬랙웨어를 설치하던 것이 94년쯤이었나, 25년이 넘어가는 지금까지도 별로 실력이 늘지를 않았다.

웹 서버와 브라우저 사이의 안전한 접속을 보장하는 SSL을 알아보자. 다음의 동영상(유튜브 링크)을 한번 감상하고, 그 다음에 나열한 웹사이트를 찬찬히 읽어보라. (1) 데이터를 암호화하여 중간에 나쁜 의도를 가진 사람이 이를 가로채도 내용을 알아볼 수 없게 하는 것, 그리고 (2) 웹 브라우저가 접속한 서버가 가짜가 아닌지를 확인하는 것이 주된 목적이다.


인증 기관의 인증서 목록이 없거나 모르는 기관에서 발급한 인증서일 경우 "curl"은 인증서 검증 에러를 발생시키고 작업을 중단한다고 한다(curl에 신뢰하는 인증기관 인증서 추가하기). 아마 conda 명령어도 비슷한 심경으로 작업을 중단했을 것으로 생각한다. 정확한 것인지 자신은 없지만 내가 생각하는 문제의 원인은 이러하다. SSL 인증서는 웹사이트 자체에, 그리고 Verisign, Comodo 등 인증기관에 같이 존재한다.
엄밀히 말해서 위 아래 단락의 밑줄을 친 부분은 정확하게 기술한 것은 아니다. 만약 이를 문자 그대로 해석한다면, 웹 서버와 최상위 인증기관에 같은 인증서가 두 벌 존재하여 접속 시에 이것이 서로 일치하는지를 확인하는 것처럼 여겨지기 때문이다. 하위 단계의 인증서에는 이것이 어디에서 발급되었는를 보여주는 정보가 들어있다. 상세한 것은 Get your certificate chain right 웹사이트를 참고하라.
웹브라우저는 https로 주소가 시작되는 웹서버에서 인증서를 가져온 다음 인증기관의 것과 같은지 비교를 한 뒤 동일함이 검증되면 다음 그림과 같이 채워진 자물쇠 그림과 함께 안전한 웹사이트임을 나타낸다. 자물쇠를 클릭하면 인증서 정보가 보이고 이를 파일로 export할 수 있다.



그러면 어떻게 해야 하는가? 임시 방편으로는 인증서 검증 작업을 하지 않게 만드는 것이 있겠다. 물론 보안 측면에서는 별로 권장할만한 일은 아니다. 다음의 방법은 StackOverflow의 conda update CondaHTTPError: HTTP None에서 힌트를 얻은 것이다. no가 아니라 false를 써야 한다는 글도 있었다. 이 해결책은 꽤 많이 알려져 있다. 이 명령에 대한 설명이 필요하면 conda config --describe ssl_verify를 입력하라.

# conda config --set ssl_verify no
SSL 인증서와 관련한 원인은 이곳에서 알아볼 수 있다. 아마도 공인되지 않은 자체 인증서를 제시하는 웹서버가 문제의 주요 원인이 아닐까 한다. 보다 근본적인 해결 방법은 ssl_verify 기능을 아예 꺼 버리는 것이 아니라, 해당 웹사이트에서 자체 인증서를 가져다가 저장하는 것이다. 아래의 사례는 git에 해당하는 것이지만 conda도 크게 다르지 않을 것이다. conda가 파일을 가져올 때 curl을 쓰기 때문이다(확인을 해 봐야 함).

Installing self-signed certificates into Git cert store

자체 인증서를 쓰는 사이트를 회사 방화벽이 막는지는 잘 모르겠다. 내가 겪는 문제는 CentOS 6.10이 설치된 리눅스 머신에서만 일어나고 있기 때문이다. 사무용 PC에서는 전혀 문제가 없는데, 방화벽이 리눅스와 윈도우를 가려서 작동할리는 없다. 리눅스 배포판이 문제인가? 하지만 바로 지난주까지는 정부출연연구소 내부에서 별 문제가 없었는데? 이를 확인하려면 리눅스를 좀 더 최신 버전 혹은 다른 배포판(예: 우분투)로 업그레이드하면 되는데 20 테라바이트쯤의 데이터를 잠시 다른 곳으로 옮기려면 보통 일이 아니다. 우분투 16.04가 설치된 집 컴퓨터를 들고 출근해서 똑같이 테스트하면 어떨까? 그러면 이것이 CentOS 버전과 관계가 있는 문제인지를 알 수 있을 것이다.

문제가 되는 웹사이트에서 인증서를 export하여 파일로 저장한 다음 그 위치를 .condrc 파일 내에 ssl_verify: corp.crt 형식으로 지정하는 것이 좀 더 근본적인 방식이다.

하지만 이렇게 장광설을 늘어놔 봐야 무슨 소용이 있겠는가? 내일 출근을 해서 테스트를 하기 전까지는 알 수 없다.

타워형 케이스 안에 6개의 6TB HDD가 있고 5개는 RAID로 묶여있는 상태이다. 장애 여부가 LED로 표시되지 않으니 만약 어느 하나에 문제가 생기면 어떻게 찾을까? 이렇게 26년차 초보 리눅서를 괴롭히는 또다른 문제는 RAID 관리에 관한 것이다. 결국은 제대로 경력을 갖춘 서버 관리자를 채용하여 더 큰 일을 도모하는 것이 정답이지만 바이오 기업 혹은 연구소에서 이런 인력을 좋은 조건을 제시하며 채용하는 것은 썩 쉽지가 않다.

2019년 4월 4일 업데이트

'conda config --set ssl_verify no'의 다음의 편법이 잘 작동함을 확인하였다. .condarc 설정 파일은 홈 디렉토리에 존재하는데, 이 명령을 실행함으로 인해서 다음과 같이 바뀌었음을 알 수 있다.

channels:
  - conda-forge
  - bioconda
  - defaults
ssl_verify: false
그러면 좀 더 안전한 방법을 실제로 실행에 옮겨보기로 하자. 나에게 고통을 안겨주었던 https://repo.anaconda.com/으로 가서 인증서 내보내기를 실행하였다. 파일 형식은 'Base 64로 인코딩된 X.509(.CER)'로 하였고 anaconda.cer라는 이름으로 저장하였다. 그 다음은 아래에 보인 것과 같이 실행하였다. .condarc 파일의 ssl_verify가 수정되었음을 알 수 있다.

# conda config --set ssl_verify ./anaconda.cer
# cat ./condarc
channels:
  - conda-forge
  - bioconda
  - defaults
ssl_verify: ./anaconda.cer
실수로 인증서 파일을 지우면 곤란하므로 .conda와 같은 숨겨진 디렉토리에 인증서를 두는 것이 좋을 것이다. 그런데... 잘 안된다. www.anaconda.com conda.anaconda.org repo.anaconda.com 등 한 사이트에서 인증서를 받아서 설치하면 다른 사이트가 막히고, 또 그것을 해결하면 다른 사이트가 막히고.. 각 사이트를 돌아가면서 접근이 안된다는 메시지가 나오는 것이다. 그러면 각 사이트에서 전부 인증서를 받아서 하나의 파일로 어떻게든 만들어야 한다는 이야기인가? 정말로 모르겠다. cert (or CA) bundle이라는 말이 종종 나오는데 도대체 어떻게 해야 할까?
CA bundle이란 루트 및 중간 단계 인증서의 묶음이다. 여기에 서버 인증서까지 포함하면 인증서 체인이 된다. conda 설정에서 ssl_verify ≠ false인 경우 제공해야 하는 것은 CA bundle이거나 혹은 trusted CA의 인증서이다. (CA bundle is a file that contains root and intermediate certificates. The end-entity certificate along with a CA bundle constitutes the certificate chain. [What is CA bundle?])

드디어 해결!

구글을 뒤지고 뒤져서 해결을 하였다. 웹브라우저에서 X.509(.cer)로 내보낼 수 있는 인증서는 한 장이다. 바로 아래에 있는 PKCS #7 인증서(.p7b)는 인증 경로에 있는 인증서를 전부 포함할 수 있다고 한다. 하지만 이 형식은 conda가 인식하지 못한다. 그래서 openssl을 사용하여 여러 인증서가 줄줄이 연결된 pem 포맷으로 전환해 보았으나 계속 에러가 발생하였다(참조 사이트: How to convert a certificate into the appropriate format). .pem 파일의 용도는 다음의 설명을 참조하라.

.pem file is a container format that may just include the public certificate or the entire certificate chain (private key, public key, root certificates). 출처

.cert .cer .crt - A .pem (or rarely .der) formatted file with a different extension, one that is recognized by Windows Explorer as a certificate, which .pem is not. 출처

그러면 웹브라우저를 거치지 않고 인증서들을 한번에 가져올 수는 없을까? 방법이 있다. 다음은 그 전체 과정을 보여준다. -showcerts 옵션을 주지 않으면 서버 인증서만 출력이 된다.

# echo quit | openssl s_client -showcerts -servername "www.anaconda.com" -connect www.anaconda.com:443 > cacert.pem
depth=1 C = KR, O = Somansa, CN = Somansa Root CA
verify error:num=19:self signed certificate in certificate chain
DONE
# conda config --set ssl_verify cacert.pem 
# conda update conda
Collecting package metadata: done
Solving environment: done

# All requested packages already installed.

# conda install -c bioconda trimmomatic
...성공!
(Somansa는 SSL 인증서 인증기관이 아니다. 그런데 왜 Root CA라고 표시되는 것일까? 이 회사에 대한 자세한 사항은 아래의 4월 6일 업데이트 참조.)

openssl 명령어를 이런 용도로 사용하는 힌트를 구한 웹사이트 주소를 잊어버려서 여기에 고마움을 표하지 못하는 것이 정말 아쉽다. 마치 에러가 있는 것처럼 나오지만(자체 인증서) cacert.pem 파일은 잘 만들어진다.

단, anaconda2에서는 여러 인증서가 하나로 합쳐진 cacert.pem을 인식하지 못하는 것으로 보인다. 이를 개별 파일로 분리하여 특정 디렉토리에 넣은 다음 ssl_verify에 대응하는 값으로 공급해도 잘 되지는 않는다.

CustomValidationError: Parameter ssl_verify = 'cacert.pem' declared in <> is invalid.
ssl_verify value 'cacert.pem' must be a boolean, a path to a certificate bundle file, or a path to a directory containing certificates of trusted CAs.

종합적인 결론을 내리자면, 아마도 사내 방화벽은 자체인증서만을 보유한 웹사이트에 접근하는 것을 싫어하는 것 같다. conda에서 인증서 확인 기능을 아예 끄는(ssl_verify: false) 위험한 방법을 동원하지 않고도 얼마든지 conda(curl..)를 즐길 수 있다!

이번에 겪은 작은 사고가 아니었더라면 웹사이트 인증서와 openssl에 대해 공부를 하는 기회를 갖지 못했을 것이다.

참고할만한 국문 사이트를 소개하면서 이틀에 걸친 포스팅을 마친다.


OpenSSH(Secure Shell)는 OpenSSL(Secure Socket Layer)과 다르다^^(SSH vs. SSL: 바보 같은 설명 참조)

https://www.openssh.com/

그러면 내 위키사이트도 인증서를 발급받아야 하지 않을까?

당연한 이야기이다. 돈이 드는 방법, 돈이 들지 않는 방법 전부 가능하다. 내가 사용하는 hostinger에서는 다음의 자료를 제공하고 있다. 큰 돈이 드는 것이 아니니 조만간 인증서를 설치하는 것이 좋겠다.
그런데 Conda documentation을 보면 내가 고민했던 것의 기본적인 원리에 대한 것이 대부분 설명되어 있다. 에러에 대처하는 직접적인 방법은 나오지 않지만 말이다.

2019년 4월 6일 업데이트: 소만사?

회사 네트워크 내부에서 conda update와 관련하여 문제가 되었던 웹사이트의 인증서 정보를 브라우저에서 살펴보니 Somansa라는 회사의 이름이 보였다. 난 이것이 인증서를 발급하는 회사라고 생각했었다. 그런데 집에서 같은 웹사이트에 접속하여 인증서 정보를 찾아보면 다른 회사이름이 나오는 것이었다(COMODO ECC Domain Validation Secure Server CA 2). 어라? 소만사가 무엇을 하는 회사인가? 아! 정보보안 솔루션(웹키퍼 SG(T-Proxy, 프록시 서버, 얼마만에 듣는 용어인가!))을 제공하는 국내 회사였다. 소만사라는 이름은 '소프트웨어를 만드는 사람들'에서 유래한 것이라 한다. 아주 쉽게 말해서 실수 혹은 악의적으로 기업의 정보를 SSL로 암호화하여 빼내는 것을 찾아내어 차단하는 하드웨어·소프트웨어 일체형 장비를 판매하는 곳이었다. '암호화 트래픽 가시성 확보'라는 용어가 이런 곳에 쓰이는 말이었다. 즉 Somansa의 웹프록시 서버가 SSL로 암호화되어 들어오는 정보를 복호화한 뒤 다시 암호화하여 내부 클라이언트로 보내는 과정에서 이를 완벽하게 되돌려놓지 못하는 것이 conda 업데이트(bioconda 패키지의 설치를 포함하여) 불능 문제의 원인이었던 것으로 보인다. 좀 더 정확하게 말하자면 bad handshake라는 에러 메시지가 많은 단서를 제공하고 있음을 나중에 알게 되었다.

SSL이 양날의 검이라는 말을 이제 조금 이해할 수 있었다. 암호화 및 인증서를 통해서 내가 접속한 웹서버가 가짜가 아님을 확신할 수 있고, 또한 사용자와 웹서버 사이에서 전달되는 패킷이 중간에 유출되어도 나쁜 의도를 가진 제3자가 이를 해독하지 못하게 한다. 그러나 실수나 악의에 의해서 '내'가 만약 기업 내부의 정보를 외부로 빼내려 한다면? 이를 막기 위한 DLP(Data Loss Prevention)의 한 방법이 바로 소만사와 같은 회사가 제공하는 솔루션이었던 것이다.

사용자 정보의 보호를 위하여 편지봉투를 밀봉하여 전달하였더니, 기밀사항을 유출하는지 알 수가 없게 되었고 이에 따라서 봉투를 아예 쓰지 못하게 하거나, 혹은 햇볕에 비추어서 내용물을 들여다보는 기술이 생긴 것과 비슷한 이치라고 하겠다.

항생제를 함부로 쓰면 감염성 세균의 내성도 이에 따라서 똑같이, 아니 그 이상으로 증가한다. 진화적 군비경쟁이 IT 분야에서도 똑같이 벌어진다.


2019년 4월 2일 화요일

회사 생활 이틀째

(이보다 앞서서 벤처기업에서 약 2년 반, 그리고 정부출연연구소에서 16년 3개월을 일했다)

일찍 퇴근하여 숙소로 돌아왔다. 창밖으로 내다보이는 높다란 건물에는 아직 일을 마치지 못한 직장인이 많은지 대부분의 사무실에 불이 켜진 상태이다.


비교적 긴장감이 적은 공공연구기관에서 직장 생활을 하다가 새로운 경험을 하고 싶어서 기업체로 온지 이틀이 지났다. 생존 혹은 생계를 위한 마지못한 선택도 아니요, 정해진 시간이 지나면 다시 돌아갈 곳이 있다는 점에서 어쩌면 매우 배부른(?) 결정이었는지도 모르겠다. 대전을 제2의 고향 삼아서 인생의 절반을 훌쩍 넘도록 살다가 다시 수도권으로 돌아와서 지하철로 출퇴근을 하노라니 정말 새로운 기분이다. 생각을 해 보니 나는 모든 학창생활 기간 동안 걷거나 자전거로 통학을 하였고 그 이후로는 승용차를 이용했기 때문에 전적으로 대중교통을 이용하여 출퇴근을 한 적이 거의 없었다. 아주 최근에는 버스를 자주 타기는 했었다.

바삐 오가는 사람들은 광역시에서 만나는 사람들보다 왠지 더 바쁘고 세련되어 보인다. 과연 이번 기업 근무 경험에서 어떤 것을 얻어가게 될 것인가? 기대감과 불안감이 공존하는 묘한 기분이 느껴진다. '하늘에서 비가 돈처럼 내려도 요리조리 피해다니는' 나의 성격 속에 과연 기업가 정신('entrepreneurship')이라는 것이 깃들어 있을까? 이것은 타고나는 것일까, 아니면 만들어지는 것일까? 어떤 사람은 할 일이 이것밖에 없어서 사업을 하게 되었다고 ㅇ농담 반 진담 반으로 말하기도 한다.

많은 어려움에도 불구하고 개인이 가장 많은 자율성을 누릴 수 있는 기회는 창업을 하여 기업을 운영할 때가 아닌가 한다. 이렇게 일구어 나간 기업이 큰 고목나무처럼 수백년, 아니 그 이상을 존속하기를 바라지만, 기업에도 분명 수명이 존재한다. 매년 포춘지가 발표하는 500대 기업을 보면 평균 수명은 40년 정도라고 한다. 상공회의소가 발표한 우리나라 기업의 평균 수명은 23.8년. 왜 이렇게 짧은가? 이는 경영자들이 변화하는 환경에 대처하여 지속적인 혁신을 하지 못하기 때문으로 여겨진다.

내가 이번 4월부터 일하는 곳은 바이오·제약 분야의 중견기업이다. 이 분야는 까다로운 규제를 통과해야 하고 성공할 가능성도 극히 낮다. 그러나 제대로 성공만 한다면 그동안의 모든 노력을 충분히 상쇄하고도 남는 수익을 보장한다. 그런데 문제는 좋은 제품을 만들어서 그 매출액으로 수익을 내는 것이 아니라, 자신이 보유한 지분을 훨씬 높은 가격에 처분하여 이익을 실현하는 것이 '정도'이다. 난 사회주의자는 아니지만, 창업교육 등에서 이러한 원칙을 듣고서도 100% 납득을 하지 못하였다.

주식의 처분을 통해 이익을 실현하려면, 상당한 지분을 갖는 주주가 아니면 소용이 없다. 성공적인 IPO(기업공개)의 혜택이 그 기업의 직원에게는 별로 돌아가지 않는 것이다. 그것이 주식회사가 현재 돌아가는 원리이다.

나는 기업이 더 많은 사람에게 번영과 자유를 주었으면 좋겠다고 생각한다. 여기서 자유란 빈곤으로부터의 자유, 더 나은 제품 또는 기술을 통해 얻는 기쁨과 즐거움을 의미한다. 그럼에도 불구하고 기업이 만들어내는 가치에 무임승차를 하는 사람은 되도록 적었으면 좋겠다.  앞으로의 경험을 통해 기업이라는 것에 대한 내 나름대로의 철학을 갖게 될 것으로 기대한다. 그 철학에 따라서 창업을 해서 성공을 해야 되겠다는 생각이 들 수도 있고, 그렇지 않을 수도 있을 것이다.

창조하고 개척하는 사람이 될 것인가, 비평가가 될 것인가?

그 어떤 결론을 내리든, 나에게는 소중한 경험이 될 것이다. 두 곳을 오가며 생활을 하느라 비용은 더 들지만 충분히 투자할만한 가치가 있는 수업료라고 생각한다. 그리고 기업 근무를 하는 동안 대부분의 블로그 집필은 퇴근 후 집에서 하게 될 것이다. 어차피 보안 등의 문제로 근무 중에는 개인적인 일을 하기가 곤란하기 때문이다.

오디오 기기를 하나도 들고 오지 못했다. 그래도 인터넷 라디오와 주워온 멀티미디어 스피커가 있어서 귀의 심심함을 달래고 있다.