스토리 홈

인터뷰

피드

뉴스

조회수 6994

BPM, RPA 그리고 Process Mining(프로세스마이닝)

새로운 IT 기술의 등장과 기업 환경의 변화로 새로운 과학 경영 기법들이 비즈니스 유행어처럼 등장하고 사라지지만 그 가운데서도 변하지 않는 것이 있다면 프로세스 개선과 관련된 대한 끊임없는 노력과 관심일 것입니다.프로세스 마이닝은 이벤트 로그를 기반으로 비즈니스 프로세스를 분석할 수 있는 프로세스 관리 기술입니다. 정보 시스템에서 기록한 이벤트 로그에 포함된 패턴 및 세부 정보를 식별하기 위해 별도의 분석 알고리즘이 이벤트 로그 데이터에 적용됩니다. 프로세스 마이닝은 프로세스의 효율성과 이해를 향상시키는 것을 목표로 하며, “자동화된 비즈니스 프로세스 발견” ABPD (Automated Business Process Discovery)이라는 좀 더 일반화된 명칭으로 불리기도 합니다.이러한 프로세스 마이닝은 어디서 갑자기 나온 개념은 아니고 기존 비즈니스 프로세스 관리 기법에 대한 연구와 데이터 분석 기술이 합쳐져서 나온 산물이기에 “비즈니스 프로세스”와 관련된 기술들을 살펴보고 프로세스 마이닝과의 연관성을 찾아보고자 합니다.BPM (Business Process Management)프로세스 마이닝은 일반적으로 BPM과 데이터 마이닝이 겹치는 중간 영역에 위치합니다.BPM은 비즈니스 프로세스를 발견, 모델링, 분석, 측정, 개선, 최적화 및 자동화하기 위해 다양한 방법을 사용하는 운영 관리 기법을 의미하며, 프로세스를 관리하여 기업 성과를 향상시키는 데 중점을 둡니다. 좁은 의미에서 BPM은 업무 프로세스를 사전에 모델링하고, 설계된 프로세스 대로 업무 결제, 승인, 구매 등의 업무 등이 자동화되어 흘러갈 수 있도록 도와주는 IT 시스템을 지칭하기도 합니다..BPM은 Top-Down 방식으로 프로세스 모델을 그려서, 해당 프로세스 모델 대로 업무를 수행하도록 강제하는 방식이라면 프로세스 마이닝은 이미 수행된 업무로부터 프로세스 모델을 도출하는 Bottom-up 방식을 따릅니다.  하지만 점점 복잡해져 가는 기업 업무 활동을 BPM처럼 중앙 집권적 방식으로 모든 것을 통제하기에는 한계가 있습니다.  BPM의 통제를 벗어난 다양한 여러 시스템을 업무 관점에서 통합적으로 관리하고 모니터링하기 위해서는 개별 시스템은 그대로 두고 이로부터 쏟아져 나오는 로그를 통해 프로세스를 관리하는 분권적 방식이 BPM의 한계를 보완하는 역할을 합니다. RPA (Robot Process Automation)로봇 프로세스 자동화 (RPA)는 소프트웨어 로봇 또는 AI (인공 지능) 작업자의 개념을 기반으로 하는 사무 자동화 기술의 새로운 형태입니다.소프트웨어 '로봇'은 컴퓨터 시스템의 사용자 인터페이스와 상호 작용하는 인간의 행동을 복제하는 소프트웨어 응용 프로그램입니다. 예를 들어, ERP 시스템에 데이터 입력을 실행하거나 실제로 비즈니스 프로세스를 수행하는 것이 소프트웨어 로봇의 일반적인 활동이 될 것입니다. 소프트웨어 로봇은 사람과 동일한 방식으로 사용자 인터페이스(UI)에서 작동합니다. 이것은 기존에 애플리케이션 프로그래밍 인터페이스(API)에 기반한 전통적 형태의 IT 통합과 크게 다릅니다. 즉, 사용자 인터페이스의 데이터 아키텍처 계층을 기반으로 한 기계 간(machine-to-machine) 통신 형태를 취합니다.앞서 언급한 BPM이 프로세스 개선을 위해 프로세스 자체를 재설계하고 변경하려는 방식이라면 RPA는 사람이 하던 현재 방식을 그대로 모방하여 소프트웨어로 대체하여 자동화하는 방식입니다. 이러한 RPA가 업무에 더 많이 적용될 수록 더 많은 시스템 로그가 나올 것이고 이에 대한 성과 분석과 모니터링이 필요해질 것입니다. 프로세스 마이닝은 RPA 도입 전 초기 단계에 전체 프로세스를 분석하여 RPA가 적용될 만한 구간을 식별하여 타당성을 검증하고, RPA 도입 이후의 전후 비교를 통해 지속적으로 업무 효율성을 측정할 수 있는 방법을 제공합니다.앞서 살펴본 것처럼 BPM, RPA, Process Mining 이 세 가지는 서로의 영역을 다투는 것이 아니라 상호 보완적인 존재로 볼 수 있습니다.프로세스 마이닝은 “프로세스”와 관련된 다양한 시스템과 활동들에 대해서 데이터에 근거한 현재 프로세스의 모델링 및 성과 측정 방법을 제공합니다. 이를 통해 과거 혹은 신규 프로세스 혁신 기법들과 맞물려 해당 시스템 및 방법론이 성공적으로 수행될 수 있도록 자동화된 “업무 조언자” 역할을 수행하게 됩니다. [참고 자료]https://en.wikipedia.org/wiki/Business_process_managementhttps://en.wikipedia.org/wiki/Robotic_process_automationhttps://www.minit.io/blog/robotic-process-automation-and-process-mininghttps://medium.com/towards-data-science/unleash-the-value-of-process-mining-4e3b5af4e9d8http://www.cdevworkflow.com/bpm-life-cycle/https://www.uipath.com/blog/the-robotic-process-automation-infographic#퍼즐데이터 #개발팀 #개발자 #개발후기 #인사이트
조회수 1080

원하는 대로 뭉치는 GROUP BY

편집자 주전문 용어는 특정의 학술 용어나 기술 용어를 말하는데, 대개 둘 이상의 단어가 결합하여 하나의 의미 단위에 대응하는 말, 곧 합성어의 성격으로 되어 있다. 아래와 같은 전문 용어는 단어별로 띄어 씀을 원칙으로 하나, 편의상 붙여 썼다. 1) 수행 결과 > 수행결과2) 수행 시간 > 수행시간3) 실행 계획 > 실행계획Overview지난 글에서는 ORDER BY를 파헤쳤습니다. 이번에는 ORDER BY만큼이나 자주 쓰이는 GROUP BY를 알아볼 시간인데요. GROUP BY는 컬럼 값을 그룹짓고(중복을 제거하고) 이에 대해 건수나 값의 합을 계산할 때 사용합니다.지난 글 보기: 순서대로 척척, ORDER BY지난 글 보기: 단일 TABLE을 SELECT하자! 1.GROUP BY의 이해GROUP BY의 기본적인 문법은 아래와 같습니다.SELECT     MBR_NM FROM test.TB_MBR_BAS GROUP BY     MBR_NM  ; 실행계획은 아래와 같습니다. 테이블을 전부 읽어서 temp를 만들고 GROUP BY를 수행하라는 의미죠. GROUP BY가 수행되는 것은 Extra에 Using filesort가 표시된 것으로 유추할 수 있습니다.참고로 Using filesort는 GROUP BY, ORDER BY, DISTINCT 등의 정렬과 관련한 작업을 수행하면 나타납니다. Query를 수행해볼까요?위와 같은 결과가 나왔는데, 수행시간은 3.77초가 걸렸습니다. 이 Query는 MBR_NM의 중복을 제거해서 화면에 표시한 것입니다. 이번에는 아래의 Query를 수행해보겠습니다.SELECT     MBR_NM      ,COUNT(*) FROM test.TB_MBR_BAS GROUP BY     MBR_NM  ; 바뀐 것이 있다면 SELECT 절에 COUNT(*) 가 추가된 것입니다. 실행계획은 다른 점이 없습니다.COUNT(*)는 레코드의 건수를 계산할 때 사용합니다. 위의 계획은 MBR_NM의 값이 같은 건수를 출력하라는 의미입니다. 수행해보겠습니다.수행시간은 3.64초로 비슷하게 나옵니다. 위의 내용을 보면 강나영 1437건, 강다은 1465건, 강도연 1445건 … 인 것을 알 수 있습니다. 만약 테이블의 전체 건수를 알고 싶다면 어떻게 할까요? 아래와 같이 수행해보세요.SELECT     COUNT(*) FROM test.TB_MBR_BAS  ; 수행결과는 다음과 같습니다.2.GROUP BY의 응용(1): 나이 구하기이번에는 나이 컬럼을 추가하고 이름별 나이의 합을 구해보겠습니다. 아래의 명령으로 컬럼을 추가합니다.ALTER TABLE test.TB_MBR_BAS ADD COLUMN AGE TINYINT UNSIGNED DEFAULT 0 COMMENT '나이'; 컬럼이 추가되고, 다음과 같은 구조를 갖출 겁니다.AGE 컬럼에 모두 0이 들어간 것을 알 수 있다.SELECT     * FROM test.TB_MBR_BAS ; 0으로 들어간 값을 1에서 100 사이의 임의 값으로 변경하겠습니다. 만약 내용을 변경한다면 아래 예시와 같이 UPDATE문을 사용하세요. UPDATE test.TB_MBR_BAS SET AGE = TRUNCATE(RAND()*100,0)+1 ; test.TB_MBR_BAS 의 AGE 컬럼 내용을 변경하라는 명령을 하기 위해 RAND() 함수를 쓰고 임의의 값을 발생시겼습니다. UPDATE 및 SELECT를 수행하면 값이 변경된 것을 알 수 있습니다.SELECT     * FROM test.TB_MBR_BAS  ; 변경된 값이번에는 이름이 같은 사람들의 나이 합을 구해볼까요? 합을 구할 때는 SUM 함수를 사용합니다. SELECT     MBR_NM     ,COUNT(*)     ,SUM(AGE) FROM test.TB_MBR_BAS GROUP BY     MBR_NM ; 실행계획은 AGE 컬럼을 추가하기 전과 바뀐 것이 없다는 걸 알 수 있습니다. 실행결과를 보겠습니다.수행시간은 4.3초 걸렸습니다. ‘강나영’이란 이름을 가진 사람의 건수는 1,437건이고, 나이의 합은 74,092인 것을 알 수 있습니다. 합산만 하면 의미가 없으니 평균 나이를 구해보겠습니다. 방법은 SUM / COUNT하는 방법과 AVG 함수를 이용하는 방법 두 가지가 있습니다.SELECT     MBR_NM      ,COUNT(*)      ,SUM(AGE)      ,SUM(AGE)/COUNT(*)      ,AVG(AGE) FROM test.TB_MBR_BAS GROUP BY     MBR_NM  ; 실행계획은 이전과 달라진 부분이 없습니다. 수행결과를 보도록 하죠.수행시간은 5.6초 정도 걸렸습니다. 좀 더 빨리 수행하면 좋을 텐데 말이죠. 시간을 단축시키려면 어떻게 해야 할까요?3.GROUP BY의 응용(2): 수행시간 단축하기기본적인 방법은 GROUP BY할 컬럼으로 INDEX를 생성하는 것입니다. MBR_NM으로 INDEX를 생성해보겠습니다.CREATE INDEX IX_MBR_BAS_02 ON test.TB_MBR_BAS (MBR_NM); 생성 후, 이전 Query를 수행합니다.SELECT     MBR_NM      ,COUNT(*)      ,SUM(AGE)      ,SUM(AGE)/COUNT(*)      ,AVG(AGE) FROM test.TB_MBR_BAS GROUP BY     MBR_NM  ; 아래의 실행계획이 달라진 것을 알 수 있습니다.실행계획을 보면 전체를 읽어서 처리하는 부분은 사라졌습니다. 대신 IX_MBR_BAS_02 INDEX를 사용하는 것으로 나옵니다. 이미 정렬된 구조를 갖추고 있는 INDEX에서는 GROUP BY 수행 시, 또 정렬하지 않아도 됩니다. 그래서 별도 정렬인 Using filesort가 Extra에 나오지 않은 것이고, GROUP BY에 INDEX를 사용하는 것으로 해석할 수 있습니다. 그렇다면 시간은 얼마나 줄었을까요? 수행해보겠습니다.0.5초 정도 걸렸습니다. 기존 5.6초보다 훨씬 많이 개선된 것을 알 수 있습니다. 시간은 단축되었는데 결과는 같습니다.이번에는 IX_MBR_BAS_02를 기존 MBR_NM에서 MBR_NM, AGE로 생성해 보겠습니다.DROP INDEX IX_MBR_BAS_02 ON test.TB_MBR_BAS; CREATE INDEX IX_MBR_BAS_02 ON test.TB_MBR_BAS (MBR_NM,AGE); INDEX를 생성하고 이전 Query를 수행합니다.SELECT     MBR_NM      ,COUNT(*)      ,SUM(AGE)      ,SUM(AGE)/COUNT(*)      ,AVG(AGE) FROM test.TB_MBR_BAS GROUP BY     MBR_NM  ; 달라진 것이 있다면 Extra에 Using index가 표시된 것입니다. 기존에 INDEX가 MBR_NM으로만 구축된 Query는 IX_MBR_BAS_02 INDEX로 GROUP BY하고, TB_MBR_BAS에서 AGE 합을 구한 것입니다. 하지만 INDEX가 MBR_NM, AGE로 구축된 이번 경우는 IX_MBR_BAS_02 INDEX를 이용해 GROUP BY 와 AGE의 합까지 구한 것이죠. 물론 결과는 같았지만, 수행속도는 0.3초로 개선되었습니다.4.GROUP BY의 응용(3): 특정 조건의 결과 출력WHERE마지막으로 성이 김 씨인 경우에만 GROUP BY하여 값을 출력해보겠습니다. 위의 Query에서 WHERE로 조건만 더하면 되는데요.SELECT     MBR_NM      ,COUNT(*)      ,SUM(AGE)      ,SUM(AGE)/COUNT(*)      ,AVG(AGE) FROM test.TB_MBR_BAS WHERE MBR_NM LIKE '김%' GROUP BY     MBR_NM  ; 위의 이미지처럼 WHERE 조건이 들어가면서 type이 index에서 range로 바뀐 것을 알 수 있습니다. 이것을 해석하면 ‘ IX_MBR_BAS_02를 WHERE조건의 범위만큼 처리하라는 것’입니다. 실행결과를 보죠.HAVINGHAVING 절은 GROUP BY로 SUM, COUNT, AVG한 값을 필터 조건으로 걸고 싶을 때 사용합니다. 예시로 위의 Query에서 AVG(AGE) 값이 50보다 작은 것을 출력해보겠습니다.SELECT     MBR_NM      ,COUNT(*)      ,SUM(AGE)      ,SUM(AGE)/COUNT(*)      ,AVG(AGE) FROM test.TB_MBR_BAS WHERE MBR_NM LIKE '김%' GROUP BY     MBR_NM HAVING AVG(AGE) < 50>결과를 출력하면 아래와 같습니다.AVG(AGE)가 50보다 작은 값들이 출력된 것이 보이는군요.글을 마치며간단한 예제를 소개해드렸지만 큰 규모로 GROUP BY를 하면 재미있는 결과들을 만날 수 있습니다. 예를 들어 대한민국 전체 국민을 대상으로 GROUP BY를 실행하면, 평균 나이가 가장 많은 성 씨를 찾을 수 있습니다. 인구통계학 분석에 적용하면 100년 안에 없어질 성 씨를 알 수도 있고요. 응용할 수 있는 범위가 아주 많겠죠? 이상으로 GROUP BY에 대한 소개를 마칩니다. 글한석종 부장 | R&D 데이터팀[email protected]브랜디, 오직 예쁜 옷만#브랜디 #개발자 #개발팀 #인사이트 #경험공유
조회수 1308

