스토리 홈

인터뷰

피드

뉴스

조회수 2979

Python 기반의 웹서비스 개발 환경 구축 방법

안녕하세요. 스포카 크리에이터팀의 프로그래밍 인턴을 맡고 있는 __박종규, 정성재, 고아라__입니다. 저희 세 명은 각각 다른 OS 환경에서 웹서비스를 개발하였는데 이번 포스팅에서는 OS별로 개발 환경을 구축하는 과정을 설명하겠습니다.PythonPython(파이썬)은 비영리의 Python 소프트웨어 재단이 관리하는 개방형, 공동체 기반 개발 모델을 가지고 있습니다. Python은 C파이썬 구현이 사실상의 표준이며 동적 타이핑 범용 프로그래밍 언어로, 펄 및 루비와 자주 비교됩니다. Python은 순수한 프로그래밍 언어의 기능 외에도 다른 언어로 쓰인 모듈들을 연결하는 Glue language로써 자주 이용됩니다. 실제 Python은 많은 상용 응용 프로그램에서 스크립트 언어로 채용되고 있습니다. 또한, 유니코드 문자열을 지원하여 다양한 언어의 문자 처리에도 능합니다. 현대의 Python은 여전히 인터프리터 언어처럼 동작하나 사용자가 모르는 사이에 스스로 Python 소스 코드를 컴파일하여 바이트 코드를 만들어 냄으로써 다음에 수행할 때에는 빠른 속도를 보여줍니다.Windows에서 Python 2.x 설치 방법Linux와 Mac OS에서 Python은 기본적으로 설치되어 있기 때문에 터미널 창에서 Python 명령만으로 쉽게 실행할 수 있지만 Windows에서는 Python을 따로 설치해주어야 합니다.Python 공식 사이트해당 사이트에 들어가서 Quick Links (2.7.3) – Windows Installer 선택하여 python-2.7.3.msi 다운로드 후 실행하여 설치합니다. 특별히 원하는 버전이 있을 때에는 DOWNLOAD – Releases에서 버전별로 설치파일을 다운로드 할 수 있습니다. Python의 기본 설치 경로는 C:\Python27 이며 설치 완료 후, 환경변수를 등록해야 합니다. 환경변수를 등록하는 방법은 다음과 같습니다.내컴퓨터(마우스 오른쪽 버튼 클릭) – 속성(시스템 등록 정보) – 고급 – 환경 변수 클릭시스템 변수 – Path 선택 후 편집 클릭변수 값에 맨 뒤에 C:\Python27;C:\Python27\Scripts; 입력 후, 확인 버튼을 눌러 시스템에 적용변수 값은 각각 ; (세미콜론) 으로 구분Python의 패키지 설치 방법시작 메뉴 – 실행 – CMD 로 커맨드 창을 실행 시킨 후에 Python이 설치된 디렉터리로 이동합니다.cd C:\Python27\Scripts 그 다음 easy_install pip 명령으로 pip를 설치해줍니다. pip는 PyPI(Python Package Index)에 등록된 패키지들을 설치하고 관리할 수 있는 패키지 관리 시스템입니다.$ easy_install pip 다음은 pip 명령의 사용법입니다.pip install packageName 명령 : 최신버전으로 설치pip install packageName==0.x.x 명령 : 0.x.x버전으로 설치패키지 설치 경로 : C:\Python27\Lib\site-packagespip uninstall packageName 명령 : package 제거pip freeze 명령 : 현재 환경에 설치된 package 이름과 버전 목록 PostgreSQLPostgreSQL는 California 대학 Berkeley computer science 학부에서 개발한 POSTGRES, Version 4.2 를 기반으로 한 오브젝트 RDB 관리 시스템(ORDBMS)입니다. 또한, PostgreSQL은 BSD 허가권으로 배포되며 오픈소스 개발자 및 관련 회사들이 개발에 참여하고 있습니다. 따라서 누구라도 사용, 수정, 배포할 수 있으며 목적과 관계없이 무료로 이용할 수 있습니다.각 운영체제 별 PostgreSQL 설치 방법WindowsWindows에서 PostgreSQL을 설치하기 위해 해당 사이트로 접속합니다.PostgreSQL 공식 사이트해당 사이트의 Download탭을 선택하여 Downloads 페이지로 이동합니다. 그 다음 Binary packages 에서 Windows를 선택하여 Windows installers 페이지로 이동합니다. One click installer 에서 Download 선택 후 이 페이지 로 이동하여 해당하는 OS 버전으로 선택하여 다운로드 후 설치합니다.Linux (ubuntu 12.04 LTS)Linux(리눅스)에서 PostgreSQL은 여러 가지 방법으로 설치 할 수 있습니다. 패키지로 설치하는 방법은 터미널 창에서 아래와 같은 명령어를 입력하시면 됩니다.$ sudo apt-get install postgresql-X.X(버전명) 다른방법으로 설치하는 방법은 아래 주소로 들어가시면 자세히 나와 있습니다.PostgreSQL 공식 사이트추가로 PostgreSQL을 편하게 이용하고 싶은 사용자는 pgadmin3이라는 PostgreSQL의 GUI 프로그램을 설치하시면 됩니다. 설치 방법은 터미널 창에서 아래와 같은 명령어를 입력하시면 됩니다.$ sudo apt-get install pgadmin3 Max OS ( MAC OS X Mountain Lion 10.8.2)Mac OS에서 PostgreSQL은 Homebrew를 이용하여 설치하도록 하겠습니다. Homebrew는 Mac OS의 패키지 관리자 프로그램입니다. PostgreSQL은 Homebrew 이외에도 PostgreSQL 다운로드 사이트, Homebrew와 비슷한 기능을 하는 MacPorts 등을 이용해서도 다운받을 수 있습니다. 하지만 PostgreSQL 이외의 다른 프로그램을 설치하기에도 패키지 관리자가 유용하기 때문에 저는 Homebrew를 이용하도록 하겠습니다. 일단, Homebrew 패키지를 컴파일 하기 위해서 xCode가 설치되어 있어야 합니다. 앱스토어에서 xCode를 검색하여 받도록 합니다.xCode 설치를 완료했으면 메뉴에서 __xCode탭 - Preferences - Downloads - Command Line Tools__를 다운받습니다. 그럼 이제 Homebrew 패키지를 컴파일할 수 있게 되었습니다.이제 터미널을 실행시키고 다음 명령을 입력하면 Homebrew가 설치됩니다.$ ruby -e "$(curl -fsSkL raw.github.com/mxcl/homebrew/go)" Homebrew가 이미 설치되어있다면 업데이트할 사항이 없는지 확인해보고 업데이트를 시켜주세요.$ brew update이제 Homebrew 설치를 완료했으니 간단하게 PostgreSQL을 설치할 수 있습니다.$ brew install postgresql 설치된 버전을 $ psql –ver 명령으로 확인해 보니 PostgreSQL 9.1.4 버전이 설치되어 있었습니다.psycopg2psycopg2는 Python library의 한 종류로써 하는 역할은 Python에서 PostgreSQL를 활용하게 해주는 library입니다. 설치 방법은 터미널 창에서 아래와 같은 명령어를 입력하시면 됩니다.$ pip install psycopg2 * 참고 ubuntu/debian 사용하시는 분 중에서 설치가 안 되시는 분들은 psycopg2를 설치하시기전에 python-dev라는 패키지 파일을 설치하시면 psycopg2를 설치 하실 수 있습니다. 설치 방법은 터미널 창에서 아래와 같은 명령어를 입력하시면 됩니다.$ sudo apt-get install python-dev FlaskFlask는 Python용 Micro Framework이며, Jinja2 template engine과 Werkzerg WSGI toolkit에 의존합니다. Flask에는 기본적으로 많은 환경설정 값들이 존재합니다. 규칙에 따라 템플릿 파일과 CSS, JavaScript, Images 등의 파일들은 templates과 static 이라는 하위 디렉터리에 각각 보관해야 합니다. 기본적으로 Flask는 다른 라이브러리에는 존재하는 Database abstraction layer, Form validation 등의 기능을 포함하지 않지만, 기능을 추가할 수 있는 확장성을 제공합니다. 이미 수많은 라이브러리들이 Database integration, Form validation, Upload handling, Various open authentication technologies등을 제공합니다. SQLAlchemy나 다른 DB Tool을 이용하여 고급 패턴을 구현할 수 있으며, Flask를 이용해보면 다양한 기능을 확장할 수 있다는 것을 알 수 있을 것입니다.Flask 설치 방법Flask를 설치하려면 터미널 창에서 다음 명령어를 입력하면 됩니다. (windows의 경우 cmd창) $ sudo pip install flask SQLAlchemySQLAlchemy는 Oracle, DB2, MySQL, PostgreSQL, SQLite와 같은 관계형 데이터베이스에 강력하고 유연한 인터페이스를 제공하는 Python SQL Toolkit이자 Object Relation Mapper(ORM)입니다. 여기서 ORM은 객체를 관계형 DB 테이블에 매핑해주는 역할을 하는데 SQLAlchemy는 객체를 매핑하기 위해 특정 클래스를 상속받지 않아도 되기 때문에 높은 수준의 라이브러리라고 할 수 있습니다.앞선 단계까지의 설치가 완료되었다면 SQLAlchemy의 설치법 역시 pip 명령을 쓰면 되므로 간단합니다. 윈도우는 커맨드창을 실행시키고, 리눅스와 MAC OS의 경우 터미널을 실행시켜 다음 명령을 입력합니다. 저는 SQLAlchemy 0.7.2 버전을 설치했습니다.$ pip install SQLAlcheymy==0.7.2Permission denied라는 문구가 뜨면 권한이 없는 것이므로 관리자 계정으로 설치를 해주어야 합니다. 관리자 계정은 $ sudo su로 로그인하거나 명령 앞에 sudo를 붙이면 됩니다.$ sudo pip install SQLAlchemy==0.7.2 여기에서 ==0.7.2는 설치할 SQLAlchemy의 버전을 뜻하며 버전을 명시하지 않으면 최신 버전으로 깔립니다.Flask-SQLAlchemyFlask-SQLAlchemy는 SQLAlchemy를 더욱 뒷받침할 수 있는 Flask의 확장으로 SQLAlchemy 0.6 이상의 버전을 필요로합니다. Flask-SQLAlchemy 역시 pip 명령으로 설치할 수 있으며 저는 Flask-SQLAlchemy 0.15 버전을 설치했습니다.$ sudo pip install Flask-SQLAlchemy==0.15 마치며지금까지 Windows, Linux, Mac OS에서 Python, PostgreSQL을 이용한 웹서비스 개발 환경 구축 방법에 대해 알아보았습니다. 이 글을 통해서 처음 접한 사람들도 특정 OS에 구애받지 않고 쉽게 웹서비스 개발 환경을 구축하는 데에 도움이 되었으면 좋겠습니다.출처Python 위키백과pip 위키백과 Flask 홈페이지PostgreSQL plusPostgreSQL 위키백과 Essential SQLAlchemy, O REILLY, 2008Flask-SQLAlchemy 홈페이지#스포카 #개발 #개발팀 #개발자 #파이썬 #Python #개발환경 #업무환경 #꿀팁 #조언 #인사이트
조회수 1076

"안정적인 서비스 운영으로 더 나은 코인원의 가치를 고객들에게 전달합니다:D" - 플랫폼셀 김영민

하나의 서비스를 출시하고 운영하기까지의 여정을 '출산과 육아'에 비유하곤 합니다. 아이를 건강하게 낳고, 올바르게 성장할 수 있도록 하기 위한 육아법은 모든 부모들의 고민일거에요. 이는 서비스를 출시한 엔지니어들에게도 마찬가지입니다. 심혈을 기울여 서비스를 개발하고, 이후 서비스가 고객들에게 안정적으로 제공될 수 있도록 유지하고 끊임없이 개선하죠.오늘은 코인원의 서비스를 건강하게 키워나가고 있는 코인원 플랫폼셀 영민님과 이야기를 나눠봤습니다. 365일 밤낮없이 운영되는 암호화폐 거래소 서비스 운영은 어떤 모습일까요? 영민님이 이야기하는 코인원 서비스 개발부터 구축, 운영까지의 여정에 함께하시죠!Q. 영민님 반갑습니다 :-) 먼저 자기소개를 부탁드립니다!안녕하세요, 플랫폼셀의 클라우드 플랫폼 엔지니어 김영민입니다. 어느덧, 코인원에 합류한지 1년 반의 시간이 흘렀네요. 저는 코인원 한국거래소를 시작으로 해외송금 서비스 ‘크로스', 글로벌거래소 ‘CGEX’와 같은 다양한 금융 서비스 인프라 업무를 경험했습니다. 현재는 코인원 한국거래소 서비스 인프라 구축과 운영 업무를 중점적으로 담당하고 있어요. 저를 포함한 플랫폼셀의 크루들은 코인원을 지탱하고 있는 인프라를 효율적으로 운영하고 있습니다. 특히, 개발과 운영셀에 속해 있는 크루들과의 밀접한 소통으로 고객에게 더 나은 서비스의 가치를 전달할 수 있도록 하는 것이 목표입니다.  Q. 플랫폼셀은 어떻게 구성되었나요? 구체적으로 어떤 일을 하시는지도 궁금합니다. 플랫폼셀은 크게 클라우드 플랫폼 엔지니어들로 구성되어 있습니다. 세부적으로 시스템 엔지니어, 네트워크 엔지니어, 데이터 사이언티스트, 플랫폼 개발 업무로 나뉘어집니다. 플랫폼셀은 코인원 초창기 시절부터 팀명과 업무범위에 많은 변화가 있었습니다. 인프라팀, SRE(Site Reliability Engineering)팀을 거쳐 지금의 플랫폼셀이 탄생하게 되었죠. 플랫폼셀의 가장 큰 목표는 안정적인 운영을 통해 서비스의 신뢰성을 확보하는 것입니다. 이를 위해 신속하게 개발을 지원할 수 있는 플랫폼을 설계하고 구축하려고해요.플랫폼셀 크루들의 열띤 업무의 현장!Q. 플랫폼셀이 많은 변천사를 겪어온 만큼, 코인원의 서비스 구성에도 큰 변화가 있었을 것으로 예상됩니다. 그 중 가장 큰 변화는 무엇인가요?초창기 코인원 서비스의 경우, 전통적인 서비스 아키텍처인 모놀리틱(Monolitic) 아키텍처 기반의 서비스가 많았습니다. 모놀리틱 아키텍처는 로컬 환경에서 개발하기에도 편리하고 통합 시나리오 테스트를 수행하기에도 쉬운 구성입니다. 다만, 코인원의 서비스가 지속적으로 성장하고 규모가 커지면서 몇가지 한계에 부딪혔습니다.서비스 복잡도가 증가하고 트래픽이 상승하면서, 서비스 확장이나 배포 관련 업무에 인프라 작업들이 수시로 발생하게 되었어요. 무중단 배포, 효율적인 리소스 사용, 인프라 표준화를 위해 ‘마이크로서비스 아키텍처'로의 전환이 필요한 시기였습니다. 이를 위해 마이그레이션(Migration, 데이터를 추출하여 새로운 시스템 내의 지정된 형식으로 옮기는 과정) 계획을 세우고 조직의 의사결정 프로세스와 개발 문화, 배포 프로세스들을 개선해 나가기 위해 노력했죠.Q. 암호화폐 거래소 ‘코인원' 서비스를 운영하시면서 다이나믹한 에피소드들이 많을 것 같습니다.2017년 12월 말, 비트코인 전고점 시기에 도달할즈음 코인원 거래소의 서비스 트래픽이 가파르게 상승했습니다. 매일마다 두배, 세배 이상의 인프라 확장작업이 필요했어요. AWS(Amazon Web Services)에 지불했던 비용이 17년 7월 대비 12월에 20배가 늘었습니다. 6개월이라는 짧은 시간동안 이렇게 급성장한 트래픽을 경험할 수 있는 업계는 몇없을거에요!Q. 코인원을 이용하는 고객들의 거래가 더 편리해질 수 있도록 플랫폼셀에서는 어떠한 노력을 기울이고 계신가요?트래픽 급증으로 서비스 업데이트를 할 경우, 서비스 지연 그리고 점검으로 인한 중단으로 불편을 겪은 고객분들이 계실 겁니다. 코인원은 이러한 문제를 해결 하기 위해 대용량 서비스를 운영 할 수 있도록 아키텍처를 변경하는 작업을 진행했습니다. CI/CD(Continuous Integration and Continuous Delivery, 지속적 통합과 지속적 전달) 자동화, 무중단 배포 환경을 갖추면서 서비스 지연과 중단의 빈도수가 점점 줄고 있습니다. 이제는 서비스를 더 빠르게 업데이트 하고 버그나 장애를 최소화 하며 트래픽이 갑작스럽게 증가하더라도 서비스 안정성을 확보 할 수 있는 플랫폼으로 진화하고 있어요.노을지는 창가 속의 슈퍼크루 영민님!Q. 코인원의 플랫폼셀만이 갖고 있는 장점을 이야기해본다면!코인원에는 어느 스타트업보다도 연륜이 가득한 시니어 엔지니어들이 플랫폼셀을 이끌고 있습니다. 블록체인, 암호화폐 업계 뿐만 아니라 직무 경험도 많으신 분들이 곳곳에 포진되어 있어요. 코인원 기술본부만이 갖고 있는 중요한 장점이기도 하죠. 또한 플랫폼셀은 내부적인 아키텍쳐, 코드 리뷰를 거치면서 일하는 방식을 지속적으로 개선해 나가고 있습니다.추후 플랫폼셀에 합류하실 분들도 새로운 것들을 찾고 계속해서 발전시키려고 하는 분들이 함께해주셨으면 좋겠습니다! 스탠드업 미팅, 회고를 통해 소통하고, 재미있는 개발문화를 만들어가고 있으니 플랫폼셀에 많은 지원 부탁드립니다 :) (저희 해치지 않아요! ㅎㅎㅎ)Q. 영민님은 코인원에 어떻게 합류하게 되셨나요?저는 실생활에 다양한 금융서비스를 제공하는 핀테크에 관심이 많았습니다. 핀테크에 대한 관심은 이전에 몸담았던 게임산업에서부터 시작되었어요. 게임에서도 암호화폐 거래소와 유사하게 서비스 내에서 통용되는 가상의 화폐가 있습니다. 그러다보니 ‘가상의 재화가 아닌 실물화폐를 다루는 곳의 서비스는 어떻게 제공될까?’ 라는 호기심이 강해졌어요. 신기술이었던 블록체인과 암호화폐를 눈여겨보게 되었고, 지금 이렇게 코인원 크루로 함께하고 있네요! 코인원에서는 실제 현금을 다루는 곳이기 때문에 막중한 책임감으로 서비스 안정성과 보안을 함께 신경쓰고 있습니다.Q. 지난 겨울에 코인원 크루들과 함께 재미난 추억을 만드셨다고 들었어요!2018년은 코인원에서 피보탈랩스를 시작으로 새로운 것들에 많이 도전해볼 수 있는 시간이었습니다. 그 중, 다양한 직무에 계신 크루들과 함께 참가했던 ‘AWS re:Invent 2018’ 행사가 기억에 남네요. 리인벤트 기술세션에서 소개되었던 Tool들이 코인원에서 많이 사용되고 있는데, 컨퍼런스에서 새롭게 배운 것들을 적용해볼 수 있을 것 같습니다! 힙한 개발문화들도 접해보고, 다양한 국가, 회사, 직군에 계신 분들을 만나뵙게 되어 개발을 바라보는 시야 또한 넓어졌네요. 코인원 크루와 함께했던 AWS re:Invent 현장!Q. 영민님이 어떠한 미래를 꿈꾸고 계신가요?거창한 미래를 이야기하기 보단 소소한 바램을 말씀드리고 싶어요. 2019년에도 그리고 이후에도 지금 함께 일하고 있는 코인원 크루들과 더 재미나게 일하고 싶습니다. 훌륭한 동료들이 제 옆에 있다는 것만으로도 난관을 헤쳐나갈 때 큰 도움이 됩니다. 똘똘 뭉친 지금의 조직력을 바탕으로 99.999%(?)의 서비스 안정화 꿈을 이룰 거랍니다. 마지막으로, 새해에는 야근을 조금 덜하고 사랑하는 두딸들과 행복한 저녁 시간을 자주 가지려구요! (아빠 얼굴 잊은거아니지?)더 안정적인 코인원 거래소를 위해 오늘도 24시간 고군분투하고 있는 영민님. 앞으로도 코인원 플랫폼셀은 암호화폐 거래에 최적화된 플랫폼 구축을 위해 최선의 노력을 다할 예정이랍니다. 코인원 플랫폼셀 크루들이 선보일 멋진 서비스에 많은 응원과 관심 부탁드립니다.이렇게 멋진 엔지니어들과 동료가 되고 싶지 않으신가요? 현재 코인원 플랫폼셀은 함께 일할 동료 크루를 애타게 기다리고 있습니다! 많은 지원 부탁드려요 :-)
조회수 1460

