Thursday, October 20, 2016

Apache Kafka (아파치 카프카)란?

Apache Kafka란?

아파치 카프카는 2011년에 링크드인(LinkedIn)이라는 회사에서 자사의 웹사이트 이벤트 체크를 하기 위한 목적으로 만들어진 사내 프로젝트로 시작했다가 2014년에 아파치를 통해 오픈 소스화된 프로젝트로 현재 빅데이터 관련 프로젝트에 가장 널리 사용되고 있는 distributed messaging system입니다. 현재 링크드인을 비롯해서 야후, 트위터, 넷플릭스, 우버 등 실시간으로 대용량의 데이터를 처리해야 하는 어플리케이션을 운영하고 있는 회사에서 메세징 시스템 뿐만아니라 실시간 모니터링, 이벤트 프로세싱등 다양한 용도로 사용되고 있습니다. 그렇다면 아파치 카프카에 어떤 특별한 점이 있길래 이렇게 짧은 시간 안에 수많은 빅데이터 회사에게 널리 사용되게 되었는지 아래의 글에서 확인해보도록 하겠습니다.

Why Use It? 왜 사용하나요?

  • High-throughput message capacity: 쉽게 이야기해서 단 시간 내에 엄청난 양의 데이터를 컨슈머 쪽으로 전달 가능합니다. 다른 경쟁 제품에 비해 많은 양의 데이터 전송이 가능한 이유는 크게 두 가지 있는데 우선 첫째, 기존의 메세지 시스템이 메세지 브로커 쪽에서 가지고 있던 모든 복잡한 과정 또는 연산들을 제거했고 둘째, 하나의 토픽에 대해 여러 개의 파티션으로 분할 할 수 있도록 해서 컨슈머 쪽에서 분산 처리할 수 있도록 하였습니다. 좀더 자세히 설명하자면 기존의 메세지 시스템들은 (RabbitMQ 같은) 각각의 토픽에 대해 컨슈머들의 인덱스 (데이터를 어디까지 전송받았는지를 알려주는) 정보를 메세지 브로커 쪽에서 관리하였는데 카프카는 이 부분을 컨슈머 쪽으로 책임을 옮겼으며 또한 메세지를 유지하는 방법도 메모리에 잠시 보관하였다가 컨슈머에 전송된 후 삭제하는 방법이 아니라 일반 파일에 Log 형식으로 (데이터가 날짜순으로 저장되고 Append만 가능한 형식) 관리하여 전송 후에 Delete 연산이 필요없는 방식을 사용하고 있습니다. 또한 토픽의 분할 기능을 제공하여 같은 토픽에 대해 여러 개의 컨슈머가 동시에 메세지를 전송 받는 등의 분산 처리를 지원하여 많은 양의 데이터 전송을 가능하게 하고 있습니다.
  • Scalability와 Fault tolerant: 카프카는 클러스터 모드를 지원하고 있으며 위에 언급했던 토픽 파티셔닝 (하나의 토픽을 여러 개의 파티션으로 나눌 수 있는 기능)과 파티션 복제 (Replication) 기능을 통해 확장성과 Fault tolerant (부분적으로 고장나더라도 중요한 기능들은 정상적으로 작동하는 특성)을 제공하고 있습니다.
  • 메세징 시스템 외에 다양한 용도로 사용 가능: 일반적인 메세징 시스템과 달리 카프카는 다양한 용도로 사용 가능하며 자세한 사용 용도에 대해서는 아래의 글을 참조하세요.

Use Cases (카프카의 사용 용도의 예)

  • Messaging System: 가장 일반적으로 많이 사용되고 있는 용도로 메세지 제공자 (Producer 또는 Source)와 수신자 (Consumer 또는 Sink) 사이에서 메세지를 전달해주는 역할을 합니다. 각각의 컨슈머 (또는 컨슈머 그룹)는 전달받기를 원하는 메세지의 토픽에 구독 신청해야 하며 하나의 토픽에 여러 컨슈머가 구독 신청 할 수 있습니다. (이 경우에 메세지는 구독신청한 모든 컨슈머한테 Broadcast 됩니다.)
  • Website Activity Checking 및 Monitoring: 링크드인에서 처음 만들고 사용했던 목적처럼 웹사이트가 정상적으로 돌아가는지 또는 웹사이트 사용 시 유저들의 패턴이 어떻게 되는지 모니터링 또는 웹사이트 이벤트 체킹의 목적으로도 사용 가능하며 (중간에서 메세지를 전달하는 중간자의 역할을 할 수도 있지만 메세지 자체가 디스크에 일정 기간 동안 로깅이 되어 있기 때문에 직접 분석도 가능합니다.)
  • Log Aggregation: 하나의 웹사이트가 여러 대의 서버로 운영되고 있다면 (대부분의 엔터프라이즈 웹사이트들이 그렇듯이) 각각의 서버에 있는 로그를 통합해주는 시스템 구축에도 사용 가능합니다.
  • Stream Processing & Batch Processing: 요즘 빅데이터 쪽에서 가장 핫한 Spark나 Storm같은 Stream Processing (스트림 처리)을 지원하는 플랫폼이나 Hadoop과 같이 Batch Processing (일괄 처리)을 지원하는 플랫폼과 연결햐여 메세지의 변환도 가능합니다.
  • Etc: 그 외에 연결된 DB나 서치 엔진의 일시적 서비스 장애 때문에 다운이 되었을 때 메세지들을 잠시 저장해줄 수 있는 임시 버퍼의 역할도 가능하며 Operational metrics (각각의 토픽에 대해 들어오는 메세지의 수를 정기적으로 체크하여 그 수가 너무 낮거나 높을 때 문제가 있는 확인차 운영팀에 메일등을 통해 알려주는 용도)나 Event sourcing (특정 이벤트들을 시간 순으로 기록하여 나중에 필요할 때 사용하는 용도) 등의 용도로도 사용되고 있습니다.