VCNC가 Hadoop대신 Spark를 선택한 이유 - VCNC Engineering Blog

요즘은 데이터 분석이 스타트업, 대기업 가릴 것 없이 유행입니다. VCNC도 비트윈 출시 때부터 지금까지 데이터 분석을 해오고 있고, 데이터 기반의 의사결정을 내리고 있습니다.데이터 분석을 하는데 처음부터 복잡한 기술이 필요한 것은 아닙니다. Flurry, Google Analytics 등의 훌륭한 무료 툴들이 있습니다. 하지만 이러한 범용 툴에서 제공하는 것 이상의 특수하고 자세한 분석을 하고 싶을 때 직접 많은 데이터를 다루는 빅데이터 분석을 하게 됩니다. VCNC에서도 비트윈의 복잡한 회원 가입 프로세스나, 채팅, 모멘츠 등 다양한 기능에 대해 심층적인 분석을 위해 직접 데이터를 분석하고 있습니다.빅데이터 분석 기술큰 데이터를 다룰 때 가장 많이 쓰는 기술은 Hadoop MapReduce와 연관 기술인 Hive입니다. 구글의 논문으로부터 영감을 받아 이를 구현한 오픈소스 프로젝트인 Hadoop은 클러스터 컴퓨팅 프레임웍으로 비싼 슈퍼컴퓨터를 사지 않아도, 컴퓨터를 여러 대 연결하면 대수에 따라서 데이터 처리 성능이 스케일되는 기술입니다. 세상에 나온지 10년이 넘었지만 아직도 잘 쓰이고 있으며 데이터가 많아지고 컴퓨터가 저렴해지면서 점점 더 많이 쓰이고 있습니다. VCNC도 작년까지는 데이터 분석을 하는데 MapReduce를 많이 사용했습니다.주스를 만드는 과정에 빗대어 MapReduce를 설명한 그림. 함수형 프로그래밍의 기본 개념인 Map, Reduce라는 프레임을 활용하여 여러 가지 문제를 병렬적으로 처리할 수 있다. MapReduce slideshare 참조MapReduce는 슈퍼컴퓨터 없이도 저렴한 서버를 여러 대 연결하여 빅데이터 분석을 가능하게 해 준 혁신적인 기술이지만 10년이 지나니 여러 가지 단점들이 보이게 되었습니다. 우선 과도하게 복잡한 코드를 짜야합니다. 아래는 간단한 Word Count 예제를 MapReduce로 구현한 것인데 매우 어렵고 복잡합니다.MapReduce로 단어 갯수를 카운트하는 간단한 예제 (Java). 많은 코드를 작성해야 한다.이의 대안으로 SQL을 MapReduce로 변환해주는 Hive 프로젝트가 있어 많은 사람이 잘 사용하고 있지만, 쿼리를 최적화하기가 어렵고 속도가 더 느려지는 경우가 많다는 어려움이 있습니다.MapReduce의 대안으로 최근 아주 뜨거운 기술이 있는데 바로 Apache Spark입니다. Spark는 Hadoop MapReduce와 비슷한 목적을 해결하기 위한 클러스터 컴퓨팅 프레임웍으로, 메모리를 활용한 아주 빠른 데이터 처리가 특징입니다. 또한, 함수형 프로그래밍이 가능한 언어인 Scala를 사용하여 코드가 매우 간단하며, interactive shell을 사용할 수 있습니다.Spark으로 단어 개수를 카운트하는 간단한 예제 (Scala). MapReduce에 비해 훨씬 간단하다.Spark과 MapReduce의 성능 비교. I/O intensive 한 작업은 성능이 극적으로 향상되며, CPU intensive 한 작업의 경우에도 효율이 더 높다. (자료: RDD 논문)Apache Spark는 미국이나 중국에서는 현재 Hadoop을 대체할만한 기술로 급부상하고 있으며, 국내에도 최신 기술에 발 빠른 사람들은 이미 사용하고 있거나, 관심을 갖고 있습니다. 성능이 좋고 사용하기 쉬울 뿐 아니라, 범용으로 사용할 수 있는 프레임웍이기에 앞으로 더 여러 분야에서 많이 사용하게 될 것입니다. 아직 Spark를 접해보지 못하신 분들은 한번 시간을 내어 살펴보시길 추천합니다.기존의 데이터 분석 시스템 아키텍처기존의 데이터 분석 시스템 아키텍처기존의 시스템은 비용을 줄이기 위해 머신들을 사무실 구석에 놓고 직접 관리했으며, AWS S3 Tokyo Region에 있는 로그를 다운받아 따로 저장한 뒤, MapReduce로 계산을 하고 dashboard를 위한 사이트를 따로 제작하여 운영하고 있었습니다.이러한 시스템은 빅데이터 분석을 할 수 있다는 것 외에는 불편한 점이 많았습니다. 자주 고장 나는 하드웨어를 수리하느라 바빴고, 충분히 많은 머신을 확보할 여유가 없었기 때문에 분석 시간도 아주 오래 걸렸습니다. 그리고 분석부터 시각화까지 과정이 복잡하였기 때문에 간단한 것이라도 구현하려면 시간과 노력이 많이 들었습니다.Spark과 Zeppelin을 만나다이때 저희의 관심을 끈 것이 바로 Apache Spark입니다. MapReduce에 비해 성능과 인터페이스가 월등히 좋은 데다가 0.x 버전과는 달리 1.0 버전에서 많은 문제가 해결되면서 안정적으로 운영할 수 있어 비트윈 데이터 분석팀에서는 Spark 도입을 결정했습니다.Apache Zeppelin은 국내에서 주도하고 있는 오픈소스 프로젝트로써, Spark를 훨씬 더 편하고 강력하게 사용할 수 있게 해주는 도구입니다. 주요한 역할은 노트북 툴, 즉 shell에서 사용할 코드를 기록하고 재실행할 수 있도록 관리해주는 역할과 코드나 쿼리의 실행 결과를 차트나 표 등으로 시각화해서 보여주는 역할입니다. VCNC에서는 Zeppelin의 초기 버전부터 관심을 가지고 살펴보다가, Apache Spark를 엔진으로 사용하도록 바뀐 이후에 활용성이 대폭 좋아졌다고 판단하여 데이터 분석에 Zeppelin을 도입하여 사용하고 있고, 개발에도 참여하고 있습니다.또한, 위에서 언급한 하드웨어 관리에 드는 노력을 줄이기 위해서 전적으로 클라우드를 사용하기로 함에 따라서1 아래와 같은 새로운 구조를 가지게 되었습니다.새로운 데이터 분석 시스템 아키텍처새로운 데이터 분석 시스템 아키텍처새로운 데이터 분석 시스템은 아키텍처라고 하기에 다소 부끄러울 정도로 간단합니다. 애초에 전체 시스템 구성을 간단하게 만드는 것에 중점을 두었기 때문입니다. 대략적인 구성과 활용법은 아래와 같습니다.모든 서버는 AWS 클라우드를 이용수 대의 Zeppelin 서버, 수 대의 Spark 서버운영Spark 서버는 메모리가 중요하므로 EC2 R3 instance 사용로그는 별도로 저장하지 않고 서비스 서버에서 S3로 업로드하는 로그를 곧바로 가져와서 분석함중간 결과 저장도 별도의 데이터베이스를 두지 않고 S3에 파일로 저장Zeppelin의 scheduler 기능을 이용하여 daily batch 작업 수행별도의 dashboard용 Zeppelin을 통해 중간 결과를 시각화하며 팀에 결과 공유이렇게 간단한 구조이긴 하지만 Apache Spark와 Apache Zeppelin을 활용한 이 시스템의 능력은 기존 시스템보다 더 강력하고, 더 다양한 일을 더 빠르게 해낼 수 있습니다.기존현재일일 배치 분석코드 작성 및 관리가 어려움Zeppelin의 Schedule 기능을 통해 수행Interactive shell로 쉽게 데이터를 탐험오류가 생긴 경우에 shell을 통해 손쉽게 원인 발견 및 수정 가능Ad-hoc(즉석) 분석복잡하고 많은 코드를 짜야 함분석 작업에 수 일 소요Interactive shell 환경에서 즉시 분석 수행 가능Dashboard별도의 사이트를 제작하여 운영관리가 어렵고 오류 대응 힘듦Zeppelin report mode 사용해서 제작코드가 바로 시각화되므로 제작 및 관리 수월성능일일 배치 분석에 약 8시간 소요메모리를 활용하여 동일 작업에 약 1시간 소요이렇게 시스템을 재구성하는 작업이 간단치는 않았습니다. 이전 시스템을 계속 부분적으로 운영하면서 점진적으로 재구성 작업을 하였는데 대부분 시스템을 옮기는데 약 1개월 정도가 걸렸습니다. 그리고 기존 시스템을 완전히 대체하는 작업은 약 6개월 후에 종료되었는데, 이는 분석 성능이 크게 중요하지 않은 부분들에 대해서는 시간을 두고 여유 있게 작업했기 때문이었습니다.Spark와 Spark SQL을 활용하여 원하는 데이터를 즉석에서 뽑아내고 공유하는 예제Zeppelin을 활용하여 인기 스티커를 조회하는 dashboard 만드는 예제결론비트윈 데이터 분석팀은 수개월에 걸쳐 데이터 분석 시스템을 전부 재구성하였습니다. 중점을 둔 부분은빠르고 효율적이며 범용성이 있는 Apache Spark, Apache Zeppelin을 활용하는 것최대한 시스템을 간단하게 구성하여 관리 포인트를 줄이는 것두 가지였고, 그 결과는 매우 성공적이었습니다.우선 데이터 분석가 입장에서도 관리해야 할 포인트가 적어져 부담이 덜하고, 이에 따라 Ad-hoc분석을 수행할 수 있는 시간도 늘어나 여러 가지 데이터 분석 결과를 필요로 하는 다른 팀들의 만족도가 높아졌습니다. 새로운 기술을 사용해 본 경험을 글로 써서 공유하고, 오픈소스 커뮤니티에 기여할 수 있는 시간과 기회도 생겼기 때문에 개발자로서 보람을 느끼고 있습니다.물론 새롭게 구성한 시스템이 장점만 있는 것은 아닙니다. 새로운 기술들로 시스템을 구성하다 보니 세세한 기능들이 아쉬울 때도 있고, 안정성도 더 좋아져야 한다고 느낍니다. 대부분 오픈소스 프로젝트이므로, 이러한 부분은 적극적으로 기여하여 개선하여 나갈 계획입니다.비트윈 팀에서는 더 좋은 개발환경, 분석환경을 위해 노력하고 있으며 이는 더 좋은 서비스를 만들기 위한 중요한 기반이 된다고 생각합니다. 저희는 항상 좋은 개발자를 모시고 있다는 광고와 함께 글을 마칩니다.연관 자료: AWS 한국 유저 그룹 - Spark + S3 + R3 을 이용한 데이터 분석 시스템 만들기↩
조회수 646

스마트링크 시즌2 : 은하철도 프로젝트