확률론적 프로그래밍 언어는 왜 필요 할까요?

AI•머신러닝은 모든 분야에서 거론되며 이를 적용해볼 수 있는 다양한 AI•머신러닝 툴들이 쏟아져 나오고 있습니다. 기본적인 머신러닝 기법들을 담고 있는 scikit-learn을 시작으로 deep learning이 화두가 되며 구글에서 내놓은 tensorflow까지 다양한 회사, 연구원이 오픈소스 트렌드에 맞춰 수많은 머신러닝 라이브러리를 공개하고 있습니다. 이러한 라이브러리들은 기존의 프로그래밍 언어를 이용하여 효율적으로 계산될 수 있도록 개발, 패키징 되어 보다 손쉽게 머신러닝을 체험해볼 수 있습니다. 최근에는 기존 프로그래밍 언어로 개발된 머신러닝 라이브러리를 넘어서 머신러닝 기법에 특화된 확률론적 프로그래밍 언어(Probabilistic Programming)들이 개발되고 있습니다. 이는 기존 하드웨어에서 머신러닝 계산에 적합한 GPU 하드웨어의 폭발적인 인기를 넘어서 인공지능에 최적화된 하드웨어(Google Tensor Processing Unit) 개발 시도가 소프트웨어에서도 일어나고 있다고 생각합니다. 백문이 불여일견이니만큼 엘리스에서 간략한 소개 튜토리얼을 해보실 수 있습니다.구글 Tensor Processing Unit (TPU)확률론적 프로그래밍 언어란?확률론적 프로그래밍 언어는 머신러닝 분야, 확률과 통계 분야, 그리고 프로그래밍 언어 분야, 총 세 분야를 아울러 만들어진 새로운 프로그래밍 언어입니다. 기존의 전산학(Computer Science)은 주어진 변수/파라미터가 있고, 이를 프로그램 및 계산하여 결과 값을 얻습니다. 머신러닝 내에서 주로 쓰이는 방법은 추론인데 이는 관측되는 결과 값 들이 있고, 이를 다양한 수학적 방식으로 추론하여 변수/파라미터값들을 구합니다. 따라서 확률 통계의 수학적 계산법을 직관적으로 프로그래밍 할 수 있기 위해선 기존의 전산학 방식이 아닌 새로운 방식의 프로그래밍 언어가 필요하고, 확률론적 프로그래밍 언어는 이러한 패러다임에 맞춘 시도라고 볼 수 있습니다. 이렇게 개발된 언어는 복잡한 머신러닝 기법도 간략한 코드로 개발할 수 있게 하는 목표를 가지고 있습니다.확률론적 프로그래밍 언어란? (NIPS Tutorial 2015)확률론적 프로그래밍 언어 리스트 (Wikipedia)우리에게 아직은 생소해 보이는 확률론적 프로그래밍 언어는 현재 활발히 연구되고 있으며, 그 종류도 30가지가 넘습니다. 각 확률론적 언어는 기존의 다양한 프로그래밍 언어에서 파생 되었는데요, 엘리스에서 사용하는 주 언어 중 하나인 Python을 기반으로 한 PyMC3을 기반으로 튜토리얼을 만들었습니다.그 외 실제 실험에서 적용된 Picture라는 확률론적 프로그래밍 언어는 2D 얼굴 사진을 토대로 3D 얼굴을 모델하는 프로그램을 단 코드 50줄로 만들어 2015년에 공개되었습니다. 이를 보통 프로그래밍 언어로 개발했다면, 몇 천줄로 개발되어야 했다고 합니다.마치며이번 글에서는 간략하게 확률적인 프로그래밍 언어를 소개했습니다. 아직은 생소할 수 있지만, 점점 다양한 분야에서 머신러닝이 사용 될 수록 이에 적합한 확률론적 프로그래밍 언어의 연구, 개발은 활발해 질 것으로 예상됩니다. 지금 엘리스에 로그인 하셔서 확률론적 프로그래밍 언어 실습 예제를 실행해보세요!엘리스에 올려진 실습문제를 실행하면 책에서만 보던 이런 그래프들이 무슨 의미인지 이해하고 실제로 그려볼 수 있습니다!글쓴이김재원: The Lead, Elice김수인: KAIST 전산학부 박사과정박정국: KAIST 전산학부 박사과정#엘리스 #코딩교육 #교육기업 #기업문화 #조직문화 #서비스소개
조회수 4958

소스코드 리뷰에 대한 짧은 이야기...