References

  • http://kafka.apache.org/intro.html
  • http://www.javaworld.com/article/3060078/big-data/big-data-messaging-with-kafka-part-1.html
  • https://www.quora.com/Can-I-use-apache-kafka-for-memory-cache
  • http://events.linuxfoundation.org/sites/events/files/slides/The%20Best%20of%20Apache%20Kafka%20Architecture.pdf
  • https://auriga.com/blog/hands-on-experience-building-architecture-of-highly-available-scale-out-systems-introduction/
  • http://blog.cloudera.com/blog/2014/09/apache-kafka-for-beginners/
  • https://sookocheff.com/post/kafka/kafka-in-a-nutshell/
  • https://www.elastic.co/blog/just-enough-kafka-for-the-elastic-stack-part1

Tuesday, October 11, 2016

Apache Kafka (아파치 카프카) 설치 (CentOS 7.2.1511 64-bit)

설치 전 준비사항

  1. CentOS 7이 설치된 서버 (또는 VM)
  2. 오픈 JDK 패키지 설치
    1.  yum install java-1.8.0-openjdk.x86_64
    2. 설치가 잘 되었는지 확인하려면 아래의 명령어를 실행해서 자바 버전 확인
      1. java -version
  3. 자바 환경 변수 설정
    1. 텍스트 에디터를 이용해서 ‘/etc/profile’에 자바 환경 변수 설정을 추가 
      1. vim /etc/profile
      2.  profile 파일 안에 아래의 내용을 추가
        1. export JAVA_HOME=/usr/lib/jvm/jre-1.8.0-openjdk
        2. export JRE_HOME=/usr/lib/jvm/jre
      3. source 명령어를 이용해서 변경된 내용 적용
        1. source /etc/profile