스마트링크 시즌2 채용공고에 보내주신 뜨거운 반응 감사합니다!! 정말 많은 분들의 열정과 관심에 분주하지만 즐거운 만남들을 여럿 가질 수 있었습니다. 그리고 드디어!! 은하철도에 함께 탑승할 5명의 동료가 최종 선발되셨습니다. 뜨거운 관심과 지원에 다시 한번 감사드리며 아쉽지만 이번에 함께하지 못한 분들도 저희가 좌석을 보다 넉넉하게 꾸리게되면 함께할 수 있는 날이 오면 좋겠습니다.여기서 잠깐!그렇다고해서 스마트링크 시즌2 채용이 완전히 완료된 것은 아닙니다. 스마트링크는 언제나 좋은 분들과 함께할 준비가 되어있습니다. 상시채용 형태로 계속 이어나갈 예정이니 스마트링크 은하철도에 관심있는 분들은 언제나 문을 두드려 주시면 감사하겠습니다. 그럼 새로운 동료들과 슬슬 날아갈 준비를 하러 이만 :) - 2019. 6. 25 어느 기분좋은 화요일---------------------------------------------------------------------안녕하세요. 스마트링크의 Mike 라고 합니다. 기획과 마케팅을 담당하고있죠. 스마트링크는 작년부터 저희와 함께할 분들을 애타게 찾고 있습니다. 그 사이에 많은 분들을 뵙고 기회를 도모하기도 했습니다. 여러 다양한 경험을 축적하기도 했구요. 이렇게 여러 과정을 거치던 와중에 그동안 아기다리고기다리던, 그리고 열심히 준비했던 성과들이 하나둘 나오기 시작했습니다. 마치 미드에서 시즌이 바뀌는 것처럼 우리에게 근본적인 패러다임의 변화가 있었다랄까요? 이런 변화를 염두하며 지난 채용공고를 봤는데...안되겠어. 다시 써야겠어!그래서 이렇게 시즌2 만을 위한 채용공고를 작성하는 중입니다. 스마트링크의 시즌2는 어떻게 진행되고 그래서 어떤 분들과 함께하고 싶은지 지금부터 이런저런 이야기를 해보도록 하겠습니다.  뭐하는 회사임?스마트링크는 소프트웨어 개발사 입니다. 끝. 참 쉽죠? 그런데 세상은 넓고 소프트웨어 개발사는 넘치고 넘칩니다. 그런데 뭐가 그렇게 다른가? 라고 물으신면! MVP(Minimum Viable Product) 소프트웨어 개발 컨설팅 전문 업체라고 말씀드릴 수 있겠습니다. 이게 뭔말이냐 하면 덩치 큰 SI도 진행하지만 주로 스타트업 또는 초기 사업 아이디어가 빠르게 시장에 진입할 수 있도록 기획, 디자인, 개발, 테스팅, 데브옵스까지 (물론 견적에 따라 달라집니다! 단호! ㅋㅋ) 풀 패키지로 작업하는걸 좋아하는 업체라고 보시면 되겠네요. 그래서 프로젝트 기간이 짧고 굵은게 많죠. 늘어지는 프로젝트 별로 안좋아 합니다. AtoZ로 빠르게, 효율적으로, 효과적으로! 일하는걸 선호하고 실제로 그렇게 일을 진행합니다. 그런데 아마 이런 의문이 드실거에요. 왜 작은일 맡는걸 좋아하지? 사실, 규모가 중요한게 아니라 AtoZ 라는게 중요합니다. (심지어 예산 높은 큰 프로젝트 요청을 까기도 합니다. 꽤 자주;;) 그 이유는? 면접때 질문 주시면 신나게 답해드리도록 하죠 ㅎㅎ 다 이유가 있습니다!  누가 일하고 있는데?AtoZ, 풀패키지로 일하는걸 좋아한다는 대목에서 아시겠지만 있을 사람은 다 있습니다. 기획, 디자인, 개발 인력 모두 있구요. 그래야 일이 되겠죠? 다만 현재 사람수가 많지는 않아요. 소수정예! 하지만 모두 각 분야에서 베테랑들이라 자부합니다. 특히 개발사이니만큼 모든 분야는 개발을 중심으로 돌아가구요, 각 영역을 생판 모르는 분야로 치부하지않고 서로를 끊임없이 알아가고 파악하고 융화되는 방식으로 일합니다. 예를 들면 기획과 개발은 DB구조나 Convention을 공유하고, 디자인은 Front-end 최적화된 디자인과 UI/UX를 뽑아냅니다. 여기서 일일이 언급하기는 뭐하지만 일 잘하는 사람들이 모여있다고 자부하고 있고, 앞으로 동료들도 일 잘하는 사람을 가장 원하고 바라고 있습니다. 일을 잘한다는 기준이 절대적일 수는 없겠지만, 예를 들면 이런거죠. 최대한 정확하고, 낭비나 누수없이, 빠르게 문제를 해결하기 위해 계속 꼼수를 쓰는 사람들! 이랄까요? 세상에 (노는것 포함) 할일이 얼마나 많은데! 극단적 효율을 추구하는 집단이라고 보시면 되겠습니다.  제대로된 꼼수는 사실 탄탄한 정석 바탕에서 나올 수 있다죠.다만 아직 목마릅니다. 일을 더 잘하고 싶어요. 그래서 우리는 시즌1을 보내면서 내부를 다지는 일도 지속적으로 탄탄하게 단내 나도록 해왔습니다. 그리고 슬슬 그 결과들이 눈 앞에 펼쳐지고 있네요. 그래서 결심할 수 있었습니다. 이제 확장의 시기가 왔다! 시즌2로 나아갈 때가 되었다!   시즌2라...시즌1엔 어떻게 했고, 시즌2에서는 어떻게 할건데??시즌1에서 스마트링크 작업방식을 정의내리자면 이렇습니다.천상천하유아독존!!네, 그렇습니다. 각자 부여된 일을 독자적으로 수행해서 최종 결과물을 내는 방식이었죠. 내부적으로 진행하는 일이야 Agile 방법론을 적극 도입한다해도 외부 프로젝트를 진행하는 경우에는 어쩔 수 없는 Waterfall 방식이었습니다. 기획 작업을 마무리하면, 받아서 디자인 작업을 하고, 마지막으로 개발을 완료하는 방식이었죠. 특히 개발은 Ownership을 기반으로한 책임개발제(라 쓰고 독박이라 읽는다)로 운영되고 있었습니다. 이 방식으로 운영했던 이유는 모호한 업무분담과 그로 인한 누수를 최소화하기 위한 방책이었죠. 사공이 많으면 배가 산으로 간다는 속설을 극복할 방법이기도 했구요. 실력있는 개발자를 중심으로 이 방법은 한동안 잘 유지되는듯 했습니다. 그런데 계속 이렇게 운영하다보니 이런 상황이 발생했습니다.될놈될, 안될안 ㅠ 개발 결과물의 빈부격차 ㅠ책임개발제는 결과물이 사람에 의해 결정된다는 의미 입니다. 실무자의 경험이나 실력에 따라 천차만별일 수 밖에 없는거죠. 그러다보니 퀄리티 확보를 위해서는 결국 다시 여러 사람들의 손을 거쳐야하는 이슈들이 종종 발생했습니다. 사실 이는 필연적인 부분일지도 모르겠습니다. Full-Stack 개발을 추구한다해도 결국 저마다 가지고있는 개성과 강점은 다르니까요. 그럼에도 불구하고 지금까지는 딱히 문제 없었습니다. 다만 미래를 염두하면 걱정되는 부분들이 있더군요. 인력이 늘어나고 보다 다양한 사람들이 함께하게된다면 과연 이 시스템이 버틸 수 있을까? 라는 근본적 의문이 드는겁니다. (그래서 이번 채용은 Front-end와 Back-end를 구분해서 진행합니다.) 그리고...Ownership이고 뭐고 다 좋은데 왜 외롭냐...외롭기도 하더군요. 기획, 디자인, 개발 모두가 그랬고 특히 개발자들은 그냥 말 그대로 굉장히 외롭게 되었습니다. 복작이며 한 팀으로 일하는 방식이라기보다는 프리랜서들 조합과 같은 이 상황은 구성원들을 각자 개인의 울타리로 고립시키는 결과로 이어졌습니다. 기획, 디자인, 개발은 각자 나름의 방식으로 일하면 결국 서로 Sync를 맞추기 위한 작업이 추가될 수 밖에 없습니다. 효과적인 분업도 좋지만 결국 우리는 함께 일하는 회사라는 공동체 안에 있습니다. 능률, 효율과 더불어 협업도 굉장히 중요하죠. 적당한 균형점을 찾는게 중요해졌습니다. 앞으로 사공은 엄청 많아질거거든요. 그것도 다양한 특징과 강점을 가진 각양각색의 사공들이 말이죠. 이렇게 사공이 많아져도 배가 산으로 가면 안되죠.  우주로 가는건 괜찮을지도... 사공이 많은 배라면 차라리 이런걸 만들면 어떨까?사공이 많은 멋진 배를 만드는 방법이란 뭘까? 누수 없는 업무처리와 능률을 모두 잡는 방법은 무엇일까? 이런 고민을 하던 와중에 우리에게 필요한건 엔진이란걸 알게 되었습니다. 이 엔진은 이런 조합으로 구성되어야 했습니다.목표한 기능을 정확하고 안정적으로 구현할 수 있는 동력자칫 시야를 좁힐 수 있는 미시적 요소들을 과감하게 skip할 수 있는 돌파력누수없이 매끄럽게 진행되는 안정적 업무 전달계통그리고 이 과정을 우리 모두 함께하고 있다는 응집력 뭔가 뜬구름 잡는 이야기들로 보일지도 모르겠습니다. 하지만 이 조합은 연역적이라기보다는 귀납적입니다. 실제 우리가 고민해온 부분을 해결하고자한 일들의 결과물이 위와 같은 역할을 하고있다는 것이 보다 정확한 표현이겠네요. 그리고 이 엔진은 한 단어로 귀결됩니다.그렇습니다. 컴포넌트.그리고 우리는 Components 를 엔진 삼아 우주전함 대신 은하철도 시스템을 구축했습니다. 이른바 스마트링크 시즌2 은하철도 프로젝트!  은하철도 프로젝트라니... 뭥미?? - 스마트링크 시즌2 은하철도 프로젝트보통 스타트업이 성장하는 모습을 로켓에 비유하기도 합니다. 빠르고 가파르게 수직상승하는 모습을 본딴 것이겠죠. 하지만 우리는 조금 다르게 생각합니다. 한가지 아이템으로 절체절명의 상황을 이겨내고 급성장하는 방법도 좋겠지만 우리는 오히려 안정성과 지속가능성에 더 초점을 맞추고 있습니다. 이를 위해서 스마트링크는 꽤 오랜시간 공들여 Component 구축을 진행했고 그 결실이 드디어 빛을 봤습니다! 장기적으로 효율적이고도 생산적인 구조를 위해 이제까지의 내부 프로세스를 과감하게 변경하고 새롭게 아래와 같은 구조로 진행합니다. 반영구적 Components 엔진을 돌리면서 모두를 리딩하는 곳, 기관실우리의 엔진 Components를 계속 다듬고 발전시킵니다. 내부 프로젝트도 진행하죠.실무자들의 즐거운 놀이터, 1등석이미 잘 구축된 Components로 안락하고 쾌적하고 빠르게 할당된 프로젝트를 진행합니다. 특히 개발자에게는 상용 서비스에서 활용 가능한 React Skill을 마음껏 연마하는 과정이기도 합니다 :)초심자들의 탄탄한 학습의 장, 일반석숙련도와 경험이 적은 초보자들은 체계적인 교육과 안정적인 Components 활용법을 익히고 1등석에 옮겨탈 준비를 합니다.뭔가 괜찮은 열차죠? 은하철도 프로젝트는 크게 이런 구조로 작동하게 됩니다. 이번 채용공고를 통해 모시고자하는 자리는 1등석과 일반석 입니다.베테랑들은 탑승한 동료들을 위해 열심히 기관실을 돌리면서 최대한 안정적이고 쾌적한 작업환경을 위해 움직입니다. 물론 내부적인 방향과 비전을 위한 고민, 세팅도 주도하겠지만 최종적으로는 모든 구성원들과 함께 공유하고 의견을 모아 진행합니다. 기관실과 객석들 역시 유기적이고 탄탄하게 연결돼야 하니까요.가즈아~ 기관실은 구비되어있다!!기관실과 객석이 설국열차처럼 꽉 막혀있지 않습니다. 본인이 원한다면 일정정도 열정과 의지로 기관실에 옮겨탈 수도 있습니다. 이건 순전히 본인의 취향에 달려있다고 생각해요. 세상은 넓고 사람은 다양하고 가치관도 제각각입니다. 그저 선택의 문제일 뿐이죠. 우리는 그저 보다 많은 사람들이 우리의 은하철도에 올라탈 수 있기를 바랄 뿐입니다. 그래서 선택할 수 있는 자리를 마련한 것 뿐이구요. 실무자들이 실무에만 집중할 수 있는 구조는 회사라는 공동체에서 매우 중요하다고 생각합니다. 선택은 여러분의 몫입니다.  1등석과 일반석이라... 좀 더 설명해보지?고민의 공간, 기관실.1등석과 일반석을 설명하자면 먼저 기관실 설명을 하지 않을 수 없습니다. 기관실은 끊임없이 소프트웨어 Core를 생산하는 곳이라고 보시면 되겠습니다. 그 중심은 당연히 Components 겠죠. 세상의 모든 서비스를 커버하겠다는 야심과 함께 사용자에게는 쾌적한 경험을, 개발자들에게는 효율적이고 신속한 개발환경을 선사하는 영역입니다. 그래서 개발언어를 잘 이해하고 보다 핵심적인 영역을 손대고 싶은 사람에게 적합합니다. 실력도 당연히 동반되어야겠지만 이제까지 경험으로 보자면 자기주도적인 취향도 핵심이더군요. 기관실은 이런 사람들이 모여있습니다. 사용자경험 뿐 아니라 내부 개발진들의 의견을 끊임없이 추적하고 해결하는 고민의 공간 입니다.기관실이 잘 할테니까 팔로팔로미~ ㅎㅎ효율의 공간, 1등석위에서 '취향'에 대해 언급했는데요. 1등석은 취향에 따라 자신의 업무방향을 선택할 수 있는 공간 입니다. 잘 짜여진 Components와 Convention에 따라 실제 상용서비스를 만들거나 관리하는 역할을 합니다. 고민의 폭은 줄이고, 실질적인 결과물에 초점을 맞추는 효율의 공간이라고 보시면 되겠어요. 새로운 결과물을 세상에 선보이고, 이들을 잘 작동시키는 사람들이 모여있는 곳입니다. 그러다가 지금 쓰고있는 Components 개선이 좀 더 필요할거 같다 싶으면 자체적으로 해결해도되고 기관실로 넘길 수도 있습니다. 이 부분이 바로 취향의 영역이라고 볼 수 있는데요. 본인의 실력과 더불어 이 취향에 따라서 기관실로 갈지, 1등석에서 작업할지 결정할 수도 있습니다.학습의 공간, 일반석일반석은 다른 말로 초심자의 영역이라고 보시면 되겠습니다. 세상은 급변하고 소프트웨어 변화 역시 엄청나죠. 우리는 끊임없이 학습하고 발전해야만하는 영역에서 일하고 있습니다. 그래서 이 부분을 절대 간과해선 안된다고 생각하고 있어요. 다만 취미 정도의 학습이라면 각자 개인의 소양 정도로 진행하는 것이 적절하겠죠. 일반석은 실제 상용 서비스에 적용 가능한 수준의 학습이 이뤄지는 공간입니다. 그 핵심은 React, Meteor, MongoDB 라고 보시면 되겠구요. 고퀄 서비스들을 실제로 만들어낼 수 있는 핵심 역량을 키울 수 있는 곳입니다. 사람들은 각자 일하는 방법이나 인생설계 방향을 가지고 있습니다. 그리고 여기에 따라 너무 다양한 나름의 스타일을 가지고있죠. 우리는 이 부분을 간과해서는 안된다고 생각해요. 우리가 말하는 취향은 바로 이런 것입니다. 취향에 따라 내가 주도적인지 수동적인지, 스스로 설계하는 스타일인지 주어진 과제를 잘 해결하는 스타일인지 나뉘는게 당연하겠죠. 이 부분은 실력과는 또 다른 축인거 같습니다. 한가지 방식을 강요해봤자 상황이 제대로 돌아갈리는 만무하고 또 그래서도 안됩니다. 일을 잘 하고싶은 스마트링크는 그래서 우리가 운영 가능한 범위 내에서 최대한의 공간과 가능성을 만들고 싶었습니다. 그래서 이런 구조를 생각해낸거구요.좀 더 솔직히 말하자면, 네. 이거 준비하는데 힘들었습니다 ㅠ 그냥 실력있는 사람들이 머리를 맞대고 모이기만 한다면야 이런 고민과 구상이 필요 없을지도 몰라요. 오히려 그게 편하기도 하구요. 척 하면 척~ 착 하면 착~ 아시죠? 그리고 이 은하철도 프로젝트를 채용공고에서 공개하는 것이 과연 좋을까? 라는 고민이 있었던것도 사실입니다. 우리 자뻑모드로로 보자면 중요한 영업비밀일지도 모른다고 생각했거든요. 하지만 채용공고가 다소 길지라도 가능한 범위 내에서는 충분히 미리 공유하는게 좋겠다고 생각했습니다. 사실 이런 생각까지는 쉬운데 실제로 이렇게 구조를 잡는건 생각보다 매우매우 오래걸리고 어렵거든요. 그리고 그 어려운걸 우리는 해냈습니다. Components를 잘 구축해놨다 이겁니다 ㅎㅎㅎ다시 한번 말하자면 스마트링크는 로켓이 아니라 은하철도 입니다!! 날아오른다!!! 이거시 바로 은하철도!!!  알겠고, 그렇다면 구체적인 채용정보를 내놓아라!그래서 누굴 뽑는것인가? 라고 물으신다면 개발자 0명 찾습니다! 0명은 무엇이냐? 좋은 사람이 있으면 있는만큼 욕심을 낼것이다! 이런 욕구와 목마름이 있다는 것이죠! 많이 지원해 주세요! 공통적으로 체크해보실 수 있는 정보를 우선 드릴까요? 현재 사용중인 기술 스택 및 도구공통: Google Drive, Trello, Slack기획: FramerX, Adobe XD디자인: FramerX, Adobe XD 포함 Adobe 모든 제품군, ZeplinFront-end: Semantic UI, React, React NativeBack-end: MeteorTesting: Mocha, JestDevOps: Jenkins, Docker, Phusion Passenger, Nginx, AWSDatabase: MongoDB 근무환경최상의 사무 환경 및 공간 제공 (넓고 쾌적한 책상! 빵빵하고 쾌적한 냉난방시설! 막 엎어져서 작업하는 소파! 등) 식대 지원 (중식/석식) 4대 보험 주5일 근무 Refresh 휴가 출근시간 선택제 (8-5 / 9-6 / 10-7 / 11-8)경조사비 지원 근무지: 서울시 서초구 양재동 4-14 3층워크샵이라 하면 적어도 뷔페와 함께하는 야간 요트 유람 정도는 해줘야하는거 아닙니까? (사실 명목은 지스타…)  알겠고, 개발자 채용요건을 내놓아라! 네, 드...드리겠습니다. 아래를 봐주세요. 참고로 위에서 충분히 설명했듯 우선 1등석과 일반석에 모셔요~ ㅎㅎ Global Spec과 실무경험을 국내에서 탑재할 수 있는 기회를 놓치지 마세요! 이제 개알못 기획자는 아웃! React 코드를 보고 이렇게 반응하는 사람이라면 우리는 이렇게 됩니다 ㅎㅎ기술 스택스마트링크는 2001년 부터 C > C++ > Java > Object Pascal > PHP > JSP > Rails > Python 등의 개발 언어 기반으로 많은 프로젝트를 수행하여 왔습니다. 현재는 Javascript, Nodejs, React, React Native, Meteor, MongoDB의 매력에 흠뻑 빠져 있지만, 프로젝트 진행의 효율을 더(even more productive) 개선할 수 있는 새로운 기술이나 방법론에 대한 목마름으로 언제든 Early Adapter가 될 준비가 되어 있습니다.   모집분야 : 각 영역의 Front-end 혹은 Back-end 개발자를 모십니다.Javascript/Nodejs/Meteor 기반의 웹/모바일 애플리케이션 개발자 React + Meteor + MongoDB 기술 기반의 Web Application 개발 React Native + Meteor + MongoDB 기술 기반의 Mobile Native Application 개발  자격요건 : 개발에 미친 사람!!! 자유로운 소통과 공유의 가치를 잘 이해하고, 자기주도적인 환경에서 최대의 능력을 발휘하며, 긍정에너지 발산이 가능한 분 논리적이고 체계적인 문제해결 능력 및 오픈 마인드 커뮤니케이션 능력 전산 관련학과 학사 이상 또는 동일한 자격 (경력 무관)  우대조건 React, React Native 등의 JavaScript SPA(Single Page Application) 프레임워크 경험 Nodejs + MongoDB 기반 Micro Service Architecture 서비스 개발 경험 영어 커뮤니케이션 능력 (특히, 영문서 이해 능력: 해외 최신 기술을 주로 이용하다보니 한글 자료가 없는 경우가 많습니다.) AWS 등 클라우드 서비스 운영 경험 Git 포트폴리오: 직접 작성한 패키지, 오픈소스 기여 경험Docker 컨테이너 기반 서비스 구축 및 운영 경험 CI 시스템 구축 및 운영 경험 Mocha, Jest 등의 테스팅 프레임워크 또는 TDD(Test Driven Development) 경험  어떻게 지원하면 되는거임? 아래 루트로 지원해주시면 서류검토 후 면접일정을 직접 안내해 드립니다. 이메일과 핸드폰 연락처가 모두 기재되어있으면 참 좋겠죠? 면접이 진행되면 스마트링크에 궁금한 것, 알아보고 싶은 모든 것을 물어보실 수 있습니다! 함께 대화하는 자리라고 생각하시는게 가장 좋을거 같네요. 1. 이메일로 지원하세요! [email protected]해당 정보들도 함께 보내시면 금상첨화!이력서 (희망연봉포함)포트폴리오개발 경력 자료 (github 주소 환영합니다!) 2. 로켓펀치에서도 지원하실 수 있습니다!일반석 채용공고 https://www.rocketpunch.com/jobs/574961등석 채용공고 https://www.rocketpunch.com/jobs/57499 3. 잡코리아도 됩니다!스마트링크 은하철도에 탑승할 개발자 정규직 채용(신입&경력)http://www.jobkorea.co.kr/Recruit/GI_Read/28711079?Oem_Code=C1 4. 사람인도 됩니다!스마트링크 은하철도에 탑승할 개발자 정규직 채용(신입&경력)http://www.saramin.co.kr/zf_user/jobs/relay/view?rec_idx=36338553&view_type=etc   지금 망설이고 있다면???국내에서는 중소기업, 특히 신생기업이나 스타트업에 대한 인식이 그렇게 좋지않죠. 이런 현실적인 부분도 감안해서 저희는 직접적인 코딩테스트나 압박면접 같은건 진행하지 않습니다. 차분하고 진실된 마음의 대화가 가장 중요하다고 생각해요. 본인의 평소 생각을 그저 편안하게 나눈다 생각하고 부담없이 관심만 가지고 다가와주세요 :)이 짤처럼 무서운거 아니에요 ㅋㅋㅋ 편하게 드루와 드루와~지금까지 소개해드린 스마트링크 시즌2, 은하철도 프로젝트 느낌이 어떠신가요? 저희의 설렘과 기대가 잘 전달이 되었을지 모르겠어요. 같은 설렘과 기대가 느껴지신다면 망설이지 마세요! 우리의 은하철도에 탑승할 분들을 그야말로 간절한 마음으로 기다리고 있습니다.  지금 당신은 지원 메일을 보내고있다~!!!
조회수 1049