개발자와 개발 조직에게 소스코드 리뷰는 필수적이다. 팀간의 협업과 대화를 보다 원활하게 만들어 주는 매우 필요한 절차이다. 슬랙과 같은 협업도구가 명쾌하게 의미 있게 활용되려면 개발팀 간의 소스코드 리뷰는 필수적으로 수행되는 것이 좋다.매우 당연한 이야기이지만, 소스코드 리뷰는 거북하고 불편하고 어렵고 힘들다. 그럼에도 불구하고 필수적인 이벤트가 되어야 하는 이유가 너무도 많다. 개발자들에게 코드리뷰에 대한 이슈를 설득하고 실제 행위를 발생시키는 것은 정말 어려운일이다. 더군다나 뜬금없이 코드리뷰 이야기를 회사나 팀리더에게서 갑자기 듣는다면 개발자는 매우 불편해 한다. 그것은 매우 당연한 반응이다. 그러므로, 가능하다면 팀 세팅 초기 시부터 이 소스코드 리뷰 문화는 만들어질 수 있게 노력하는 것이 최선일 것이다.초기에 세팅된다면 그 후에 들어오는 팀원들은 자연스럽게 그 문화에 익숙해진다. 이런 일련의 작업들은 결국 조직과 팀의 단결과 협력, 향후 유지보수에 매우 긍정적인 효과를 준다.매우 당연하지만 개발자들은 팀에 소속되고 빠져나가기를 반복한다. 이를 두려워하지 않는 방법 중에 가장 먼저 선택할 수 있는 것이 바로 코드 리뷰라는 행위다. 인수인계와 유지보수를 위해서 소스코드 리뷰를 각 단계별에 배치해두고, 그 시간을 투자하는 것을  아까워하지 않도록 하자.그렇다면, 소프트웨어의 본체인 소스코드를 타인이 리뷰한다는 것이 왜 어려울까? 그것은 소스코드는 언제나 완성상태가 아니라는 점 때문이다. 개발자의 생각은 무언가 다양한 변화를 예측하고 있고, 그 상세한 준비를 담고 있다. 언제나 소스코드는 완성 상태가 아니라, 변화되어야 하는 시간의 축을 담고 있기 때문이다.하지만, 소프트웨어 품질이 중요한 현재의 시점에서 본다면, 코드 리뷰라는 행위는 정말 필수 불가결한 행위에  해당한다고 생각한다.이런 필수적인 코드리뷰는 그 형태와 범위에 대해서 팀 내부에 잘 정의되어야 한다.그래서, 보통 이 코드리뷰를 어떻게 할 것인가에 대해서 조직이나 담당하는 사람의 경우에는 명쾌한 판단 기준이 있어야 한다. 그러한 ‘판단기준’을 가져야만 명확한  리뷰될 수 있다.이를 두고, 디자이너에게는 크리틱(critique-비평)이 있고, 개발자에게는 코드리뷰가 있다고 정의한다.좋은 비평을 받고 좋은 리뷰를 하려면 다음의 3가지 원칙이 필수이다.1. 리뷰는 언제나 상호 합의가 되어진 상황에서 진행되어야 한다.2. 리뷰어의 해당 결과물에 대해서 객관성을 가지고 서로 인지해야 한다3. 개발자 자신의 작업물에 대해서 정말 객관적으로 바라볼 수 있는 작성가가 선정되어야 한다.특히, 소프트웨어 코드는 정량적인 검토와 정성적인 검토를 구분해야 한다. 이 영역의 구분이 모호해지면, 리뷰는 그 방향성을 상실하게 된다. 그중에 특히, 정량적인 검토와 기본적인 규칙들은 가능한 자동화하고, 소스 형상관리 도구에서 기본적인 것들의 규칙들을 지키도록 권장하여야 한다. 최소한 이 정량적인 것만 자동화하고  규칙화해도 소프트웨어의 품질은 급상승한다.하지만, 코드는 논쟁을 발생시키고, 어떤 것이 우선적인지에 대해서 서술하기 매우 어렵다. 이러한 점은 정성적인 부분에 대해서 검토할 때에 고민하자.코드리뷰의 정도는 어느 정도 해주어야 하는가?그 전부터 주목하는 개발 방법론의 추세는 ‘테스팅’을 주로 하고, SRS와 같은 요구사항에 집중하기 보다는, TDD와 같은 방법으로 완성 산출물을 높이는 방법을 현재에는 주로 사용하고 있다.그것은 과거에는 요구사항을 통해서 결과물이 완성되는 SI성 개발이 주로였다면, 현재에는 요구사항은 계속 변화하고 버그 없는 결과물이 중요시되는 테스트를 얼마나 더 집중적으로 하느냐에 따른 웹서비스의 시대이기 때문에 그 방향성은 시대에 따라서 변화를 많이 하였다. 그래서, 슬프지만, 당장의 성과물을 위해서라면 코드리뷰보다는 테스팅에 집중하는 것이 더 효율적이다. 빠르게 고속 개발하고 테스트를 통해서 버그를 찾은 다음 수정하는 것이 ‘특정 기능들을 나열하고 기능을 만족하는 소프트웨어’의 경우에는 테스트 주도 개발 방법이 가장 적합하다고 할 수 있다.물론, 이러한 방향성이나 전체적인 틀에 대해서는 아키텍트가 잘 결정하여야 한다. 내가 속한 개발 결과물이 어떤 결과물이냐에 따라서 이 방법은 혼용되어져서 사용되어야 하기 때문이다.하지만, 이번 글의 주목적은 코드리뷰. SRS중심이건, TDD중심이건. 코드리뷰는 중요하다는 것을 강조하고 싶다. 특히, 코드리뷰는 ‘기능 나열’이 아닌, 어느 정도 이상의 복잡도나 코드 품질이 필요한 경우에는 필수적으로 수행하는 것이 매우 현명한 행동이다.물론, 코드리뷰 행위가 불필요한 업무들도 많다. 정해져 있는 단순한 업무를 수행하는 경우에는 굳이 할 필요 없다. 국내에서 SI를 하는 경우에는 대부분 코드리뷰가 필요 없는 업무를 하는 소프트웨어 개발자들이 절대 다수인 경우도 많이 보았다.일반적인 SI의 형태라면 워크 스루의 형태만 적합하다. 특정 도메인에 매몰되어 있고, 처리방법이 명쾌하기 때문에, 해당 경험들을 교환하는 것으로도 충분하기 때문이다. 그리고, 자동화된 테스트 수행방법을 최대한 갖추어두는 것이 가장 현명하다.그러므로, 코드리뷰는 어느 정도 솔루션이나 서비스 등을 고려하고 있는 곳에서 더욱 적합하다고 정의한다.코드리뷰는 특정 제품이나 서비스를 발전적으로 지향하고 있는 경우라면 필수적으로 선택해야 한다. 하지만, 일부 제품의 경우에는 발전적인 지향이 굳이 필요 없는 제품 라인업을 가진 경우에도 굳이 수행할 필요 없다.그 경우에는 선택적인 코드리뷰를 지향하면 된다. 비용상의 문제 때문에 굳이 코드리뷰를 억지로 진행할 필요는 없는 경우도 많다. 대부분의 소프트웨어 개발은 테스트 케이스를 잘 만들고, 통과시키는 것으로써 충분한 신뢰를 가지면 충분한 경우가 대부분이다.특히, 시장이 고착상태이거나, 특별한 변화의 폭이 없다면, 그 정도로 충분한 경우가 된다. 다만, 글로벌 서비스나 웹서비스 등의 지속적인 확장이 필요한 경우라면, 코드리뷰는 필수라고 할 수 있다.코드리뷰가 필요 없는 경우 체크리스트는 다음의 5가지 정도를 체크해보자.1. 특정 도메인만 다루는 팀이나 회사의 개발팀인가?2. 지난 2~3년 정도 솔루션이 크게 변한 것이 없으며, 향후로도 기업이나 팀에서 투자가 없을 예정이다.3. 현재 개발자들이 해당 솔루션에 대한 개발일을 5년 이상하고 있다.4. 기능 위주의 SI성 업무를 주로 처리하고 있으며, 복잡한 알고리즘은 존재하지 않는다.5. 비용과 일정상 개발팀에게 리소스 투여가 불가능하다위의 사례에서 1개 이상이라도 체크된다면, 코드리뷰는 성립하기 힘들다. 대부분 단념하고, TDD나 테스트 케이스를 가능한 많이 축적하여 소프트웨어 품질을 올리기를 권장한다.코드리뷰가 필요한 경우의 체크리스트도 다음의 5가지 정도를 체크해보자.1. 다국어와 시장이 다변화된 환경에서 소프트웨어가 구동되어야 한다.2. 코드의 복잡도가 높으며, 단순 기능 나열의 요구사항이 아니라, 소프트웨어 아키텍처가 별도로 구성되기 시작하였다.3. 사용자의 경험성을 증가하기 위하여 매우 많은 변화가 예측된다.4. 현재 개발 중인 서비스는 중단 없이, 지속적으로 발전되어야 하는 서비스이다.5. 목표 요구사항이 계속 변화하고 있고, 프레임워크를 지향하여 소프트웨어 품질의 요구사항이 매우 중요하다.위의 케이스에서 하나라도 해당이 된다면, 코드리뷰는 매우 효과적으로 소프트웨어에 의미 있는 결과물들을 얻어 내기 위한 좋은 방법이 된다.하지만, 다음과 같은 경우도 같이 고려하여야 한다.코드리뷰의 정도와 질에 대한 검토 리스트의 최소 체크리스트는 다음의 3가지이다. 물론, 이 정의는 조직 내의 아키텍트나 아키텍트 롤을 하는 사람이 결정하는 것이 좋다.1. 실험적인 코드인가?2. 1~2명 이상이 공동으로 작업하는 코드인가?3. 향후 버려질 가능성이 높은 코드인가?코드리뷰를 하지 않는 경우에는 해당 코드의 repository나 디렉터리를 완전하게 분리하고, 리뷰가 안된 코드를 명쾌하게 구분할 수 있어야 한다. 그리고, 그 정보는 팀 전체에게 공개되어야 한다.가장 첫 번째는 코딩규칙 가이드라인의 준수 여부를 체크하는 것이다.개발자들 간의 상호 중요한 것은 스타일 가이드이다. 하지만, 정말 지키기 어려운 것 또한 스타일 가이드라고 할 수 있다. 하지만, 스타일 가이드는 가능한 준수해야 한다. 하지만, 100% 준수하려는 것은 매우 비효율적인 상황을 만들 수 있다. 하지만, 이 경우에 최소한 리뷰어가 제시하는 기준이나 변경 방향에는 대부분 수긍하는 것이 가장 현명하며, 이 부분은 해당 팀의 가장 경험이 풍부한 사람이 리드하는 것이 좋다.그래서, 소프트웨어 개발에는 경험이 풍부한 아키텍트의 역할과 선임의 역할이 가장 중요하다. 소셜에서 이야기하는 가장 중요한 포인트는 이런 경험이 풍부한 선임 개발자가 있다면, 돈이 얼마가 들더라도 ‘개발팀’에 모셔야 한다! 가 정답일 것이다.아직까지 이 부분은 ‘공학’으로 해결할 수 없고, ‘엔지니어링’과 ‘경험’에 의존할  수밖에 없다.주석의 경우에도 ‘가독성’이 충 부한 코드에는 서술할 필요 없다. 이 부분에 대해서는 꾸준한 팀원들 간에 코딩 문화에 대해서  커뮤니케이션하면서 주석의 범위에 대해서 공론화하는 것이 현명하다. 그래서, 소프트웨어 개발은 대부분이 ‘커뮤니케이션’이고 ‘소통’이다. 그래서, ‘팀워크’이 가장 중요한 것이고. 변수의 명칭에 대해서도 ‘명확’하다는 선에서 합의해야 한다.테스트가 쉽지 않은 구조는 다른 문제를 야기한다. Junit과 같은 단위 테스트 도구로 손쉽게 정의가 가능한 구조가 아니라면, 변경해야 한다.코드리뷰 후에 분명하고 타당한 지적에도 고집이 세서 변화가 없는 경우에는 한두 번 이야기하고 더 이상 변화가 없다면, 포기하고. 해당 코드를 격리하여 관리하는 것이 현명하다.  팀원들 간에 감정이 상하는 것이 더 위험하다. 사람은 변하지 않는다 감정에 대한 다툼이나 기대를 할 필요가 없다.UI가 중요한 코드는 해당 코드들이 급변할 가능성이 농후하다. 처음부터 공을 들여서 추상화를 실현하지 않으면, 해당 코드 때문에 프로젝트가 심각해질 수 있다. 사용자에게 더 좋은 경험을 전달하려고 하면, UI코드는 계속 변화를 일으킨다.테스트 코드 여부? 로직에 대한 검토, 변수 네이밍 검토와 레이아웃에 대한 것들? 에 대해서는 다음과 같이 판단하고 체크해보자.코드리뷰는 대부분 ‘직관’에 의존한다. 그래서, 정말 어렵고. 경험이 풍부한 사람이 할  수밖에 없다. 다만, 이러한 코드 리뷰 시의 체크리스트 항목을 몇 가지 간단하게 정리할 수 있다. 최소한의 2가지는 꼭 지키자.코드 리뷰 시의 필수 내용 두 가지는 다음과 같다.1. 코드 검토는 1시간 이내에 끝낼 분량으로 검토한다.2. 코드는 200라인 이상을 한 번에 검토하지 마라이 기준이 어겨지면, 리뷰어는 제대로 된 리뷰를 하기 어려울 것이다.  그리고, 이러한 리뷰를 하는 동안 기능에 대한 검토 체크사항에 대해서 나열해 보면 다음과 같이 나열이 될 수 있을 것이다.1. 시스템의 요구사항이 제대로 반영되었는가?2. 시스템의 설계의 규격대로 구현되었는가?3. 과도한 코딩을 하고 있지 않는가?4. 같은 기능 구현을 더 단순하게 할 수 있는가?5. 함수의 입출력 값은 명확한가?6. 빌딩 블록들( 알고리즘, 자료구조, 데이터 타입, 템플릿, 라이브러리, API )등이 적절하게 사용되었는가?7. 좋은 패턴과 추상화( 상태도, 모듈화 )등을 사용해서 구현하고 있는가?8. 의존도가 높은 함수나 라이브러리 등의 의존관계에 대해서 별도 기술하고 있는가?9. 함수의 반환(exit)은 한 곳에서 이루어지고 있는가?10. 모든 변수는 사용 전에 초기화하고 있는가?11. 사용하지 않는 변수가 있는가?12. 하나의 함수는 하나의 기능만 수행하고 있는가?또한, 스타일과 코딩 가이드에 대해서고 검토하고 리딩을 해야 한다.1. 코딩 스타일 가이드를 준수하고 있는가?2. 각 파일의 헤더 정보가 존재하는가?3. 각 함수의 정보를 코드에 대해서 설명하기에 충분한가?4. 주석은 적절하게 기술되어있는가?5. 코드는 잘  구조화되어있는가? ( 가독성, 기능적 측면 )6. 헤더, 함수 정보를 도구로 추출해서 자동으로 문서화할 수 있는 구조인가?7. 변수와 함수의 이름이 일관되게 기술되어 있는가?8. 프로젝트의 가이드를 통한 네이밍 규칙을 준수하고 있는가?9. 숫자의 경우 단위에 대해서 기술하고 있는가?10. 숫자를 직접 서술하지 않고, 상수를 사용하고 있는가?11. 어셈블리 코드를 사용하였다면 이를 대체할 방법은 없는가?12. 수행되지 않는 코드는 없는가?13. 주석 처리된 코드는 삭제가 되었는가? ( 버전 체크가 되었는가? )14. 간결하지만 너무 특이한 코드가 존재하는가?15. 설명을 보거나 작성자에게 물어봐야만 이해가 가능한 코드가 있는가?16. 구현 예정인 기능이 있다면, ToDo주석으로 표시되어 있는가?가장 중요한 아키텍처에 대한 검토를 잊으면  안 된다.1. 함수의 길이는 적당한가? ( 화면을 넘기면  안 된다. )2. 이 코드는 재사용이 가능한가?3. 전역 변수는 최소로 사용하였는가?4. 변수의 범위는 적절하게 선언되었는가?5. 클래스와 함수가 관련된 기능끼리 그룹화가 되었는가? ( 응집도는 어떤가? )6. 관련된 함수들이 흩어져 있지 않는가?7. 중복된 함수나 클래스가 있지 않는가?8. 코드가 이식성을 고려하여 작성되었는가? ( 프로세스의 특성을 받는 변수 타입이 고려되어있는가? )9. 데이터에 맞게 타입이 구체적으로 선언되었는가?10. If/else구분이 2단계 이상 중접되었다면 이를 함수로 더 구분하라11. Switch/case문이 중첩되었다면 이를 더 구분하라12. 리소스에 lock이 있다면, unlock은 반드시 이루어지는가?13. 힙 메모리 할당과 해제는 항상 짝을 이루는가?14. 스택 변수를 반환하고 있는가?15. 외부/공개 라이브러리 사용하였을 경우에 MIT 라이선스를 확인했는가? GPL의 경우에는 관련된 영역에서만 사용해야 한다.16. 블로킹 api호출시에 비동기적인 방식으로 처리하고 있는가?당연하겠지만, 예외처리 관련 체크리스트도 제대로 검토해야 한다.1. 입력 파라미터의 유효 범위는 체크하고 있는가?2. 에러코드와 예외(exception)의 호출 함수는 분명하게 반환되고 있는가?3. 호출 함수가 어려와 예외처리 코드를 가지고 있는가?4. Null포인트와 음수가 처리되는 구조인가?5. 에러코드에 대해서 명쾌하게 선언하고 처리하고 있는가?6. switch문에 default가 존재하고, 예외처리를 하고 있는가?7. 배열 사용시에 index범위를 체크하는가?8. 포인트 사용시에 유요한 범위를 체크하는가?9. Garbage collection을 제대로 하고 있는가?10. 수학계 산시에 overflow, underflow가 발생할 가능성이 있는가?11. 에러 조건이 체크되고 에러 발생 시 로깅 정보를 남기는가?12. 에러 메시지와 에러코드가 에러의 의미를 잘  전달하는가?13. Try/catch 에러 핸들링 사용방법은 적절하게 구현되었는가?요즘 프로그램은 대부분 이벤트성으로 구동되지만, 시간의 흐름에 대한 체크는 프로그램의 뼈대를 이루게 된다. 이 부분에 대해서도 제대로 검토해야 한다.1. 최악의 조건에 대해서 고려하였는가?2. 무한루프와 재귀 함수는 특이사항이 아니라면 없어야 한다.3. 재귀 함수 사용시에 call stack값의 최댓값이 고정되어 있는가?4. 경쟁조건이 존재하는가?5. 스레드는 정상 생성, 정상 동작하는 코드를 가지고 있는가?6. 불필요한 최적화를 통해서 코드 가독성을 희생하였는가?7. 임베디드의 경우에도 최적화가 매우 중요하지 않다면, 가독성을 더 중요하게 해야 한다가장 중요한 검증과 시험에 대해서도 제대로 인지하여야 한다. 그리고, 테스트를 위해서 가능한 최대한 자동화를 하기 위한 방법들을 이용해야 한다.1. 코드는 시험하기 쉽게 작성되었는가?2. 단위 테스트가 쉽게 될 수 있는가?3. 에러 핸들링 코드도 잘  테스트되었는가?4. 컴파일, 링크 체크 시에 경고 메시지도 100% 처리하였는가?5. 경계값, 음수값, 0/1등의 가독성이 떨어지는 코드에 대해서 충분하게 경계하고 있는가?6. 테스트를 위한 fault 조건 재현을 쉽게 할 수 있는가?7. 모든 인터페이스와 모든 예외 조건에 대해서 테스트 코드가 있는가?8. 최악의 조건에서도 리소스 사용은 문제가 없는가?9. 런타임 시의 오류와 로그에 대비한 시스템이 있는가?10. 테스트를 위한 주석 코드가 존재하는가?간혹 등장하는 하드웨어에 대한 테스트도  마찬가지이다. 다음과 같은 기준들을 통해서 검토해야 한다.1. I/O 오퍼레이션 코드에 대한 테스트로 하드웨어가 정상적인 동작을 보장하는가?2. 최소/최대 타이밍 요구사항에 대해서도 하드웨어 인터페이스가 충족하는가?3. 멀티 바이트 하드웨어 레지스터가 read/write오퍼레이션 중에도 값이 바뀌지 않음을 보장하는가?4. 시스템이 잘 정의된 하드웨어 상태로 리셋하는 것을 S/W가 보장하는가?5. 하드웨어의 전압이 떨어지거나 전원이 차단되는 경우에 잘 처리하는가?6. 대기모드 진입 시와 빠져나 올 때에 시스템이 옳게 동작하는가?7. 사용하지 않는 인터럽트 벡터가 에러 핸들러에 연결되어 있는가?8. EEPROM손상(데이터 깨짐)을 막기 위한 메커니즘이 있는가? ( 쓰기 동작 중 powe loss)등구체적으로 코드리뷰를 하고자 한다면, 다음의 코드리뷰에 대한 기법과 적당한 방법을 다음과 같이 설명할 수 있다.이러한 코드 리뷰를 위한 몇 가지 방법들이 알려져 있다. 그것들을 몇 가지 정리하여 보면 다음과 같다. 코드 인스펙션은 가장 정형화된 기법으로 전문화된 코드리뷰팀을 통해서 구분하는 방법이다. 이 방법은 리소스가 풍부하고, 일정에 여유가 있는 경우에만 사용이 가능하다. 대부분 대기업이나 대형 포털에서 구현 가능한 방법이라고 할 수 있다. ( 이런 곳에 있다면 행복해 하자. ~.~ ) 하여간, 비용과 일정 등이 있다면 이 방법이 현명하다. 그리고, 코드리뷰에 대한 품질에 대해서 정량적인 보고와 구성을 만들어 낼 수 있다는 것은 코드 인스팩션의 가장 좋은 장점이다. 이 코드 인스팩션을 하기 위한 롤을 구분하면 다음과 같이 4가지 롤로 구분할 수 있다.1. ModeratorA. 실질적인 매니저로 팀 간의 인터페이스와 리소스, 인프라를 확보하고, 프로세스에 대한 정의와 산출물의 정리를 담당한다.2. ReaderA. 각 산출물을 읽고, 리뷰하고, 방향성을 제시한다. 보통, 지식이 많은 사람이 담당한다.3. Designer/CoderA. Reader의 지시에 따라서 코드를 검증하고 잠재적인 발견 등의 수정 방안을 만든다.4. TesterA. 진행 중인 코드와 권장 수정 코드에 대해서 검증한다.그리고, 코드 인스펙션은 다음과 같은 6단계로 진행된다.1. PlanningA. 계획 수립2. OverviewA. 교육과 역할 정의3. PreparationA. 인터뷰와 필요한 문서 습득, 툴 환경 구축4. Meeting(Inspection)A. 각자의 역할대로 수행5. ReworkA. 보고된 Defect 수정6. Follow-upA. 보고된 Defect가 수정되었는지 확인이러한 절차를 통해서, 코드 인스팩션이 수행되면, 상당히 명쾌한 리뷰가 진행되게 된다. 하지만, 일정과 비용 문제 때문에 이 작업은 대부분의 스타트업에서는 선택하기 어렵다. 그래서 사용하는 방법 중의 하나가 팀 리뷰이다.팀 리뷰는 일정한 계획과 프로세스만 따르는 방법으로, 코드 인스펙션보다는 좀 덜 정형화된 방법으로 진행한다. 보통은 일주일에 한번 정도 팀 리뷰를 수행하거나, 특정 모듈이나 기능이 완료되는 시점을 기준으로 테스트 결과를 가지고 리뷰를 하는 방법을 사용한다.또한, 위험하거나 의견이 필요한 경우에도 팀 리뷰는 유용하다. 일반적인 팀에서 사용하는 방법이다.하지만, 이 역시. ‘리뷰’에 대한 제대로 된 인식이 없다면, 적용하기 어렵다. 그래서, 가끔 사용되는 방법이고, 과거 국내 SI업체들이 주로 사용하던 방법 중의 하나가 ‘웍쓰로’이다.웍 쓰루(Walkthrough)는 단체로 하는 코드 리뷰 기법 중에 비정형적인 방법으로, 발표자가 리뷰의 주제나 시간을 정해서 발표하고 동료들로부터 의견이나 아이디어를 듣는 시간을 가지는 방법으로써 주로 사례에 대한 정보 공유나 아이디어 수집을 위해서 사용하는 방법이다.이 방법은 ‘특정 도메인’에 종속된 코드를 만들거나, 비슷한 SI성 형태의 업무를 수행하는 경우에 적합하다. 그래서, 국내의 SI업체에서는 적극적으로 사용되면 좋겠지만. 이 ‘시간’마저도 부정확하고, 갑을병정의 SI체게에서 ‘정보공유’나 ‘아이디어 수집’과 같은 커뮤니케이션이 자유롭게 일어나는 것은 매우 힘들다.이 웍 쓰루는 동일한 조직 내에서 동일한 목적의식이 분명한 팀에서나 활용이 가능한 방법이다. 웍 쓰루를 SI에서 시도한 경우에는 대부분 실패했거나, 목적의식이 다르기 때문에 불분명한 결론들이 대부분 도출되었다.대부분의 국내 스타트업이나 IT 전문기업들은 ‘리뷰’에 대해서 상급 관리자들이 제대로 허락을 해주지 않는다.대부분은 팀내에서 어떻게든 자체적으로 해보려고 한다. 그래서, 팀장의 권한 선에서 적절하게 리뷰를 하는 방법 중의 하나가 Peer review or over the shoulder review방법이다. 이 방법은 보통 2~3명이 진행하는 코드리 뷰로 코드의 작성자가 모니터를 보면서 코드를 설명하고, 다른 한 사람이 설명을 들으면서 아이디어를 제안하거나 Defect를 발견하는 방법이다.또한, 이 방법은 신입사원이나 인턴사원의 경우에 업무 이해도를 높이면서 해당 코드를 사용할 수 있는 수준으로 활용할 경우에 의미 있는 방법이다. 문제는 이 방법은 개발자의 인력 투입이 거의 두배 이상으로 증가하는 것으로써, 고품질의 영역을 개발하거나, 빠른 시간 안에 신입 개발자의 업무 이해도를 높이는 경우가 아니라면 시행하지 않는다.이렇게도 리뷰가 진행이 되지 않으면, Passaroud는 돌려 보기 방법을 사용한다. 이 방법은 원래 상세한 리뷰 방법은 아니다. 온라인이나 실시간성이 아니라, 리파지토리나 이메일 등을 사용하여 천천히 리뷰하는 방식에 해당하는데, 속도는 느리지만, 중요한 코드이거나, 제품의 기능 개선이 필요한 경우에는 아주 의미가 있다. 보통은 제품의 기능 개선을 위하여 사용하는 방법이다.이처럼 리뷰의 방법에는 다양한 방법이 있지만, 결론적으로는 어느 정도 개발 조직이 서로  커뮤니케이션하고, 목적의식을 통일하고, 적절한 시간 분배를 통해서 리뷰를 할 수 있는 시간을 만들어 내느냐가 리뷰의 핵심이라고 할 수 있다.리뷰를 통해서 소프트웨어의 품질을  끌어올리고, 개발자들과 소통하고, 방향성을 만들어 내며, 새로운 기능 개선 작업을 위해서 리뷰는 다양하게 활용된다. 어떤 관점으로 리뷰를 할 것이고, 어떤 관점으로 리뷰라는 프로세스를 개발 프로세스에 탑재할 것인가에 대해서 진지하게 고민하는 것. 그것이 아키텍트의 첫 번째 역할 아닌가 한다.
조회수 2463

MySQL의 Transaction Isolation Level (Lock에 관하여)