설치 단계

  1. Kafka 패키지 다운로드
    1. wget http://www-us.apache.org/dist/kafka/0.10.0.1/kafka_2.11-0.10.0.1.tgz
      1. 위의 버전이 최신 버전이 아니면 kafka 웹사이트 (http://www-us.apache.org/dist/kafka)에 들어가셔서 최신 버전을 확인 후 다운 받으세요.
    2. tar xvf kafka_2.11-0.10.0.1.tgz
    3. mv kafka_2.11-0.10.0.1 /opt
    4. cd /opt/kafka_2.11-0.10.0.1
  2. Zookeeper 서버 시작
    1. bin/zookeeper-server-start.sh -daemon config/zookeeper.properties
  3. Kafka 서버 시작
    1. bin/kafka-server-start.sh config/server.properties
      1. 서버 시작 후 아래와 같은 로그를 확인하셨다면 서버가 정상적으로 시작된 것입니다.
      2. INFO [Kafka Server 0], started (kafka.server.KafkaServer)
  4. Kafka 패키지에서 제공하는 클라이언트 프로그램을 이용한 간단한 서버 테스트
    1. 테스트 토픽 생성
    2. bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
    3. Consumer 생성
      1. bin/kafka-console-consumer.sh --zookeeper localhost:2181 --topic test —from-beginning
    4. Producer 생성
      1. 같은 SSH 연결에서 Consumer와 Producer를 같이 생성할 수 없기 때문에 새로운 SSH 연결을 한 후 에 아래의 명령어를 실행합니다.
      2. bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test
      3. 위의 명령어를 실행 후 콘솔에 텍스트를 입력하고 엔터를 누르면 입력한 텍스트가 Consumer 쪽 콘솔에 출력 되는 것을 확인하실 수 있으십니다.
  5. References
    1. https://www.vultr.com/docs/how-to-install-apache-kafka-on-centos-7
    2. http://davidssysadminnotes.blogspot.com/2016/01/installing-apache-kafka-and-zookeeper.html
    3. http://www.javaworld.com/article/3060078/big-data/big-data-messaging-with-kafka-part-1.html

Sunday, October 9, 2016

Redis Cluster (레디스 클러스터) 설치 (CentOS 7.2.1511 64-bit)

설치 전 준비사항

  1.  최소 2개 이상의 서버 (또는 VM)에 CentOS 7 설치. 아래의 설명에 사용된 서버들 정보는 아래와 같습니다. 
    1. Server A: 192.168.2.105
    2. Server B: 192.168.3.105
    3. Server C:  192.168.3.102
  2.  Redis 3.0 이상 버전의 패키지를 인터넷에서 다운 받아서 설치. 참고로 Redis Cluster는 3.0 이상 버전부터 지원 가능합니다. 아래는 레디스 3.0.0을 다운 받아서 설치하는 명령어의 예이며 만약 더 최신 버전을 원하시면 http://download.redis.io/releases 페이지에 들어가셔서 최신 패키지 정보를 얻으셔서 다운 받으시면 됩니다. 
    1. mkdir build && cd build
      wget http://download.redis.io/releases/redis-3.0.0.tar.gz
      tar -xvfz redis-3.0.0.tar.gz
      cd redis-3.0.0/
  3.  아래의 패키지들을 yum을 이용해서 설치
    1.  yum install gem ruby ruby-devel ruby gems redis-stat rpm-build

설치 단계

  1. Redis Cluster용 설정파일 생성
    1.  기존의 설정파일인 ‘redis.conf’를 수정해서 사용해도 되나 우선 불필요한 설정들도 많고 Redis를 한 서버에서만 사용하게 되면 (클러스터 모드가 아닌) 다시 수정을 해야 하기 때문에 클러스터용 설정 파일을 새로 생성해서 사용하는게 좋습니다. (예를 들어 파일명은 ‘redis-cluster.conf’) 클러스터용 설정 파일의 예는 아래와 같습니다.
          port 6379
          cluster-enabled yes
          cluster-config-file nodes.conf
          cluster-node-timeout 5000
          append only yes
    2.  위의 설정파일을 이용해서 Redis Server 시작. 만약 클러스터 모드로 정상적으로 시작되었다면 서버 시작 후에 ‘Running in cluster mode’라는 글을 확인할 수 있습니다. 
      1. src/redis-server redis-cluster.conf
    3.  위의 두 사항을 클러스터에 포함될 다른 서버들에 반복해서 수행합니다. 
    4.  위의 과정을 거쳐 클러스터 모드로 시작된 Redis Server들을 아래의 명령어 실행을 통해 연결합니다. 참고로 이 과정은 하나의 서버에서만 수행하면 됩니다. 예를 들어 클러스터를 형성할 서버 A, B, C가 있다고 가정하면 A에서만 아래의 명령어를 실행하면 클러스터가 바로 형성되기 때문에 같은 작업을 B랑 C에서 반복적으로 할 필요가 없습니다. 
      1. src/redis-cli -p 6379 CLUSTER MEET 192.168.3.105 6379
      2. 참고로 위의 명령어는 서버 B의 IP가 192.168.3.105 이고 서버 A에서 클러스터를 형성한 경우의 예입니다.
    5.  ‘redis-trib.rb’라는 Redis 패키지에서 제공하는 유틸리티 프로그램을 이용해서 아래의 명령어를 실행해서 slot들을 할당합니다. 참고로  이 절차는 총 16384개의 슬롯을 오픈하고 오픈된 슬롯들을 클러스터 서버에 N 등분 해서 (여기서 N은 클러스터에 등록된 서버수) 할당하는 과정입니다. 
      1. src/redis-trib.rb create 192.168.2.105:6379 192.168.3.105:6379
    6. 만약 5번 실행 중 문제가 발생했다면 아래의 명령어들을 서버 A에서 실행해보세요. 
      1. for slot in {0..5400}; do redis-cli -h 192.168.2.105 -p 6379 CLUSTER ADDSLOTS $slot; done;
      2. for slot in {5400..10800}; do src/redis-cli -h 17.198.30.160 -p 6379 CLUSTER ADDSLOTS $slot; done;
      3. for slot in {10801..16383}; do src/redis-cli -h 17.198.30.157 -p 6379 CLUSTER ADDSLOTS $slot; done;
    7.  References
      1. http://redis.io/topics/cluster-tutorial
      2. https://www.digitalocean.com/community/tutorials/how-to-configure-a-redis-cluster-on-centos-7
      3. https://www.javacodegeeks.com/2015/09/redis-clustering.html
      4. https://ilyabylich.svbtle.com/redis-cluster-quick-overview

Monday, October 3, 2016

WebSocket이란?

WebSocket이란?

WebSocket이란 Transport protocol의 일종으로 쉽게 이야기하면 웹버전의 TCP 또는 Socket (소켓)이라고 이해하시면 됩니다.  WebSocket은 서버와 클라이언트 간에 socket connection을 유지해서 언제든 양방향 통신 또는 데이터 전송이 가능하도록 하는 기술이며 2008년에 HTML5에 포함이 되어서 여러 번의 토론을 통해 프로토콜이 제정되었고 2009년 구글 크롬을 시작으로 여러 웹브라우저에서 이 기술을 적용하여서 현재 Real-time web application 구현을 위해 널리 사용되어지고 있습니다. 참고로 Real-time web application이란 서버 쪽 또는 클라이언트 쪽 데이터가 실시간으로 업데이트 되는 웹 어플리케이션을 의미합니다.

왜 사용하는가요?

WebSocket을 사용하는 이유 또는 사용시 얻을 수 있는 장점에 대해서 이해를 하려면 WebSocket 이전에 사용되었던 기술과 어떤 차별성이 있는지를  이해하는게 중요합니다. 우선 웹어플리케이션에서 기존의 서버와 클라이언트 간의 통신은 대부분 HTTP를 통해 이루어 졌으며 HTTP는 Request/Response 기반의
Stateless protocol입니다. 무슨 말이냐 하면 서버와 클라이언트 간의 Socket connection 같은 영구적인 연결이 되어 있지 않고 클라이언트 쪽에서 (예를 들어 웹브라우저 쪽에서)  필요할 때 Request를 할 때만 서버가 Response를 하는 방식으로 통신이 진행되는 프로토콜이란 뜻입니다. (짧게 이야기하면 클라이언트 쪽에서만 대화를 시작할 수 있는 한 방향 통신입니다.) 그래서 어떤 문제가 생기냐면 서버 쪽 데이터가 업데이트 되더라도  클라이언트 쪽 (예를 들어 웹페이지)에는 화면을 Refresh 하지 않는 한 바뀐 데이터가 업데이트가 되지 않는 문제가 발생합니다. 그렇지만 이런 문제는 일반적은 웹 어플리케이션에서는 기존에 있던 임시 방편인 Long polling 이라던가 Ajax를 사용해도 어느 정도 해결이 가능하지만 데이터의 빠른 업데이트가 아주 중요한 요소 중에 하나인 어플리케이션 (예를 들어 주식 관련 사이트라던가 비디오 채팅 어플리케이션)에서는 실시간 업데이트가 아주 중요하기 때문에 (그리고 기존의 Long Polling 같은 기술은 서버에 많은 부담을 주는 부작용이 있기 때문에) WebSocket이 아주 유용하고 중요한 기술로 사용되고 있습니다.
또한 WebSocket은 Stateful protocol이기 때문에 클라이언트와 한 번 연결이 되면 계속 같은 라인을 사용해서 통신을 하기 때문에 HTTP 사용 시 필요없이 발생되는 HTTP와 TCP 연결 트래픽을 피할 수 있습니다.  마지막으로 WebSocket은 HTTP와 같은 포트 (80)을 사용하기 때문에 (Secure한 채널 같은 경우에는 HTTPS와 같은 443을 이용) 기업용 어플리케이션에 적용할 때 방화벽을 재설정하지 않아도 되는 장점도 있습니다. (대부분의 기업 방화벽은 외부에서의 접속은 HTTP나 HTTPS만을 기본으로
허용하고 있으며 만약 이외의 포트를 허용해야 할 경우에는 방화벽의 설정을 수정해야 하는데 큰 회사일 수록 방화벽 설정 수정 절차가 복잡하기 때문에 HTTP와 같은 포트를 사용한다는 점이 꽤 큰 장점이 될 수도 있습니다.)

작동 원리 및 그 외의 정보

우선 서버와 클라이언트 간의 WebSocket 연결은 HTTP 프로토콜을 통해 이루어집니다. 만약 연결이 정상적으로 이루어진다면 서버와 클라이언트 간에 WebSocket 연결 (TCP/IP 기반으로 하는)이 이루어지고 일정 시간이 지나면 HTTP 연결은 자동으로 끊어집니다.
기본적으로 WebSocket API는 아주 간단한 기능들만을 제공하기 때문에 대부분의 경우 SockJS나 Socket.IO 같은 오픈 소스 라이브러리를 많이 사용하고 있으며 메세지 포멧 또한 STOMP 같은 프로토콜을 같이 이용합니다. 마지막으로 스프링 프레임워크도 WebSocket을 간단한 메세지 브로커랑 SockJS 그리고 STOMP와 같이 지원하고 있습니다.

WebSocket 사용의 어려운 점

WebSocket은 사용시 위에 서술한 것과 같은 장점들을 주지만 그에 못지 않는 비용을 지불해야 합니다. 아래는 WebSocket 사용 시 발생할 수 있는 어려운 점 또는 문제점들입니다.
1. 프로그램 구현에 보다 많은 복잡성 초래: WebSocket은 HTTP와 달리 Stateful protocol이기 때문에 서버와 클라이언트 간의 연결을 항상 유지해야 하며 만약 바정상적으로 연결이 끊어졌을 때 적절하게 대응해야 합니다. 이는 기존의 HTTP 사용 시와 비교했을 때 코딩의 복잡성을 가중시키는 요인이 될 수 있습니다.
2. 서버와 클라이언트 간의 Socket 연결을 유지한다는 것 자체가 비용이 드는 일입니다. 특히나 트래픽양이 많은 서버 같은 경우에는 CPU에 큰 부담이 될 수 있습니다.
3. 오래된 버전의 웹 브라우저에서는 지원하지 않습니다. (물론 SockJS 라이브러리 같은 경우에는 Fallback option을 제공하고 있습니다.) 참고로 인터넷 익스플로어 같은 경우에는 10 버전부터 지원합니다.
4. 이건 제 개인적인 경험인데 서버와 클라이언트 간의 연결이 끊어졌을 때 생성되는 에러 메세지가 구체적이지 않아서 (예를 들어 여러가지 다른 이유로 연결이 끊어졌는데 에러 메세지가 같은 경우) 디버깅을 하는데 어려움이 많았습니다.

아무리 좋은 기술이라 할지라도 모든 경우에 유용할 수는 없는 법이기 때문에 프로그램에 꼭 필요한 기술인지 잘 체크하고 수용 여부를 결정하는 것이 바람직합니다.

대표적인 사용예

1. 페이스북 같은 SNS 어플리케이션
2. LOL 같은 멀티플레이어 게임들
3. 구글 Doc 같이 여러 명이 동시 접속해서 수정할 수 있는 Tool
4. 클릭 동향 분석 데이터 어플 (특정 시간동안 어느 사이트에 주로 접속했는지 등의 정보를 파악하는 어플)
5. 증권 거래 정보 사이트 및 어플
6. 스포츠 업데이트 정보 사이트 및 어플
7. 화상 채팅 어플
8. 위치 기반 어플
9. 온라인 교육 사이트 및 어플

References

https://www.websocket.org/aboutwebsocket.html
http://www.javaworld.com/article/2071232/java-app-dev/9-killer-uses-for-websockets.html
https://en.wikipedia.org/wiki/WebSocket
https://samsaffron.com/archive/2015/12/29/websockets-caution-required
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API



Sunday, August 7, 2016

ACID란?




데이터베이스 영역에서 ACID란 Atomicity(원자성), Consistency(일관성), Isolation(고립성) 그리고 Durabiliy(지속성)의 약어로 데이터베이스 트랜젝션의 가장 중요한 특성들을 나타내는 말로 데이터베이스 시스템에서 기본적으로 제공해야할 가장 중요한 특성들입니다. 각각의 특성들에 대한 설명은 아래와 같습니다.
  • Atomicity (원자성): 하나의 데이터베이스 트랜젝션에 여러 개의 데이터를 변환 (수정/삭제/입력 등과 같은)하는 도중에 문제가 발생했을 때 문제가 발생한 시점과 상관없이 그 트랜젝션에 포함된 모든 데이터의 변환이 이루어지지 않도록 보장하는 것이 원자성의 중요한 특징입니다. 쉽게 이야기하면 데이터를 변환할 때 문제가 발생하면 트랜젝션에 포함된 내용의 어떠한 데이터의 변환이 이루어지지 않으며 많약 아무 문제가 없을 때는 트랜젝션에 포함된 내용의 모든 데이터의 변환이 이루어 지는 것을 의미합니다. (All or nothing)
  • Consistency (일관성): 일관성은 어떠한 트랜젝션 전후에도 데이터베이스가 valid 상태를 유지함을 보장하는 특성으로 쉽게 이야기해서 트랜젝션 동안 데이트베이스에서 지정된 Rule에 부합된 데이터들만 데이터베이스에 유지가 되어서 트렌젝션이 끝난 후에도 데이터베이스가 사용가능한 상태를 유지할 수 있도록 보장하는 특성입니다.
  • Isolation (독립성): 독립성이란 만약 한 데이터베이스 시스템에 여러 개의 트랜젝션이 발생했을 때 각각의 트랜젝션이 서로 독립적으로 (또는 서로 영향을 끼치지 않게) 데이터를 변환할 수 있게 보장하는 특성을 이야기합니다. 만약 독립성이 지원 않는 데이터베이스에서 동시에 두 개의 트랜잭션에서 같은 데이터를 변환한다면 그 값이 어떻게 변환될 지 (어떤 트랜젝션이 먼저 실행되는지에 따라) 예측 불가능하기 때문에 많은 문제들을 발생 시킬 수 있습니다.
  • Durability (지속성): 한 번 데이터베이스에 저장된 데이터는 그 데이터의 변환에 대한 다른 트랜젝션 요청이 없을 때까지 항상 같은 값을 유지함을 보장하는 특성을 데이터베이스에서의 지속성이라고하며 갑작스럽게 전원이 꺼졌을 때나 시스템 오류 같은 문제가 발생했을 때 자동으로 데이터베이스에 저장된 데이터의 복구도 이 특성에 포함됩니다.

References
  • https://en.wikipedia.org/wiki/ACID
  • http://terms.naver.com/entry.nhn?docId=860356&cid=42346&categoryId=42346
  • http://www.service-architecture.com/articles/database/acid_properties.html
  • http://searchsqlserver.techtarget.com/definition/ACID
  • https://vladmihalcea.com/2014/01/05/a-beginners-guide-to-acid-and-database-transactions/

Monday, July 4, 2016

Framework vs Library: 프레임워크와 라이브러리의 차이

많은 사람들이 프레임워크와 라이브러리의 차이를 단순히 사이즈의 차이 (프레임워크가 라이브러리에 비해 훨씬 크다 또는 여러 개의 라이브러리의 묶음이 프레임워크이다)라고 생각하는 경향이 있는데 이는 사실이 아닙니다. (물론 대부분의 경우 프레임워크가 라이브러리보다 사이즈가 더 크고 프레임워크가 여러 개의 라이브러리를 포함하고 있지만 그렇다고 라이브러리의 묶음이 프레임워크다라고 단순히 규정하기는 힘듭니다. 자세한 이유는 아래에 서술하였습니다.) 그 대신 기능적으로 무엇을 제공하는지와 사용할 때 어떤 방식으로 어떻게 사용할 지의 차이가 프레임워크와 라이브러리를 구별할 수 있는 더 중요한 요소가 아닐까 생각합니다.

우선 라이브러리는 보통 큰 개념으로 볼 때 하나의 기능을 제공하며 그 기능을 구현하기 위한 (또는 그 기능과 관련된) 부수적인 여러 개의 작은 기능들을 제공합니다. 예를 들어 GSON 라이브러리 (구글에서 제공하는 JSON 데이터 변환 라이브러리) 같은 경우에 큰 개념적으로 보면 JSON 형식의 데이터를 다른 형식으로 변환하는 기능을 제공하고 있으며 세부적인 기능들로는 JSON 형식의 데이터를 Java Object  형식으로 변환하는 기능을 제공하고 반대로 Java Object에 저장된 데이터를 JSON 형식의 데이터로 변환해주는 기능을 제공하고 있습니다.

반면에 프레임워크는 하나의 특정 기능을 제공하기 보다는 어플리케이션을 만드는데 있어서 뼈대가 될 수 있는 기능들을 제공하고 있습니다. 예를 들어 Spring Framework를 이용해서 MVC 모델의 웹어플리케이션을 만든다고 했을 때 스프링은 웹어플리케이션을 만들기 위한 기본적인 기능들만을 제공하며 (UI와 서버 쪽의 연동이나 데이터의 교환 또는 공유) 웹어플리케이션 구동을 위한 추가적인 기능들 (예를 들어 Front-end 쪽 디자인 관련 기능들이라던지 또는 서버의 효율성을 증진시킬 수 있는 기능들) 에 대한 지원을 기본적으로 하고 있지 않습니다.

위의 차이점 때문에 라이브러리와 프레임워크는 사용 방식 (또는 어플리케이션과의 연동방식)에서도 차이가 발생합니다. 우선 라이브러리는 보통 어플리케이션에 포함이 되어서 사용되고 있으며 개발자의 입장에서 봤을 때 라이브러리에서 제공하는 API 호출을 어플리케이션에서 어떻게 해서 사용할 지를 고민하게 됩니다. 그 반면에 프레임워크는 어플리케이션의 뼈대가 되기 때문에 어플리케이션의 메인 코드가 프레임워크의 여러 부분에 접합되어서 사용되어지며 (프레임워크가 사용자가 작성한 코드를 호출합니다.) 개발자의 입장에서 봤을 때 본인의 코드가 프레임워크와 얼마나 연동이 잘 되어서 사용되어지는 지 (또는 잘못 사용되어서 문제를 일으키지 않는지)를 고민하게 됩니다.

마지막으로 만약 로봇을 만든다고 가정을 했을 때 프레임워크를 사용하게 되면 로봇에 대한 기본적인 골격을 프레임워크가 제공하는 것이며 (아주 초보적인 걸음 정도를 할 수 있는) 개발자는 거기에 사람처럼 보일 수 있게 실리콘 피부를 입힌다거나 달리기를 잘 할 수 있는 로봇, 또는 시력과 청력이 아주 좋은 로봇을 만드는 일 (관련 기능들을 로봇에 추가해서)을 한다고 생각하시면 됩니다. 반면에 라이브러리를 사용해서 로봇을 만든다면 기본적인 골격은 직접 만들지만 특정 기능 (시력을 높이는 기능 또는 빨리 뛰게 할 수 있는 기능) 또는 특정 부위 (손, 발) 등은 라이브러리를 이용해서 구현한다고 생각하시면 됩니다.

Sunday, June 12, 2016

[잡담] 실리콘밸리(Silicon Valley)에서의 Software Engineer 포지션 구직 관련 팁 및 정보


미국에서 소프트웨어 엔지니어로 일하기 가장 좋은 지역이 세 곳이 있는데 (씨애틀 지역, 샌프란시스코/실리콘 벨리 지역, 텍사스 오스틴 지역) 그 중에서도 가장 평균 연봉도 높고 구글과 애플 그리고 페이스북 같은 거대 IT 대기업의 본사가 있을 뿐만 아니라 많은 스타트업 회사들이 포진해 있어서 기회가 많은 샌프란시스코/실리콘 밸리가 지역이 가장 엔지니어한테는 일하기 좋은 지역이 아닐까 생각합니다. 이 글은 필자가 실리콘밸리 지역에서 경험한 내용과 주변 사람들의 이야기를 통해 배운 구직 관련 내용입니다.

1. 접근성
본인이 정말 실리콘밸리에 있는 회사에 취직을 하고 싶다면 우선은 실리콘밸리 쪽으로 오는 것이 가장 좋다고 생각합니다. 사실 이 부분은 꼭 실리콘밸리 지역에 국한된 것은 아니지만 많은 분들이 이 접근성의 중요성에 대해 간과하고 있는게 사실입니다. 학교를 실리콘 밸리 쪽에 있는 학교로 오든 아니면 본인이 원하는 회사는 아니지만 실리콘 밸리 쪽에 있는 회사로 취직을 한후 이직을 준비하든 우선 이 곳에 와서 생활을 하고 인맥을 넓히고 실력을 쌓으면서 인터뷰 준비를 성실히 잘 한다면 기회는 꼭 찾아올 것입니다. 특히 인맥이 중요한 이유는 다른 사람들의 인터뷰 경험을 들을 수 있으며 때에 따라서는 그 회사의 오픈 포지션에 대한 리퍼 (추천)를 받을 수도 있어서 인터뷰 성공 확률을 높일 수 있습니다. 참고로 미국 내에 있는 대부분의 회사들은 추천만으로 고용이 되는 경우는 극히 드물지만 추천을 받게 되면 서류 심사 절차는 생략이 되는 경우가 많기 때문에 인터뷰를 함에 있어서 큰 도움이 됩니다. (특히 구글이나 페이스북 또는 애플 같은 큰 회사는 온라인으로 레즈메를 접수해도 너무나 많은 지원자들 때문에 서류 심사를 통과하는 것도 힘이 드는 경우가 많습니다.) 마지막으로 실리콘 밸리 지역에서는 개발자들을 위한 여러 형태의 컨퍼런스나 Hackathon 같은 이벤트가 매년 꾸준히 열리고 있어서 기술 동향이나 인맥 형성에도 큰 도움이 되고 있습니다.

2. 실력
물론 당연한 이야기지만 실리콘 밸리에 있는 좋은 회사에 취직하기 위해서는 경력과 레벨에 따른 실력이 있어야 합니다. 작은 회사일 경우를 제외하고는 다른 사람의 추천 만으로 취직을 하기가 쉽지 않고 실력이 없다면 대부분의 Technical 인터뷰 과정에서 떨어지기 때문입니다. 참고로 이제 막 졸업한 학생일 경우에는 몇 가지 특별한 도메인의 스페셜리스트가 되기 보다는 다양한 분야에 대한 경험이 있는 것이 더 좋을 수 있습니다. 그 이유는 첫째, 학교에서 경험할 수 있는 프로젝트에는 한계가 있고, 둘째, 그 경험들이 실제 인더스트리에서 사용되는 경우도 거의 없으며 (여러가지 환경적인 요인들 때문에) 마지막으로 그렇게 되면 결국 자신이 구할 수 있는 취직 기회의 범위를 축소하는 결과를 낳기 때문입니다. 대략적인 인터뷰 과정과 준비해야할 항목에 관해서는 따로 글을 작성해서 올리도록 하겠습니다.

3. 학력
몇몇 특정 기업의 특정 포지션에 한해서는 학력을 중요시하는 경우가 있지만 이곳에 있는 대부분의 회사들은 특정 학교 졸업을 요구하거나 인터뷰 시 중요하게 보고 있지 않습니다. 단 학사 졸업은 보통 기본으로 요구하고 있으며 (CS나 CE 쪽) 석사를 선호하는 편입니다. 어떤 학교를 나오든 인터뷰를 보는 절차는 같기 때문에 인터뷰 준비만 잘 하면 학력은 크게 문제가 되지 않는 것 같습니다.

4. 언어 능력 (영어)
미국 내에 있는 회사에서 일을 하려면 영어 구사 능력은 필수이지만 그래도 다른 직종에 비해 (회계사나 세일즈맨 같은) 엔지니어들한테 요구되는 언어 능력은 조금 덜 한 편이며 특히나 실리콘 밸리 지역은 워낙에 외국인 엔지니어들이 많기 때문에 (특히 인도인과 중국인) 미국 내의 다른 지역에 비해 언어 능력 부족에 조금 관대한 편입니다. 기본적인 회화 능력과 자기 생각에 대한 정확한 서술을 할 수 있고 상대방의 이야기를 이해하고 토론 가능한 정도면 일을 하는데 있어서 큰 무리가 없습니다. (물론 이전에 미국에서 생활한 경험이 없거나 영어권 국가에서 연수 및 유학을 하지 않은 경우에는 이 정도까지 오는데도 쉽지는 않겠지만요) 그렇지만 위의 내용은 말단 엔지니어일 때의 경우이고 좀더 높은 포지션의 인터뷰 때는 (매니저나 테크니컬 리드 같은) 기술적인 실력도 중요하지만 언어 능력이 더 많이 중요하게 작용하기 때문에 이 부분에 있어서는 좀더 많은 개선이 있어야 합니다.

5. 대기업 vs 스타트업 회사
일반적으로 스타트업 회사는 경험이 많이 있거나 여러가지를 다양하게 할 줄 아는 엔지니어를 선호하며 (지금 당장 쓸수 있는 엔지니어) 대기업은 경험이 부족해도 잠재력이 있거나 기초가 튼튼한 엔지니어들을 고용하는 경우가 많이 있습니다. 입사 후에 하는 일들도 대기업은 특정 분야에 대해서만 일을 하게 되지만 스타트업 같은 경우에는 여러 가지 다양한 일을 동시에 진행하는 경우들이 대부분입니다. 참고로 이야기하자면 스타트업의 업무 환경이 대기업보다 더 좋은 곳이 많으며 평균 이상의 스타트업 같은 경우 (투자금 상황이 괜찮은 경우) 직원 대우 (연봉 + RSU)도 대기업과 거의 비슷한데다가 향후 주식상장을 하거나 대기업에 합병되었을 때 스톡옵션이 대박나는 경우들이 있기 때문에 오히려 대기업보다 더 들어가기 힘든 곳들이 꽤 있습니다. (Uber나 Airbnb 같은)

6. 회사별 몇 가지 정보
 - Google: 구글은 웬만한 지원자들한테 인터뷰 기회를 주는 편이며(학벌이나 경력 상관없이) 인터뷰한 사람들의 DB를 구축해서 관리하고 있은 것으로 알고 있습니다. 인터뷰 난이도는 높은 편이지만 절차가 상당히 체계적이고 공정하게 진행되는 것으로 알려져 있습니다. 구글 인터뷰 과정의 특징은 Hiring Manager의 권한이 제한되어 있어서 소수의 인맥을 통한 편법적인 채용이 힘들고 모든 인터뷰 절차가 끝난 후 인터뷰를 진행한 사람들이 모여 인터뷰 결과를 공유하는데 이 때 다수로 부터 높은 점수를 받아야 합격이 되는 것으로 알고 있습니다. 만약 인터뷰에 패스를 못 하면 1년 안에 다시 지원을 못하며 (지원을 하더라도 새로운 인터뷰 진행이 안됩니다) 온사이트 같은 경우에는 최대 3번까지 가능합니다. (만약 온사이트까지 가서 떨어진게 3번이 되면 삼진 아웃제 같이 차후에 지원을 하더라도 인터뷰 진행 자체가 아예 안되는 것으로 알고 있습니다.)
 - Apple: 애플은 같은 부서에서 나온 포지션만 아니면 여러 부서의 여러 포지션에 대한 동시 인터뷰 진행이 가능합니다. 인터뷰 과정 중 특이한 점은 알고리즘 쪽 관련 질문 외에도 그 부서에서 사용하는 기술 관련 질문들의 비중도 꽤 높은 편이며 구글보다는 Hiring Manager의 권한이 큰 편입니다.
 - Amazon: 애플과 비슷하게 여러 오픈 포지션에 대해 동시에 지원이 가능하며 아마존 만의 특징은 우선 Scalability 관련 질문을 많이 하는 편이며 인터뷰 시작 때 Behavioral Question을 꼭 하나 이상 하는 경향이 있습니다.
 - 스타트업 회사들: 위에 언급한 것처럼 일반적으로 경험이 많이 엔지니어를 뽑으려 하는 경향이 있으며 인터뷰 과정이 나쁘지 않더라도 자신보다 나은 경쟁자가 있을 시에는 제한된 버젯 때문에 채용이 안 되는 경우도 더러 있습니다. (돈에 여유가 있는 대기업 같은 경우에는 인터뷰 과정이 괜찮은 후보자가 여럿 있을 경우 없는 포지션을 만들어서라도 둘다 고용하는 경우가 있는데 스타트업 회사 같은 경우에는 아마래도 돈에 제한이 있다보니 꼭 정해진 인원만 뽑으려는 경향이 있습니다. 물론 인터뷰를 정말 잘 했을 경우에는 다른 이야기지만요.) 또한 인터뷰 난이도도 일반 대기업들보다 더 높은 경우들도 많습니다.