스토리 홈

인터뷰

피드

뉴스

조회수 2436

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]브랜디, 오직 예쁜 옷만
조회수 1182

EOS Smart Contract 를 위한 준비

EOS Smart Contract 를 위한 준비와 토큰 발행 그리고 C++를 활용해 토큰의 간단한 기능을 개발해 보겠습니다.환경 구성 및 지갑 생성은 SAM 님의 아래 2글을 참고해 주시기 바립니다.EOS — 설치 및 실행 (1/2)EOS — 동작구조 및 환경설정(2/2)지갑 생성하기SAM 님의 포스트를 참고 하셨다면 아마 다음과 같이 ‘default’ (별도의 이름을 지정하지 않았을 시) 지갑을 생성 하셨을 겁니다.이 지갑을 사용하여 계정을 Create 한 후 Key 를 Import 하겠습니다.Key 생성하기$ cleos create key위 명령을 실행 하시면 다음과 같은 화면을 얻을 수 있습니다.create key 명령의 결과**주의 : Private Key는 Public Key의 소유를 증명하는 중요한 개념으로 절대 타인에게 노출하면 안됩니다.AdditionalKey 생성 후 지갑에 import 하기 귀찮으시다면 생성된 지갑에서 바로 Key 를 생성하셔도 됩니다.$ cleos wallet create_key위와같이 key가 생성 됩니다. 하지만 public key 만 보이기 때문에 하단 명령 입력 후 지갑 key를 입력하면 private key를 확인할 수 있습니다.$ cleos wallet private_keys지갑에 Key import하기지갑은 Public Key — Private Key를 저장하는 저장소 입니다. 생성된 키를 지갑에 저장하기 위해 다음과 같은 명령어를 입력합니다.$ cleos wallet import-n : 옵션을 사용하면 지갑의 이름을 지정합니다. 지정하지 않는다면 기본 생성된 default 지갑으로 지정됩니다.위 명령을 입력 하면 key 가 임포트 되었다는 결과를 확인 할 수 있습니다.** 만약 지갑을 Unlock 한 상태가 아니라면 ‘private key: Error 3120003: Locked wallet’ Exception 이 나옵니다.unlock 을 위해 다음 명령을 실행한 후 wallet 생성시 저장했던 Key를 입력하여 Unlocked 상태로 만들어 줍니다.$ cleos wallet unlock password: Unlocked: default(Optional) 지갑에 저장된 Key 리스트 확인다음 명령어를 입력하여 지갑에 key 가 잘 import 됐는지 확인합니다.$ cleos wallet keys계정 생성eosio.token 이라는 이름으로 계정을 생성하도록 하겠습니다.** 지갑과 Key 그리고 계정에 관해서는 Hexlant 미디움에 게재될 예정입니다.$ cleos create account eosio eosio.token EOS63kstp8kthzJY3rAotp1LAxUDbWk4MywReG578R2ddbktrDHYKcreator : eosioaccount name : eosio.tokenowner key : 지갑에 import 된 keyAdditional본 포스팅은 local 환경에서 빌드 후 System Contract 들이 적용되지 않은 상황을 가정하였습니다. 만약 Public Network 환경에서 접속 시 eosio 와 eosio.token을 사용할 수 없습니다.또한 계정이름은 다음과 같은 규칙을 따릅니다.- 12문자- 12345abcdefghijklmnopqrstuvwxyz 만 사용 가능** 만약 ‘Error 3090003: provided keys, permissions, and delays do not satisfy declared authorizations’ 에러 발생 시 eosio 에 대한 key 를 지갑에 import 해야 합니다.eosio 에 대한 정보는 다음과 같습니다.public key: EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CVprivate key: 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3위 과정을 모두 마쳤다면, EOS 지갑과 키 그리고 계정에 대한 권한을 모두 가지고 있는 상태가 됩니다. 다음 포스팅에서는 이 계정을 사용 하여 Token 을 발행하는 방법을 알아보도록 하겠습니다.감사합니다#헥슬란트 #HEXLANT #블록체인 #개발자 #개발팀 #기술기업 #기술중심
조회수 3013

GUI가이드라인 정의와 목적

S/W 개발자가 디자인대로 화면을 구현할 때, 어떻게 디자인 요소 위치를 잡아야 하는지 정확한 정보가 필요합니다. 이런 정보는 GUI 디자이너가 포토샵과 같은 디자인 툴을 사용하여 개발자가 사용 가능한 형태로 사이즈 정보와 리소스를 만들어 전달하는 작업을 GUI 가이드라인 제작 작업이라 합니다.GUI 가이드 문서 상에는 화면상에 표현되는 모든 GUI 요소들의 정보가 표시가 됩니다. 화면상의 위치 X/Y 좌표값, 디자인 요소의 폭/높이 사이즈 정보, 이미지 파일 리소스명, 폰트 타입, 폰트 크기 등 다양한 그래픽 요소의 정보를 정확하게 수치화 하여 기재한 것입니다.가이드 문서의 양식은 딱 정해진 틀은 없지만, 소위 대기업의 경우 표준 템플릿을 이용합니다. 단말 하나에 탑재되는 앱 별로 수십 벌의 문서를 제작하여 관리해 왔습니다. 현재 과도기적인 단계라 스케치(.sketch) 파일과 가이드라인 문서를 함께 운영하는 곳도 있을 정도입니다.기존에 GUI 가이드 문서 제작을 위해서는 아래와 같은 일련의 순서로 작업을 하였습니다.디자인 시안 작업 > 디자인 시안 확정 > 개발 가능성 리뷰 > 최종 수정 >GUI 가이드라인 문서 제작 & 이미지 파일 리소스 작업이 중에서 가이드 문서 제작 과정을 초점에 두고 살펴보면, GUI 디자이너가 직접 이미지를 자르고 위치와 크기 정보를 확인하여, 파워포인트 문서로 정보를 입력하는 일련에 단순 노가다를 반복적으로 진행하게 됩니다.대부분의 에이전시 신입 디자이너들이 중국집 요리사 탱크트리와 유사하게 최소 2년 정도 GUI 가이드라인 작업을 하고 난 뒤에 시안 디자인 작업을 참여할 수 있는 구조였습니다. 크리에이티브를 위해 디자인 작업에 시간을 일주일 중 3일을 쓰고, 4일은 가이드를 쳐야 할 정도의 노력과 시간이 드는 노동 집약적 작업이었습니다.이렇듯 GUI 가이드라인 문서 제작은 모든 디자인 요소 정보들을 일일이 확인한 후, 파워포인트로 옮겨 적어야 하는 야근의 헬게이트를 열어주는 대표적인 업무였습니다.디자인 완료 후 개발자에게 “디자인을 이렇게 구현해 주세요.” 라고 말하면 얼마나 쉽나요? 근래에는 야근의 대부분을 차지하는 이러한 업무들로부터 스케치 툴이 많은 디자이너를 구해준 셈입니다.업무의 프로세스상 디자이너가 가이드라인 문서와 이미지 리소스 파일들을 넘겨줘야 개발자들이 개발진행을 할 수 있기에 디자이너들은 타이트한 데드라인에 쫓기듯 업무할 수 밖에 없었습니다.이러다 보니, GUI 가이드라인 문서 제작 중 휴먼에러(크기 정보 오타, 이미지 파일 누락 등)로 개발자가 작업하던 도중 디자이너에게 가이드라인 문서 업데이트 요청을 해오는 경우가 매우 빈번했습니다. 또한, 대규모 프로젝트 일수록 가이드라인 문서, 이미지 리소스 파일, PSD 디자인 파일 등 관리해야 할 대상이 많아서 개발자와 디자이너 사이의 커뮤니케이션 빈도수도 잦아지고 많은 비용이 필요했습니다.비단 3년 전만해도 GUI 디자인을 개발자가 구현하기 위해 필요한 정보를 수천 페이지나 되는 파워포인트 문서로 전달했지만, 요즘은 스케치를 활용한 제플린이나 심플리 등과 같은 가이드 정보를 제공해주는 여러 서비스를 이용하여 가이드 문서 제작은 거의 하지 않고 있습니다. 조만간 가이드 문서가 완전히 사라지는 날이 오지 않을까 싶습니다.그 끝에 크래커나인이 일조하는 날이 오기를 바라며 글을 마칩니다.#에이치나인 #디자이너 #개발자 #협업툴 #크래커나인 #솔루션기업
조회수 1273