Jeykll에서 플러그인 없이 sitemape 생성하기

오늘은 구글에서 블로그를 검색할 수 있도록 설정하는데에서 크게 삽질했다.. 구글 웹마스터에 사이트맵을 등록해야 했는데 그 사이트맵이 자꾸 테스트를 통과못해서 3시간이나 삽질했다.. ㅠㅠ계속 삽질하다가 찾은 이유는.. _config.yml 파일에 url 속성이 없어서 url을 가져오지 못해 생긴 문제였다. ㅠㅠ 정말 허무하고 신나고.. 아무튼 모든 문제를 해결하여 성공적으로 완료했으니 그 방법에 대해 정리하도록 하겠음.참고한 블로그: 스우의 게임서버와 클라이언트! 미친듯이 영어 검색어들로 오류를 찾으며 삽질했었는데 의외로 한글 블로그에서 이 부분에 대해 언급되어 있어 해결할 수 있었다. 감사합니다 ㅠㅠsitemap 생성하기1. sitemap.xml 파일 생성블로그의 root 디렉토리에 sitemap.xml 파일 생성.2. sitemap.xml 파일 작성하단의 코드를 복사하여 만들어준 sitemap.xml 파일에 붙여넣기.            3. url 설정추가_config.yml 파일에 url 설정이 없는 경우 url 설정을 추가하여 sitemap.xml에서 site.url 변수값을 사용할 수 있도록 해줌. (이 부분 때문에 무한 삽질 ㅠㅠ)4. 구글 웹마스터 툴에서 테스트 혹은 제출구글 웹마스터 툴에서 테스트 혹은 제출을 통해 만들어준 sitemap이 제대로 동작하는지 확인.여태 GA나 기타 여러가지를 설정하느라 공개하지 않았는데 이제서야 공개합니다.제 블로그는 https://heelog.github.io/about/ 입니다!#트레바리 #개발자 #안드로이드 #앱개발 #Jeykll #백엔드 #인사이트 #경험공유
조회수 1625

로봇 공학의 새로운 패러다임! 한화정밀기계의 협동 로봇을 만드는 로봇사업부 인터뷰!

한화정밀기계의 협동로봇 HCR-5 / 출처 - 한화정밀기계 이제 번거로운 작업은똑똑하고 안전한 협동 로봇에게 맡기세요! 제조 산업의 다양한 과정들이 점차 기계화되어가고 있습니다. 기계화의 과정에서도 사람이 개입되어야 하는 번거로운 과정들이 남아있기 마련인데요. 사람이 꼭 필요한 섬세하고 동적인 역할까지 수행하면서 기계의 편리성을 살릴 수 있는 ‘협동 로봇(코봇)’의 탄생으로 그 고민이 해결되었습니다.머지않은 미래에 협동 로봇의 춘추전국시대가 예상되는 가운데, 2017년 시장에 진입한 한화정밀기계의 HCR 시리즈 협동 로봇은 뒤늦게 시장에 합류했지만, 유려한 디자인과 다양한 기능, 안전성을 고려한 특색 있는 제품 생산으로 전 세계 고객들의 사랑을 받으며 점유율을 확대해가고 있습니다. 협동 로봇의 발전으로 개발과 연구를 전문으로 하는 직업도 탄생했는데요. 한화정밀기계에는 협동 로봇 전문가집단인 로봇사업부가 존재합니다. 이 부서의 수장인 장우석 로봇사업부장에게 자세한 이야기를 들어보겠습니다. Q. 안녕하세요. 우선 협동 로봇에 대해 간단히 설명 부탁드립니다!한화정밀기계 장우석 로봇사업부장 / 출처 - 한화정밀기계안녕하세요. 한화정밀기계 로봇사업부의 장우석입니다. 산업 현장에서 사람들을 돕기 위해 만들어진 로봇이 바로 협동 로봇입니다. 이들은 정확성과 일관성이 요구되는 반복적인 업무들을 처리하는데요. 기존의 반복적인 업무를 대신하고, 작업자는 주관적인 판단이나 유연성이 요구되는 일을 할 수 있도록 돕는 것이죠. 현재의 협동 로봇 이전에 주로 사용했던, 기존의 산업용 로봇은 굉장히 한정적인 업무만을 수행할 수 있었습니다. 가령 물건을 하나 옮긴다고 가정하면, 그에 맞는 고난도의 컴퓨터 프로그램을 입력해야 그 일을 할 수 있습니다. 만약 다른 장소로 물건을 옮기려고 한다면 조립공정을 멈추고 중장비를 사용해 옮겨야 합니다. 따라서 시간과 비용이 굉장히 많이 듭니다. 반면 협동 로봇은 이러한 번거로운 과정들을 한 번에 해결해줍니다. 특히, 한화정밀기계의 HCR 협동 로봇은 사용자 친화적인 인터페이스를 갖추고 있어서 작업자가 작동법을 익히는데 하루도 채 걸리지 않습니다. 또한, HCR 협동 로봇의 워크플로를 세팅하거나 변경할 때는 단순히 필요한 항목들만 클릭해 바꾸면 됩니다.싱가포르 합자법인 공장에서 HCR-5를 생산하고 동남아시아 시장에 공급할 예정인 한화정밀기계 / 출처 - 한화정밀기계 Q. 한화가 로봇 산업에 진출하게 된 계기는 무엇인가요?한화그룹은 4차 산업혁명의 일환으로 로봇 산업을 시작했습니다. 다양한 분야 중 저희는 협동 로봇에 초점을 맞췄고, 작년에 국내 최초의 협동 로봇인 HCR 시리즈를 출시했습니다.한화그룹은 항공엔진, 에너지, 산업 장비, CCTV 카메라와 같이 다양한 산업 분야에 관심을 두고 있습니다. 이러한 시장을 키우고 선두가 되기 위해, 한화는 정밀기계, 동작 조종 기술, 사물 인식 소프트웨어, 자동 내비게이션과 같은 분야에서 전문성을 높이고 있습니다. 이러한 모든 것의 중심이 바로 로봇 산업입니다.이렇게 다양한 산업 지식, 경험 그리고 기술을 바탕으로 로봇사업부를 키울 수 있었고, 지금의 HCR 시리즈 같은 제품을 시장에 내놓을 수 있게 된 것입니다. 특히 로봇 공학 분야와 소프트웨어 개발에 매우 높은 전문성을 가진 인력을 보유하여 협동 로봇 기술 개발(R&D)을 빠르게 진전시킬 수 있었습니다. 한화정밀기계와 싱가포르 정밀 엔지니어링 전문 업체인 PBA 그룹의 합자법인 "PBA-Hanwha Robotics"의 개소식 모습 / 출처 - 한화정밀기계  Q. 한화 협동 로봇의 제품 현황과 고객 반응은 어떤가요?한화정밀기계의 협동로봇 HCR-5 / 출처 - 한화정밀기계한화정밀기계는 현재 세 종류의 협동 로봇(HCR)을 출시하였으며, 각각 3kg, 5kg, 12kg의 무게를 들 수 있습니다. 이 세 종류의 협동 로봇은 크기가 작고, 옮기기 쉬우면서 방대한 범위의 업무를 진행할 수 있기 때문에 다양한 업무 지원이 필요한 중소 제조 기업에 이상적인 모델이라 할 수 있습니다. HCR 시리즈의 시장 내 고객 반응은 매우 호의적입니다. HCR 시리즈만이 가진 가장 큰 장점은 사용자가 단일 제어 장치에서 두 개의 HCR 협동 로봇을 실행할 수 있다는 점입니다. 그렇기 때문에 운영비가 최대 10%까지 절감되는 효과가 있죠. 거기에 HCR 시리즈 조작이 쉽다는 점까지 장점으로 작용하면서 시간을 절약하고 생산성을 더욱 높일 수 있습니다.  기능과 안정성을 모두 잡은 HCR 시리즈만의 디자인 또한, 고객들은 HCR 협동 로봇의 수려한 디자인을 가장 크게 평가합니다. 보통 산업용 기계는 튀어나온 부분들이 있어서 긁히거나 부딪힐 위험이 있는데 HCR은 부드러운 곡선 모양으로 제작되어 안전하고 디자인이 뛰어납니다. 산업 디자인은 보이는 게 전부가 아닙니다. 사람들이 협동 로봇과 같이 일할 때 실제로 안정감을 느낄 수 있어야 합니다. 그런 이유로 더 안전하고 부드럽게 보이도록 곡면을 살려 디자인했습니다. 디자인과 기능 면에서도 HCR 시리즈는 매우 안전한 제품입니다. HCR 협동 로봇은 작업자의 옆에서 업무를 보조하는데, 자동 충돌 감지 기능이 있어서 부딪히면 즉각적으로 작동을 멈춥니다. 2017 iF 디자인 어워드, 제품 디자인 부분에서 본상을 수상한 HCR 협동 로봇 / 출처 - 한화정밀기계 Q. 협동 로봇의 미래에 대한 예측과 향후 개발하고자 하는 협동 로봇은?미래에는 AI와 딥러닝, IoT 등 4차 산업혁명을 대표하는 기술들이 접목된 협동 로봇이 시장을 주도할 것이라 예측합니다. 특히 AI와 딥 러닝 기술로 인해 조만간 로봇 산업에는 큰 지각 변동이 있을 것이라 예상합니다. 원래는 5년이나 10년 주기로 일어날 것으로 생각했는데, 이제는 그것보다 더 앞당겨질 것 같네요. 예전에는 몇 년 더 걸릴 것으로 생각했던 기술들이 AI와 딥러닝 기술이 접목된 지 2년 반 만에 이미 구현되고 있으니까요!그래서 한화정밀기계에서는 앞으로 생산될 제품에 AI나 빅데이터, IoT를 어떻게 접목하고, 실제로 어떻게 적용될 수 있을지에 대해 연구하고 있습니다. AI가 접목된 협동 로봇은 어떠한 상황이나 조건에서도 최대한 쉽게 일을 수행할 수 있습니다. 특히 기술 접목 분야에서 한화그룹은 다양한 산업군과 계열사가 있다는 것이 매우 큰 장점인데요. 다양한 계열사에 자문하면서 실제로 협동 로봇이 어떻게 업무에 적용이 되고, 앞으로 어떻게 발전시킬지 논의하고 있습니다. 협동로봇 합자법인 공장 투어 모습 / 출처 - 한화정밀기계 한화정밀기계의 장우석 부장은 피처폰에서 스마트폰 시대로 바뀌었듯이, 로봇 시장도 향후 몇 년 이내로 큰 패러다임 전환이 일어나리라 전망했습니다. 단순히 몇 개의 일을 수행하는 로봇에서 거의 모든 일을 처리할 수 있는 로봇으로 변화하는 것입니다. 협동 로봇 시장은 아직 초기 단계에 있으며 시장 규모도 매우 작지만, 앞으로의 사업 성장 가능성이 매우 큰 분야입니다.한화정밀기계는 현재 유럽과 동남아시아 시장의 큰 성장 가능성을 두고 사업에 박차를 가하고 있는데요. 단기적인 목표는 시장점유율을 매년 두 배로 늘리는 것이며, 장기적인 목표는 협동 로봇 분야에서 세계적인 선도 기업이 되는 것이라고 합니다.4차 산업혁명에 힘입어 자동차와 스마트 팩토리를 중심으로 기술 트렌드를 이끄는 기업을 목표로, 글로벌 로봇 시장을 선도하는 기업이 되기 위해 끝없는 노력을 거듭하고 있습니다. 점차 확대되는 협동 로봇 시장을 선도하는 한화정밀기계의 미래를 함께 응원 부탁드립니다!#한화 #한화그룹 #한화정밀기계 #구성원인터뷰 #직무정보 #기업정보 #기업문화 #비전 #목표 #채용정보 #공채정보
조회수 1004