편집자 주문맥에 따라 ‘Transaction’과 ‘트랜잭션’으로 영어와 한글을 혼용함.문맥에 따라 ‘LOCK’과 ‘lock’으로 대문자와 소문자를 혼용함.OverviewMySQL DB는 일반적인 운영환경에서 뛰어난 성능을 제공합니다. 특히 적은 양의 자료가 빈번하게 교류되는 환경에서는 더욱 빛을 발하죠. 국내에서는 주로 작은 규모의 웹사이트를 구축할 때 MySQL을 사용합니다. 그런데 문제는 사이트의 규모가 커지면서부터 생긴다는 것이죠. 조금씩 느려지는 Query가 생기면 원인도 파악하고, Query를 튜닝하고, 설계도 변경하지만 MySQL의 특징적인 문제를 곧 만나게 됩니다.테이블을 복제(CREATE SELECT)하거나 다른 테이블로 옮기면(INSERT SELECT) 작업을 하는 동안 SELECT 절에 있는 테이블들이 Lock이 걸립니다. 게다가 다른 Session에서 해당 테이블을 수정(UPDATE / DELETE)하면 복제와 이동을 마칠 때까지 대기 상태로 있어야 한다는 것입니다. 이러한 문제는 시스템을 구축하고 자료가 일정량 쌓이기 전까지는 알 수 없습니다. 또한 Oracle과 같은 DB를 사용하던 사용자가, MySQL을 사용하면 이와 같은 문제가 있을 것이라고 생각하기도 어렵습니다.이러한 특징을 가진 MySQL의 Transaction Isolation Level을 알아보고자 합니다. Transaction Isolation Level 은 Transaction의 경리 수준을 말합니다. 트랜잭션 처리 시 다른 트랜잭션에서 접근해 자료를 수정하거나 볼 수 있도록 하는 수준입니다.Transaction Isolation Level의 종류와 특성Transaction Isolation Level에는 READ UNCOMMITTED, READ COMMIITED, REPEATABLE READ, SERIALIZE 네 가지 종류가 있습니다. 1)READ UNCOMMITTED1) COMMIT 되지 않은 데이터에 다른 트랜잭션에서 접근할수 있다.2) INSERT, UPDATE, DELETE 후 COMMIT 이나 ROLLBACK에 상관없이 현재의 데이터를 읽어온다.3) ROLLBACK이 될 데이터도 읽어올 수 있으므로 주의가 필요하다.4) LOCK이 발생하지 않는다.READ COMMIITED1) COMMIT 된 데이터에 다른 트랜잭션에서 접근할 수 있다.2) 구현 방식이 차이 때문에 Query를 수행한 시점의 데이터와 정확하게 일치하지 않을 수 있다.3) LOCK이 발생하지 않는다.4) MySQL에서 많은 양의 데이터를 복제하거나 이동할 때 이 LEVEL을 추천한다.REPEATABLE READ1) Default LEVEL이다.2) SELECT시 현재 시점의 스냅샷을 만들고 스냅샷을 조회한다.3) 동일 트랜잭션 내에서 일관성을 보장한다.4) record lock과 gap lock이 발생한다.5) CREATE SELECT, INSERT SELECT시 lock이 발생한다.SERIALIZE1) 가장 강력한 LEVEL이다.2) SELECT 문에 사용하는 모든 테이블에 shared lock이 발생한다.LOCK과 테이블, 어떻게 해결할 수 있을까?지금부터는 관련된 내용을 확인해보겠습니다. 우선 현재의 경리 수준부터 알아보겠습니다.mysql> SHOW VARIABLES WHERE VARIABLE_NAME='tx_isolation'; +---------------+-----------------+ | Variable_name | Value | +---------------+-----------------+ | tx_isolation | REPEATABLE-READ | +---------------+-----------------+ 1 row in set (0.00 sec) 다음으로 TEST 테이블을 만듭니다. 이때 SELECT절의 테이블을 UPDATE할 경우, 대기 상태로 빠지는 것을 확인해보겠습니다. 테이블을 만들고 상태를 확인합니다.CREATE TABLE test.TB_PROD_BAS_TEST ( PRIMARY KEY (PROD_ID) ) SELECT T101.PROD_ID ,T101.PROD_NM ,T101.PROD_EN_NM ,T101.PROD_MEMO FROM test.TB_PROD_BAS T101 ; -- 생성시 INFORMATION_SCHEMA.PROCESSLIST 로 상태를 확인합니다. mysql> SELECT -> * -> FROM INFORMATION_SCHEMA.PROCESSLIST -> WHERE USER = 'hansj' -> AND COMMAND <> 'Sleep' -> \G *************************** 1. row *************************** ID: 11004 USER: hansj HOST: 192.168.1.150:50711 DB: test COMMAND: Query TIME: 5 STATE: Sending data INFO: CREATE TABLE test.TB_PROD_BAS_TEST ( PRIMARY KEY (PROD_ID) ) SELECT T101.PROD_ID ,T101.PROD_NM ,T101.PROD_EN_NM ,T101.PROD_MEMO FROM test.TB_PROD_BAS T101 1 row in set (0.00 sec) 다음으로 테이블 생성 시 UPDATE를 해 대기 상태로 빠지는지 확인해보겠습니다.UPDATE test.TB_PROD_BAS SET PROD_MEMO = 'TEST' WHERE PROD_ID = 1 ; mysql> SELECT -> * -> FROM INFORMATION_SCHEMA.PROCESSLIST -> WHERE USER = 'hansj' -> AND COMMAND <> 'Sleep' -> \G *************************** 1. row *************************** ID: 11004 USER: hansj HOST: 192.168.1.150:50711 DB: test COMMAND: Query TIME: 24 STATE: Sending data INFO: CREATE TABLE test.TB_PROD_BAS_TEST ( PRIMARY KEY (PROD_ID) ) SELECT T101.PROD_ID ,T101.PROD_NM ,T101.PROD_EN_NM ,T101.PROD_MEMO FROM test.TB_PROD_BAS T101 *************************** 2. row *************************** ID: 11006 USER: hansj HOST: 192.168.1.150:50719 DB: test COMMAND: Query TIME: 22 *****이부분 중요합니다.****** STATE: updating *****이부분 중요합니다.****** INFO: UPDATE test.TB_PROD_BAS SET PROD_MEMO = 'TEST' WHERE PROD_ID = 1 2 rows in set (0.00 sec) 위의 TIME을 보면 테이블이 생성될 때까지 대기하고, UPDATE 문의 상태가 updating 으로 표시됩니다. 하지만 이렇게 나올 경우 건수가 많으면 실제 UPDATE 중인지 대기상태인지 확인하기가 어렵습니다. LOCK이 걸린 테이블을 확인하려면 INNODB LOCK 테이블로 정확하게 알 수 있습니다. 아래 세 가지 테이블로 확인해보겠습니다. 보다 자세한 설명은 MySQL 홈페이지를 확인합니다.information_schema.INNODB_TRXLOCK을 걸고 있는 프로세스 정보information_schema.INNODB_LOCK_WAITS현재 LOCK이 걸려 대기중인 정보information_schema.INNODB_LOCKSLOCK을 건 정보위의 각 항목마다 테이블 생성 및 UPDATE 시 정보가 어떻게 나타나는지 확인해보겠습니다.1.information_schema.INNODB_TRXmysql> SELECT -> T101.TRX_ID -> ,T101.TRX_STATE -> ,T101.TRX_STARTED -> ,T101.TRX_REQUESTED_LOCK_ID -> ,T101.TRX_WAIT_STARTED -> ,T101.TRX_WEIGHT -> ,T101.TRX_MYSQL_THREAD_ID -> ,T101.TRX_ISOLATION_LEVEL -> ,SUBSTR(T101.TRX_QUERY,1,10)AS TRX_QUERY -> FROM information_schema.INNODB_TRX T101 -> ; +---------+-----------+---------------------+-----------------------+---------------------+------------+---------------------+---------------------+------------+ | TRX_ID | TRX_STATE | TRX_STARTED | TRX_REQUESTED_LOCK_ID | TRX_WAIT_STARTED | TRX_WEIGHT | TRX_MYSQL_THREAD_ID | TRX_ISOLATION_LEVEL | TRX_QUERY | +---------+-----------+---------------------+-----------------------+---------------------+------------+---------------------+---------------------+------------+ | 8771591 | LOCK WAIT | 2019-05-27 16:15:53 | 8771591:70031:4:306 | 2019-05-27 16:15:53 | 2 | 11006 | REPEATABLE READ | UPDATE tes | | 8771586 | RUNNING | 2019-05-27 16:15:51 | NULL | NULL | 1538969 | 11004 | REPEATABLE READ | CREATE TAB | +---------+-----------+---------------------+-----------------------+---------------------+------------+---------------------+---------------------+------------+ 2 rows in set (0.00 sec) TRX_ID_STATE트랜잭션의 상태를 나타냅니다. 실행 중인지 LOCK WAIT 상태인지 알 수 있습니다.TRX_MYSQL_THREAD_IDPROCESSLIST 의 ID를 나타냅니다.TRX_ISOLATION_LEVELISOLATION LEVEL을 나타냅니다.따라서 위의 내용을 보면 CREATE TABLE이 실행 중인 것과, UPDATE가 LOCK WAIT인 것, 그리고 관련된 PROCESSLIST의 ID까지도 알 수 있습니다2.information_schema.INNODB_LOCK_WAITSmysql> SELECT -> * -> FROM information_schema.INNODB_LOCK_WAITS T101 -> ; +-------------------+---------------------+-----------------+---------------------+ | requesting_trx_id | requested_lock_id | blocking_trx_id | blocking_lock_id | +-------------------+---------------------+-----------------+---------------------+ | 8771591 | 8771591:70031:4:306 | 8771586 | 8771586:70031:4:306 | +-------------------+---------------------+-----------------+---------------------+ 1 row in set (0.01 sec) requesting_trx_idLOCK WAIT 인 TRX_IDblocking_trx_idLOCK 을 건 TRX_ID현재 LOCK이 걸린 TRX_ID와 LOCK을 걸어둔 TRX_ID를 알 수 있습니다.3.information_schema.INNODB_LOCKSmysql> SELECT -> * -> FROM information_schema.INNODB_LOCKS -> ; +---------------------+-------------+-----------+-----------+----------------------+------------+------------+-----------+----------+-----------+ | lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data | +---------------------+-------------+-----------+-----------+----------------------+------------+------------+-----------+----------+-----------+ | 8771591:70031:4:306 | 8771591 | X | RECORD | `test`.`TB_PROD_BAS` | PRIMARY | 70031 | 4 | 306 | 1 | | 8771586:70031:4:306 | 8771586 | S | RECORD | `test`.`TB_PROD_BAS` | PRIMARY | 70031 | 4 | 306 | 1 | +---------------------+-------------+-----------+-----------+----------------------+------------+------------+-----------+----------+-----------+ 2 rows in set (0.01 sec) lock_trx_idLOCK 과 관련된 TRX_IDlock_modeX 쓰기, S 읽기 2)어떤 테이블이 LOCK을 걸고 있는지 알 수 있습니다.위의 내용들을 통해 REPEATABLE READ에서 CREATE SELECT시 SELECT 테이블에 LOCK이 걸려 UPDATE가 대기하게 되는 것을 알 수 있습니다. 이번에는 Transaction Isolation Level 을 READ COMMIITED로 변경하고 CREATE SELECT 및 UPDATE를 진행해보겠습니다.SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; SHOW VARIABLES WHERE VARIABLE_NAME='tx_isolation'; +---------------+-----------------+ | Variable_name | Value | +---------------+-----------------+ | tx_isolation | READ-COMMITTED | +---------------+-----------------+ 1 row in set (0.00 sec) UPDATE 문은 다음과 같이 수행됩니다. mysql> UPDATE test.TB_PROD_BAS -> SET PROD_MEMO = 'TEST' -> WHERE PROD_ID = 1 -> ; Query OK, 0 rows affected (0.04 sec) Rows matched: 1 Changed: 0 Warnings: 0 기존에 대기했던 것과 다르게 0.04초가 걸렸습니다.mysql> SELECT -> * -> FROM INFORMATION_SCHEMA.PROCESSLIST -> WHERE USER = 'hansj' -> AND COMMAND <> 'Sleep' -> \G *************************** 1. row *************************** ID: 11004 USER: hansj HOST: 192.168.1.150:50711 DB: test COMMAND: Query TIME: 9 STATE: Sending data INFO: CREATE TABLE test.TB_PROD_BAS_TEST ( PRIMARY KEY (PROD_ID) ) SELECT T101.PROD_ID ,T101.PROD_NM ,T101.PROD_EN_NM ,T101.PROD_MEMO FROM test.TB_PROD_BAS T101 1 row in set (0.00 sec) -- 프로세스 정보도 CREATE TABLE 만 진행중임을 알수 있습니다. mysql> SELECT -> T101.TRX_ID -> ,T101.TRX_STATE -> ,T101.TRX_STARTED -> ,T101.TRX_REQUESTED_LOCK_ID -> ,T101.TRX_WAIT_STARTED -> ,T101.TRX_WEIGHT -> ,T101.TRX_MYSQL_THREAD_ID -> ,T101.TRX_ISOLATION_LEVEL -> ,T101.TRX_QUERY -> FROM information_schema.INNODB_TRX T101 -> ; +---------+-----------+---------------------+-----------------------+------------------+------------+---------------------+---------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+ | TRX_ID | TRX_STATE | TRX_STARTED | TRX_REQUESTED_LOCK_ID | TRX_WAIT_STARTED | TRX_WEIGHT | TRX_MYSQL_THREAD_ID | TRX_ISOLATION_LEVEL | TRX_QUERY | +---------+-----------+---------------------+-----------------------+------------------+------------+---------------------+---------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+ | 8771856 | RUNNING | 2019-05-27 17:17:45 | NULL | NULL | 4594347 | 11004 | READ COMMITTED | CREATE TABLE test.TB_PROD_BAS_TEST ( PRIMARY KEY (PROD_ID) ) SELECT T101.PROD_ID ,T101.PROD_NM ,T101.PROD_EN_NM ,T101.PROD_MEMO FROM test.TB_PROD_BAS T101 | +---------+-----------+---------------------+-----------------------+------------------+------------+---------------------+---------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) READ COMMITTED LEVEL로 CREATE만 수행 중인 것을 알 수 있습니다.mysql> SELECT -> * -> FROM information_schema.INNODB_LOCK_WAITS T101 -> ; Empty set (0.00 sec) mysql> SELECT -> * -> FROM information_schema.INNODB_LOCKS -> ; Empty set (0.00 sec) LOCK을 걸고 걸린 것이 없어 내용도 없습니다.Conclusion지금까지 Transaction Isolation Level 을 기준으로 CREATE SELECT 시 SELECT 에 사용되는 테이블도 LOCK이 걸릴 수 있는 것을 확인했고, 그에 따른 해결 방법까지 알아봤습니다.INSERT INTO SELECT에서도 같은 현상이 나타납니다. 그렇기 때문에 운영 중인 테이블을 복제(CREATE SELECT)하거나 다른 테이블로 옮길 경우(INSERT SELECT) Transaction Isolation Level을 READ COMMITTED 변경하고 작업하기를 권장합니다.그렇지 않으면 관련된 TABLE은 LOCK이 걸리고, 관련 Query들이 대기 상태로 빠지면서 시스템 장애가 발생할지도 모릅니다.참고1)MySQL :: MySQL 5.6 Reference Manual :: 14.7.2.1 Transaction Isolation Levels2)MySQL :: MySQL 5.6 Reference Manual :: 14.7.1 InnoDB Locking글한석종 부장 | R&D 데이터팀[email protected]브랜디, 오직 예쁜 옷만
조회수 1444

반복적인 모니터링 프로세스 구축

IT 서비스에 장애가 발생 할 경우 모니터링 프로세스는 장애를 찾는 것으로 끝나지 않습니다. 장애를 발견하는 것은 모니터링 프로세스의 시작 점이며 최종적으로 모니터링을 통해 장애의 근본 원인을 찾아낼 수 있어야 합니다. 그리고 찾아낸 원인들은 예측과 추론에서 확인까지 이르는 하나의 프로세스로 정착되어 다시금 모니터링 과정에 포함되어져야 합니다. 이렇게 서비스를 운영하는 과정에서 근본적인 장애를 찾기 위해 모니터링을 어떻게 이해해야 하는지 알아보겠습니다. 우리가 모니터링 해야 하는 지표어플리케이션 지표(WORK METRICS)- 처리량 지표(THROUGHPUT)- 성공 지표(SUCCESS)- 에러 지표(ERROR)- 성능 지표(PERFORMANCE)시스템 지표(RESOURCE METRICS)- 가동률(UTILIZATION)- 포화상태(SATURATION)- 에러 지표(ERROR)- 이용률(AVAILABILITY)이벤트(EVENTS)- 코드 변경(CODE CHANGES)- 경고 알림(ALERTS)- 규모 변경(SCALING EVENT)- 기타(ETC)IT 서비스를 운영하는 과정에서 발생하는 문제의 근본원인을 추적하기 위한 모니터링 데이터는 크게 3가지로 나눌 수 있습니다. 어플리케이션 지표(Work metrics)서비스의 흐름(트렌젝션)을 측정하여 시스템의 최상위 레벨의 이슈를 보여줍니다. 시스템 지표(Resource metrics)이용률, 상태, 에러 또는 시스템 의존적인 리소스의 이용률을 수량화합니다.이벤트(Events)코드변경, 내부 경고, 확장 이벤트와 같이 드물게 발생하는 불연속적이 이슈를 보여줍니다.일반적으로 IT 모니터링의 핵심 이슈는 어플리케이션 지표를 통해 확인할 수 있습니다. 하지만 다른 지표들 또한 어플리케이션의 지표에서 나타난 문제의 원인을 찾기 위한 중요한 요소이기 때문에 같이 모니터링 해야 합니다. 시스템 지표를 통한 모니터링인프라스트럭쳐는 대부분 시스템의 자원으로 구성됩니다. 최상위 수준에서 유용한 작업을 하는 각각의 시스템들은 다른 시스템들과 연동하기도 하는데요. 예를 들어, 여러분의 아파치 서버가 MySQL 데이터베이스를 자원으로 사용하여 요청을 처리하는 작업을 지원할 수 있습니다. 연관된 작업을 따라 들어가보면 MySQL은 제한된 커넥션 풀을 관리하기 위한 리소스를 가지고 있고 MySQL이 실행되는 서버의 물리적인 리소스 레벨에서는 CPU, Memory, Disk 같은 지표를 보게 됩니다.어플리케이션이 서비스를 제공하는 데 있어서 각각의 리소스가 그 작업을 지원한다면 우리는 장애가 발생한 경우에, 필요한 원인을 얻는 좋은 방법을 시스템을 통해서도 찾아볼수 있습니다. 이런 프로세스를 만들어 간다면 시스템에서 발생한 경고를 통해 장애의 원인을 체계적인 조사하는데 도움이 될 것입니다. 1. 최상위 어플리케이션 지표에서 시작하기첫번째 해야 하는 질문은 "발생한 장애를 설명할 수 있는가?" 이다. 처음부터 문제를 명확하게 정의하지 못하면 이슈를 분석하기 위해 파고들어가야 하는 시스템 패스를 잃어버릴 확률이 높다.다음으로 문제가 있을 것으로 보여지는 최상위 시스템의 작업 지표를 검사해라. 이 지표들은 종종 문제의 원인을 알아내거나 또는 적어도 추적해야 하는 방향을 알려 줄 것이다. 예를 들어 성공적으로 진행된 작업의 성공율이 한계치 이하로 떨어졌다면 에러 지표를 찾아보고 반환된 에러의 형러의 타입을 살펴봄으로써 문제의 방향을 찾아나갈 것이다. 반면에, 대기시간이 길고 외부 시스템에 의해서 요청된 작업처리량이 매우 높다면 시스템 과부하로 인한 문제일 확률이 높다. 다만 와탭의 어플리케이션 분석 서비스를 사용한다면 약간 방법을 달리해도 된다. 와탭의 성능 분포도(어플리케이션 히트맵)와탭의 어플리케이션 성능 분포도를 통해 문제가 발생한 트랜잭션을 드래그하여 선택하게 되면 실제 어플리케이션에서 발생하는 스탭들을 추적하여 문제 해결에 바로 도달할 수도 있다. 하지만 더 복잡한 형태의 장애라면 시스템의 리소스 정보를 찾아봐야 합니다.  2. 리소스 찾아보기최상위 work metrics를 조사하여 문제의 원인을 알수 없다면, 다음으로 시스템이 사용하는 리소스(물리적인 요소 뿐만 아니라 시스템의 리소스 역할을 하는 소프트웨어 또는 외부 서비스)들을 조사합니다. 해당 리소스가 높다면 리소스를 사용하는 하위 Application 지표를 찾아보는 방식으로 찾아나갑니다. 와탭의 데시보드(CPU, MEMORY)3. 변경 내용 찾아보기다음으로 지표에 연관된 경고와 다른 이벤트들을 살펴봅니다. 문제가 발생하기 직전 코드가 릴리즈 되었거나, 내부 경고가 발생하고나 다른 이벤트가 등록되었다면 문제와 연관된 부분을 찾아봐야 합니다. 4. 수정하기 (잊지 말기)문제의 원인을 찾았다면 문제의 원인이 되는 상태를 수정해보고 증상이 사라지는 것을 확인합니다. 증상이 더이상 나오지 않는다면 향후 유사한 문제를 피하기 위해 시스템을 어떻게 변경할지 고민해야 합니다.  서비스가 중단된 상황이 오면 1분이 중요합니다. 문제를 찾는 속도를 높이기 위해 눈앞에서 벌어진 상황에 대한 높은 집중력을 유지하면서 대쉬보드를 상황에 맞춰 재 조정합니다. 최상위 어플리케이션 데쉬보드와 각각의 서브시스템들을 위한 대시보드를 하나씩 설정합니다. 시스템 대시보드는 시스템 지표의 하위 시스템의 키 메트릭스와 함께 어플리케이션 메트릭을 확인 할 수 있어야 합니다. 이벤트 데이터도 이용가능한 상황이라면 연관 분석 차트에서 관련된 이벤트가 올라가 있어야 합니다. 와탭의 알림 서비스정리하기   서비스에 장애는 무조건 발생하지만 우리는 모니터링을 통해 빠르게 해결 할 수 있습니다. 이를 위해 표준화된 모니터링 프로세스를 만들고 대시보드로 연관관계를 만들어 놓는다면 문제를 빠르게 추적 조사할 수 있습니다. 가능하면 모든 지표는 어플리케이션 지표에서 부터 찾을 수 있도록 대시보드를 구성합니다.인프라스트럭처를 통해서도 문제를 분석할 수 있습니다. 시스템에 대해 대시보드를 설정하고 주요 지표들을 올려놓아야 합니다. 문제의 원인을 조사하는 것은 증세가 나타나는 최상위 시스템에서 부터 시작합니다. 문제가 되는 리소스가 발견되면 문제를 발견하고 수정할 때가지 리소스에서 발견되는 패턴을 조사하고 적용시키는작업을 반복해야 합니다. #와탭랩스 #개발자 #개발팀 #인사이트 #경험공유 #일지
조회수 2524