MySQL에서 RDS(Aurora) 로 이관하기

안녕하세요. 스티비팀 서버 개발자 이학진 입니다. 저희는 최근 서비스에서 사용 중이던 MySQL DB를 RDS로 이관하는 작업을 진행하였습니다. 무엇 때문에 이관을 결정하게 되었는지와 어떻게 이관을 진행하였는지에 대해 글을 써보도록 하겠습니다.배경stibee.com은 작년 11월에 정식 오픈한 새내기 이메일 마케팅 서비스 입니다. 사실 오픈 초기부터 얼마전까지만 해도 AWS EC2의 m4.large 인스턴스 하나로 운영되던 서비스였습니다.(사실 웹+API 서버 1대, 메일발송서버 1대)그리고 이 싱글 인스턴스에 무려 6개의 서버, mysql 1개, kafka 1개, redis 1개가 돌고 있었습니다. 그럼에도 불구하고 cpu사용률은 20%를 넘지 않았습니다.하지만 최근 사용자도 점점 늘어났고, 네이버에서 메일 수신정책을 변경하면서 메일발송서버에 대한 요청이 급증했습니다.스티비에서 네이버로 대량메일을 발송했을 때 해당 메일의 본문 링크를 자동검사하는 것을 발견했는데요, 따라서 네이버로부터 비정상적으로 많은 요청이 들어오고 있었습니다. (어떤 기준으로 이런 검사를 하는 것인지 정확한 정책은 아직 모릅니다. 담당자분 이 글을 보신다면 연락주세요. 친하게 지냈으면 합니다#슬로워크 #스티비 #개발 #서버개발 #개발환경 #MySQL #인사이트
조회수 1664

데이터, 기록되고 있습니까?

올해 2월에 썼던 글을 이제야 올려봅니다. 태블로는 아직 잘 사용하고 있습니다. : )“아무개 님, 지난번에 요청한 자료 언제까지 받을 수 있죠?”다행이다. 꿈 이었다.가벼운 발걸음으로 출근하던 중 일감 하나가 떠오른다. 간밤의 꿈이 꿈 만은 아니었던게다.아뿔싸, 아직 시작도 못했는데.오늘 할 일을 내일로 미룬 자의 아침은 발걸음이 무겁다.Business Intelligence 라는 것이 있다. 뭔가 멋드러진 단어의 조합처럼 보이지만, 현실은 그리 아름답지 않다. 대부분의 시간을 비슷한 일을 반복하며 숫자를 맞춰야하고 엑셀과 SQL 에 빠져 살기 일쑤다. 잘못된 데이터라도 발견되면 이걸 어디서부터 수습해야 하나 고민해야 한다. (끝이 없는 재귀호출)반복, 반복, 반복. 비용을 줄이자.반복은 비용이다. 한두번 반복되는 일을 최적화 하는 것은 최적화 자체가 비용 이겠지만, 매일같이 반복되는 일, 주기적으로 찾아야 하는 데이터들은 그 자체만으로도 최적화의 대상이다.특히나, 아직 성장하고 있는 ‘스타트업’ 이라면 회사의 데이터가 잘 정리되어 있을리 만무하다. 몇몇 데이터는 잘 관리되고 있겠지만, 상당수는 흩어져 있을 것이다. 어느 순간을 지나면 이들을 모으는 게 일이 되어버린다. 임계점을 넘어서버린 일을 한다는 것은 손을 더럽히는 일이 된다는 뜻이기도 하다. 아무쪼록 그대에게 이 임계점을 분간할 지혜가 있기를.시간 비용을 절약하자스타트업의 구성원들에게 가장 중요한 것은 무엇일까? 나의 짧은 생각으로는 사람과 시간이라고 생각된다. 이 중에서 BI 툴이 해결해 줄 수 있는 것은 무엇일까?나 스스로에게 질문해보니 이런 답이 나온다. ‘사람은 쉽게 바뀌지 않는다’ 그럼 시간은? 다행히, 시간은 모두에게 공평하게 주어진다.‘그럼 이 시간을 아껴보자!’여기에 하나 더, 내가 모르는 것이 있었다.앞으로 회사가 데이터를 다루는 스펙트럼을 얘상할 수 없다는 것이다.Zeppelin무엇을 사용할까 고민하던 중 가장 먼저 떠오른 것은 다름 아닌 제플린 이었다.< 이 형님들 말고 >(출처 : http://fortune.com/2016/07/26/led-zeppelin-stairway-heaven-appeal/)아파치 제플린은 한국에서 시작해 아파치 인큐베이터에 들어간 오픈소스 데이터 분석 및 시각화 툴 이다.장점은 개발자에게 익숙한 노트북 기반이라는 것과 강력한 인터프리터를 통해 다양한 데이터 소스에 접근할 수 있다는 것이다.나프다 팟캐스트에서 들은 내용인데, 트위터의 경우 태블로에서 제플린으로 갈아탔다는 이야기도 있었다.기본적으로 프로그래밍이 가능하기 때문에 어떤 형태의 데이터를 요구해도 제공할 수 있다는 장점도 있다.물론, 단점도 있다. 먼저 시각화 부분이 약하다는 것이다. D3.js 를 같이 사용하면 보완할 수 있지만 개발자의 꾸준한 지원이 있어야 할 것이었다.더불어, 비개발자들에겐 노트북 형태로 데이터를 가공하는 것에 진입장벽이 있다고 생각 했다.한번쯤 사용해보고 싶었지만 개발 리소스가 부족한 우리 상황에는 맞지 않다고 생각했기에 다음을 기약해본다.Spotfire, Amazon Quicksight, Google Data Studio다음으로 찾아본 툴 들은 바다 건너에서 잘 사용 되는 몇가지 것들 이었다.Spotfire 는 레퍼런스도 충분했지만 다음에 등장한 강력한 후보로 인해 제외됬다.아마존 퀵사이트는 잠깐 사용해봤지만 회사의 요구사항을 맞추는데 부적절해 보였다.구글의 데이터 스튜디오 역시 기능에 제약이 많았다.아마존과 구글의 솔루션은 무료로 사용할 수 있거나 가격이 합리적이라는 장점도 있었다.Spotfire 역시 비싸지 않은 가격이었다.태블로, 그리고 plotly태블로는 동료 직원의 지인 중 사용해본 분이 있어서 직접 만나서 여러가지를 물어볼 수 있었다. 나중에 알았지만 한국에 공식 총판이 있어서 메일로 문의하면 다양한 안내를 받을 수 있었다.태블로는 장점이 많은 툴이다. 다양한 데이터 소스를 지원하며, 강력한 시각화를 통해 데이터를 분석할 수 있다.데이터를 유연하게 다룰 수 있어서 여러가지 인사이트를 얻는데 도움을 줄 것이라 생각됐다.온라인 튜토리얼도 잘 되어있고, 한국에서 오프라인으로 기초교육도 받을 수 있다.종합적으로 비교해 본 결과 비슷한 성격의 툴 중에선 가장 강력한 툴 이었다.유일한 단점이라면 가격이다.plotly 는 리서치 중 가장 마지막으로 접했는데 대시보드로도 사용할 수 있고 노트북에도 붙일 수 있는 라이브러리 형태로 제공되는 툴 이었다.데이터 분석에 주로 사용되는 파이썬, R, 매트랩에 모두 사용 가능했고 훌륭한 시각화도 가능했다. 학생이라면 아주 저렴한 가격으로도 이용이 가능하다.단점이라면, 개발자에게 더 친화적 이라는 것과 데이터 커넥터가 태블로에 비해 부족하다는 것 이었다.BI 툴, 개발자와 분석가 중 누구에게 더 쉬워야 할까?회사마다 개발자의 비중이 다르다. 스타트업 이라고 해서 개발자들로만 이루어진 것도 아니고, 이미 안정적으로 비즈니스를 운영하는 회사라고 해서 개발자가 적은 것도 아니다.각 회사가 처한 상황에 따라 어떤 툴을 사용할 지는 다를 것이다.나는 우리 회사가 어떤 BI 툴을 써야 최적일지 생각해 봤다.같은 작업을 하는데 있어서 시간을 줄여줄 수 있어야 하고, 앞으로의 변화에 유연하게 대응할 수 있는 툴이었으면 했다.개발자의 지원을 최소화 하면서 비즈니스를 이해하는 분들이 적극적으로 사용하는데 어려움이 없었으면 했다.가격적인 면도 중요했지만, 국내에서 사용하는데 참조할 수 있는 레퍼런스, 교육이 풍부한 것도 선택에 한 축이 되었다.모든 것을 종합해 본 결과 태블로 만한 것이 없다고 생각됐다.< 이제 데이터와 사랑에 빠져 볼까? >(출처 : https://www.youtube.com/watch?v=2onPdVj5zgQ)여러분들의 상황은 어떤가.지금 사용중인 툴이 충분한 효과를 가져다주고 있는가? 혹시 기존에 익숙하던 것을 습관적으로 사용하고 있지는 않나?대부분의 스타트업은 부족한 인원으로 복잡한 이슈를 해결하기 위해 고군분투 중일 것이다.특별히, 데이터를 들여다보고 최적화를 해야하는 업무를 담당하는 사람이라면 지금 이 순간도 머리를 싸메고 고민에 빠져 있을 것이라 생각된다.데이터 때문에 잠이 부족한 그대에게, 비슷한 고민을 하는 분들에게, 아무쪼록 이 글이 조금이나마 도움이 되었기를 바란다.#8퍼센트 #에잇퍼센트 #협업 #업무프로세스 #팀워크 #수평적조직
조회수 1709

StyleShare Engineering Blog?!

변정훈님 강의 모습생각해보기한 번도 생각해본 적이 없다! 왜 글을 작성해야 하는가?! 왜냐하면, 우리는 글로 먹고사는 사람도 아니고, 수려한 글솜씨도 없기 때문에?! 하지만, 이미 우리 사회는 PR의 시대를 뛰어넘어 미디어의 홍수에서 살아가고 있고, 매우 쉽게 무의식적으로 많은 글을 읽고 있다.하지만, 우리가 글을 작성하기 위해서 얼마나 많은 준비가 되어 있을까? 이 글을 쓰고 있는 필자 역시 글을 써본 경험이 거의 없다. 특히 회사의 이름을 걸고 글을 쓴다는 것은 매우 부담스러운 일이다.그래서 우리는 변정훈[Outsider’s Dev Story]님을 초대하여, 그분이 생각하는 블로그 일상과 엔지니어링 블로그에 대한 생각 공유의 시간을 가져보았다.엔지니어링 블로그회사 블로그 운영을 해보았는가?아쉽게도 변정훈 님도 회사 블로그를 운영해본 적은 없다고 하신다. 그 원인을 다음과 같은 이유로 해석을 하였다.주제가 많지 않다.개발보다 우선순위가 떨어진다.누구나 처음부터 글을 잘 적을 수 있는 건 아니다.그렇다. 이 글을 쓰는 중에도 위와 공감할 수 있는 부분이 적지 않다.우선 글을 많이 써보지 못한 필자로서도 어떤 글을 적어야 할지 난감하게 느껴지고, 업무 중에서도 중요도가 떨어지는 것은 분명하다. 마지막으로 주제 선정부터 매우 어렵게 느껴진다.그런 이유로 글쓰기를 즐겨 하시는 변정훈 님 조차 회사 블로그 운영을 잘 이끌어 본 적이 없다고 하신다.변정훈 님의 블로그는 2007년 부터 총 1,300여개 글이 게시되어 있다고 한다.왜 우리는 블로그를 운영하려 하는가?여러 가지가 있겠지만, 필자가 가장 공감한 부분은 이 부분이었다.팀 내 지식/경험 공유잠재적 입사자에게 기술 스택 및 문화 공유팀 전체의 실력 향상그동안 개발일을 해오면서, 몇 년 동안 풀리지 않는 큰 숙제 중에 하나가 좋은 개발자를 찾는 것이었다. 항상 사람을 찾는 것이 어렵다. 좋은 사람의 기준이 높아서인지 더 좋은 기업이 많아서인지 알 수는 없지만, 일하면서 느낀 가장 어려운 문제 중에 하나이다. 결국, 내부의 인력을 더 좋은 사람으로 만들고, 외부의 좋은 사람과도 교류의 장을 만들 수 있다는 희망을 품을 수 있게 되는 것이다.글 작성의 문턱을 어떻게 낮춰야 할까?좋은 점은 쉽게 공감이 되지만, 언제나 가장 어려운 것은 실천이 아닐까 싶다. 특히 회사에서 업무로 이런 일이 발생된다면, 많은 사람들이 엄청난 부담감을 가질 것이고, 결국 회사 엔지니어링 블로그는 대문만 남은 유명무실한 블로그가 될 가능성이 높다.그래서 변정훈 님은 이렇게 제안하셨다.월 1개 보다 적어도 된다.주제를 계속해서 제안하고 만들어 내야 한다.돌아가면서 작성한다.챙겨주는 사람이 필요하다.글도 리뷰하는게 좋다.부담감은 의도적으로 줄여야 …특히 변정훈님은 부담감을 줄이는 방법에 대해서, 팀 공유를 해주셨는데 잠시 소개하면 다음과 같다.나보다 모르는 사람 — 나 — 나보다 잘하는 사람언제나 어떤 기술에 대하여, 나보다 잘 모르는 사람과 나보다 잘 하는 사람이 있다는 것을 인지하고, 나보다 못하는 사람을 위해서 글을 작성한다는 것이다. 그러다 나보다 잘하는 누군가가 어쩌다 피드백을 준다면 오히려 매우 감사하게 새로운 지식을 터득하게 된다는 것이다. 역시 모든일에는 긍정적인 마인드가 중요하다. 세상 어딘가에는 나의 작은 지식이라도 필요로하는 사람들이 분명히 있을테니, 작은 용기를 가지고 세상에 누군가를 위해서 작성한다면, 세상은 분명 아름다워질 것이다.좋은 글, 좋은 주제란 무엇일까?사실 가장 어려운 이야기일지도 모른다. 변정훈님은 이런 내용을 좋다고 표현하셨는데, 잠시 정리하면 다음과 같다.개발팀의 문화어떻게 일하는가?프로젝트 수행 회고실패기개인적으로 실패기가 가장 적기 어려운 글이라고 생각한다. 하지만, 누군가에게는 가장 소중한 경험이 될지도 모르니, 간접경험의 공유는 특히 소중한 것일 수 있다.만약 회사 블로그의 글이 회사 내/외부의 사람들에게 지식 공유와 전달이 목적이라면, 그리고 좋은 문화를 계속 가지고 유지하기 위해서라면, 실패기가 어쩌면 가장 소중한 경험의 공유가 아닐까 생각해본다.질문과 답변을 통한 소통의 시간마지막으로 이 날 소개 받은 좋은 글의 흐름이란 다음과 같았다.하고자 했던 일 (Context)경험한 문제 사황 정리(격리된 상황)시도해 본 방법(내가 아는 지식)왜 동작이 안되는가? 왜 동작하는가?(가설)문제 상황 재현예제 코드관련 링크개념 설명지금까지 적은 이 글을 위의 원칙대로 다시 한번 살펴본다. 부족한 부분이 있는지, 수정할 부분이 있는지…이제 부터 회사 블로그를 더욱더 적극적으로 운영해보자!!!#스타일쉐어 #개발팀 #조직문화 #블로그 #기업문화 #사내복지
조회수 1078

2016, 개발자의 Life.. 꿈...#1

주변 개발자들의 삶이 매우 행복을 추구하는 삶으로 변해가고 있다는 것을 느낀다. 주변의 개발자들의 모습을 몇 가지 정리해보자. 이를 '지속 개발을 위한 개발자 Life 스타일'이라고 정의하겠다.개발자#A10년 넘게 개발하던 패키지를 기반으로 필요 기능을 최소화하여 1인 개발기업에 성공하였고 제주도로 내려가서 지역에 속한 분들과 호흡하는 삶을 추구하면서도 소프트웨어 개발의 핵심을 잃지 않았다. 정말, MVP 기능에 최대한 집중하면서 필요한 시장 영역을 더 확대하지 않고, 소프트웨어를 개발하고 있는 개발자와 해당 소프트웨어를 사용하는 고객과 시장에 대해서 같이 합리적으로 지속할 수 있는 지속할 수 있는 소프트웨어 개발의 삶을 이루었다.그리고, 그러한 Life환경을 주변에 전파하면서 불과 얼마 전 또 한 명의 구 루급 개발자에게 비슷한 삶의 길을 가르쳐준다. 정말 부러운 개발자들...개발자#B복잡한 업무나 더 많은 보수를 위해서 더 좋은 회사를 찾기보다는 삶이 존재하는 근무시간을 위해서 재택근무를 찾고 있다. 비용도 최대한 낮추면서 생활을 위한 회사를 찾아다니고 있다. 아무래도, 외국계 개발회사를 선택할 것 같다.개발자#C오픈소스 진형에서 인정받는 개발자이다. 본인이 원하는 오픈소스 프로젝트를 추진하는 것을 보장받고 외국계 기업의 원격근무를 선택했다. 보수도 나쁘지 않고, 근무시간은 알아서 하는 것이지만, 원격으로 일하는 것이기 때문에 '능력'을 보여주기 위해 더 많은 시간을 소프트웨어 개발에 투자한다. 굳이, 서울 시내에 있을 필요가 없기 때문에 외각으로 집도 옮겼다.개발자#D일부러, 실리콘 벨리의 스타트업을 선택했다. 조만간 상장 예정인데 매우 큰 혜택을 받을 것 같다. 그 역시 지속 개발이 가능한 삶을 추구한다.2016년 올 초의 개발자 트렌드는 '지속 개발을 위한 Life'를 지향하는 개발자들이 늘어났다고 평가해본다.우리 모두 지속개발이 가능한 삶을 지향해 보는 것은 어떨까나...
조회수 460

iOS 개발자를 구합니다!

“세상 모든 광고영상을 누구나 쉽게 만들 수 있게 한다.”영상광고는 사업의 규모와 업종을 막론하고 모든 분야에서 필수적인 요소로 자리잡고 있습니다. 잘 만든 영상광고가 매출로 이어진다는 사실은 검증되었고, 그 중요성은 나날이 증가하고 있습니다.하지만, 영상제작 전문기술 없이 광고영상을 제작한다는 것은 시간과 비용적인 측면에서 매우 어려운 일입니다. 광고영상을 SNS에 업로드 하고 싶은 마케터나 창업가들은 영상 전문가나 디자이너가 되는 것을 꿈꾸지 않습니다. 단지 자신의 서비스와 제품이 멋지게 홍보될 영상을 원하고 있습니다.더브이플래닛은 전문기술 없이도 누구나 쉽고 빠르게 광고영상을 제작할 수 있는 브이플레이트를 통해 많은 마케터들과 창업가들이 겪는 시간과 비용에 대한 어려움을 해소할 것입니다.“더브이플래닛”에서 영상광고 생태계의 흐름을 바꿀 iOS개발자를 모집합니다.광고영상을 누구나 쉽게 만들 수 있도록 함께 고민하고 시장을 주도해나갈 분을 애타게 찾고 있어요.우리는 한사람 한사람의 소중한 능력들이 맘껏 발휘될 수 있도록 존중과 배려로 서로를 응원하고 있어요. 우리와 함께 소중한 능력을 맘껏 발휘하실 분들의 많은 지원 부탁드려요.
조회수 1602

2017 NDC 리뷰) 크립돈 퓨처 미디어와 하츠네미쿠

 이번글은 덕력이 솟구친다는!!!은 아니고요(진짜 아니에요), 혹시 "하츠네 미쿠"라는 캐릭터를 보신 적 있으신가요?하츠네 미쿠! 설마 처음보는 분들이 계신가요?? 출처: https://ec.crypton.co.jp/pages/prod/vocaloid하츠네 미쿠는 VOCALOID(보컬로이드)로서, 간단히 설명하면, 야마하에서 만든 음성 엔진입니다(자세한 내용은 링크를 확인!). 해당 엔진을 기반(자세히는 VOCALOID2인데... 아, 저는 잘 몰라요 진짜예요...)을 기반으로 크립톤 퓨처 미디어사가 아티스트를 만들고, 이를 지적 재산권(이하 IP라고 하겠습니다)으로 창출해 낸 사례입니다! 해당 세션은 이 보컬로이드가 성공할 수 있게 된, 창작자들에게 프로그램 번들 시디를 팔던, 크립톤 퓨처 미디어사가 새로운 미디어와 아트의 중심에 설 수 있게 된 이유를 들을 수 있게 된 좋은 시간이었습니다. 앞으론 말이 매우 딱딱하니 이점 히해해 주세요~! 시작하겠습니다!씨디파는 회사가 인터넷 시대를 맞이하며 겪게 된 위기, 그리고 해결방안. 앞서 말씀드렸든, 크립톤 퓨처 미디어(이하 크립톤이라고 하겠습니다)는 창작자들을 위한 서비스(또는 프로그램)를 번들 또는 디스크 형식으로 판매하는 회사였습니다. 그리고 새로운 세대로 들어서면서, 해당 사업이 사양되고 있고(디스크 판매> 콘텐츠 다운로드의 변화), 특히 음악 제작 서비스의 경우, 작은 시장의 규모 때문에 비즈니스에 대한 한계를 느끼고, 새로운 사업 영역을 펼쳐나가기 위해 방향 모색하기 시작했다고 합니다. 그리고 크립톤이 생각할 수 있는 "자사가 가장 잘할 수 있는 것"을 생각해 보았을 때, "소리"라는 콘텐츠를 방점으로 서비스를 응용해 나가면서 스팩트럼을 넓히자!라는 생각을 했다고 합니다. 그래서 시작한 것이 바로, 보컬로이드!라는 것이었죠.보컬 합성 기술(보컬로이드) + IP의 도입은 처음부터 성공적이진 않았습니다. 처음 크립톤은 야마하의 보컬로이드 기술을 기반, Leon과 Lola라는 소프트웨어를 제작,  당사에서 유통을 시작했을 때에는, 타깃 유저를 잡는데 실패해 매출에 전혀 도움이 되지 않았다고 합니다(아래 사진을 보면 왠지 알 거 같...)첫 보컬로이드 레온과 로라입니다..... 음... 입술이 매력적 이네요.... 출처: http://vocaloid.wikia.com/wiki/Forever_(Zero-G_song) 그 이유는 해당 서비스를 사용할 것이라고 타게팅한 아티스트들의 경우, 목소리에 관해 리얼함을 추구하는 데, 해당 소프트웨어는 하드웨어로 조정하는 음과 음성들이 리얼함이 다소 떨어져 전혀 니즈가 없었던 것이죠.그래서 트립톤은"해당 서비스를 진짜 사용하는 유저들은 어떤 사람들 일까?"에 대한 고려를 기반으로,"메이코"라는 일본어로 노래하는 보컬로이드를 제작, 흥미를 끌 수 있도록 캐릭터를 모티브로 하는 커버 디자인 작업 시작(안드로이드 아니 보컬로이드 이니깐요!)이제는 버전 쓰리가 된 메이코! (출처:http://vocaloid.wikia.com/wiki/MEIKO) 첫 출시 당시, 거부감도 있었지만, 당시 KPI 목표인 500개를 훌쩍 넘어 3,000개의 판매 성공을 거뒀고, 성공의 요인은 패키징 디자인과 단순한 아티스트뿐만이 아닌, 다양한 콘텐츠에 관심을 가지는 다양한 유저들을 유저들을 이끌 수 있는 요소들이 있어서 라고 판단하였다고 합니다. (서비스를 사용할 것이다 라는 사용자의 경험에 대한 고려를 더 많이 한 포인트라고 생각되는 부분이지요!)메이코 이후 드디어 그분을 만들어 내는 것을 준비합니다.크립톤은 이때부터 정말로 사용자들이 무엇을 원하는가에 대한 생각을 많이 한 것 같다고 보이는 포인트입니다. 메이코의 등장 이후, "하츠네 미쿠"라는 캐릭터 산업으로 만들어 내는 것을 준비합니다. 그리고 해당 캐릭터를 하나의 "사업전략"으로 생각해 낸 이유는 메이코의 KPI달성도 있겠지만, "사람의 목소리와 극히 다른 목소리로 노래를 부르게 된다면, 이상하지 않을까?라는 부분을 오히려 역으로 기획, "인간이 아닌 다른 안드로이드가 하는 노래"라는 새로운 존재로서 IP를 만들어 버린 것이죠!또,  캐릭터를 기반으로 다양한 성격을 가질 수 있도록 "성우"라는 시스템을 집어넣어 "특별한 존재"라는 특징 성을 추가하였고, 기존의 보컬로이드는 "인간의 가수를 대체하는 것"이었으나, 하츠네 미쿠는 "안드로이드 가 부르는 진짜 보컬로이드"라는 접근을 통해 새로운 존재를 만들고, 메이코 디자인을 기반으로, "아이돌 라이즈 된 새로운 사이버 가수"를 만든 것이죠!아아.... 이제 고인이 되신 사이버 가수 아담... (http://beautinaru.tistory.com/196 또한, 해당 콘텐츠를 기반으로 음악을 만들었던 유저들에게 레트로 한 마크들을 집어넣어서 예전에는 이랬었지 라는 향수를 불러일으키고, 해당 콘텐츠를 기반으로 다시 작업을 할 동기를 줄 수 있도록 유저들의 의견을 듣고 반영하는 일들을 굉장히 많이 했다고 합니다!그리고 하츠네 미쿠의 진정한 아이덴티티를 생성합니다. 그것은 바로 Chain of Co-creation!!!하츠네 미쿠가 이렇게 성장할 수 있었던 이유는 저는 하나만 꼽으라 라고 한다면 이쁘잖아요! 가아니라... "확산 가능 여부"에 대한 많은 고려가 있었기에 가능했다고 생각합니다.인터넷 덕분에 음악 등을 만드는 사람들이 쉽게 업로드하고 공유할 수 있는 많은 플랫폼들이 생성되는 현실.덕이 많은 분들이 공유를 통해 자아실현을 하는 공감대를 형성할 수 있는 움직임이 확산.콘텐츠가 콘텐츠를 만들고 퍼져나가는 순기능적인 부분들이 늘어나는 현상들을 확인하고,2차 3차 저작물을 통한 확산> Chain of co-creation의 순선환 적인 기능들이 생겨나는 것이죠!! 그리고 그런 상황을 기반으로, 궁극적으론,모든 사람들이 제작자가 될 수 있는 현실 상황을 받아들이고,제작할 수는 있지만,  저작에 관련한 법률 등에서 막히는 상황을 막기 위해, 창작자들의 창작활동을 돕고, 실제 업로드된 콘텐츠를 기반으로, 실제 사업이 일어날 수 있는 방향으로 전개합니다!그리고 수익화를 통해서 창작자들이 창작활동 = 수익활동이 될 수 있도록 플랫폼 화를 추진한 것이죠!그래서 처음 하츠네 미쿠가 나온 2007년부터 10년이 지난 지금까지도 "보컬로이드"의 선두 주자로 전 세계적으로 콘서트를 다니며 성공적인 투어를 하고 있습니다.투어는 계속된다. (출처: http://mikuexpo.com/) 저는 하츠네 미쿠가 단지 덕후들의 승리라고 요만큼도 생각하지 않습니다.하츠네 미쿠를 성장시킬 수 있었던 건 "우리가 제공하는 서비스가 어떤 유저들에게 더 많은 강점이 있고, 해당 유저들은 어떤 행동을 통해서 자아를 성찰할 수 있을까? 그리고 해당 행동을 통해 유저가 얻는 궁극적인 이익들이 잇을까?"를 생각했던, 크립톤의 유저를 생각하는, 유저의 직접적인 경험을 서비스에 반영하려고 하는 강한 의지가 해당 서비스를 성공시킬 수 있게 한 요인이라고 생각해요. 그런 의미에서 저에겐 정말로 뜻깊고 즐거웠던 세션이었습니다!P.S.: 이제 슬슬 NDC2017 영상들이 올라오기 시작하네요! 관심 있는 분들은 https://ndc.nexon.com/main에서 확인해 보세요~오늘도 긴 글 읽어주셔서 감사합니다! 다소 글이 엉망진창이라도 이해해 주세요! #코인원 #블록체인 #기술기업 #암호화폐 #스타트업인사이트