Good Bye, Parse

한 번도 안 써 본 개발자는 있어도 한 번만 써 본 개발자는 없을 듯한 Parse(parse.com)가 오늘 아침 충격적인 공지 메일을 보내왔는데, 1년후 서비스 종료한다는 것이었다. Parse는 모바일에 특화된 DB 플랫폼을 시작으로, 어드민툴, 푸시, 애널리틱스, 로그인, 크래쉬리포트 등으로 서비스를 확장하며 모바일 개발자들의 백엔드 구축을 편하게 만들어주었는데 2013년 페이스북에 인수되면서 안정성에 대한 신뢰가 커지고, 가격 정책이 변경되어 상당히 저렴해지면서 개발자들의 더욱 큰 호응을 얻었다. 1초에 30개의 요청까진 무료였으니 1개월로 환산하면 7700만 요청이 무료이고, 이는 10만 사용자 이상도 무난하게 대응할 수 있는 숫자이다. 물론 사용자와 요청 수가 늘어나면 월 100~200달러씩 비용을 추가하면 되고 무엇보다 서버 확장에 신경쓰지 않아도 됐다. 푸시 발송은 100만대의 기기까지 발송이 무제한 무료였고 크래쉬리포트와 유저 리텐션 분석도 심플하고 쓸만했는데 무료였다. 역시 무료인 2TB 트래픽은 상용 CDN을 사용하면 수십만원의 비용이 든다.복잡한 쿼리를 작성하기 어렵고 서버사이드 코드를 디버깅하기 쉽지 않아 서버 로직이 복잡한 서비스에는 적합하지 않았지만 계속 보완된다는 느낌이 있고 무료이니 불편해도 감수하고 쓸만 했어서, 이외에는 단점을 찾기가 어려울 정도였다. 무료티어가 워낙 후해서 돈을 내고 쓰는 개발자가 얼마나 될까 싶다는 점이 오히려 불안요소였다. Parse 그리고 페이스북 입장에서 수익성이 어떻게 확보될까 의구심이 들었던 것이다.  수익성 측면에서 무료로 사용하던 앱들의 트래픽이 늘어나 과금티어로 넘어가야 하는데 그러려면 100만 다운로드 이상의 중대형 서비스로 성장해야 하고, 그 정도 되면 그 스타트업도 자체 백엔드 엔지니어가 확보되고 백엔드 로직도 복잡해져 Parse와 궁합이 잘 안 맞게 되는 것이다. 수익성이 아니라면 잠재적인 가치로써 Parse를 사용하는 스타트업과 페이스북의 연결고리를 찾아 유저 베이스를 활용하던지 광고 매체로써 활용하던지 방안이 있어야 하는데 페이스북 자체 패밀리들(페이스북, 메신저, 인스타그램, 와츠앱)의 매체력과 광고수익이 워낙 크고 견고하게 성장하는 중인데다 페이스북 애널리틱스와 외부 광고 서비스가 자리잡으면 Parse는 더더욱 투자가치가 떨어진다. 당장 수익성이 없고, 잠재적인 가치도 잘 모르겠고, 똑똑한 내부 엔지니어들이 묶여 있고, 무료로 쓰는 개발자들은 매일 뭐 만들어달라 뭐 고쳐달라 요청을 하니 '우리가 이걸 왜 붙들고 있어야 하지' 내부 논의가 계속 있어왔을 것 같은데, 그래도 작년 가을까지는 페이스북 코리아에서 Parse 관련 세미나와 컨퍼런스도 열고 미국에서 F8이 열린 시점에는 IoT와 React로 확장하는 등 좀더 적극적으로 활용하려는 듯 했다. 작년 겨울부터 분위기가 이상해졌다. 우선 작년 말 크래쉬리포트 서비스 종료. Parse의 서비스의 일부이긴 했지만 다른 대안과 비교해서 확실한 우위가 있던 서비스여서 '수익성'의 이유 외에는 정리할 이유가 없어보였다. 그 동안 문제 삼지 않았던 '수익성'이 이제는 문제가 된건가? 그러면 사실 Parse 전체 서비스도 접을 수 있다는 생각이 들었다. 그리고 이어서 나온 '오픈소스화'와 'Heroku 연동'. 오픈소스는 좋은 의미 또는 서비스의 발전을 위해서라고 볼 수도 있는데 Heroku 연동은 굳이 왜? Parse 입장에서나 Parse를 쓰는 개발자 입장에서나 백엔드를 Parse 클라우드 코드 대신 Heroku로 이동할 이유가 없어 보였다. Parse를 접게 되어 마이그레이션 해야 한다면 모를까...??? 가 현실이 되었다.나도 작년까지는 서버비 한 푼 내지 않고 대부분의 서비스를(수십개) Parse에 올렸었고 주변에나 Parse 세미나에서도 Parse의 장점에 대해 이야기하곤 했는데... 수익성 없는 앱들을 정리하면서 Parse에 대한 의존도가 낮아지긴 했지만 지금 제작하고 있는 것들부터 마이그레이션 해야 하고, 추천했던 지인들에게는 마이그레이션 전략을 컨설팅해야 할 판이다. 서비스 종료라는 극단적인 선택을 하기 전에 무료 티어를 좁혀서 수익화를 한 상태로 좀더 오래 버텨줬으면 어땠을까 하는 아쉬움이 든다. 구글앱스도 수익화를 하면서 유지하듯이. 광고 외의 B2B 비즈니스에서 페이스북에 대한 신뢰가 많이 하락하지 않을까 싶다. 마이그레이션 비용은 상당하다. 우선 Parse의 슬로건이 백엔드 작업 없이 백엔드를 이용할 수 있는 것이었기 때문에 이제 백엔드를 직접 구성하던지 Parse가 제공하던 서비스들의 대체제들을 각각 찾아 옮겨야 하고, 초기부터 그런 대안으로 구축한 것보다 이전하는 비용이 훨씬 큰 것은 당연하다. 클라이언트 엔지니어가 Parse로 구축했다가 아직까지 백엔드 엔지니어가 없는 서비스들은 그냥 정리될 가능성도 크다. 사실 백엔드 서비스들의 이용료 자체는 많이 낮아진 상태이기 때문에 여기서 말하는 마이그레이션 비용은 대부분 외주/컨설팅이나 백엔드 개발자 채용 등의 엔지니어링 비용이다. 나도 대안들을 이제 막 찾기 시작했지만 이전할 수 있는 대안들을 정리하면서 마무리해본다. Parse DB: http://firebase.com/ (구글이 인수했다. 데자뷰의 느낌이 들 수도 있지만 그래도 믿어보자)Parse Push: http://valuepotion.com/ (푸시 & 분석& 마케팅툴 - 카카오 국내 자회사의 글로벌 서비스)https://www.pushwoosh.com/ (urbanairship보다 저렴하다고)Parse Crash Reporting: http://crashlytics.com (트위터 인수, 과거에 유료였으나 무료로 전환됨)Parse Cloud Code:http://heroku.com/ (Parse의 Heroku 연동과 함께 살펴보자)https://github.com/ParsePlatform/parse-server (Parse에서 제공한 서버 오픈소스. 이를 활용한 마이그레이션 서비스가 나올 듯 싶다)
조회수 2727

PHP CI 환경에서 완전한 Vue 사용하기