사운들리 코드 품질 관리 이야기

안녕하세요 "사운들리"입니다 :)오늘은 사운들리의 코드 품질 관리에 대해 이야기 해보려 합니다.몇몇 개발자에게는 지루하고 악몽같은 이야기일 수 있겠네요.제 경우에는 예전에는 이런 품질이라는 단어를 멀리했지만 결국 제가 작성한 코드에 발목을 많이 잡히다 보니, 자연스레 관심을 갖게 되었습니다.일단, 어떤 소프트웨어가 좋은 품질의 소프트웨어일까요?좋은 품질이란? 책에 나올법한 내용을 보면, 아래와 같은 항목을 토대로 소프트웨어 품질을 판단한다고 합니다.ISO/IEC 9126 : Software engineering - Product qualityFunctionality: 명시된 요구사항을 잘 충족했는지Reliability: 명시된 조건과 시간 아래에서 일정 성능을 유지 하는지Usability: 사용하기 위해 어느정도의 노력과 자원이 필요한지Efficiency: 소모 자원과 성능간의 효율Maintainability: 수정하기 위해 어느정도의 노력이 필요한지Portability: 다른 환경에서도 사용 할수 있는지출처: https://en.wikipedia.org/wiki/ISO/IEC_9126 뭔가 복잡해 보이지만, 결국 개발자라면 위의 항목은 누구나 추구하게 되는 가치라고 생각 합니다.그런데 말입니다. 이런 좋은 내용을 마음 속으로만 간직한 채 코드를 작성하면 정말 좋은 소프트웨어를 만들 수 있을까요? 저는 객관적인 방법으로 코드를 평가한다면 좋은 피드백이 될 것이라고 생각합니다. (물론 이 성적표를 남에게 보여주는 것과는 다른 문제에요 ㅎㅎ)어떻게 품질을 체크하는가 소프트웨어의 품질을 체크하는 데에 다양한 방법과 툴이 제시되고 있는데요, 저는 크게 두 가지로 분류 해보겠습니다.유저 입장의 품질: 유저의 요구사항에 맞는 소프트웨어인지 체크개발자 입장의 품질: 내가 지금 이 코드를 의도한 대로 잘 작성하고 있는지 체크 유저 입장의 품질은 언급하지 않아도 중요함을 누구나 알고 있습니다. 이 부분이 만족이 되지 않으면 제품이 아니죠! 그래서 저는 개발자 입장에서 스스로 챙길수 있는 품질을 사운들리는 어떻게 챙겨보고 있는 지 이야기 해보도록 하겠습니다. 실은 제가 개발자 입니다 ㅎㅎ사운들리 개발자의 코드는 아래와 같이 흘러갑니다.<그림1> 사운들리 코드 개발상의 품질 관리 순서도간단히 각 항목을 훑어 보겠습니다.Local Machine 각자 갖고 있는 맥북으로, 다양한 IDE를 사용해 코딩합니다. 그리고 git 을 이용해 commit 하고, github 에 push 하죠.Github push 된 수정사항은 pull request 를 통해 동료에게 알려집니다. 이후 코드리뷰를 통해 merge 하게 됩니다. 코드리뷰는 많은 사람들에 의해 그 중요성이 부각되고 있습니다. 사운들리는 같은 모듈을 만드는 개발자끼리, 그리고 다른 모듈에 영향을 주는 코드일 경우에는 해당 모듈의 개발자도 리뷰를 합니다. 코드리뷰를 통해 다른 사람이 어떤 기능을 작성했는지 보고, 오류도 찾고, 더 좋은 방법이 있으면 공유도 하고, 칭찬도 하고, 훈수도 두고 합니다. 참고로 사운들리는 git-flow 정책에 따라 git branch를 운영하고 있습니다.Jenkins  Github 에 commit 이 등록되면 Jenkins 는 자동으로 빌드를 시작 합니다. Jenkins 는 단순 빌드 성공 실패를 떠나서, 코드 품질에 대한 몇가지 report 를 발생 시킵니다. 아래에서 좀더 자세히 다뤄보겠습니다.SonarQube Jenkins 에서 빌드하면서 SonarQube 에 포함된 분석 기능을 사용하게 됩니다.그렇다면, 코드 품질의 지표는 무엇일까요?Jenkins가 발생시키는 레포트를 통해서 알 수 있는 내용은 아래와 같습니다.코딩 스타일 체크 결과: 작성된 코드가 미리 정의된 코딩 스타일에 맞게 작성되어 있는지?Unit Test 결과: 유닛 테스트 결과 (당연히 전부 pass 해야겠죠)Test code coverage 결과: 테스트 코드가 전체 코드의 몇 % 를 커버 하고 있는지 (우리의 최종목표는.. 60%.. 덜덜덜)정적 분석 결과: 코드를 실행하지는 않지만, 코드 그 자체에서 발생할 수 있는 결함을 찾아줍니다. 이 네 가지 레포트는 객관적 수치를 나타내주기 때문에 일종의 코드 품질 지표로 삼을 수 있습니다. 물론 이 지표만 잘 관리 했다고 해서 좋은 코드를 작성했다고 말할 수는 없습니다. 다만 좋은 코드를 작성하기 위한 기초 중의 기초라고 볼 수 있겠죠 :)품질 체크를 위한 툴(tool)은 개발 언어에 따라 다를 수 있습니다. 사운들리에서는 다양한 언어로 소프트웨어가 작성되어 있습니다. 따라서 언어마다 위의 결과를 얻기 위해서 서로 다른 툴을 사용하고 있습니다. AndroidJavaJavascriptC/C++코딩 스타일checkstylecheckstyle jshintcppcheckUnit testjunitjunitmochagoogletestCode coveragejacococoberturamocha-covgcov정적 분석sonarqubesonarqube sonarqubecppcheck 각 개발자는 위의 네 가지 결과를 얻기 위해서 빌드 시스템에 툴을 포함하여 개발하고 있습니다. 제가 주로 개발하고 있는 java 언어에 해당하는 툴들을 좀 더 자세히 살펴보겠습니다.checkstyle코딩 스타일을 체크 해줍니다. xml 파일로 미리 정의 되어있고요. 매번 빌드할때마다 스타일이 틀린것을 지적해 줍니다.코딩 스타일은 중요합니다. 같이 개발하는 개발자와 코딩 스타일이 같다면 마치 내가 작성한 코드처럼 쉽게 읽을 수 있죠.junitjunit 은 자바 유닛 테스트 프레임워크 입니다. 유닛 테스트 코드를 편하게 작성하게 해주고, 쉽게 테스트 결과를 볼 수 있습니다.유닛 테스트 코드를 작성하면 내가 작성한 모듈을 작은 단위로 테스트 해서, 작은 로직에서 발생하는 시시콜콜한 문제를 방지 할 수 있습니다. 테스트 코드를 작성해서 검증한 부분은 스스로도 신뢰가 갑니다.기능 수정간에 유닛 테스트에서 fail 이 나는 경우가 발생하는데, 모르는 사이에 다른 모듈에 영향을 준 것을 알게 됩니다. 다른 모듈에 모르고 영향을 주게 되면 뒷처리가 어려워지잖아요~coberturacode coverage 를 계산해 주는 툴입니다.유닛 테스트 코드가 실행되면, 작성된 코드의 각 부분을 실행하게 됩니다. cobertura 는 이때 각 코드의 어느부분이 실행되었는지 확인해서 통계를 내줍니다.주로 line coverage / branch coverage 두 지표를 보는데요, line coverage 는 해당 라인이 한번이라도 실행 되면 check 되고, branch coverage 는 각 라인에 있는 조건문을 다 따로 check 합니다. 당연히 branch coverage 를 달성하는게 어렵겠죠?sonarqube소나큐브는 다양한 plug-in 을 통해서 정적 분석을 하고, 시각화를 해주는 툴입니다.사운들리는 주로 정적 분석 용도로만 소나큐브를 사용하고 있습니다. (지원하는 plug-in 을 보면 젠킨스와 기능이 겹치는 부분이 있습니다.)정적분석으로 실제 문제가 되는 부분을 찾는 경우도 있고, minor 한 부분에 대한 지적을 하는 경우도 있습니다. 그러나 이런 minor 한 부분도 꼼꼼하게 잘 챙겨야 좋은 개발자가 된다고 믿고 있습니다.마치며 여기까지 사운들리의 코드 품질 관리에 대해 이야기 해보았습니다. 품질 관리를 해보신 분은 아시겠지만, 이런 툴을 쓰다보면 항상 행복하게 코드 품질을 관리할 수는 없습니다. 매달 세워놓은 목표를 달성하기 위해서 뼈를 깎는 노력으로 테스트 코드를 작성해야 되고, 당장 기능 수정해서 배포해야 되는데, 작성해 둔 테스트 케이스가 Fail 되어 말썽을 부릴 수도 있습니다. 그렇지만 객관적 기준으로 코드 품질을 관리하다보면 어느샌가 큰 노력없이 좋은 코드를 작성하는 개발자가 되지 않을까 생각해 봅니다. 코드 졸면서 막 짜도 style warning 0건/ 정적분석 오류없음 / 테스트 코드 기본 탑재 뭐 이런 개발자 말입니다 ㅎㅎ 다른 개발자분들은 어떻게 자신이 작성한 코드의 품질을 관리하고 있는지 궁금하네요.알고 계신 좋은 방법이 있다면 언제든지 공유 부탁드리겠습니다~!#사운들리 #개발자 #개발 #인사이트 #조언 #개발후기 #후기
조회수 1836

소프트웨어 개발자에게 성공이란...