조회수 2584

[인공지능 in IT] 네가 내 마음을 알아?

지난 2018년 3월, 고용노동부는 10월부터 발효되는 '감정노동자 보호법 개정안'을 통과시켰다. 해당 개정안은 고객의 폭언이나 폭력으로부터 스트레스를 받는 감정노동자의 인권과 업무의 질을 개선시킬 사업주 조치를 의무화하는 내용을 담고 있다. 감정노동이란, 고객을 응대하며 자신의 본래 감정과는 상관없이, 업무상 정해진 감정 표현을 연기하는 것을 일상적으로 수행하는 노동을 말한다. 예로 콜센터, 백화점 안내, 텔레마케터 등이 있다.< 감정노동자 보호를 위한 5개 금융업법 개정안 주요 내용, 출처: 동아닷컴 >이제 정부는 감정노동자의 '적응 장애'와 '우울증' 등을 업무상 질병으로 인정한다. 세계보건기구(WHO)에서 정의한 건강은 '육체적, 정신적, 사회적, 영적으로 안녕한 상태'다. 즉, 감정노동자들은 육체뿐만 아니라 정신적, 사회적으로 고통받을 수 있다는 것이다. 그들은 자동으로 저장된 말을 내뱉는 음성 안내기가 아니고, 일반 사람들처럼 똑같이 울고 웃는 사람이다. 그렇지만, 아직까지 국내에서 심리상담에 대한 정서적인 장벽은 높고, 상담 받을 수 있는 인프라도 잘 갖춰지지 않다. 감정노동자들이 실질적인 상담 도움을 받기는 어렵다는 의미다.감정노동 소식 뒤, 국내 인공지능 기술 업체 중 한 곳이 심리상담 서비스를 출시했다는 기사를 접했다. 전문 심리 상담사들이 축적한 수많은 상담 시나리오 데이터를 수집하고 구축해, 개별적이고 정확한 서비스를 제공한다는 것이 취지다. 또한, 통화 목소리를 기반으로 이를 감정 데이터로 변환시켜 정신 건강에 대한 정보와 스트레스 관리 등을 위한 맞춤형 콘텐츠를 제공하는 것이 목적이다. 정확도는 알 수 없지만, 인공지능이 인간의 감정을 인지하고 생활에 도움을 줄 수 있다는 사실만으로도 큰 의미가 있다고 생각한다.사실 필자는 몇 년 전까지 매 순간 변하는 복잡한 인간의 감정은, 인간 고유의 것이라고 생각했다. 인간은 자신의 감정을 알지 못할 때도 있고, 긍정적인 감정과 부정적인 감정을 주체하지 못하기도 한다. 아직 우리 스스로 감정에 대해 확실하게 정의할 수 없고, 통제할 수 없다. 하지만, 그럼에도 불구하고, (앞서 언급한) 심리상담 서비스처럼 여러 분야에서 기계가 인간의 감정을 이해하고, 심지어 감정 표현을 돕는 연구는 거듭되고 있다.기계와 감정의 접목은 2000년대 이전부터 시작되었다. 1995년 MIT의 피카드(Rosalind Picard) 박사가 처음으로 감성컴퓨팅이라는 용어를 사용하며, 인간의 감성을 분석하고 해석하는 기술 개발을 시작했다. 감성 컴퓨팅은 인간이 느끼는 바를 인지, 해석, 처리할 수 있는 시스템을 설계하기 위한 인공지능 기술을 연구하고 개발하는 분야다. 감정 인식은 상상 이상으로 복잡하고, 아직까지 정확하게 구현하기 힘든 어려운 기술이지만, 조금씩 그 영역을 확장하며 다양한 분야에서 사용되고 있다.아무래도 사람의 감정을 드러내는 표면적인 수단 중 가장 눈에 띄는 것이 표정일 것이다. 얼굴에 드러나는 인간의 감정은 안면 근육의 움직임을 통해 여러 표정으로 나타나기 때문이다. 여기에 영상 처리 기술을 활용하면, 기계가 인간의 감정을 분류할 수 있다. 이를 기반으로 한 감정인식은 다음의 과정으로 이루어진다.먼저 영상이나 이미지 안에서 얼굴 영역을 찾는다. 일반적으로 스마트폰 카메라 앱에서 많이 볼 수 있듯, 네모 박스 형태로 얼굴을 인식한다. 그리고 해당 박스 안에서 눈, 코, 입 등 랜드마크라고 불리는 특징점들을 찾는다. 이어서 각 특징점을 바탕으로 각각의 위치나 배치를 파악하는 프로세스를 거친다. 마지막으로 학습을 거쳐 사람의 표정을 인식할 수 있다.일반적으로 감정 쪽을 연구하고 기술을 개발하는 업체 대다수는 이러한 딥러닝 방식을 적용한다. 그리고 미리 지정한 각각의 감정 메트릭에 사용자의 표정을 맵핑하는 식으로 결과값을 도출한다. 하나 주의해야 할 점은 표정과 비교하는 감정이라는 결과값을 '확률(%)'로 산출한다. 예를 들어, 눈썹을 찌푸리고 눈이 커지면서 입을 벌리고 있으면, 감정은 '화남 95%, 놀람 20%, 슬픔 5%...' 등으로 표현하는 방식이다.< EMOTION>이외에도 톤, 크기, 템포 등 감정 변화에 따라 변하는 목소리를 분석하는 음성 인식 기술이나 몸의 특정 움직임을 분석해 감정 상태를 인지하는 동작 인식 기술 등이 있다. 특히, 음성 인식은 CS(고객 응대) 영역에서 빛을 발할 수 있다. 실시간으로 고객의 감정을 분석해 소통방식을 바꾸거나, 그들의 구매 패턴을 예측하는 데 도움을 준다.최근에는 페퍼를 비롯한 가정용 휴머노이드 로봇이 여럿 출시되면서, 감정인식 기술의 적용사례를 쉽게 찾아볼 수 있다. 이들 로봇들은 인간과 대화할 때 억양이나 표정을 인식하며, 심지어 때로는 인간의 감정을 예측하고 묻기도 한다. 물론, 아직까지 우리의 머리 속에는 기계라는 생각 때문에 상호간 자연스러운 대화나 감정을 전달하기 어렵다. 하지만 문자, 음성, 시각 등 현재도 여러 영역에서 인공지능 기술은 발전을 거듭하고 있다.< 핸슨로보틱스(hansonrobotics)의 휴머노이드 로봇 소피아(Sopjia), 출처: 핸슨로보틱스 >인간의 감정이라는 것은 하나의 영적인 매개체가 아닌, 복합적인 것이다. 결국 각 영역별 인공지능 기술이 고도화될수록 감정 인식에 적용할 수 있는 기술 또한 정교해진다는 것을 의미한다. 언젠가는 기계가 인간의 말상대가 되어주고, 함께 어려운 문제에 대해 의논할 수 있는 단계까지 이르지 않을까? 감정 노동자의 마음을 어르고 달래는 로봇이 등장할지도 모를 일이다.이호진, 스켈터랩스 마케팅 매니저조원규 전 구글코리아 R&D총괄 사장을 주축으로 구글, 삼성, 카이스트 AI 랩 출신들로 구성된 인공지능 기술 기업 스켈터랩스에서 마케팅을 담당하고 있다#스켈터랩스 #기업문화 #인사이트 #경험공유 #조직문화 #인공지능기업 #기술기업
조회수 1099