편집자 주Vue 또는 VUE로 혼용하나 공식 사이트의 표기에 맞춰 아래와 같이 통일함-Vue-Vuex-Vue-Router목차1.Controller2.VIEW3.webpack Vue 소스 진입점4.webpack 설정5.Package.json6.Vue-Router7.Vuex8.공통 처리 mixin9.요약10.마치며시작하며드디어 브랜디 관리자 서비스에 Vue를 도입하고자 떠났던 여정의 마지막 장입니다. 브랜디 관리자 서비스는 PHP Codeigniter와 jQuery로 구성되어 있습니다. 사실 잘 운영되고 있는 서비스에 리스크가 큰 신기술을 도입하는 것은 도박에 가깝습니다. 몇 시간만 운영이 정지되어도 회사에 엄청난 피해를 안겨줄 수도 있으니까요. 하지만 여러 번의 검증과 실험으로 도박에서 이길 확률을 100%에 가깝게 끌어올린다면 한번 도전해볼 만하지 않을까요?이전 글인 PHP Codeigniter 환경에서 VUE 사용해보기에서 기본적인 webpack + Vue + Codeigniter 환경 구축 방법을 알아봤는데요. 하지만 단순히 webpack과 Vue만 적용했다고 해서 “우리 시스템은 UI 프레임워크로 Vue를 사용하고 있습니다.”라고 말할 순 없습니다. 아주 중요한 숙제가 남았죠.Vue에는 활용도를 대폭 끌어올려주는 Vue-Router와 Vuex Store1)가 있는데 그중 Vue-Router를 이번 글에서 자세히 다루려고 합니다.2) Vue-Router는 Vue.js의 공식 라우터입니다. 공식 홈페이지의 소개는 아래와 같습니다.중첩된 라우트/뷰 매핑모듈화된, 컴포넌트 기반의 라우터 설정라우터 파라미터, 쿼리, 와일드카드Vue.js의 트랜지션 시스템을 이용한 트랜지션 효과세밀한 내비게이션 컨트롤active CSS 클래스를 자동으로 추가해주는 링크HTML5 히스토리 모드 또는 해시 모드(IE9에서 자동으로 폴백)사용자 정의 가능한 스크롤 동작한마디로 정리하면 입력된 URL에 반응해 부분에 해당 URL의 view를 보여주는 기능인 것입니다. 다시 말해 URL이 변경될 때 한 페이지에서 화면 전체를 갈아끼우거나, 화면의 일부분(부분)을 치환해주는 역할을 한다는 것이죠. 더 나아가 해당 화면이 로드되기 전후로 전처리, 후처리 기능까지 가능합니다.착안점Vue와 Vue-Rotuer를 알게 되었을 땐 PHP 기반 프로젝트에 Vue-Router를 적용할 수 없으니 처음부터 새로 만들어야 한다고 생각했습니다. 로그인 인증 문제, 메뉴의 권한 관리 등 모든 것이 Vue 아래에 있어야 한다고 생각했기 때문입니다.어느 날 관리자 서비스에 TDD를 구현해보려고 Python Flask + webpack + Vue 프로젝트를 구성하고 있었습니다. 그러던 중 우연히 Flask + Vue-Router에서 404 페이지를 처리하려면 Flask Fallback 페이지를 Vue-Router 메인 페이지(가 있는 페이지)로 보내고, Vue-Router에서 진짜 매핑된 URL이 없으면 404 처리를 하는 식으로 구성한다는 글을 읽고 문득 호기심이 생겼습니다.‘관리자 서비스에서도 컨트롤러로 여러 URL을 한 가지 페이지로 보낸다면?’PHP를 거쳐 페이지로 이동한 것이므로 권한 관리와 메뉴 트리까지는 PHP에서 처리되면서 URL이 변할 것이고, 실제로 화면을 보여주는 Contents 영역만 를 사용한다면 어떻게 될지 궁금해졌습니다. 바로 하던 일을 멈추고 관리자 소스에 Vue-Router를 활용한 테스트 소스코드를 작성해봤습니다.예상했던 대로 PHP의 로그인 인증 처리를 거치면서 실제로 보이는 부분에는 부분만 정상적으로 치환되었습니다. 이 간단한 실험을 바탕으로 통계 시스템의 일부를 구현하는 데에 Vue-Router와 Vuex Store, 공통 처리 Mixin을 추가해 제작했습니다.1.Controller4개의 페이지를 가진 통계 시스템의 Codeigniter 컨트롤러 모습입니다. 기존의 서비스 URL들이 존재하기 때문에 Fallback을 통으로 Vue-Router로 보낼 순 없었고, 라우터를 사용할 페이지들을 하나의 페이지로 보냈습니다.1-1) /application/controllers/[컨트롤러 경로]... 생략 /* [라우터 view]에서 태그를 포함하고 있습니다. */ public function salesAnalysisProduct() { $this->load->view('[라우터 view]'); } public function salesAnalysisSeller() { $this->load->view('[라우터 view]'); } public function trendAnalysisProduct() { $this->load->view('[라우터 view]'); } public function trendAnalysisSeller() { $this->load->view('[라우터 view]'); } ... 생략 2.VIEWCodeigniter 환경에 반영하는 것이므로 CI에서 인식시킬 PHP view와 webpack에서 빌드 결과를 자동으로 바인딩할 html 파일로 구성됩니다.2-1)/application/views/[Vue용 view 경로]/index.php// [index.php] Vue 를 매핑할 php파일 컨트롤러의 view로딩용 [라우터 view]입니다. ... header, menu 생략 ... //바인딩될 부분 //자동매핑 html 인클루드 <?php include('index.html'); ?> ... footer 생략 ... 2-2)/application/views/[Vue용 view 경로]/index.html webpack의 빌드 결과로 자동으로 생성되는 파일입니다. [removed][removed] 위는 webpack의 HtmlWebpackPlugin에 의해 자동으로 바인딩된 모습입니다. 빌드되기 전 index.html은 다음 항목에 있습니다.3.webpack Vue 소스 진입점관리자에서는 프로젝트 폴더 안에 webpack과 Vue 용 서브 폴더를 두고 webpack.config.js에서 output 옵션을 통해 빌드 결과를 삽입하는 구조입니다. webpack 루트 폴더는 application 폴더와 같은 레벨에 위치하며, 폴더 구조나 파일 위치는 어디에 둬도 상관없습니다. webpack.config.js에서 entry 속성으로 잡아주시면 됩니다.3-1)/[webpack루트]/index.html// HtmlWebpackPlugin으로 스크립트를 삽입하기 위한 빈 템플릿 파일 3-2)/[webpack루트]/index.js/** * 진입용 index.js */ import Vue from 'vue' import axios from 'axios' import router from './router' import App from './App.vue' Vue.prototype.$http = axios new Vue({ el : '#app', router, components : { App }, template : '' }); 3-3)/[webpack루트]/App.vue [removed] import mixin from './common/common-mixin.js' import store from './vuex/store' export default { store, name : 'App' } [removed] Vuex와 통신 모듈 axios, Vue-Router 등을 루트 Vue 객체에 추가해줍니다. 브랜디 관리자의 webpack은 babel을 사용하고 있기 때문에 위의 store처럼 축약해서 작성하면 빌드된 파일에는 store: store와 같이 입력됩니다.Vue-Router는 태그에 자동으로 매핑되며, 위와 같은 구조로 상위 컴포넌트에서 할당되어 있어야 합니다. Vuex와 Vue-Router 설정은 글 아래에서 다루겠습니다.4.Webpack 설정이번에 Vue-Router와 Vuex를 도입하면서 webpack의 설정도 실제 서비스용과 개발용으로 분리했습니다. 폴더는 편의상 추가하였으며, package.json에서 자신이 설정한 경로로 설정하면 됩니다.Webpack 설정 파일은 Webpack의 시작과 끝이라고도 할 수 있습니다. Webpack 설정 파일에서 빌드할 소스의 경로와 빌드 결과 파일의 명명 규칙을 정하고, html 파일에 스크립트파를 자동으로 주입시키거나, Babel 플러그인을 통해 최신 스크립트 작성법을 브라우저를 신경쓰지 않고 사용할 수도 있습니다.그중에서도 중요한 옵션이 있는데 바로 Code Splitting에 관련된 옵션입니다.관리자 초기 Vue 모델에는 Vue-Router가 없었기 때문에 js 번들 파일의 크기가 그렇게 크지 않았습니다. 하지만 Vue-Router를 사용해 싱글 페이지 어플리케이션이 되거나 화면의 UI가 복잡해 컴포넌트 수가 많아지면 번들 js 파일의 크기가 매우 커집니다. 즉, 캐시를 사용하지 않는 익스플로러라면 소스에서 한 글자만 바뀌더라도 모든 페이지에서 거대한 번들 js를 새로 로딩하게 되고, 상당한 서버 자원을 소모합니다.Code Splitting 적용 전위의 이미지는 Code Splitting을 적용하기 전의 번들 js 정보입니다. 실제로 완성된 Vue 프로젝트의 번들 js는 더욱 큽니다. 정말 단순한 페이지 하나를 띄우는데 매번 뚱뚱한 js를 로딩해야 하는 것은 서비스 제공자와 서비스 사용자를 모두 괴롭게 할 것입니다.Code Splitting 적용 후하지만 위처럼 작은 조각으로 나눠 필요한 시점마다 필요한 번들 js만 로드하면 매우 빠른 페이지를 제작할 수 있습니다. 따라서 Code Split 기능은 매우 중요한 이슈입니다.물론 개발을 진행하다 보면 역시 어느 것 하나 쉽게 넘어가지지 않습니다. 관리자의 웹팩은 4.x 버전대를 사용하고 있습니다. 예전에 TF에서는 Webpakc 3.x 버전대를 사용하였는데 당시에는 CommonChunkPlugin 설정을 통해 Code Splitting을 사용할 수 있었습니다. 그대로 관리자에 적용하려 했는데..Removed라고 쓰여 있습니다. 찾아보니 CommonChunkPlugin이 옵티마이즈 옵션 하위의 splitChunk 속성으로 들어가면서 설정 방법이 바뀌었더군요. 머리를 싸매고 설정을 잡습니다.4-1) /[webpack루트]/build/webpakc.config.js : 공통 설정파일'use strict' const HtmlWebpackPlugin = require('html-webpack-plugin'); const { VueLoaderPlugin } = require('vue-loader'); const path = require('path'); module.exports = { entry: { //string, object, array 가능 - 기본은 ./src app: path.join('[스크립트 파일 경로]', 'index.js') //진입점 스크립트 파일입니다. }, output: { path: '[빌드된 js 목적지 경로]', publicPath: '[이미지등의 웹상 리소스 경로]', filename: './[name].[chunkhash].js', // 엔트리 파일명명규칙 chunkFilename: '[id]_[chunkhash].js', // chunk파일 명명 규칙 // --mode development에서는 [id]에도 chunkName들어갑니다. }, //vue와 js, css 로드 규칙을 설정합니다. module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', include: [ /[Vue 소스 경로]/ ] }, { test: /\.js$/, use: { loader: 'babel-loader?cacheDirectory', }, include: [ /[Vue 소스 경로]/ ] }, { test: /\.css$/, oneOf: [ { use: [ 'vue-style-loader', 'css-loader' ] } ] } ] }, resolve: { alias: { '@': '[Vue소스 경로]', // 편의상 소스단축경로를 설정합니다. }, //파일 확장자 자동인식 임포트시 해당 확장자는 생략가능합니다. extensions: ['.js', '.vue', '.json'], }, plugins: [ // Vue 파일 로더 new VueLoaderPlugin(), // html 자동 바인딩 // 아래의 플러그인으로 인해 index.html에 해시네임으로 빌드된 index.js가 자동으로 매핑됩니다. new HtmlWebpackPlugin({ // index.php에서 include할 파일이 생성될 경로와 파일명 입니다. filename: path.join('[View경로]', 'index.html'), // 자동으로 매핑할 진입점파일을 지정합니다. template: path.join('[Vue소스 경로]', 'index.html'), inject: true, minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true } }), ], optimization: { //웹팩 4.x 버전에서 옵티마이즈 속성으로 추가된 CodeSplitting 기능입니다. splitChunks: { //initial - static파일만 분리, async - 동적로딩파일만 분리, all - 모두 분리 chunks: 'async', minSize: 30000, minChunks: 1, maxAsyncRequests: 5, //병렬 요청 chunk수 maxInitialRequests: 3, //초기 페이지로드 병렬 요청 chunk수 automaticNameDelimiter: '_', //vendor, default등 prefix 구분문자 (default : '~') name: true, //development모드일때 파일에 청크이름 표시여부 cacheGroups: { default: { minChunks: 2, //2개 이상의 chunk priority: -20, reuseExistingChunk: true //minChunks이상에서 사용할경우 공통사용 }, //axios, vue 같은 공통 모듈은 vendor로 관리합니다. vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 } } } } }; 4-2) /[webpack루트]/build/webpack.dev.config.js 개발용 설정 파일 (네이밍은 자유)'use strict' const merge = require('webpack-merge') const webpack = require('webpack') const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin const baseWebpackConfig = require('./webpack.config') const config = require('../config').dev //개발용설정 const devWebpackConfig = merge(baseWebpackConfig, { //mode는 chunk[id], 디버깅 코드 등에 영향을 줍니다. webpack 3.x 버전에서는 Env 속성을 통해 관리했다고 합니다. mode: 'development', plugins: [ new BundleAnalyzerPlugin(), //번들 무게 분석기 제대로 스플릿 되었는지 확인할 때 사용합니다. new webpack.DefinePlugin({ env : config.env }), ], watch: true, //코드의 변화를 감지해 자동으로 재빌드해주는 옵션입니다. cache: true, //캐시 사용을 활성화하면 변경사항이 있는 코드만 재빌드합니다. optimization: { //uglify 플러그인 코드 압축 여부를 설정합니다 압축 시 용량을 매우 줄일 수 있으나 빌드 속도가 크게 저하되므로 개발 시에는 꺼줍니다. minimize: false, } }) module.exports = new Promise((resolve, reject) => { resolve(devWebpackConfig); }) 4-3) /[webpack루트]/build/webpack.prod.config.js 서비스용 설정파일 (네이밍은 자유)'use strict' const merge = require('webpack-merge') // 설정파일 결합에 사용합니다. const webpack = require('webpack') const baseWebpackConfig = require('./webpack.config') //베이스 설정파일 const config = require('../config').prod //서비스용 설정 const prodWebpackConfig = merge(baseWebpackConfig, { mode: 'production', //chunk[id], 디버깅 코드등 영향 있음 plugins: [ new webpack.DefinePlugin({ env : config.env }), ], //개발용과 반대로 용량은 줄이고 필요 없는 기능은 꺼줍니다. watch: false, cache: false, optimization: { minimize: true, } }) module.exports = prodWebpackConfig 5.package.json웹팩 설정 파일이 분리되면서 package.json의 런 스크립트도 변경했습니다.... "scripts": { "build": "webpack --config build/webpack.prod.config.js --progress", "build-dev": "webpack --config build/webpack.dev.config.js --progress" }, ... 6.Vue-RouterVue-Router는 위에서 설명한 대로 Vue의 컴포넌트와 밀접하게 결합된 라우터입니다. 그런데 여기서 webpack의 Code Split을 사용하려면 컴포넌트 import 방법이 매우 중요한데요.import './testComponent' 위처럼 import 구문을 사용해 컴포넌트를 불러오면 코드가 쪼개지지 않고 한 덩어리로 빌드되므로 아래와 같은 형태로 사용해야 합니다.const testComponent = () => import('./testComponent') webpack 공식 문서에도 나와있듯이 위처럼 ES2015 Loader spec에 있는 import()를 사용하여 컴포넌트를 생성해야 번들 js가 제대로 분리되며, Dynamic Import가 가능해집니다.Vue-Router를 쓰는 순간 싱글 페이지 어플리케이션이 되기 때문에 이곳에서 설정을 잘못 잡아주는 순간 육중한 컴포넌트 한 덩어리가 튀어나오면서 Code Splitting은 물거품이 되어버립니다. 조심합시다!또한 import 함수 안쪽엔 아래와 같은 주석을 달아야 청크 이름이 적용됩니다.const testComponent = () => import( /* webpackChunkName: '[청크이름]'*/ './testComponent') 라우터 경로 속성인 path 와 Codeigniter의 컨트롤러 경로를 맞춰주는 것이 포인트입니다!6-1) /[webpack루트]/router/index.js - 경로와 파일명은 자유입니다!import Vue from 'vue' import Router from 'vue-router' // 주석의 webpackChunkName = 코드 스플릿 chunk Name으로 사용됩니다. // 꼭 컴포넌트와 청크 이름을 같게 설정할 필요는 없습니다. const SalesAnalysisProduct = () => import(/* webpackChunkName: "salesAnalysisProduct" */ '[컴포넌트 파일 경로]') const SalesAnalysisSeller = () => import(/* webpackChunkName: "salesAnalysisSeller" */ '[컴포넌트 파일 경로]') const TrendAnalysisProduct = () => import(/* webpackChunkName: "trendAnalysisProduct" */ '[컴포넌트 파일 경로]') const TrendAnalysisSeller = () => import(/* webpackChunkName: "trendAnalysisSeller" */ '[컴포넌트 파일 경로]') Vue.use(Router) const router = new Router({ mode: 'history', routes: [ /* 통계 */ { path: '[CI컨트롤러 url]/salesAnalysisProduct', name: 'salesAnalysisProduct', component: SalesAnalysisProduct }, { path: '[CI컨트롤러 url]/salesAnalysisSeller', name: 'salesAnalysisSeller', component: SalesAnalysisSeller }, { path: '[CI컨트롤러 url]/trendAnalysisProduct', name: 'trendAnalysisProduct', component: TrendAnalysisProduct }, { path: '[CI컨트롤러 url]/trendAnalysisSeller', name: 'trendAnalysisSeller', component: TrendAnalysisSeller }, ] }) // 아래의 함수로 전처리 후처리도 가능합니다! router.beforeEach((to, from, next) => { // ... }) router.afterEach((to, from) => { // ... }) export default router 7.Vuex앞서 Vue와 Vuex, 컴포넌트간 통신과 상태 관리에서 소개했던 상태 관리와 통신을 위한 Vuex도 추가합니다. Vuex는 하나의 Store만 쓸 경우 상태 변수의 과포화로 인해 유지 보수가 어려워질 수 있으므로 namespace: true 옵션을 통해 도메인별로 관리합니다.7-1) /[webpack루트]/vuex/store.js - Vuex 진입파일import Vue from 'vue' import Vuex from 'vuex' // 각 도메인별 store들이 들어있는 modules 를 임포트해줍니다. import * as modules from './modules/index' Vue.use(Vuex) export default new Vuex.Store({ state : { }, getter: { }, mutations : { }, actions : { }, modules : modules.default }) 7-2) /[webpack루트]/vuex/modules/index.js - 도메인별 Store 자동 바인딩 스크립트const files = require.context('.', false, /\.js$/) const modules = {} //자신(index.js)를 제외한 파일들을 파일이름을 Key로 modules에 담습니다. files.keys().forEach((key) => { if (key === './index.js') return modules[key.toLowerCase().replace(/(\.\/|\.js)/g, '')] = files(key).default }) export default modules 7-3) /[webpack루트]/vuex/modules/statistics.js(통계 store 파일) - 예시입니다.export default { namespaced : true, //해당 속성을 통해 파일명을 namespace로 사용합니다. state: { /* 상태값 및 데이터 */ ... }, getters: { }, mutations: { /* state 변경처리 */ ... }, actions: { /* 통신처리 */ ... } } namespace: true로 되어있으므로 파일명인 statistics를 namespace로 사용하게 됩니다. 따라서 store 각 항목에 대한 접근은 다음과 같이 이뤄지며 computed 속성에 state: this.$store.state.statistics 처럼 정의해두면 편리합니다.dispatch는 this.$store.dispatch(‘statistics/[action 이름]’)commit은 this.$store.commit(‘statistics/[mutation 이름]’)state 변수 접근은 this.$store.state.statistics.[state 이름]8.공통 처리 mixinapi 통신에 사용되는 통신 라이브러리와 그 라이브러리의 복잡한 설정 코드, 단순한 Toast 출력 함수, 로딩 이펙트를 보여주는 함수 등 모든 항목들이 매 페이지마다 있으면, 통일되지 못한 UI, 페이지마다 일관되지 못한 설정 등으로 휴먼 에러가 발생할 확률이 높아집니다. 유지 보수 측면에서도 비용이 높아집니다. 이러한 단순 반복 코드들은 한번만 정의하고 재사용하는 것이 바람직합니다. 나중에 수정할 때도 용이하죠.공통사항을 묶어 Vue 전역 믹스인으로 Vue 루트 객체에 추가합시다. 단, global 옵션인 만큼 조심해서 써야 합니다. 시스템에 영향을 줄 것 같으면 하위 컴포넌트 mixins 속성에 넣어 해당 스코프에서만 사용하는 것이 바람직합니다.8-1) /[webpack루트]/common/common-mixin.js (파일이름, 경로는 자유입니다!)import Vue from 'vue' import Vue from 'axios' import Cookies from 'js-cookie' const TIMEOUT = '[타임아웃 시간(ms)]' /* mixin의 기본 형태는 Vue 컴포넌트의 형태와 동일합니다. 주로 전역 통신과 상태 관리는 vuex store에서, 전역 data 속성과 전역 함수는 mixin에서 관리합니다. */ Vue.mixin({ /* 전역 사용 data속성 선언 */ data: () => { return { ... //이곳에 선언하는 data 속성은 전역에서 this로 접근 가능합니다. } }, created: function() { // 공용 axios 객체 생성 this.axios = axios.create({ timeout: TIMEOUT, withCredentials: true, //공통해더는 여기에 headers : { } }); //axios 의 success와 error를 mixin method에서 처리 하도록 등록 this.axios.interceptors.response.use(this.onSuccess, this.onError) }, /* 전역 사용 함수 선언 */ methods: { /* axios의 response handling 함수*/ onSuccess : response => { }, onError : function (error) { }, /*GET, POST 등의 통신 함수, Toast(alert) 표출함수, 에러핸들링함수 등 선언*/ /*... 내용이 너무 길어서 생략 ...*/ } }); 9.요약지금까지의 내용은 파일 경로를 토대로 요약하면 다음과 같습니다. 참고로 아래의 폴더 구조는 절대적인것은 아닙니다. 모든 폴더 구조는 자율이며, 폴더 구조에 맞게 webpack.config.js에서 조정해주면 됩니다.[프로젝트 루트] └ [웹팩 루트] └ package.json └ [Vue 소스 루트] └ [common] └ [router] └ index.js // 라우터 설정파일 - CI 컨트롤러와 url 맞춰줘야함 └ [vuex] └ index.js // 도메인별 store module export 스크립트 └ [modules] └ 도메인별 store.js └ [컴포넌트 폴더] //예시에서는 ststistics └ App.vue //진입점 vue파일 Vuex와 전역 mixin 세팅 └ index.html //index.js가 주입될 껍데기 └ index.js //진입점 js Vue-Router와 App.vue 세팅 └ [build] // 빌드파일경로 └ webpack.config.js //베이스 설정파일 └ webpack.dev.config.js //개발용 설정파일 └ webpack.prod.config.js //서비스용 설정파일 └ [application] //Codeigniter 루트 └ [controllers] └ [컨트롤러 경로] // 예시의 통계부분 └ [views] └ [웹팩빌드 결과 폴더] └ [index.php] // CI 에서 로드하는 view (index.html include) └ [index.html] // js 번들이 자동 주입된 빌드결과 파일 └ [include] └ [scripts] └ [빌드결과 js 경로] //public path 속성 경로 └ 빌드 결과 js chunk들 마치며관리자 서비스에서 완전한 Vue를 사용하기 위해 꽤 험난한 과정을 거쳤습니다. 지금도 잘 돌아가는 서비스에 리스크를 감수하면서도 새로운 것을 도입하려는 이유를 찾아야 했고, 한동안은 레거시와 Vue로 된 소스를 2중으로 개발해야 했습니다.게다가 이 글을 작성하기 시작했을 땐 Code Splitting 설정 방법이 바뀌어 적용하지도 못한 상황이었기 때문에 사실 Code Splitting 내용이 없었습니다. 그런데 글을 작성하면서 splitChunk옵션을 성공해버렸어요! 덕분에 이 글도 모두 수정해야 했죠. Vue의 도입을 고려하는 개발자분들에게 도움이 되길 바라는 마음으로 글을 마칩니다.참고1)Vuex Store는 Vue와 Vuex, 컴포넌트간 통신과 상태 관리에 자세히 정리해두었다.2) 브랜디 관리자 서비스는 jQuery로 작성되어 있다. 따라서 jQuery를 베재할 수만은 없는 상황이었다. 이에 따라 기존 jQuery 컴포넌트들에 대한 해결책은 천보성 팀장님이 작성한 JQuery 프로젝트에 VUE를 점진적으로 도입하기를 참고했다. props와 emit 기능을 이용해 jQuery로 제작한 컴포넌트를 깔끔하게 Wrapping 하는 방법에 대해 자세히 기술되어 있으며, 이를 활용하면 레거시 UI 플러그인을 마치 네이티브 Vue 플러그인처럼 사용할 수 있다.글강원우 과장 | R&D 개발2팀[email protected]브랜디, 오직 예쁜 옷만
조회수 1394