소프트웨어 개발자들이 생각하는 ‘성공’이라는 단어와 키워드에는 어떤 것들의 의미를 포함하고 있을까? 한편으로는 단편적이고 획일적인 ‘성공’이라는 단어에 너무 많은 개발자들이 매몰되어 있는 것 아닌가 하는 생각을 해본다. 필자 스스로 실무경력 20년을 넘겨서 소프트웨어 개발을 하고 있는 경험을 바탕으로 주변의 성공한 개발자들에 대해서 혼자 생각해 보았다.일반적으로 의미의 ‘성공’이라는 것이 무엇을 의미하는 것인가에 대한 정의는 이번 칼럼의 말미에서 이야기하도록 하자. 정말 많은지 모를 대한민국에서 성공한 개발회사나 개발된 서비스들을 살펴보는 것부터 시작을 하는 것이 정답인지는 필자도 잘 모르겠다. 성공적인 서비스나 소프트웨어, 프로그램은 세상에 선보인다는 것. 그러한 것을 만들어낸 순수한 아이디어나 원천기술로 무장한 기술로 축적되었고, 그 아이디어를  뛰어넘어, 새로운 기술이라고 할 수 있는 것을 보유한 제품이나 상품들이 얼마나 되는지에 대해서부터 냉정하게 필자는 잘 모르겠다라고 먼저 인지하고 넘어가자. 아니, 다시 말하자면, 냉정하게 국내에서 그런 것을 본적이 별로 없는  듯하다.더욱더 삐딱하게 이야기하자면, 국내에서 성공한 개발 서비스들은 대부분 아류작이거나 남의 아이디어를 도용한 제품과 서비스들이 대부분이 아닌가라고 생각한다. 심지어는 특정 솔루션 시장은 오픈소스를 그대로 제품에 반영해 두고서는 자신의 제품인 것처럼 위장하는 사례까지 보이고 있으니, 과연 대한민국 소프트웨어 시장은 과연 얼마나 ‘성공’이라는 키워드를 그대로 사용해도 되는지에 대해서 매우 의문시된다.(물론, 필자의 삐딱한 시선에서만 그렇게 보일지도 모른다.)대한민국의 소프트웨어 시장에서 1위를 지키고 있다고 하는 서비스와 제품들이 되려면 어떻게 해야 하는가?. 삐딱하게 이야기하자면, 오로지, 대한민국에서 성공한 개발회사나 개발자가 되려면, 창의적인 아이디어나, 독특한 아이디어로 무장하는 승부수를 던지기 보다는, 해외의 서비스 중에 알차고, 괜찮은 것들에 대해서 관심을 가지는 것이 중요하다고 생각한다. ( 그래서, 영어공부를 잘해야 하는지도 모르겠다. )필자가, 대기업과 신규사업기획을 할 때에 작업하는 내용을 보고서는 경악을 금치 못했던 경험을 한적이 있다. 정말 상당한 컨설팅 금액( 수십억을 넘긴 비용 )을 지불해서, 대기업이 유명한 컨설팅업체를 통해서 신규사업에 대한 기획과 아이디어에 대한 컨설팅을 받는 것에 전문가의 한 사람의 참여했었다. 그런데, 그 중요한 작업의 모티브는 해외에서 이미 성공적으로 안착한 서비스에 대한 분석과, 한국에서의 서비스 시에 벌어질 일에 대해서 예측을 하는 일을 하고 있었다는 점이다. 새로운 아이디어가 아니라는 점이다.물론, 성공한 서비스를 도입해서, 로컬 화한다는 것 또한 매우 어려운 일이라고 생각하지만, 대부분의 새로운 기획이나 신규 서비스에 대한 작업들의 대부분을 이런 식으로 진행한다는 이야기를 들었을 때에 받은 충격은 정말 놀라운 경험이었다, 물론, 지나고 나서 생각해보니, 그렇게 놀랄만한 경험도 아니었는지 모르겠다. 대부분의 대기업들이 이런 식으로 한다는 이야기를 듣고 더 놀라기는 했지만. 물론, 이렇게 로컬화 한다는 것 자체도 대단한 도전이고 어려운 점이라는 것은 인정한다고 하지만, 이런 로컬화와 아류작에 대해서 비판적인 시야를 가진 필자의 생각은 그렇다.성공한 서비스들은 대부분 아류작들이다?냉정하게 국내에서 성공한 대부분의 서비스들은 아류작들이고, 복제본들이고, 독창적인 아이디어보다는 해외 서비스를 대부분 국내에 안착한 서비스라고 생각한다. 심지어 독창적인 mp3 플레이어마저도, 아이팟의 생태계가 한층 더 발전적인 시장을 창출했으니, 국내에서 만들어진 디지털적인 요소들 중에 독창적인 것이 얼마나 있는가?필자는 생각한다. 예술에 있어서 복제와 창작의 차이는 매우 크다는 것을. 물론, 소프트웨어 개발이 이런 예술에 비견될 정도의 가치를 부여해서 그런 것 만은 아니다. 소프트웨어 개발은 아이디어와 구현하고자 하는 추진력과 열정이 결합되어져서 만들어지는 최고의 가치 구현을 위한 세계이기 때문에 그렇게 생각할 뿐이다.필자가 좋아하는 만화 중에 ‘맛의 달인’이라는 만화에 나온 표현을 그대로 옮기자면 다음과 같은 장면이 나온다. 프랑스의 유명한 요리를 그대로 일본에서 구현하지만, 그 요리에 대한 평가는 ‘프랑스의 요리를 그대로 구현한 요리이다’. ‘매우 아름답지만 최저의 요리’라는 평가를 받는다. 그러한 최저의 요리라는 평가를 받은 이유는 ‘로컬화 한다는 것은 실정에 맞게 고치고, 연구 개발한 맛이라면 완벽하겠지만. 너무도 프랑스 요리와 똑같이 만든 것은 처절한 아류라는 점이다. 지금 먹은 요리에는 프랑스 요리사의 모습이 그대로 남아있다는 점. 원형이 프랑스의 것을 그대로 답습했다는 것.오리지널을 복사했다는 냉정한 평가는 정말 명확하다. 요즘 가장 국내에서 최근에 성공한 서비스를 이야기한다면, 카카오톡과 애니팡을 예로 들 수 있겠다. 다른 사람들은 어떻게 평가할지 모르지만, 정말 대단한 성공을 가진 것은 사실이다. 하지만, 둘 다 원형을 그대로 복사했을 뿐, 새로운 것은 아무것도 없다는 점이다. 아니, 오히려. 기존의 원형을 대한민국의 안 좋은 통신사의 서비스와 결합한 케이스라고 평가를 해야 정확하지 않을까 한다. 원형을 오히려 퇴보시킨 서비스라고 평가하고 싶다.카카오톡은 WatsApp을 그대로 복제했다. 대표적으로 등록되어진 전화번호로 연계하는 원형의 아이디어를 그대로 받아들였다. 하지만, 카카오톡의 새로운 신규 비즈니스 모델인 게임센터는 자체적인 생태계를 만들어서 통제하려 하는 기존의 통신사의 방식과 그다지 차이가 없다고 보인다. 뭐, 돈을 벌어야 하는 기업의 입장을 반대하는 것이 아니다. 단지, 필자의 삐딱한 시선으로는 진보를 위한 선택이 아니라, 퇴보를 위한 선택이었다는 점이 불편할 뿐이다.애니팡도 마찬가지이다. 기존의 게임방식을 그대로 복제했다. 그리고, ‘하트’라는 이름으로 무분별한 ‘스팸’을 활성화해서, 기존 통신사들이 SMS에서 얻어들이는 대량 SMS 발송을 통한 이익을, 그대로 실현한 점이다.물론, 카카오톡이나 애니팡의 ‘이익 실현 구조’는 매우 성공적으로 국내에 론칭한 것은 사실이고, 이러한 구조로 ‘돈’을 벌어야 한다는 점이 매우 안타까울 뿐이다. 개인적으로는 ‘국내’에서는 어느 정도 ‘돈을 버는 성공은’할 수 있지만, 해외에서까지 성공적으로 론칭할 것인지는 조금 의심스럽다. ( 어차피, ‘돈’을 벌면 성공이라는 관점으로는 매우 대성공이다. )넥슨의 카트라이더와 마리오 카드와 같이 일일이 나열하기에는 너무도 많은 사례들이 있어서 굳이 더 나열하지 않겠다.다만. 정말 중요한 것은 복사보다는 진짜가 더 좋다는 점이다. 가령, 오리지널이 존재하는 영역이나 예술과 같은 고부가가치의 영역에서는 ‘화가나 작가가 다른 사람의 작품을 흉내내면  웃음거리밖에 되지 않는다’는 점을 이야기하고 싶다. 필자 개인적으로는 ‘그런 웃음거리를 통한 수익실현’을 그렇게 높게 평가하고 싶지 않기 때문이다.대표적으로 통신사는 ‘스팸’과 ‘보이스 피싱’을 해결하지 못하는가? 에 대해서 필자는 그렇게 생각한다. ‘대량 SMS수입’을 포기하지 못하고, ‘전화번호를 통한 대량 통화의 수익’을 포기하지 못하는 구조적인 문제 때문에 그렇다고 생각한다.과거에 문제가 된 iOS6로 업데이트가 되면서 SKT 아이폰4S에서 발생한 전화번호 호출의 문제, ‘112 신고가 안 되는 아이폰’이라는 기사와 사건에 대한 문제의 근본적인 원인은 SKT가 국제표준 방식을 따르지 않아서 발생한 문제라는 것을 모르는 사람들이 정말 많다. 이 문제를 더 파고들어가면, 부당한 SMS수입을 얻고 있는 국내 통신사들의 부도덕한 점도 드러난다. 2003년 이후 3G 서비스(WCDMA)가 도입되었지만, 문자 메시지 국제표준이 기존의 80 byte에서 140 byte로 늘어났지만, 정작 통신사들은 국제표준규격을 지키지 않으면서 연간 수백억의 이익을 부당하게 얻어냈다. 다만. 아이폰4s 출시 당시 KT는 140바이트를 맞추었지만, SKT는 아직도 80 byte였다는 점을 예로 들고 싶다.국제표준을 따르거나, 해외의 서비스가 ‘돈’이 되는 것에는 빠르지만, ‘돈’이 안 되는 기준에는 미온적이고, 대처가 느린 것에 대해서는 참으로 훌룡(?)한 성공적인 방법이라고 평가를 굳이 필자와 같은 주변 사람이 할 필요가 있을까 한다. 그런 훌륭한 평가는 비싼 컨설팅 비용을 지불한 뛰어난 전문가들이 할 것이기 때문에...내 주변에 성공한 개발자와 성공한 벤처 사업가...성공한 개발자. 고급 승용차를 몰고, 출근하는 개발자의 모습을 본다면, 성공한 개발자의 향기를 느낄 수 있을까? 물론, 일반적으로 그럴 수 있다고 생각한다.자본주의 사회에서 ‘돈’은 그 사람을 평가하는 가장 기본적인 ‘수단’이기 때문이다. 성공하지 못한 필자는 아니지만, 필자 주변에는 고급 승용차인 BMW나 벤츠를 직접 몰고 다니는 성공한 개발자들이 여럿 있다. 그리고, 상당히 많다. 사업을 하는 사람으로부터, 프리랜서인 사람까지 매우 다양하다.분명, 그들은, 자신만의 서비스와 제품을 실현하였고, 시장에서도 안정적인 자신만의 브랜드를 확립하였고, 후배들로 존경을 받고 있으며, 직원들에게 비전과 꿈을 주고 있으며, 새로운 기술과 시장에 대해서 언제나 도전하고 있는 사람들이 있다.그들은 충분히 ‘성공’한 사람들이다.‘복제’와 ‘아류작’이 아니더라도. 독특한 자신들만의 서비스와 제품을 구현하여 성공한 개발자들이 분명 존재한다.그들의 성공요인을 주변의 사람으로서 살펴본다면, 몇 가지의 요인이 있다고 정의할 수 있다. 그것들을 필자의 주관적인 생각으로 정리해보면, 크게 4가지 정도로 정리할 수 있다고 본다.하나. 그들은 뛰어난 개발자는 아니었다.그들은 아주 탁월한 능력을 소유한 개발자들은 아니었다는 점이다. 그리고, 아주 뛰어난 학벌을 가진 개발자들도 아니었다. 개발자 동호회에서 만난 친구도 있고, 직장생활이나 사회생활에서 만난 사람도 있었지만. 그들은 아주 탁월한 재능을 지녔거나, 엄청난 코딩능력, 뛰어난 직관을 지닌 사람만은 아니었다.순수한 개발 능력만 놓고 본다면, 오히려, 뒤처지는 개발자들이었는지도 모른다. 하지만, 뛰어난 개발자들이나 아이디어를 가진 사람들과 친하게 지냈으며, 그들의 도움을 자연스럽게 얻어내는 소통의 달인은 아니었지만, 개발자 커뮤니티에 매우 즐겁게 활동을 하던 사람들이었다.둘. 그들은 우직하지만, 묵묵하게 자신의 상품과 아이디어를 다듬었다.그들은 하나의 아이디어가 실현되는 것을 쉽게 포기하지 않았다. 사업을 하기 전에는 그 아이디어를 실현하기 위해서 애썼고, 속한 회사가 아이디어에 대해서 낮은 평가를 하는 것에 대해서도 크게 실망하지 않았다. 오히려, 반대를 해도 해당 서비스와 제품, 기술에 대한 애정이 정말 높았으며, 그것을 실현하려고 매우 애썼다.처음에는 언제나 소프트웨어는 단순한 것부터 시작한다.그 단순한 것을 꾸준하게 다듬고, 소프트웨어에서 제품으로 다듬어서 시장에서 가치를 인정받을 수 있도록 수년 이상을 투자하고 노력해야만 얻어진다. 그것은 스티브 잡스도 똑같았다. iOS는 하루 이틀 만에 나온 소프트웨어가 아니기 때문이다.심지어, 몇 년 동안 밥을 굶더라도, 자신이 생각하는 가치를 실현하기 위해서 포기하지 않고 도전했던 우직한 도전이 오히려 성공을 만들어 내었다. 분명, 훌륭한 소프트웨어는 뛰어난 기술로 만들어지는 것만은 아니다는 것을 요 근래에서야 필자도 느낀다.필요한 가치가 적정한 가격에 구현되어진 것이 정말 필요하다는 점이다. 뛰어난 기술이 뛰어난 제품을 만드는 것이 아니라, 뛰어난 제품이 뛰어난 기술을 만든다는 것이다. 그것이 사용자들로 하여금, 또 다른 가치를 얻을 수 있는 기능을 제공한다는 것에 대해서 굳이 설명하지 않더라도, 그들은 그 아이디어와 생각을 실현하기 위해서 자신만의 길을 걸었다.정말 우직할 정도로... 필자 주변의 그들은, 몇 년을 일 년에 몇백만 원을 벌더라도, 그 꿈을 포기하지 않았다.셋. 시장과 세상의 시선을 그렇게 두려워하지 않았다. 자신의 ‘가치’와 ‘비전’을 실현했다.자신의 아이디어와 자신의 서비스, 제품을 지키기 위해서 약간의 주변 사람들에게 욕을  얻어먹는 것을  두려워하지 않는다. 필자가 아는 어떤 기업은 시장에서는 냉혈안이라는 말도 듣고, 불법 복제된 제품에 대해서는 가차 없는 소송도 불사하는 어떤 기업을 알고 있다. 하지만, 그 회사와 그 사장에 대해서 필자는 비난하지 않는다. 왜냐하면, 그는 기업 내부의 직원들에게는 절대 급여를 밀리지 않고, 야근을 시키지 않는 최고의 사장이었기 때문이다.시장과 타인에게는 가차 없지만, 자신이 생각한 비전을 실현한 회사를 만들기 위해서 언제나 최선을 다하는 사람이었을 뿐이다. 그리고, 자기 것을 지키기 위해서 애를 썼고, 직원들과의 거리도 언제나 적절하게 유지했다. 냉정하게 기업과 사업이라는 것은 자선사업이 아니라는 것을 잘 알고 있었다. 충분하게 돈을 벌고, 외제 승용차를 사장은 타고 다니지만 ( 외제 승용차를 타는 것도, 대한민국은 간단하다. 법인세를 충분하게 낼 정도로 수익이 생기면, 그 수익으로 차를 리스해서 타면 간단하다는 대한민국의 세법 구조 때문이다. ), 모든 직원들에게 그 이익을 100% 나누어주지는 않는다. 직원은 직원일 뿐이니까.그들은 회사의 재정이 힘들어지면 소속된 직원을 힘들기 전에 내보낼 줄도 알고, 필요하다면... 해고도 그리 어렵지 않게 결정하는 사람도 있다, 영업기밀을  들고나간 직원과 소송도 불사했다. 차라리, 친구와 따로 술을  마실지언정, 직원들과의 ‘관계’는 냉정하고 쿨한 관계를 유지했다. (물론, 그렇지만. 인간관계가 깨어지는 것을 매우 괴로워하는 사람들이다. 다만, 아래 직원들에게 속시원히 이야기를 못할 뿐이다. )넷. 필요한 기술자나 기술은 기필코 얻으려 노력했다.그들은 자신이 부족한 점을 잘 이해하고 있었다. 부족한 것을 오히려, 더 널리, 많이 이야기를 하였다. 그리고, 그것을 커버하기 위해서 매우 많은 노력을 한다. 다 잘하고자 하는 팔방미인이 되는 것이 아니라, 자신이 부족한 점을, 자신이 가장 잘하는 것으로 커버하려 애쓴 것이다. 전문적인 기술을 소유한 사람에게 도움 요청하는 것을 부끄러워하지 않고, 도와준 사람에게 충분한 대우나 접대를 잊지 않았다. 그래서, 그들이 도와달라고 하면, 주변의 전문가들이 아낌없이 그를 도와준다.그 이외에서 그들은 그렇게 ‘성실’하게 일하는 친구들은 아니었다. 실제, 사장이었던 그들이 직원의 입장으로 회사를 다닐 때에는 근태 문제로 지적을 받은 친구들도 꽤 많다는 점이다. 아마도, 사업이나 자신이 좋아하는 일을 하는 것과, 어떤 일이 주어진 상태에서 일을 하는 것은 분명 다른 지도 모르겠다. 직원일 때에 불성실하지만, 자신의 일을 할 때에 성실한 것은 전혀 상관관계가 없어 보인다. 한편으로는 ‘사장’이나 ‘자신의 일’을 하는 사람의 경우에는 특별하게 ‘근무시간’이라는 것 자체는 큰 의미가 없다는 점이 더 정답일 것이다. 하여간, 그들은 성공한 개발자들이고, 성공한 기업인이 되어 있었다. 자신만의 제품이나 서비스를 만들면 자연스럽게 ‘사장’이 되어버리는 것이 소프트웨어 업계의 현실인 듯하다.그렇다면, 대한민국에서 ‘성공’이란 ‘돈’을 의미하는가?강남의 최고급 아파트와 외제 승용차가 성공을 의미할까?자신의 뛰어난 기술력으로 커뮤니티에서 인정받고, 유명해진 명예를 얻는 것이 성공을 의미할까? 다른 사회현상을 생각하면서 다시 한번 비교해보자.요즘 개발자들도 오디션 프로에 영향을 받은 듯하다. 요즘 연예계 지망자들이나 배우나, 가수를 꿈꾸는 친구들이 선배나 멘토들에게 묻는 것이 언제나 똑같다고 한다.그것은 ‘빠르게 성공’하고 ‘빠르게 명예’를 얻는 방법이 무엇이냐 묻는 것이다.어렵고 복잡하고, 길게 걸리는 방법은 무시하고, 오디션 프로에서 1등을 해서, 빠르게 성공하는 방법만을 생각한다고 한다.물론, 그 방법도 있을 것이다.소프트웨어의 세계에도 똑같은 방법이 있다. 대표적인 방법이 유명대학을 가서, S 멤버쉽이 되고, 대기업에 입사해서 경력을 쌓은 다음, 해외의 서비스를 적당하게 분석하다가, 성공적으로 론칭한 서비스를 재빠르게 국내에 도입해서 성공에 이르게 하는 방법이 아마도 가장 빠른 방법일 수 있겠다.물론, 이 방법으로 ‘성공’을 쟁취하려 하는 개발자라고 하더라도. 비난하지 않는다.분명, 그 길은 대다수 ‘성공’이라고 부른다. 하지만, 그 길을 선택하고 집중하는 것 또한 매우 어렵고 힘든 길이다. 선택한다고 얻을 수 있는 길도 아니다.가령, 이 글을 읽는 독자가 학생이라면. 가장 먼저 명문대학을 가는 것부터 시작해야 할 테니, 당장, 이 내용을 덮어버리고, 국영수를 공부하는 것에 몰두해야 하기 때문이다.사실, 가장 넓게 알려진 성공으로 가는 길은 가장 가기 어려운 길인지도 모른다. 경쟁이란 정말 어렵고 힘들 것이라는 것을 잊지 말자.본론으로 다시 돌아와 보자. 개발자로서 '성공'이란 무엇을 의미하는가? 아니, 개발자로서 비전을  갖는다는 것은 무엇을 의미하는가?  원천적으로 개발자의 삶이란 어떻게 살아야 하나요라고 묻는다면,이 문제는 정말 어렵고, 사람마다 다르기 때문에 최선을 다하는 것이 정답이라라는 교과서적인 답변만 늘어놔야 하는지도 모르겠다.이점에 대해서는 이제는 폐간했지만 오랫동안 개발자들의 벗이 되었던 마이크로소프트웨어 잡지에 대해서 원망을  슬쩍해보자.그것은, 나에게 ‘정말 대단히 큰 재미’를 선사했다는 것이 나에게 가장 처음 다가온 충격이었는지도 모른다. 처음에 가진 꿈은 그냥, ‘소프트웨어 개발’을 통해서 삶을 영유할 수 있는 것만으로 나는 행복했다는 점이다. 그래서, 이 소프트웨어의 세계로 진입하게 된 마이크로소프트웨어에 대해서 원망을 해야 하는지도 모르겠다.하지만 필자는 소프트웨어로써 ‘개발자로서 성공’을 하기 위해서, 이 직업과 삶을 선택한 것이 아니라, ‘개발자로 살기 위해서’이 삶을 선택한 것이었다. 나이를 먹고, 무언가를 목표로 살아온 경험을  되돌아본다면, ‘돈’과 ‘명예’를 선택하지 않았을 때에, 오히려, ‘돈’과 ‘명예’를 얻지 않았는가 하다. 오히려, ‘돈’을 선택하던 시기에 ‘돈’을 더 많이 잃어버린 경험도 가지게 되었다.이제는 주변을  되돌아보면, 필자는 꽤 넓은 스펙트럼을 가지게 되었다는 것을 느끼게 된다. 한때는 고인이 되셨지만 대통령이셨던 분부터, 수천억을 소유한 재벌 총수, 의료재단과 대학법인을 소유하신 분, 병원의 원장님들을 비롯한 분들을 비롯하여, 출판계, 영화계, 물론. 다수의 소프트웨어 개발자들까지. 매우 넓은 사람 관계를 만들어본 것 같다.그중에 소프트웨어 개발자들은 참 착하고 바보스러운 사람들이 많은 것 같지만, 한편으로는 너무도 욕심이 많은 사람들이 존재하는 참, 신기한 동네이다.그리고, 여러 계층을 경험해보니. 모든 계층은 똑같이 피라미드 구조를 가지고 있다는 점이다. 대부분 다 똑같았다. 하층의 사람들은 싼 가격에 노동력과 지식을 제공하고, 상위 레벨에서는 적절한 대우 이상과 재미있고 신기한 일들을 많이 한다는 점이다. 이 부분은 어느 계층이나 똑같다.대표적으로 출판일을 경험했을 때에 자신의 이름이 들어간 편집장이 되는 사람과, 그것을 목표로 기획자로 일하는 직원의 급여 수준이나 처우, 대우는 정말 최고급 아키텍트와 SI 개발자를 비교하는 것 이상으로 그 상대 감은 소프트웨어 개발세 상의 것 이상으로 매우 컸다.행복한 개발자라고 한다면, ‘개발이 정말 재미있고’, ‘개발도 잘하고’, ‘소프트웨어 개발 피라미드의 상층부의 일’을 하고 있다는 사람이 있다면. 그 사람은 정말 행복할 것이다. 뭐, 그런 사람은 이 글을 읽고 있지도 않을 것이다.그러나, 개발이 재미있지 않거나, 개발을 뛰어나게 잘하지도 못하고, 소프트웨어 개발 피라미드의 하층부에서 일하고 있다면, 어떻게 생존해야 하는 가에 대해서 정말 심각하게 고민해야 한다.이 글을 읽는 독자가 이제 개발자의 길을 시작한 사람이라면 고민해라, 소프트웨어 개발을 비롯한 모든 전문적인 직업들은 새로운 것을 배우고, 익히고, 소모하면서 계속 변화되는 것을 즐길 줄 알아야 재미있는 직업이다. 그런 것이 아니라면, 정말 힘들고, 피곤하고 어려운 것이 전문직과 같은 직업이다. 만일 그런 것이 힘들다면 다른 일을 알아보는 것이 현명하다.소프트웨어 개발자들과 가장 비슷하게 일하는 웹디자이너들의 푸념이 있다.‘낮은 급여에 야근은 허구한 날, 거기에. 불투명한 미래’에 대한 그들의 이야기를 들으면서, 흔히 소프트웨어 개발자들은 그 질문에 답변한다. ‘너희들은 모니터라도 크지’라고. 대부분의 프로젝트들은 ‘분석’에 의해서 ‘일정’을 만들지 않고, ‘일정’을 통해서, ‘품질’을 선택한다고 봐야 한다.‘정말 하고 싶은 것이 무엇인가?’개발자들에게 물어보면, 대부분 당황하는 경우가 많다. 이것은 개발자이기 때문에 답변을 못하는 것이 아니라, 자신의 비전이나 꿈에 대해서 명쾌하게 정의하지 못하고 있기 때문이다. 주변의 초보 개발자들에게 이야기하고 싶은 점은...가끔은 수필집이나 여행기, 그리고. 다른 사람의 생각과 꿈에 대한 글을 많이 읽어보라고 권하는 것이다. 그러면, 그 비전과 꿈에 대해서 이야기해달라는 사람들이 꽤나 있고는 하다.문제는 그 비전은 누가 정해주는 것이 아니라, 자신이 생각하거나, 자신이 발견하는 것이 옳지 않냐고 다시 이야기를 해준다. 물론, 이렇게 이야기하는 사람도 있다.‘저는 이번 프로젝트에서 인정을 받아서, 다음 프로젝트를 수행할 때에는 팀장이 되고 싶어요!’라고 이야기할 수 있다. 하지만, 이런 ‘단기적인 비전’을 말하는 것은 아니다. 이런 ‘단기적인 비전’만을 따라가다 보면, 냉정하게 수단만 중요시 여기게 되고, 목적 자체를 잃어버린 인생의 방랑자가 될 가능성이 매우 크다.내가 생각하는 ‘성공’이란 과연 무엇인가?또 하나는, 그 ‘성공’의 목표를 너무 작게 가져도 문제이고, 너무 커도 문제라는 점이지만, 그래도, ‘꿈’과 ‘목표’가 있다는 것 자체가 재미있고, 신기하지 아니한가?‘성공은 자신이 정한 것을 이루는 것’을 의미한다고.그럼 ‘꿈’을 어떻게 정의하나요?1. 10년, 20년, 30년 후의 자신의 모습을 상상해보고 정의해봐라.2. 현재 내가 좋아하는 모든 것들을 적어봐라.3. 내가 가장 잘하고 가장 인정받는 것을 적어봐라.보통은 이렇게 끄적거리다 보면, 무언가가 조금은 구체적인 비전이 나올 수도 있지만, 아무렇지도 않은 것이 나올 수 있다. 하지만, 일단, 끄적이기 시작했다면, 다음번에는 좀 더 잘할 수 있다는 것이 중요하다. 가장 중요한 것은 ‘내가 비전에 대해서 생각하기 시작했다’는 점이다. 일단 작심 3일이라도 중요한 결정이다. 그것은, ‘결정’을 하고 ‘결심’을 하기 시작했다는 것이기 때문이다.일단, ‘써야 한다’. ‘생각은 생각일 뿐이다’주변의 개발자들이 가장 잘 못쓰는 말 중의 하나가 ‘머릿속에 다 있다’라는 말이고, ‘글로 쓰기에 너무 어려운 이야기’이다라는 이야기가 가장 잘못된 것이라는 것을 잘 모르는 경우가 많다.‘머릿속에 다 있다’라는 이야기는 한번 생각은 해봤으나, 결론을 내리지 못하였다는 이야기로 들리고, ‘글로 쓰기 어렵다는 이야기’는 그만큼 정리가 안되고, 그 일에 대해서 잘 모른다는 이야기와 똑같다.10년 20년 특정 도메인에서 일한 베테랑이라고 하는 개발자와 일을 할 때에, 자신이 하는 일은 너무도 복잡하여, 설계도나 다이어그램, 순서도, 타이밍 차트 등을 그릴 수 없다는 사람들이 있다.그들과 이야기하고, 그 업무를 다이어그램과 설계도로 만들어 주어도, 그들은 그것 말고, 설명이 안 되는 그 무언가가 있다고 이야기를 한다. 물론, 필자는 그때에 이렇게  이야기해준다.‘만일 그러한 것이 존재한다면. 그것은 당신만이 생각하는 경험이나 당신이 소중하게 생각하는 가치인지 모른다. 하지만, 그것은 어떤 지식이 되기에 매우 부족한 것일 수 있다. 지식은 설명하기 쉽고, 이해하기 쉬운 것이 지식이다. 설명하기 어려운 경험은 정규화되거나 전달되어지기 매우 어렵다’더 쉽게 이야기하면. ‘쉽게 설명하거나 글자로 남기지 못한다면, 당신은 그것에 대해서 잘 알고 있지 못한 것입니다’비전이나 목표 잡기가 너무 어려워요?!그렇다면, 당장 휴일에 컴퓨터를 내버려두고, 아이폰이나 패드와 같은 스마트하다고 우기는 디지털기기를 집안에 던져두고 여행을 떠나는 것이 현명한 방법이겠다. 그리고, 다른 매체를 들여다보고, 개발자 이외의 사람들을 만나서 이야기해보라라고 권유해야 하는 것이 맞을  듯하다.생각 이상으로 소프트웨어 개발자의 세계는 정말 좁다. 그리고, 단편적인 지식들과 단편적인 경험들만이 존재하는 세상인지도 모른다. 그래서, 소프트웨어 개발자들은 ‘관심의 폭을 넓히고,’ ‘자신을 확장’하는 것이 결론적으로는 더 뛰어난 개발자가 된다는 것을 나중에야 깨달을 것이다. 마지막으로 이야기한 한다면, 소프트웨어 개발자에게 ‘성공’이란 일단... 전혀 해보지 않았던 것을 도전해보는 것, 그리고. 삶은 소프트웨어 개발처럼 버전을 나누어서 설명하기 어렵다는 것을 이해하고. 무언가 계속 새로운 것에 도전한다는 것이 진정한 ‘성공’ 아닌가 한다.#와탭랩스 #와탭 #개발자 #개발 #프로그래머 #성공 #성공한개발자
조회수 9484