앱 공모전 기획자에서 비전공 개발자가 되기까지

스푼을 만드는 사람들 다섯 번째 이야기클라이언트팀의 유일한 여성 개발자 Julia를 소개하고자 한다.바나나 최대 몇 개까지 드세요?"마케팅팀 썸머에겐 아귀찜이 있다면, 저에겐 '바나나'입니다. 저는 바나나 우유도 좋아하고, 바나나 한 송이를 그 자리에서 혼자 다 먹을 만큼 좋아해요. 카카오톡 이모티콘도 바나나 이모티콘을 가장 많이 사용할 정도로요. 바나나는 맛도 있지만, 먹으면 기분이 좋아지는 과일이에요"(인터뷰 후, 줄리아에게 바나나 한 다발 선물해드렸습니다. 맛있게 드셨길 바라요)Q. 할머니 감성을 가지셨다고 들었는데, 사실인가요? "네, 모르시는 분들이 많으시겠지만 저는 친구들이 '할머니'라고 불러줘요. 이유인즉슨, 건강에 관심이 워낙 많아서 영양제도 잘 챙겨 먹고 꽃무늬 옷이 많거든요. 정확히 말하면 꽃무늬 치마! 그리고 사석에서는 고향(전라도) 사투리를 많이 써서 그런 것 같아요"줄리아 닮은꼴: 닥터 슬럼프 아리 '줄리아'를 더 알아가고 싶어요본인은 어떤 사람이라고 생각하세요?독한 사람 - 저는 웬만한 것에 있어서 타의적으로 절대 포기를 하지 않아요. 제 스스로가 싫증이 날 때까지는 꼭 끝까지 해내고 말거든요.그래서 전 제 스스로를 독한 사람이라고 말하고 싶어요. 이전부터 개발자로서 커리어를 쌓아오셨나요?"저는 원래 문과생이에요. 비전공자죠. 대학 때 독어를 전공했고, 개발과는 사실 거리가 먼 사람이었어요. 저는 이 전에 많은 경험들을 해왔어요. 세계일주를 하고 싶어서 해상 승무원 준비도 했었고, 중국에서 무역회사에서 근무도 했었고요. 통역도 잠시 했었고, 이 전에는 앱 공모전 기획자로서의 삶도 있었어요. 앱 공모전 기획자라는 건, 회사 및 대회를 홍보하기 위해 직원 대상 또는 시민을 대상으로 행사 및 공모전을 기획해서 행사업체를 고용하거나 직접 운영하는 업무랍니다. 그리고 현재는 안드로이드 개발자로 커리어를 쌓고 있습니다."많은 커리어를 거쳐 개발자가 되신 계기가 있다면?"저는 인생 계획을 짧으면 5년, 길게는 10년씩 잡고 살아가요. 20대 때는 해보고 싶은 게 너무 많았고, 지금도 여전히 많아요. 그래서 20대는 정말 하고 싶은 모든 걸 해보자라는 마음으로 살아왔어요. 30대가 되면서 조금 더 안정적으로 살고픈 마음이 생기기 시작했고 무엇보다 하나의 전문적인 직업을 가지고 싶단 욕구가 커졌어요. 그래서 개발을 선택하게 되었습니다."책상에 약이 굉장히 많네요?"제가 아까 할머니 감성이 있다고 했는데.. 저는 건강을 엄청 챙기거든요.. 그래서 탕비실에도 돼지감자 차 및 영양제 등 굉장히 뭘 많이 챙겨 먹습니다. 그래서 제 책상엔 비타민 등 영양제가 가득하답니다!"집에서 가져온다는 돼지감자 차 당신의 회사생활이 궁금합니다Q. 여성 개발자로 일하는 삶은 어떤가요?"사실 저는 '개발'을 하는 일을 성별로 나누고 싶지는 않아요. 남자 개발자가 많은 이유는 아무래도 공대에 남성 비율이 더 많기 때문이라고 생각이 들기도 하고, '여자' 이기에 특별히 다르다거나 불편한 점은 없어요. 아직은 신입 개발자이다 보니, 배우고 있는 시점이기도 하고요. 그저 열심히 배우는 단계라고 봐주시면 좋을 것 같습니다 :) 무엇보다 제 위로 8년 차, 14년 차 선배분들과 함께 일하면서 정말 많이 배우고 있습니다."Q. 일하면서 언제가 가장 뿌듯하세요?"개발을 하시는 분들은 공감하실 텐데.. 안되던 문제가 갑자기 될 때(?)에요. 분명히 어제는 안됐는데, 오늘은 되는 날이 있거든요. 반대인 경우도 있고요. 그때 정말 뿌듯(?)하고 행복해요. 또 다른 하나는, 보통 다른 곳은 신입 개발자는 보조만 하는 경우가 많거든요. 하지만 팀원들이 저를 믿어주셔서 제가 새로운 기능을 맡아서 짠 추가 코드가 프로덕트에 적용이 될 때가 정말 뿌듯해요."Q. 회사 다니면서 가장 기억에 남는 일이 있다면?"제가 입사 후 함께 처음으로 새로운 국가에 출시했을 때요. 저는 새로운 국가에 서비스를 출시할 때마다 너무 기대되고 업무가 더 즐거워져요. 조금 더 다양한 업무가 주어지고, 생각도 더 많이 하게 되거든요. 그리고 저는 건강에 정말 신경 많이 쓰는데, 저번에 Jun 이 막내 특집(?)으로 홍삼 음료를 주셨는데.. 너무 취향 저격인 거예요. 딱 제가 정말 좋아하는 건강한 맛! 그래서 그날도 너무 행복했어요."Q. 어떤 사람과 일하고 싶으세요?배울 점이 있는 사람이요. 저 또한 누군가에게 배울 점이 있는 사람이고 싶어요.줄리아 업무 공간 당신의 사생활이 궁금합니다Q. 안드로이드 개발자는 안드로이드만 사용하나요?"모두가 그런 건 아니겠지만, 저는 사실 여태 살면서 안드로이드 폰만 사용했었어요. 무엇보다 저는 안드로이드 캐릭터가 너무 귀엽다고 생각하기에.."Q. 주말에는 무엇을 하며 시간을 보내세요?"저는 지난 1년간은 매주 주말마다 코딩 스터디를 해왔어요. 아무래도 비전공자에 늦게 시작한 개발자다 보니 엄청난 노력이 필요하거든요. 지금도 스터디를 하고 있어요. 그리고 2019년부터 목표는 한 달에 한 번쯤은 리프레쉬하기 위해 가까운 곳이라도 여행을 가려고 노력하고 있어요."Q. 개발자가 된 후 삶에 있어 변한 점이 있다면?"예전에는 어떤 것을 설명하거나 표현할 때, 굉장히 문과적(?) 이게 표현을 했었던 것 같아요. 지금도 완전히 바뀌진 않았어요. 하지만, 무언가 문제가 있을 때 원인과 결과를 먼저 파악하는 성향이 생겼달까요? 그리고 편견일 수도 있지만 조금 더 프로페셔녈 해 보이고 싶어서 백팩이나 후디를 자주 입습니다!" 비전공자로서 개발자를 꿈꾸는 사람들에게 "먼저, 비전공자라 하여 못할 거라는 생각을 하지 않으셨으면 좋겠어요. 저도 여전히 배우고 있는 입장이지만 생각보다 비전공자 중에 개발자로서 훌륭하신 분이 굉장히 많거든요. 늦더라도 정말 하고 싶은 마음이 있다면 꼭 도전하라고 말하고 싶어요. 그리고 꼭 영어 공부하세요. 아무래도 문서들이 영어로 되어있으니, 영어를 배워두면 번역기의 도움이 없이도 되기에 큰 도움이 되고 시간이 절약되거든요! 아, 그리고 개발을 배우고자 만약 학원에 가서 수업을 들을 예정이시라면, 수업을 듣기 전에 혼자라도 미리 예습을 하고 가셨으면 좋겠어요. 학원을 다닌다고 해서 정말 모든 걸 알려주진 않거든요. 얼마나 열심히 하고 노력하느냐에 따라 성패가 달린다고 생각합니다."안드로이드 팀원들이 줄리아를 한마디로 표현한다면?Derek 曰:  “줄리아는 강한 사람이라고 생각합니다. 외부의 환경에 흔들리지 않고 자신의 꿈을 향해 계속 전진하는 강한 사람이라고 생각합니다.”Yong 曰:  "낯선 길에서 의지를 잃지 않고 가고자 하는 길을 걷는 사람, 그리고 미소가 예뻐서 꽃 같은 사람입니다" 
조회수 1523