웹 서비스 개발자가 APM을 사용해야 하는 이유

백엔드 서비스를 만들고 운영하는 개발자라면, 지금 바로 APM 서비스를 사용해 보세요. 와탭의 APM은 국내 수많은 Enterprise 기업에서 자사의 서비스를 분석하기 위해 사용되고 있으며 많은 효과를 보고 있습니다. 북미에서는 이미 수많은 스타트업이 DevOps의 기본 도구로 APM을 선택하고 있습니다. APM은 원래 대규모 서비스를 운영하는 분들이 전문적으로 사용하고 있었지만 최근 트렌드는 운영자에서 개발자로 이동하고 있는 서비스 이기도 합니다. 특히 와탭의 APM은 개발자 분들을 위한 스택 분석 기능이 있습니다. 개발자라면 와탭 APM 서비스가 제공하는 아래의 3가지 스택 분석 기능을 꼭 사용해 보세요. 유니크 스택탑 스택액티브 스택많은 개발자들이 자신이 만든 서비스가 어떻게 동작하는지 또는 웹 서비스에 어떤 영향을 주고 있는지 알지 못합니다. 하지만 와탭 애플리케이션 성능 모니터링(APM) 서비스를 사용하면 메소드가 애플리케이션에서 어떻게 사용되는지 얼마나 사용되는지 알수 있습니다. 와탭은 다른 APM 서비스와 다르게 10초에 한번씩 활동중인 트랜잭션을 검사하여 트랜잭션에 콜스택정보를 저장하고 있습니다. 그리고 이렇게 저장된 스택정보를 가지고 3가지 형태로 가공하여 보여주는데, 이 것이 유니크 스택 / 탑 스택 / 액티브 스택입니다. 먼저 유니크 스택은 가장 많이 사용된 스택 정보를 보여주는 방식입니다. 트랜잭션에서 실행되고 있는 메소드가 A 이고 이를 호출한 메소드가 모두 일치하는 스택을 유니크 스택이라고 합니다.1. A() ← C()2. A() ← C()3. B() ← D()4. B() ← E()5. B() ← F()위와 같은 경유 유니크 스택은 아래와 같이 통계를 내어 보여 줍니다. 40% A()    A()    C()20% B()    B()    D()20% B()    B()    E()20% B()    B()    F()이렇게 콜스택 정보 전체를 기준으로 분석을 하는 경우에는 성능에 영향을 주는 기능 단위의 분석이 가능합니다. 하지만 성능에 영향을 많이 주는 메소드를 알고 싶을 때가 있습니다. 이런 경우에 사용하는 것이 탑 스택 분석입니다. 아까와 같은 상황을 예를 들겠습니다.1. A() ← C()2. A() ← C()3. B() ← D()4. B() ← E()5. B() ← F()이런 상황에서 탑 스택 분석은 아래와 같이 가장 많이 사용되느 메소드를 알려줍니다. 60% B()    33% D()    33% E()    33% F()40% A()    100% C()유니크 스택에서는 A() ← C() 가 가장 많이 사용된 스택이라는 것을 알려주지만 탑 스택에서는 B() 메소드가 가장 많이 사용된 메소드라는 것을 알려줍니다. 이 두가지 내용을 통해 가장 많이 사용되는 메소드의 집합가 가장 많이 호출되는 메소드를 알아 낼 수 있습니다. 만일 서비스를 메소드 단위에서 개선하고 싶다면 이 정보를 기반으로 개선 작업을 진행하면 많은 도움을 받을 수 있습니다. 위에 화면에서 메소드를 선택하면 메소드를 호출한 스택들의 정보를 확인 할 수 있습니다. 마지막으로 액티브 스택입니다. 액티브 스택은 WAS 서버와 URL 그리고 발생 시간을 기준으로 저장된 콜스택의 정보를 보여줍니다. 서비스 성능이 떨어진 시간대의 콜스택 정보를 확인 함으로써 메소드 구간에서의 튜닝 정보를 제공합니다. 액티브 스택은 핵심 기능이 하나더 있습니다. 바로 서비스가 동작하는 스탭정보에 통합됨으로써 문제를 바로 확인할 수 있는 기능입니다. 와탭의 APM에서만 분석가능한 기능이며 특허로 등록되어 있습니다. 액티브 스택은 통계 관점이 아니라 실행 관점에서 문제를 바라보고 있습니다. 우리가 만든 웹 어플리케이션을 고객에 입장에서 보면 아래와 같이 동작합니다. 고객 → 웹 서비스 요청 → 서버 접속 → 서비스 접속 → 애플리케이션1 → 메소드 1 → DB 1접근 → Query 1 → Query 2 → 메소드 2 → 파일 접근 → 메소드 3 → 결과 취합 → WAS 통과 → 웹 서비스 결과 반환 일반적으로 애플리케이션 모니터링은 이런 상항을 아래와 같이 보여줍니다. 서비스 접속 → Query 1 → Query 2 → 파일 접근 → 트랜잭션 종료와탭의 애플리케이션 모니터링은 수집된 콜 스택 정보를 기반으로 아래와 같이 보여줍니다.  서비스 접속 → Query 1 → 메소드 2 → Query 2 → 파일 접근 →메소드 3 → 트랜잭션 종료위에 상황은 트랜잭션에서 메소드 2와 메소드 3이 수집된 경우에 트랜잭션의 스탭의 실행시간에 맞쳐서 정보를 재구성하는 것을 보여주고 있습니다. 이렇게 확인하게 된다면 메소드에서 발생하는 성능 문제를 확인 할 수 있습니다. APM 서비스는 와탭 / 뉴렐렉 / 데이터 독과 같은 서비스들을 통해서 2주에서 한달간 언제든 무료로 사용가능합니다. 다만 메소드에 대한 분석 기능은 와탭의 APM에서만 제공하는 기능들이 많습니다. 개발자라면 한번쯤 와탭의 APM 서비스를 통해 자신이 만들고 운영하고 있는 서비스에서 가장 많이 사용되는 메소드가 무엇인지 확인 해 보시기 바랍니다. Tip!! APM은 개발시에 사용하는 디버깅 도구라기 보다는 막대한 량의 트랜잭션이 발생하는 운영과정에서 사용되는 도구입니다. 트랜잭션 자체가 적다면 원하는 데이타가 안 나올 수 도 있습니다. 와탭으로 모니터링 하기 - 목차 바로가기#와탭랩스 #개발자 #개발팀 #인사이트 #경험공유 #일지 #서비스소개
조회수 2049