AWS 비용 얼마까지 줄여봤니?

최근 들어 스타트업의 인프라는 DevOps의 유행과 함께 IDC에서 클라우드로 급속도로 이전해가고 있습니다. 많은 클라우드 업체가 있지만 그중에서도 Amazon Web Service (AWS) 가 가장 선호되고 있고 잔디도 AWS를 이용하여 서버 인프라를 구성하고 있습니다. 하지만 AWS 비용은 예상보다 만만치 않습니다. 잔디에서는 비용을 줄이기 위해 여러 가지 노력을 하고 있는데 이 글에서는 스케쥴링 기능을 이용하여 비용을 줄이는 방법에 대해 공유하도록 하겠습니다.AWS는 저렴한가?AWS는 ‘저렴한 비용’을 자사 서비스의 큰 강점이라고 홍보하지만 실제 사용해보면 막상 ‘과연 정말 저렴한가?’ 라는 의문을 가지게 됩니다. 여러 클라우드 업체의 비용을 비교한 리포트를 보더라도 AWS는 절대 저렴하지 않습니다. 오히려 클라우드 업체 중 가장 비싼 곳 중 하나입니다. 그렇다고 이제 와서 클라우드 업체를 옮기는 건 배보다 배꼽이 더 클 수도… (들어올때는 맘대로지만 나갈땐 아니란다.)예약 인스턴스? 스팟 인스턴스? 온디맨드?AWS에서는 제공하는 요금 할인 방법은 예약 인스턴스나 스팟 인스턴스를 이용하는 것입니다.예약 인스턴스는 계약 기간에 따라 최대 60%까지 저렴한 가격으로 이용할 수 있습니다. 하지만 정확한 기간과 수요예측을 하지 못한다면 잉여 인스턴스가 될 수 있습니다.스팟 인스턴스는 입찰가격을 정해놓고 저렴할 때 이용할 수 있습니다. 하지만 그때가 언제일지도 알 수 없고 인스턴스를 가져갔다고 하더라도 더 높은 입찰가격을 제시한 사용자에게 인스턴스를 뺏길 수 있습니다. 마치 KTX를 입석 티켓으로 빈 좌석에 앉아서 가다가 좌석 티켓 주인이 나타나 ‘내 자린데요?’ 하면 얄짤없면 좌석을 내줘야 하는 느낌입니다. 그때 느끼는 그 서러움은 느껴보지 못한 자는 알 수 없습니다.온디맨드는 사용한 만큼 할인 없이 비용을 지불하는 것입니다. 언제든지 필요할 때 사용하고 사용한 만큼만 과금되어 가장 적절해 보이지만 예약이나 스팟에 비해 역시나 비쌉니다. 비싸지만 현실적으로 가장 많이 사용됩니다.개발서버는 얼마 안쓰는데 좀 깍아줘!일반적으로 개발서버도 라이브와 같이 구성합니다. 고가용성은 고려하지 않더라도 아키텍쳐는 똑같이 구성하게 됩니다. 그리고 아키텍쳐가 복잡해질수록 구성하는 서버도 많아지고 언제부턴가는 개발서버도 비용을 무시할 수 없는 수준에 이르게 됩니다. 하지만 개발서버는 24시간 사용하지도 않고 업무시간에만 사용합니다. 이쯤 되면 한 번쯤 이런 생각을 하게 됩니다. ‘개발서버는 실제로 얼마 쓰지도 않는데 좀 깍아줘야 되는 거 아냐?’ 개발서버뿐만 아니라 정해진 시간만 사용하는 모든 서버들이 해당될 것입니다.EC2 SchedulerAWS는 이러한 원성(?)을 들었는지 EC2 Scheduler 라는 간단한 솔루션을 소개했습니다. 내용을 보면 설정된 시간과 요일에 자동으로 EC2 인스턴스가 자동으로 켜지고 꺼집니다. 하루 10시간 가용한다면 주말 제외 월~금요일만 작동시켜 비용을 70%나 절감할 수 있습니다.이대로만 된다면 왠만한 스팟이나 예약 인스턴스보다 더 저렴하게 개발서버를 이용할 수 있습니다. 하지만 이 솔루션을 그대로 도입하기에는 문제점들이 있었습니다.EC2 Scheduler 의 문제점EC2 Scheduler는 다음과 같은 문제점들이 있습니다.서버 아키텍쳐에 따라서 의존성이 있어 서버 실행 순서가 보장되어야 하는 경우가 고려되지 않는다.단순히 EC2 한두 대 띄워서 사용하는 게 아니고 훨씬 더 복잡한 서버 의존 관계를 가지게 됩니다. 예를 들어 DB -> Middleware -> API -> Batch 같은 관계가 있다고 한다면 의존관계에 있는 서버들이 순차적으로 실행되어야 합니다.스케쥴 시간이 UTC로만 작동한다.UTC로만 작동하기 때문에 시간 설정을 할 때는 항상 UTC 기준으로 변환해야 하는 불편함이 있습니다.스케쥴링의 예외적인 상황이 고려되지 않는다.평일이 공휴일인 경우에는 서버를 작동할 필요가 없고 평소보다 서버를 일찍 켜야 하거나 야근을 하게 되어 중지 시간을 변경해야 되는 경우에는 해당 일자에만 변경이 가능해야 했습니다.EC2에 대해서만 작동하도록 되어 있다.EC2보다 비싼 RDS도 최근에 Stop 시킬 수 있도록 추가되었습니다. Aurora는 미지원잔디의 서버 아키텍쳐는 훨씬 복잡하여 서버의 실행 순서가 맞지 않으면 정상작동을 하지 않기 때문에 1번은 반드시 해결되어야 하는 가장 치명적인 문제였습니다.AWS Instance SchedulerEC2 Scheduler의 문제점을 보안한 Instance Scheduler를 소개하겠습니다. EC2나 RDS 모두 하나의 서버를 Instance로 부르기 때문에 Instance Scheduler라 하였습니다. Instance Scheduler는 Serverless 아키텍쳐인 Cloudwatch + Lambda를 이용하여 구성되어 있습니다.작동방식Cloudwatch Event를 이용하여 Lambda를 함수를 실행시키고 Dynamo DB에 저장된 스케쥴 정보와 Instance의 Tag 값을 기반으로 RDS와 EC2를 조회하고 Instance를 시작하거나 중지합니다. 그리고 JANDI의 Incoming Webhook을 이용하여 토픽에 알림 메시지를 보내줍니다.Cloudwatch EventInstance Scheduler Lambda 함수를 작동시키는 트리거는 Cloudwatch Event를 이용합니다. 5분마다 작동시키도록 되어 있으며 각각의 사용 환경에 따라 변경할 수 있습니다.Cron 식 0/5 * * * ? *, 대상은 Instance Scheduler Lambda를 지정합니다.Dynamo DBDynamo DB에는 Schedule, Schedule 예외 설정, Schedule 서버 그룹에 대한 정보가 정의되어 있습니다.1. ScheduleSchedule 작동에 대한 기본 정보를 정의하고 있습니다.{ "ScheduleName": "Development", "TagValue": "Development", "DaysActive": "weekdays", "Enabled": true, "StartTime": "09:30", "StopTime": "22:00", "ForceStart": false } ScheduleNameSchedule 이름 입니다.TagValue적용 대상 Instance를 조회할 때 참조하는 Tag 값입니다. Instance를 Schedule에 적용 대상에 포함시키기 위해서는 해당 Instance의 Tag에 ScheduleName이라는 Key에 TagValue를 Tagging 하면 됩니다.DaysActiveSchedule 적용 요일입니다. 아래와 같은 옵션이 적용됩니다.all : 매일weekdays : 월~금mon,wed,fri : 월,수,금요일EnabledSchedule의 작동 여부입니다.StartTime, StopTime서버 시작 시간과 중지 시간입니다.ForceStartSchedule 강제 시작 여부를 나타냅니다. (Enabled 여부에 상관없이 작동합니다.)2. Schedule Server Group하나의 Schedule에는 N 개의 서버 그룹을 정의할 수 있고 각각은 먼저 실행되어야 하는 의존관계 서버 그룹을 정의하고 있습니다. 의존관계에 있는 서버 그룹의 Instance Status를 확인하여 시작 여부를 결정하도록 하였습니다. 그러면 의존관계가 없는 서버 그룹부터 시작하고 의존관계의 Depth 가장 깊은 서버 그룹은 가장 늦게 시작하게 되어 서버 실행 순서를 보장하게 됩니다.{ "Dependency": [ "GROUP1", "GROUP2", "GROUP3", "GROUP4" ], "GroupName": "GROUP5", "InstanceType": "EC2", "ScheduleName": "Development" } Dependency의존관계 서버 그룹 목록입니다.GroupName서버 그룹 이름입니다.InstanceTypeEC2와 RDS를 지원합니다.3. Schedule Exception공휴일이나 야근 등으로 인해 스케쥴을 미작동 시키거나 시간을 변경해야 하는 경우에 예외사항들을 정의하고 있습니다.{ "ExceptionUuid": "414faf09-5f6a-4182-b8fd-65522d7612b2", "ScheduleName": "Development", "ExceptionDate": "2017-07-10", "ExceptionType": "stop", "ExceptionValue": "21:00" } ScheduleName예외 적용 대상 Schedule의 이름입니다.ExceptionDate예외발생일 (YYYY-MM-DD)ExceptionTypestart : 시작stop : 중지ExceptionValueNone : 미작동H:M : 변경시간LambdaInstance Scheduler의 Lambda 코드는 Python으로 개발되었으며 Github에 오픈소스로 공개하였습니다. boto3는 배포 package에 Dependency를 추가하지 않아도 Lambda 실행환경에서 가용 라이브러리로 사용할 수 있습니다. 하지만 현재 기본적으로 사용할 수 있는 boto3 버전에서는 RDS Instance를 stop 할 수 있는 함수가 없기 때문에 최신 버전이 필요합니다. 따라서 boto3 버전을 변경하여 함께 packaging 하여 업로드하여야 합니다. 배포는 Lambda 관리 도구인 Apex를 이용합니다. Apex를 이용하면 Dependency package 및 Lambda 생성 및 업데이트, 환경 변수 설정 등을 모두 한 번에 할 수 있습니다.참조 : Lambda Execution Environment and Available LibrariesAWS SDK는 Python boto3 (botocore:1.5.75, boto3:1.4.4) 를 이용합니다.TimeZone 설정Lambda는 기본적으로 UTC TimeZone으로 설정되어 있으며 Instance Scheduler에서는 TimeZone을 변경할 수 있도록 하였습니다. 기본 설정은 Asiz/Seoul이고 아래 코드를 수정하여 변경할 수 있습니다.os.environ['TZ'] = 'Asia/Seoul' time.tzset() JANDI 메신저와 연동Instance Scheduler는 JANDI 메신저의 Incoming Wehbook 을 이용하여 Webhook URL을 Lambda의 환경 변수에 설정하면 서버의 시작과 중지에 대한 알람과 중지 10분 전부터 곧 서버가 중지된다는 알람을 발송하여 필요하다면 서버 중지 시간을 연장할 수 있도록 합니다.Incoming Webhook 설정JANDI의 토픽에서 Incoming Webhook을 연결하고 Webhook URL을 복사합니다.배포된 Lambda 함수의 Code 탭에서 Environment variables에 WEBHOOK_URL을 설정하거나 function.json에서 변경 후 재배포 하여도 됩니다.Instance Scheduler 알람서버 그룹이 시작되면 아래와 같이 알람 메시지를 표시합니다.서버가 중지되기 전에 알람 메시지를 표시합니다.정리Instance Scheduler는 EC2 Scheduler에 비해서 다음과 같은 기능이 추가되었습니다.스케쥴 시간의 타임존 적용서버 그룹 설정 및 의존관계 설정스케쥴의 예외 설정RDS 스케쥴 추가스케쥴에 상관없이 강제 시작 및 중지메신저로 상태 알람EC2 Scheduler에 비해 아쉬운 부분이나 예외사항에 대해서 좀 더 유동적으로 대응할 수 있도록 개선하였습니다.다음 장에는 스케쥴을 컨트롤을 위한 Bot 적용기를 소개하도록 하겠습니다.#토스랩 #잔디 #JANDI #AWS #서버개발 #개발 #개발자 #개발팀 #경험공유 #인사이트 #후기 #일지
조회수 1749

변화하는 웹 플랫폼 따라가기

플랫폼이 어떻게 변화해가는지를 살펴보면, 직접 경험해보지 않더라도 사람들의 문제의식이 어디에 있는지, 어떤 문제들이 언제부터 풀리게 되는지를 파악할 수 있습니다.이 글에서는 이런 변화들을 살펴볼 수 있는 몇가지 유용한 링크들을 소개하려고 합니다.어떤 논의들이 어디서 오가고 있을까WICG discoursehttps://discourse.wicg.io/WICG는 웹 인큐베이터 커뮤니티 그룹이라고 해서, 웹 표준에 기여해본 사람이 아니라도 토론을 통해 아이디어를 발전시켜서 사람들이 실제로 겪는 문제를 W3C 표준까지 끌어올리는 것을 목표로 하는 커뮤니티입니다.이 곳에서는 주로 CSS, DOM API에 대한 아이디어가 올라옵니다.ES-Discusshttps://esdiscuss.org/ES-Discuss는 WICG와 비슷하게 ECMAScript 스펙에 대해서 논의하는 메일링 리스트입니다. 위 링크는 메일링 리스트에서 오간 이야기를 쉽게 조회할 수 있도록 아카이빙 해놓은 사이트입니다.논의된 아이디어는 어디서 표준으로 다듬어지고 있을까HTML: https://github.com/w3c/html 또는 https://github.com/whatwg/htmlCSS: https://github.com/w3c/csswg-draftsJS: https://github.com/tc39/ecma262HTML은 W3C의 WebPlat WG와 WHATWG에서, CSS는 W3C의 CSSWG에서, JS는 ECMA의 TC39에서 표준을 이끌고 있습니다.위 저장소들에 공개된 초안은 표준이 되기까지 여러 단계를 거치게 되는데, 여기서 다루지는 않겠습니다. (2018-01-25 수정) 이에 대한 내용은 다음의 블로그 포스트에서 자세히 설명하고 있습니다.W3C 표준화 제정 단계ECMAScript와 TC39다듬어진 표준은 어떤 브라우저에서 얼마나 구현되고 있을까다음의 링크에서 각 주제에 대해 브라우저들이 현재 어디까지 구현을 했는지 파악할 수 있습니다.Chrome: https://www.chromestatus.com/featuresFirefox: https://platform-status.mozilla.org/Edge: https://developer.microsoft.com/en-us/microsoft-edge/platform/status/Safari: https://webkit.org/status/크롬 플랫폼 사이트의 경우 각 주제들이 어떤 버전에 반영되었는지 같이 확인할 수 있어서 편리합니다.나머지 브라우저들의 버전별 구현 상태는 https://caniuse.com/에서 주제를 검색하여 참고할 수 있습니다.구현된 기능들은 언제부터 사용할 수 있었고, 언제부터 사용할 수 있게 될까크롬과 파이어폭스는 릴리즈 캘린더를 공개적으로 관리하고 있습니다. 위에서 확인한 기능들을 담고있는 안정 버전이 언제쯤 릴리즈 될 지 다음의 링크를 보고 대략적으로 예상할 수 있습니다.Chrome: https://www.chromium.org/developers/calendarFirefox: https://wiki.mozilla.org/RapidRelease/Calendar크롬과 관련된 플랫폼 따라가기특정 크롬 버전이 어떤 V8 버전을 사용하고 있는지는 https://omahaproxy.appspot.com/에서 확인할 수 있습니다.Node.jsNode.js의 릴리즈 스케쥴은 https://github.com/nodejs/Release에서 확인할 수 있습니다.어떤 Node.js 버전이 어떤 V8 버전을 사용하고 있는지는 https://nodejs.org/en/download/releases/에서 확인할 수 있습니다.Electronhttps://electronjs.org/에서 일렉트론 최신버전이 어떤 노드, 크로미움, V8 버전을 사용하고 있는지 확인할 수 있습니다.일렉트론의 크로미움 팔로업은 깃헙 일렉트론 저장소의 Projects에서 확인할 수 있습니다: https://github.com/electron/electron/projects따라가는데 도움이 되는 블로그브라우저 벤더들이 직접 운영하는 블로그를 구독하면 웹 플랫폼의 소식을 가장 빠르게 접할 수 있습니다.ChromeChromium Blog: https://blog.chromium.org/V8 Blog: https://v8project.blogspot.kr/FirefoxMozilla Hacks: https://hacks.mozilla.org/SafariWebKit Blog: https://webkit.org/blog/EdgeMicrosoft Edge Dev Blog: https://blogs.windows.com/msedgedev/(2018-01-25 수정): @SaschaNaz님 제보로 Webkit status 사이트와 Edge 블로그 추가#스포카 #개발팀 #개발자 #인사이트 #업무일지 #후기
조회수 1048