개발자의 시간 벌기

Overview지루한 작업은 저와 어울리지 않습니다. 한마디로 귀차니즘이 가득한 개발자입니다. 반복적인 일을 하고 있으면 딴 생각이 많이 떠오릅니다. 특히 개발 과정은 쿼리를 작성하고, 프로그램에 적용하고, 검증하는 일이 자주 발생하는데 필요 이상으로 내 시간을 낭비한다는 생각이 들었습니다. 매번 다시 작업해야 하는 쿼리의 조합을 책상 서랍에 착착! 정리해둔 물건처럼, 코드도 언제든 쓸 수 있게 착착! 준비해두면 시간도 절약되고, 업무도 편리해지지 않을까요. 도대체 최종 결과는....?개발언어를 PHP로 전향하면서 제일 오래 걸리는 부분은 프로그램에서 발생하는 쿼리를 다시 조합하고, 검증하는 작업이었습니다. 프로그램에 사용하는 조건을 체크하고, 대입되는 변수들을 체크하고, 치환할 부분에 넣어주는 작업을 반복해야 하고, 야근하고, 건강 잃고… 쿼리가 정상적으로 조합되지 않으면 어느 부분이 틀렸는지 매번 확인해야 합니다. 이 번거로운 작업을 안드로이드 개발에서 사용하는 logcat 같은 기능으로 만들면 좋을 것 같았습니다. 그래서 PHP용 Log 프로그램을 간단하게 만들기 시작했습니다.Logcat 화면, 한결 보기 편해 보인다. ㅂㄹ개발 컨셉손으로 쓱쓱 그려 보았습니다.PHP 쿼리 요청 코드// sql 디버깅 코드: 쿼리 시작 if (ENVIRONMENT == 'testing') {     if(function_exists('localDebugger')) localDebugger( 'sql_start', "0,".$sql);  } // Run the Query if (FALSE === ($this->result_id = $this->simple_query($sql)))  {     // 소스 생략     if ($this->db_debug)      {              // 소스생략 ...            $this->trans_complete();              // sql 디버깅 코드: 쿼리 에러           if (ENVIRONMENT == 'testing') {               if(function_exists('localDebugger'))  localDebugger( 'sql_error', '0, -- Error  Number: '.$error_no  ."\n--  message: ".$error_msg."\n");           }              // 소스생략 ...      }     return FALSE;  } // 소스 생략 // sql 디버깅 코드: 쿼리 종료 if (ENVIRONMENT == 'testing')  {     if(function_exists('localDebugger')) localDebugger( 'sql_done', ($em + $es) - ($sm + $ss).",");  } PHP 디버그 서버에 요청 코드$callNo = time();           /**           *로컬서버에 디버깅 메세지           * 지정된 서버에 디버깅 메세지 전달           * @access public           * @author BoseungChun           * @param string $message   디버깅할 메세지           */ function localDebugger( $type, $message ) {           global $callNo;           //debugger server           $url = 'http://127.0.0.1:3000';           $ch= curl_init($url);            // 요청 파일 분석           $trace= debug_backtrace();           $fileName= substr( $trace[1]['file'],strrpos($trace[1]['file'], '/') );           $line= $trace[1]['line'];           $fileName2= substr( $trace[2]['file'], strrpos($trace[2]['file'], '/'));           $line2= $trace[2]['line'];             // POST로 로깅 서버에 메세지 전달            curl_setopt($ch, CURLOPT_POST, 1);           curl_setopt($ch, CURLOPT_POSTFIELDS, $callNo.' '.$type.' '.uri_string().' '.$fileName2.':'.$line2."\n".$fileName.':'.$line.' '.$message);           curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);           $response = curl_exec($ch);           curl_close($ch);     } nodejs 일부 코드 // 서버 기동 const http = require('http');   const hostname = '127.0.0.1';  const port = 3000;   const server = http.createServer((req, res) => {       res.statusCode = 200;       res.setHeader('Content-Type', 'text/plain');       var body = '';       req.on('data', function (chunk) {           body += chunk;       }).on('end', function () {           var pos = body.indexOf(' ');           var no = body.substring(0, pos);           body = body.substring(pos+1);           pos = body.indexOf(' ');           var type = body.substring(0, pos);           body = body.substring(pos+1);           pos = body.indexOf(' ');           var uri = body.substring(0, pos);           body = body.substring(pos+1);           pos = body.indexOf(' ');           var file = body.substring(0, pos);           body = body.substring(pos+1);           pos = body.indexOf(',');           addSqlBlock( no, uri, file, body.substring(pos+1), body.substring(0, pos), type );      })      res.end('');  });   server.listen(port, hostname, () => {       console.log('Server running at http://${hostname}:${port}/');   }); // 코드 생략   function addSqlBlock( no, uri, file, sql, ms, type ) {      // UI를 구성해서 코드 블럭를 관리하는 태그에 붙여준다.   } 코드는 위의 코드와 같이 간단한 것들을 사용했습니다. 아래의 이미지는 nodejs를 이용해서 디버깅 메시지를 받을 서버를 만들고, 포트를 열어둔 것입니다. 정리하면 PHP 코드에서 발생하는 쿼리의 최종 내용을 디버깅 서버에 HTTP post 방식으로 전달해주는 구조입니다. 코드는 몇 줄 안 되지만, 꽤나 강력한 도구가 만들어졌습니다."어때요. 참 쉽죠?"짜란~~~ Logger 베타 버전이 도구는 페이지를 요청하는 즉시 쿼리가 잡힙니다. 어떤 페이지 요청에서 어떤 쿼리가 발생하는지 쉽게 분석할 수 있으니 번거롭게 쿼리를 조합하는 과정은 자연스럽게 사라졌습니다.색상으로 쿼리의 속도를 표현했다.이 프로그램의 제작자이지만, 유일한 사용자이기도 합니다. 불편한 게 느껴지면 바로 수정해야 했습니다. 어렸을 때 학습지 좀 풀었던 실력으로 알아서 척척척 스스로 기능을 보강했습니다. 위의 이미지처럼 색상만 추가해도 쉽게 분별할 수 있습니다. 쿼리 실행시간을 추가해 어떤 쿼리가 병목을 잡는지도 빠르게 찾을 수 있습니다.PHP 요청 패스를 넣었더니 개 이득!디버깅에 유용한 정보까지 추가했습니다. 요청된 경로, 쿼리가 실행된 파일의 이름, 라인 위치 모델을 요청한 상위 파일의 이름과 라인 위치를 추가해 트래킹을 보강했습니다. 이쯤 되니 거의 절대반지급입니다. 쿼리 이즈 마이 프레셔스..개발에 필요한 정보들이 노출되니 기쁘지 아니한가!이외에도 현재까지 아래의 기능들을 추가했습니다.쿼리 카피 기능과 신텍스 하이라이트, 쿼리 라인쿼리 에러 메시지 로깅url 요청 단위로 쿼리 묶어주기시간이 지난 쿼리 자동 지우기키워드 검색 기능필요한 걸 직접 만들어 사용하는 것이 귀찮을지도 모릅니다. D.I.Y도 아닌데 말입니다. 하지만 자신의 개발 능력을 활용해 업무 환경을 개선하고, 개선된 만큼의 시간을 다시 투자해 선순환 구조를 만든다면 행복한(?) 개발이 될 거라 생각합니다. (=더 많은 일을 하게 되는 건 안 비밀)오늘은 업무 전, 반복 작업을 개선하면 어떨까요. 참고(사용기술)nwjsPHP (codeigniter)CSS3 + HTML5JQuery글천보성 팀장 | R&D 개발2팀[email protected]브랜디, 오직 예쁜 옷만#브랜디 #기업문화 #조직문화 #업무환경 #인사이트 #경험공유

기업문화 엿볼 때, 더팀스

로그인

/