출시의 기록 - #1 랜딩페이지

이 글은 "친구끼리 쓰는 라이브 스트리밍 앱, 라이비오(LIVEO)"의 앱 출시 과정을 담는 글입니다. 어디까지나 현재 겪고 있는 과정을 기록하는 것으로, 최선의 방법이 아닐 수도 있으니 더 좋은 방법이 있다면 언제든지 소개 부탁드립니다.앱을 출시하게 되면서 가장 먼저 준비하게 되는 것 중에 하나. 웹사이트이다.지난 사업인 위제너레이션이나 오드리씨 모두 웹 사이트 자체가 중심이 되는 사업이었기에, 팀 내에 웹 개발자가 있었고 직접 사이트 제작을 건드려야 할 일은 따로 없었다.그러나 라이비오라는 앱 서비스를 준비하게 되면서, 팀 내 개발자들은 앱 서비스 개발에 바쁘고 웹 사이트는 기본적인 소개의 역할만 담당하면 되기 때문에, 직접 사이트를 만들게 되었다.이렇게 가장 기본적인 소개의 역할만을 담당하는 한 페이지짜리 웹 사이트를Promotional Landing Page, 혹은 랜딩 페이지라고 줄여서 부른다.우리는 총 세 가지 과정을 거쳐 웹 사이트를 만들어왔는데, 순서대로 아래와 같다.[1] 시중에 떠도는 HTML5 템플릿을 활용해 앱 개발자분께 부탁하여 간단하게 직접 만들었다[2] IMXPRS 라는 서비스를 이용하여 직접 만들었다[3] Instapage 라는 서비스를 이용하여 직접 만들었다결론만 말하자면 IMXPRS 는 내가 어떻게 알았는지 모르지만 완전 비추인 서비스이다.직접 만드는 것도 돈은 들지 않지만 그 때 그 때 커스텀이 안되기 때문에 불편하다.알아본 결과 랜딩페이지 제작으로는 주로 wix(바로가기) 나 Instapage(바로가기)를 추천하는데, 두 서비스가 유사하지만 개인적으로 Instapage 의 디자인이 더 마음에 들어서 선택하게 되었다.*wix의 경우 한글 버전이 있고, 이후 결제를 붙이는 것이 좀 더 용이하다고 알고있다.각각의 템플릿과 기능을 보고 적절한 것으로 선택하면 될 것이다.Instapage 사용 경험의 경우 개인적으로 10점 만점에 9.5점을 줄 정도로 아주 높다.당연히 직접 개발하는 것 만큼이야 커스텀이 안되겠지만, 매우 쉽게, 꽤 높은 수준으로 커스텀이 가능하다.예를 들어, 애초에 사용한 템플릿은 위의 템플릿이었는데, 아래와 같이 커스텀했다                                                  애초의 템플릿                                                   최종 결과물거의 다른 모습임을 알 수 있는데 그만큼 커스텀이 정말 쉽다는 뜻이다.- 기본적인 디자인은 모두 템플릿에서 제공하며- 핵심이 되는 Headline 및 본문 글꼴을 수정할 수 있고- 원하는 이미지 등을 손쉽게 원하는 위치에 삽입하고, 요소를 원하는 위치에 원하는 크기로 넣는다- 배경 사진 또한 유료 사진을 즉석에서 보고 어울리는 것을 쉽게 결제할 수 있다- 모바일 페이지도 자동 생성되며 별도로 변경할 수 있다(!)이러한 기능들 덕택에 개발자나 디자이너가 아니더라도, 30분~1시간만에 어느 정도 수준의 랜딩페이지를 손쉽게 완성할 수 있다.가장 마음에 들었던 부분은 외부 서비스와의 연계인데, 특히 이메일 주소를 받는 등의 추가기능이 필요한 경우 Integration 탭에서 정말 쉽게 넣을 수 있다. (라이비오의 경우 현재 이메일 주소를 받는 부분은 Mailchimp 라는 타 서비스와 연결되어있다.)                        Edit > Integration 탭에 가면 볼 수 있는 수많은 서비스들향후에는 좀 더 공식 사이트스러운 것들이 필요하겠지만, 초반 몇 달간 사용하기에 손색이 없는 서비스라고 생각한다. 일정 기간동안 무료로 제공되며, 향후 이용료를 낸다. (위의 사이트 수준이면 월 $29 정도)완성된 홈페이지: http://liveo.me랜딩 페이지는 이 정도로 하고, 이후 스마트 앱 배너를 추가할 계획이다.모바일로 랜딩페이지에 접속하면 앱 설치로 유도하는 배너이다.이 부분은 SDK 연동 등도 필요해서 개발자분들의 바쁨이 조금 잦아들면 출시 직전이나 직후에 넣으려고 한다. 관련 서비스는 branch.io 등이 있다.                                Smart App Banner 사례: 맨 위에 저거...사실 처음에는 랜딩 페이지(Promotional Landing Page)니, 스마트 앱 배너(Smart App Banner)니 하는 용어 자체를 몰라서 관련 서비스를 찾기가 어려웠다. 하지만 일단 용어를 알고나니 관련하여 이용할만한 좋은 서비스들이 많았다.혹시 앱 출시를 처음 해 보는 팀이 있다면 앱 출시 마케팅 자체에 대한 조사를 먼저 하고 큰 그림을 그려둔 후 가지를 쳐가며 준비하기를 추천한다. 개인적으로 어떤 부분을 모르는지, 어떤 부분을 알아야 할지를 알 수 있어 훨씬 수월했던 것 같다.하나 하나 완성된 모습으로 채워가는 과정이 왠지 괴롭고도(?) 재미있다.앞으로 소셜미디어와 프레스킷을 만들어가는 과정도 담아보기로 한다.+ 여담: 배경색 선정은 페이스북 '포토샵 완전정복' 디자이너 그룹의 힘을 빌었다.  투표의 힘!정말 많은 분들이 투표에 참여해주셨고 그 중 아는 언니가 준 의견 덕분에 지금의 검은 색상 옵션을 추가하게 되었다.사실 내가 처음 밀었던 색상은 아래의 보라색이었고 우리 팀도 대표님 제외하고 모두 보라색을 택했다 ㅋㅋㅋ 그러나 디자이너들의 의견은 가차없이,검은색 > 민트색 > 보라색 이었다.역시 기술만 있는 나에게 디자이너의 안목을 기르기란 끝없는 과제이다.이 글은 "친구끼리 쓰는 라이브 스트리밍 앱, 라이비오(LIVEO)"의 앱 출시 과정을 담는 글입니다. 어디까지나 현재 겪고 있는 과정을 기록하는 것으로, 최선의 방법이 아닐 수도 있으니 더 좋은 방법이 있다면 언제든지 소개 부탁드립니다.#라이비오 #경험공유 #출시 #업무프로세스 #인사이트
조회수 9065

왜 SQLite 에서 Realm 으로 옮겼는가?

SQLite 와 Realm잔디 앱은 2015년 중반부터 앱 내에 Offline Caching 기능이 포함되면서 본격적으로 Local-Databae 를 사용하기 시작했습니다.당시에 Realm 과 SQLite 를 검토하는 과정에서 다음과 같은 사유로 Realm 을 포기하였습니다.1.0 이 아직 되지 않은 미성숙된 상태의 라이브러리사용 사례에서 리포팅되는 버그들 (CPU 지원 등)Data 의 상속을 지원하지 않는 문제Robolectric 미지원 (안드로이드 팀 당시 테스트 프레임웍은 Robolectric 이었으며 현재 Android Test Support Library 입니다.)위의 문제로 인해 SQLite 를 선택하였고 여러 SQLite-ORM Library 를 검토한 후 ORMLite 를 선택하였습니다.누구보다 가볍고 빠르게2016년 6월경 앱의 핵심 데이터에 대해 개선작업이 되면서 그에 따라 기존의 Cache Data 로직도 많은 부분이 변경되었습니다. 그에 따라 실시간성으로 DB 를 대상으로 Read-Write 동작이 발생하게 되었습니다. Locking 등에 대한 처리가 되면서 성능에 대한 이슈가 계속적으로 발생할 수 밖에 없었습니다.간헐적인 성능 이슈는 사용자에게 나쁜 UX 로 다가갈 수 있기 때문에 다음과 같은 병목지점들에 대해 성능 향상을 꾀하였습니다.서버와의 통신 향상비지니스 로직 개선내부 DB 로직 향상서버와의 통신 향상병목 지점이 되는 것으로 판단되는 API 를 찾아 원인을 분석하여 개선요청을 서버팀에서 개선할 수 있도록 하였습니다.비지니스 로직 개선불필요한 객체 생성, 비동기로 처리해도 되는 동작들에 대해서는 로직 수정, 최소한의 검증 후에만 앱 실행, 네트워크 동작 최소화, 캐싱 활용 등 다양한 전략을 시도하였습니다.내부 DB 로직 향상SQLite 를 대상으로 빈번한 쿼리 작업을 최소한으로 하기 위해 2~3개의 쿼리로 이루어진 부분에 대해서 최소한의 쿼리만으로 동작하도록 여러 시도를 하였습니다.ORMLite 의 한계점ORMLite 를 대상으로 여러가지 시도를 하였습니다. 쿼리를 최소한으로 하고 1:N, N:M 동작에 대해서 로직 중간에 Query 가 발생하지 않도록 애초에 Join Query 를 하도록 하는 등 여러가지 전략을 시도하였으나 궁극적으로 ORMLite 자체에 대한 성능을 개선하는 것은 불가능하다는 결론이 도출하였습니다.여러 시도를 하였으나 고작 10~20% 정도의 성능향상밖에 없었으며 이는 사용자 관점에서 여전히 느릴 수 있다고 느끼기 충분한 수준이었습니다. 기존에 목표했던 100ms 이하의 쿼리를 기대하기엔 어려운 상황이었습니다.그래서 GreenDAO, Requery 라이브러리를 검토하였습니다.GreenDAO 의 문제점GreenDAO 를 검토하는 과정에서 겪은 가장 큰 문제점은 실제 Object 코드에 GreendDAO 코드가 생성이 붙으면서 유지보수에 큰 걸림돌이 될 수 있다는 것이 예상되었습니다.Requery 의 문제점성능면에서 ORMLite 에 비해서 큰 개선을 가져오지 못했습니다. Requery 는 JPA 를 가장 잘 채용한 것으로 알려져 있지만 그렇다고 SQLite 자체의 성능을 극적으로 개선했다고 보기엔 어려운 부분들이 있었습니다.SQLite vs RealmSQLite 가 가진 자체적인 성능 이슈를 SQLite 기반 라이브러리 범위안에서는 개선할 수 없다는 결론에 도달하였습니다.검토 방법 : 기존의 Object 를 대상으로 ORMLite 와 Realm 을 대상으로 성능을 검토합니다.데이터는 1:N / 1:1 관계가 되어 있는 여러 Object 의 집합으로 구성되어 있다.Database 에서 데이터를 가져올 때는 Eager Loading 방식으로 택한다.Write : 20회, Read : 20회 를 수행했고 그에 대한 평균 성능을 비교한다. SQLiteRealm성능 향상Write4039ms1142ms3.5xRead6010ms2450ms2.5x(Realm 의 벤치마크 정보와 너무 상이하여 재테스트한 결과 수정하였습니다.)위의 비교차트에서 봤듯이 Realm 은 무시무시한 성능이 입증되었습니다.도입 검토시에 Realm 버전은 2.0 이었기 때문에 충분히 신뢰할 수 있을 만큼 성숙되었다고 판단하고 최종적으로 도입을 결정하였습니다.Realm 도입 과정에서 문제점Realm 을 도입한다고 해서 여전히 잠재적인 문제가 해결된 것은 아니었습니다.파악된 다음 문제를 해결 해야 했습니다.Primitive 타입에 대해 Collection 저장을 지원하지 않는다.RealmObject 에 대한 호출 Thread 를 유지해야 한다.상속을 지원하지 않는다.Primitive 타입에 대한 Collection 관리를 해결하기이 문제는 ORMLite 에서 이미 겪었기 때문에 의외로 쉽게 구할 수 있었습니다. long, int 등에 대한 Wrapper 를 만들고 Json Convert 등의 과정에서 Post Processing 과정에서 Wrapper 로 데이터를 이관하도록 처리하였습니다.// example class Data extends RealmObject { private transient List refs; private List refIds; } class RealmLong extends RealmObject { private long value; } RealmObject 에 대한 호출 Thread 분리Realm 은 Object 에 대해 query 후 객체를 받는다 하더라도 실제로 객체 내 데이터르 접근할 때는 다시 Query 로 접근하기 때문에 실제로 Object 전체에 대해서 Eager Loading 방식으로 접근해야 합니다.Jandi 는 싱글톤 객체를 통해 데이터베이스에 접근하며, Background Thread 에서 진행하고 UI Thread 에서 객체 내 변수에 접근해서 UI 에 그리는 작업이 빈번하기 때문에 Thread 독립을 반드시 해야했습니다.Realm 에서는 Eager-Loading 을 지원하고 있습니다. Realm.copyFromObject() 를 사용하면 Return 값이 Eager-Loading 된 Object 가 반환됩니다.단, Realm 의 가장 큰 특징이로 보는 ZeroCopy 를 포기하는 것이기 때문에 신중하게 생각해야 합니다.// example public Chat getChat(long chatId) { return execute((realm) -> { Chat it = realm.where(Chat.class) .equalTo("id", chatId) .findFirst(); if (it != null) { return realm.copyFromRealm(it); } else { return null; } }); } 상속을 지원하지 않는다.가장 큰 문제였는데 해결방법을 찾을 수 없어 결국 상속을 포기하고 모든 Data 를 1개의 Object 에 표현하기로 하였습니다.위의 3가지 문제를 이렇게 해결해서 안드로이드팀에서는 1차적으로 도입을 완료하였습니다.결론현재까지 Realm 전환에 있어서 성공적인 도입으로 판단되어 차후에 다른 데이터에 대해서도 하나씩 DB 이전을 할 예정입니다.Realm 은 이제 충분히 신뢰할 수 있을만큼 성숙되었다고 생각이며 Realm 에서 처음부터 강조하던 성능또한 믿기 어려울 정도로 빨라졌습니다. 더 빠른 Mobile Database 를 원하신다면 Realm 을 적극 추천합니다.#토스랩 #잔디 #JANDI #개발 #개발환경 #업무환경

기업문화 엿볼 때, 더팀스

로그인

/