컴공생의 AI 스쿨 필기 노트 ⑥인공신경망

인공지능, 머신러닝, 딥러닝이번 6주차 AI 스쿨에서는 딥러닝의 가장 기초적인 부분을 배웠어요. 인공지능과 머신러닝, 그리고 딥러닝을 많이 들어보긴 했는데 이 셋의 차이는 무엇일까요?인공지능이라는 개념은 1956년 미국 다트머스 대학에 있던 존 매카시 교수가 개최한 다트머스 회의에서 처음 등장했고 최근 몇 년 사이 폭발적으로 성장하고 있는 중이에요. 1956년 당시 인공지능의 선구자들이 꿈꾼 것은 최종적으로 '인간의 지능과 유사한 특성을 가진 복잡한 컴퓨터'를 제작하는 것이었죠. 이렇듯 인간의 감각, 사고력을 지닌 채 인간처럼 생각하는 것을 인공지능이라고 해요.인공지능은 위 세 개념 중 가장 큰 개념이에요. 머신러닝은 일반적으로 사람들이 이야기하는 인공지능, 즉 머신러닝에 기반한 인공지능을 말하는데요. 인공지능을 구현하는 구체적인 접근 방식이라고 할 수 있어요.머신러닝에는 linear regression, logistic regression 등의 여러 알고리즘이 있는데요.  그중 학습에 사용되는 모델을 딥러닝이라고 해요. 즉 딥러닝은 완전한 머신러닝을 실현하는 기능이라고 볼 수 있어요. 이러한 딥러닝의 등장으로 인해 머신러닝의 실용성은 강화됐고 인공지능의 영역은 확장됐다고 해요.인공 신경망(Neural Network)오늘 수업의 핵심인 인공 신경망(Neural Network)은 어떻게 만들어졌을까요?뉴런의 구조이것은 우리 몸에 존재하는 신경세포인 뉴런이에요. 뉴런은 전기적인 신호를 전달하는 특이한 세포인데 뇌는 뉴런의 집합체라고 할 수 있어요. 뉴런은 수상 돌기(dendrites, input)에서 신호를 받아들이고 축색 돌기(axon terminals, output)에서 신호를 전송해요. 신호가 전달되기 위해서는 일정 기준(임곗값 : threshold) 이상의 전기 신호가 존재해야 해요. 이 신호들의 전달을 통해서 정보를 전송하고 저장해요.이런 신경세포로 이뤄진 신경망 시스템을 위의 그림처럼 표현할 수 있어요. 이처럼 인공신경망은 사람 몸속의 신경들을 모방해서 만든 시스템이에요.위의 식처럼 뉴런을 수학적으로 표현할 수 있는데요. 입력 값들(X)에 가중치를 두어(W) 값 (f(x))을 구하고 그 값과 임계치와의 관계를 활성함수(active function)*로 판단하여 결괏값을 출력하게 돼요.( * 활성함수는 인공신경망의 개별 뉴런에 들어오는 입력신호의 총합을 출력 신호로 변환하는 함수로 비선형 함수(non-linear function)를 씁니다.**)이때 활성함수는 뉴런에서 임곗값을 넘었을 때만 출력하는 부분을 표현한 것으로 sigmoid 함수, Relu 함수 등 여러 방식이 있어요.인공 신경망의 구조인공 신경망 구조는 위의 그림처럼 나타낼 수 있어요. 인공 신경망 구조는 입력층(input layer), 은닉층(hidden layer), 출력층(output layer)으로 이루어져 있어요. 위의 그림은 그 구조에 의해 3-layer Neural Network 또는 2-hidden-layer Neural Network라 부를 수 있는데요. 3-layer Neural Network는 3개의 층을 가지는 인공신경망이라는 뜻이고, 위 그림에서는 은닉층1, 은닉층2, 출력층이 해당되겠죠. 인공 신경망에 입력층과 출력층은 항상 존재하기 때문에 은닉층의 개수만을 고려하여 부르기도 해요. 위 그림에서는 은닉층이 2개 있기 때문에 2-hidden-layer Neural Network라고 부를 수 있어요. 전파(Propagation)이번에는 실제로 학습하는 과정인 인공신경망의 알고리즘에 대해 알아볼게요. 순전파(Forward Propagation)와 역전파(Backward Propagation)가 있어요.순전파는 입력값에서 출력값으로 가중치를 업데이트를 하고 활성화 함수를 통해서 결괏값을 가져오는 것을 말해요. 인공신경망이 설계된 정방향(input → hidden → output)으로 데이터가 흘러가기 때문에 순전파라고 해요. 말 그대로 입력값을 앞쪽으로 보낸다고 생각하면 돼요.역전파는 출력값을 통해서 역으로 입력값 방향으로 오차를 다시 보내며 가중치를 재 업데이트하는 것이에요. 출력값에서 계산된 오차에 가중치를 사용해 바로 이전 층의 뉴런들이 얼마나 오차에 영향을 미쳤는지 계산해요. 결과에 영향을 많이 미친 뉴런일수록 더 많은 오차를 돌려줘요.개념을 코드에 적용하기NumPy로 구현된 Neural Network(이하 NN)의 작동 방법을 살펴볼게요. NN은 총 2개의 레이어로 이루어져 있어요. 이번 과제에서는 입력 x가 들어왔을 때, 레이블에 따라 예측치가 1로 수렴하는지 알 수 있는 인공신경망을 구현하는 것이 목적이에요.Neural Network다음 코드는 simpleNueralNet() 클래스를 나타내는 코드예요. simpleNueralNet()은 두 개의 레이어로 구성된 NN이에요.N, D_in, H, D_out = 64, 1000, 100, 10- N은 batch size, 즉 한 번에 처리할 수 있는 데이터 사이즈를 말해요. - D_in은 입력값 차원에 쓰이는 값으로 1000을 할당해요.- H는 은닉층 차원에 쓰이는 값으로 100을 할당해요.- D_out은 출력값 차원에 쓰이는 값으로 10을 할당해요.아래 코드를 통해서 랜덤 입력과 출력 데이터를 만들어요.x = np.zeros((N, D_in))     #1  x.fill(0.025)                         #2y = np.ones((N, D_out))   #31. np.zeros() 함수를 사용하여 (64, 1000)의 차원을 갖는 0인 행렬을 만들어요.2. fill() 함수를 통해 x 안의 모든 0을 0.025로 바꿔요.3. np.zeros() 함수를 사용해 (64, 10)의 차원을 갖는 0인 행렬을 만들어요.아래는 랜덤 값을 갖는 가중치(weight)들을 초기화하는 코드예요. w1은 1000, 100 차원의 랜덤 값을 갖는 행렬로, w2는 100, 10차원의 랜덤 값을 갖는 행렬로 만들어요.w1 = np.random.randn(D_in, H)   w2 = np.random.randn(H, D_out)learning_rate는 학습 속도를 의미해요. 아래는 단계별로 움직이는 학습 속도를 1e-6으로 정의하는 코드예요.learning_rate = 1e-6이제 5000번의 순전파를 할 거예요.h = x.dot(w1)     h_relu = relu(h)  y_pred = h_relu.dot(w2)h는 은닉층에 전달할 값이에요. x와 w1을 행렬곱한 값을 가져요.활성 함수 relu에 h를 넣어서 계산해요.y_pred는 예상되는 출력값이에요. relu로 계산된 h_relu와 가중치 w2를 행렬곱한 값이에요.아래는 순전파로 얻은 y_pred에서 진짜 y를 뺀 값을 제곱한 것의 합을 구해 손실 값(loss)을 구하는 코드예요. print(loss) 코드로 손실을 확인할 수 있어요.loss = np.square(y_pred - y).sum()순전파 후 역전파를 이용해 손실에 대한 가중치 w1과 w2의 gradients를 계산하여 update 할 거예요.grad_y_pred = 2.0 * (y_pred - y)              #1grad_w2 = h_relu.T.dot(grad_y_pred)    #2grad_h_relu = grad_y_pred.dot(w2.T)    #3grad_h = grad_h_relu.copy()                    #4grad_h[h < 0>grad_w1 = x.T.dot(grad_h)                         #61. 순전파로 얻은 y_pred에서 진짜 y값을 뺀 값에 2.0을 곱하여 grad_y_pred를 구해요.2. grad_w2는 순전파에서 y_pred = h_relu.dot(w2) 식을 사용했으므로  h_relu.T.dot(grad_y_pred) 로 구해요. h_relu가 반대로 곱해지기 때문에 T를 이용하여 shape을 바꿔줘야 해요.3. grad_h_relu는 방금 위에서 사용한 y_pred = h_relu.dot(w2)을 이용하여 grad_y_pred.dot(w2.T) 로 구해요. 이번에는 w2 shape의 반대를 grad_y_pred에 곱해줘야 해요.4. 순전파에서 h_relu = relu(h)였는데요. 역전파에선 grad_h와 grad_h_relu가 같기 때문에 copy() 함수로 그대로 복사해요!5. 0보다 작은 h는 0으로 만들어요.6. 가중치 w1의 값인 grad_w1은 순전파의 h = x.dot(w1)와 반대로 x.T.doT(grad_h) 곱해요. 역전파는 순전파의 식에서 이항한다고 생각하면 조금 더 쉽게 이해할 수 있을 것 같아요. 이항한 값은 .T를 붙여서 표현한다고 생각하면 될 것 같아요.아래는 가중치를 재업데이트하는 코드예요.w1 -= learning_rate * grad_w1 w2 -= learning_rate * grad_w2 과제1을 통하여 NN을 알아보았는데요. 복잡하지만 순전파와 역전파를 알고 있다면 많이 어렵지는 않은 것 같아요. 과제 2는 정확도를 95% 이상으로 만들어보는 과제인데 여러 가지 방법을 동원해서 풀어보는데 생각보다 쉽지가 않아요. ^^;이번 수업시간에 배운 딥러닝의 기초인 신경망은 굉장히 중요한 개념이라고 해요. 신경망을 기반으로 한 딥러닝을 강화하여 안면인식을 가능하게 하거나 저장된 데이터를 정확하게 인식하고 분류할 수 있는 기기들도 만들어지고 있어요. 이처럼 AI는 점진적으로 활용 범위가 넓어지고 있기 때문에 이 수업을 통해 쌓은 AI 지식을 마음껏 뽐낼 수 있는 날이 왔으면 좋겠어요!** 왜 활성함수로 비선형 함수를 쓸까요?선형함수인 h(x)=cx를 활성함수로 사용한 3-layer 네트워크를 생각해봐요. 이를 식으로 나타내면 y(x) = h(h(h(x)))가 되는데요.  이는 y(x) = c3x와 같습니다.  이렇게 활성함수로 선형함수를 사용하면 은닉층을 사용하는 이점이 없어요.* 이 글은 AI스쿨 - 인공지능 R&D 실무자 양성과정 6주차 수업에 대해 수강생 최유진님이 작성하신 수업 후기입니다.
조회수 1473

크몽 gulp 개선기

안녕하세요. 프론트개발자 bk입니다 :)이 글은 gulp사용법에 대한 글이 아닙니다. build 자동화 도구를 개선할까 말까 고민하는 개발자들을 위해 제 경험을 공유드리려 합니다.음... build 자동화 꼭 해야 해..?가 아닙니다. 크몽이라는 서비스가 어떤 개발 환경을 통해 만들어졌는지, 좀 더 편하고 효율적으로 개발 생활을 즐기기 위해 어떻게 개선을 했는지에 대한 개발 경험을 나눠 보려고 합니다.왜 이 작업을 하게 되었고 뭐가 그리 중요했는지, 크몽 개발 환경에서 gulp가 개선되어야 했던 이유에 초점을 맞추었습니다.시작에 앞서본격적인 gulp에 대한 이야기를 하기 전에 왜 내가 크몽에 입사하자마자 gulp를 개선해야겠다 마음먹었습니다.크몽에서의 개발크몽에 입사한 지 이제 3개월이 되었습니다. 회사의 개선사항, 변화가 필요한 것들에 대해선 반드시 말하는 스타일이라 크몽의 자유로운 분위기와 수평적 문화는 정말 만족했고 적응에 큰 어려움은 없었습니다.첫 주는 개발환경 laravel + vuejs 공부의 시간을 보냈고 둘째 주부터 이벤트 페이지를 맡아서 작업했습니다. 기존 사용하였던 개발환경과 크게 다르지 않아 크게 어려움 없이 이벤트 페이지 작업을 완료하고 배포가 되었습니다.호환성을 위한 es6 환경 필요성하지만 늘 그렇듯 다음 날 출근을 하니 버그가 날 기다리고 있었습니다. 조금 생소한 버그였습니다. script관련 오류였는데, 이전의 개발환경에선 babel, browserify가 거의 대부분의 script에 걸려있었기 때문에 습관적으로 es6로 작업했습니다. 결국은 es5스타일로 복구하여 수정했습니다. 곰곰이 생각해보니 호환성을 위해 es6를 사용하지 않는 것이 아닌 es6를 사용하도록 환경이 구성되어야 하는 게 맞는 것 아닌가 라는 생각했습니다.gulp가 개선되어야만 하는 이유크몽에 입사한 지 1주일 만에 다른 작업을 뒤로하고 회사에서 gulp만 외치고 다녔습니다. 다른 무언가 개선을 하려면 gulp가 필연적으로 개선이 되어야 했습니다. 기존의 개발환경은 파일 수정할 때마다 terminal에서 gulp를 명령어를 쳐야 했습니다. 주르륵 코드를 적고 한번 새로고침해서 짠하고 바뀌는 스타일이 아니라, 내가 짠 코드도 의심이 되어 자주 스텝별로 확인 스타일이라 이러한 현재 환경은 저와 정말 맞지 않았습니다.앞잡이(크몽의 프론트앤드 멤버) 챕터 회의 때 gulp개선을 요청하였고 모두에게 현재의 문제를 공유하고 gulp개선을 해야 하는 이유에 대해 설득 한 뒤 크몽개발팀 내 프로젝트 일정으로 잡히게 되었다.나 편하자고 시작한 작업, 내가 편한 건 팀원도 편하다우선 gulp 개선의 가장 큰 목적은 4가지였다.es6 및 최신 기술과 라이브러리를 사용하자gulp watch를 효율적으로 사용하자script태그와 style태그로 쓰는 것을 지양하자 (.js, .scss파일 많아지는 것에 대한 부담 가지지 말자)script, style, directory 구조를 기능별로 구조화시키자bk's PLANs그렇게 gulp는 이렇게 만들었습니다.기존 크몽 개발 환경에서 너무 확 바뀌진 않도록 개발자 분들과 협업하여 flow를 최대한 유지하며 작업했습니다. (공통 모듈, 유틸, 서비스 관련, 인증, 라이브러리, 이벤트, 구매 판매 트랙, sass)로 모듈을 나누어 bundle을 하였고 각각에 watch를 걸어 파일을 변경하면 자동으로 관련 모듈만 bundle이 실행되도록 작업했습니다.gulp를 위한 작업이었지만directory구조도 깔끔해지고 project도 좀 더 가벼워졌습니다. 계획은 거창했고 의욕은 앞섰지만 build 자동화 툴을 제대로 만져본 적이 경험이 없어서 (gulp, elixir, babel, browserify, stream) 작업과 공부를 병행하느라 예상보단 조금 더 시간이 걸렸지만 결과적으론 개선된 지금이 훨씬 개발하기 편해졌다.불필요한 작업이 습관이 되기 전에 개선을 실행했습니다.사실 크몽의 이전 개발환경에선 gulp가 크게 중요하지 않았지만, 크몽의 팀원이 많아지고 개발자도 많아지면 제가 아니더라도 크몽팀 누군가는 했을 작업이었습니다. 더 나은 환경이 분명히 존재하는데도 불구하고 기존의 불필요한 작업이 습관이 되어 개선을 망설이거나 하는 회사, 개발자가 많다고 생각합니다.개발자가 더 나은 환경에서 개발하는 걸 막자고 할 사람은 없을 것입니다. 그것이 입사한 지 1개월이 되든 10년이 되든 누가 말하든지 간에 말입니다. 갓 들어온 주니어 개발자의 말을 잘 들어주고 gulp 개선에 대한 필요성을 인정해주어 작업이 가능했던 것 같습니다.올바른 방향으로 문제 해결방법을 목표로 삼았습니다.앞으로의 bk의 계획이제 gulp가 완성이 됨과 동시에 directory 구조와 es6가 해결되었으니, 원래 가장 하려던 크몽의 코드 스타일, ESLint를 적용할 예정입니다. 그 후 vue2 마이그레이션 작업이 진행될 예정입니다.마무리작지만 하나하나 개선해 나가면 더 나아진 개발환경 구축이 되고 이런 작은 개선 사항들이 모여서 더 나은 크몽이 될 것이라 생각합니다.real _마무리이렇게 개발했던 경험을 블로그로 포스팅한 건 이번이 처음입니다.역시 글을 쓰는 건 어렵고 두서없었지만 build 자동화 툴에 대해 더 깊게 공부할 시간을 가지게 되어 좋은 경험이었습니다.글을 마무리 지으려니 어떻게 지어야 할지 모르겠네요.그래서 급 마무리 인사드립니다.이렇게 부족한 글 귀한 분들께서 읽어주셔서 감사합니다.다음 포스팅에는 크몽의 개발 조직문화 소개로 돌아오겠습니다.#크몽 #개발팀 #개발자 #개발문화 #경험공유 #인사이트

기업문화 엿볼 때, 더팀스

로그인

/