스토리 홈

인터뷰

피드

뉴스

조회수 2891

코딩, 어떤 언어로 시작하지?

경영학과 학생 윤수는 요즘 주변에서 이런 말을 자주 듣는다."앞으로는 코딩을 모르면 문맹이다.""4차 산업혁명 시대에 대비해야 한다.""소프트웨어가 세상을 잡아먹고 있다."정확히 뭔 소리인지는 모르겠지만 일단 프로그래밍을 배우기로 결심한다. 그런데 '프로그래밍 언어'라는 게 또 뭐가 이렇게 많은지... 어떤 걸로 시작해야 할지 도무지 감이 안 잡힌다.그래서 공대생 친구들에게 물어본다. 친구 1: "일단 가장 기본인 C부터 배워."친구 2: "한국에서 제일 많이 쓰는 자바부터 배워."친구 3: "파이썬이 배우기 쉬워."친구 4: "요즘은 자바스크립트가 대세지."누가 정답일까? 사실 이 중에 "틀린" 사람은 없다. 각자 관심 분야와 목적이 다르기 때문이다. 만약 다음 달에 아이폰 어플을 개발해야 한다면 어쩔 수 없이 곧장 스위프트를 배워야 한다. 내일모레까지 사이트 레이아웃을 완성해야 한다면 더 물을 것도 없이 그냥 HTML과 CSS를 시작하면 된다. 그러나 일반적으로 첫 프로그래밍 언어를 추천하라면 내 톱 초이스는 단연 파이썬, 그다음은 HTML/CSS + 자바스크립트일 것이다. 이 3개의 기준으로 평가하였다:1. 배우기에 얼마나 어려운 언어인가?2. 이 언어에 대한 수요가 얼마나 있는가?3. 나는 프로그래밍으로 뭘 하고 싶은가?*우연히 보게 된 CSDojo라는 유튜브 채널에서 너무 훌륭하게 정리해줘서 참고하였다.1. 배우기에 얼마나 어려운 언어인가?나는 고등학교 때 C를 독학하는 것으로 프로그래밍에 입문했다가 금방 질려서 그만두었다. 창업에 관심이 생겨 다시 시작했는데 이번에는 파이썬으로 배워보았다. 그제야 흥미를 느꼈고, 프로그래밍이 마냥 어렵기만 한 게 아니라는 걸 깨달았다.어떤 차이가 있는 걸까?파이썬은 C보다 쓰기 쉽다. C로 수백 줄을 써야 하는 프로그램을 파이썬 몇십 줄로 쓸 수 있다. 파이썬 코드 몇 줄이면 쓸모 있고 흥미로운 결과물을 만들어낼 수 있다는 뜻이다. "Life is short, use Python"이라는 말이 있을 정도다. 물론 파이썬이 무조건적으로 C보다 좋은 건 아니다. 파이썬 프로그램은 C 프로그램보다 느리기 때문에 특정 업무에는 적합하지 않다. 하지만 그런 건 지금 신경 쓸 필요가 없다. 첫 프로그래밍 언어로 "컴퓨터적인 사고력"을 익히고 나면 새로운 언어를 배우는 것은 어렵지 않기 때문에, 일단은 배우기 쉬운 언어로 시작해라.비교적 배우기 쉬운 언어:    - Python    - Ruby    - JavaScript2. 이 언어에 대한 수요가 얼마나 있는가?시장에서 필요로 하는 언어를 배우는 게 좋다. 세계에서 가장 큰 웹사이트들은 어떤 기술을 사용하는지 살펴보자:출저: 위키피디아위 테이블에는 미국의 웹 서비스들만 정리되어 있다. 지역과 직군에 따라 요구하는 언어가 다르기 때문에 로켓펀치, 더팀스, 위시켓, 링크드인, 인디드, 사람인, 잡코리아 등의 구인/구직 사이트에서 직접 살펴보는 걸 추천한다.인기가 많은 언어일수록 커뮤니티가 크기 때문에, 도움을 받을 수 있는 자료들이 많고 가져다 쓸 수 있는 코드가 많다는 장점도 있다. 세계 최대 규모의 프로그래밍 커뮤니티인 스택오버플로우의 언어 점유율을 참고해보자.출저: 스택오버플로우이 중에서 HTML/CSS(웹 레이아웃), SQL(데이터베이스), Bash/Shell(Unix)은 아주 특수한 경우에 쓰이는 언어이기 때문에 제외하고 보자. 수요가 높은 언어:    - JavaScript    - Java    - Python3. 나는 프로그래밍으로 뭘 하고 싶은가?분야별로 자주 사용되는 언어가 있다. 간단하게 정리하자면:1. 데이터 과학, 공학 => Python, R, MATLAB2. 웹 프런트엔드 => HTML/CSS + JavaScript3. 웹 백엔드 (서버) => Python, Ruby, JavaScript, Java, Go, C, C++, PHP 등4. 아이폰 어플 => Objective-C, Swift (이제는 거의 Swift로 넘어갔다)5. 안드로이드 어플 => Java, Kotlin (슬슬 Kotlin으로 넘어가고 있다)6. 게임 개발 => C#, C++7. 임베디드 시스템 => C, C++결론: 왜 파이썬, 자바스크립트인가?앞서 이야기했듯 당장 급히 배워야 하는 언어가 있으면 그 언어를 배우면 된다. 교수님이 연구실에서 다음 주부터 C언어를 쓴다고 하면, 뭐 어쩌겠나? 그냥 당장 C를 배우는 수밖에. 하지만 조금 더 여유롭게, 제대로 프로그래밍을 배우고 싶다면 이 포스트에 나와 있는 세 가지 기준을 고려해서 결정하는 걸 추천한다. 배우기 쉬운 언어로는 파이썬, 루비, 자바스크립트를 선정했고, 수요가 높은 언어로는 자바스크립트, 자바, 파이썬을 선정했다. 두 기준에 모두 부합하는 언어는 파이썬과 자바스크립트이다. 이 중 무엇을 택할지는 3번 기준으로 결정하면 된다. 데이터 분석에 관심 있으면 파이썬부터, 웹 개발에 관심 있으면 자바스크립트부터 시작하면 된다. 참고로 자바스크립트를 하기 위해서는 기본적으로 HTML과 CSS를 알아야 한다!데이터 과학과 웹 개발 둘 다 관심 없으면 자바스크립트보다는 파이썬으로 시작하는 걸 추천한다. 개인적인 의견이지만 초보자 입장에서 파이썬 언어가 자바스크립트보다 깔끔하다고 생각하기 때문이다. 또한 HTML과 CSS를 미리 배워야 하는 수고를 덜 수 있다.어디서 배우지?온라인으로 프로그래밍을 가르치는 사이트가 굉장히 많다. 해외에는 Codecademy, Treehouse, Coursera, MIT OpenCourseWare 등이 있고 한국에는 인프런, 엘리스, 코드잇, 생활코딩 등이 있다. 국내외 서비스를 통틀어서 가장 추천하는 곳은 코드잇이다. 영어로 된 수업이 당연히 더 좋을 것이라 생각한다면 큰 오산이다. Codecademy나 Treehouse는 쉽고 재미있지만 막상 수업을 다 들어도 직접 무언가를 할 수 있겠다는 생각이 들지 않는다. 반면 Coursera나 MIT OpenCourseWare는 대학 수업과 흡사하기 때문에 지루하고 어려워서 이수율이 5% 정도밖에 되지 않는다. 코드잇은 내용의 깊이와 재미를 모두 잡았다. 심도 있는 내용을 난해하지 않고 간결하게 풀어내어 졸업률이 60%나 된다. 코드잇 수업 안 들은 사람은 있어도 하나만 들은 사람은 없다는 말이 있을 정도인데, 수강 후기를 보면 정말 수강생들의 애정이 드러난다. 무료로 샘플을 들어볼 수 있으니 일단 한 번 해보도록.Python으로 배우는 프로그래밍 기초 수업, HTML/CSS로 배우는 웹 퍼블리싱 수업, JavaScript로 배우는 인터랙티브 웹 수업을 모두 들으면 자신감을 갖고 프로그래밍 커뮤니티에 입문할 수 있을 것이다.이제 어떤 프로그래밍 언어를 어디서 배워야 하는지 알았으니, 주저 말고 시작해보길 바란다!#코드잇#코딩교육 #개발자양성 #교육기업 #인사이트 #경험공유
조회수 8037

Node.js로 Amazon DynamoDB 사용하기

DynamoDB 로컬 설정 (다운로드 버전)실제 DynamoDB 웹 서비스에 액세스하지 않고 로컬에서 애플리케이션 작성 및 테스트를 할 수 있음1. 다운로드 링크에서 DynamoDB 무료 다운로드2. 압축 해제 후 해당 디렉터리에서 아래의 명령어로 실행java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb* Ctrl+C로 중지할 수 있고 중지하기 전까지 수신 요청을 처리함* 기본적으로 8000번 포트를 사용Node.js 용 AWS SDK 설치1. 설치npm install aws-sdk2. 실행// app.jsvar AWS = require("aws-sdk");var s3 = new AWS.S3();// 버킷 이름은 모든 S3 사용자에게 고유한 것이어야 합니다.var myBucket = "dynamodb.sample.wonny";var myKey = "myBucketKey";s3.createBucket({ Bucket: myBucket }, function(err, data) {  if (err) {    console.log(err);  } else {    params = { Bucket: myBucket, Key: myKey, Body: "Hello!" };    s3.putObject(params, function(err, data) {      if (err) {        console.log(err);      } else {        console.log("Successfully uploaded data to myBucket/myKey");      }    });  }});node app.js테이블 생성// CreateTable.jsvar AWS = require("aws-sdk");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var dynamodb = new AWS.DynamoDB();var params = {  TableName: "Movies",  KeySchema: [    { AttributeName: "year", KeyType: "HASH" }, // Partition key    { AttributeName: "title", KeyType: "RANGE" } // Sort key  ],  AttributeDefinitions: [    { AttributeName: "year", AttributeType: "N" },    { AttributeName: "title", AttributeType: "S" }  ],  // 다운로드 버전인 경우 아래 코드 무시  ProvisionedThroughput: {    ReadCapacityUnits: 10,    WriteCapacityUnits: 10  }};dynamodb.createTable(params, function(err, data) {  if (err) {    console.log(      "Unable to create table. Error JSON: ",      JSON.stringify(err, null, 2)    );  } else {    console.log(      "Created table. Table description JSON: ",      JSON.stringify(data, null, 2)    );  }});node CreateTable.js샘플 데이터 로드1. 이곳에서 샘플 데이터 파일 다운로드데이터 형태는 아래와 같음[    {        "year": 2013,        "title": "Rush",        "info": {            "directors": ["Ron Howard"],            "release_date": "2013-09-02T00:00:00Z",            "rating": 8.3,            "genres": [                "Action",                "Biography",                "Drama",                "Sport"            ],            "image_url": "http://ia.media-imdb.com/images/M/MV5BMTQyMDE0MTY0OV5BMl5BanBnXkFtZTcwMjI2OTI0OQ@@._V1_SX400_.jpg",            "plot": "A re-creation of the merciless 1970s rivalry between Formula One rivals James Hunt and Niki Lauda.",            "rank": 2,            "running_time_secs": 7380,            "actors": [                "Daniel Bruhl",                "Chris Hemsworth",                "Olivia Wilde"            ]        }    },    ...]- year 및 title을 Movies 테이블을 위한 기본 키 속성 값으로 사용- info의 나머지 값들은 info라는 단일 속성에 저장- JSON을 DynamoDB 속성에 저장2. 샘플 데이터 Movies 테이블에 로드// LoadData.jsvar AWS = require("aws-sdk");var fs = require("fs");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();console.log("Importing movies info DynamoDB. Please wait.");var allMovies = JSON.parse(fs.readFileSync("moviedata.json", "utf8"));allMovies.forEach(function(movie) {  var params = {    TableName: "Moves",    Item: {      year: movie.year,      title: movie.title,      info: movie.info    }  };  docClient.put(params, function(err, data) {    if (err) {      console.error(        "Unable to add movie",        movie.title,        ". Error JSON:",        JSON.stringify(err, null, 2)      );    } else {      console.log("PutItem succeeded:", movie.title);    }  });});node LoadData.js테이블에 항목 추가// PutItem.jsvar AWS = require("aws-sdk");var fs = require("fs");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();var table = "Movies";var year = 2017;var title = "The Big Wonny";var params = {  TableName: table,  Item: {    year: year,    title: title,    info: {      plot: "Nothing happens at all.",      rating: 0    }  }};console.log("Adding a new item...");docClient.put(params, function(err, data) {  if (err) {    console.error(      "Unable to add item. Error JSON:",      JSON.stringify(err, null, 2)    );  } else {    console.log("Added item:", JSON.stringify(data, null, 2));  }});node PutItem.js- 기본 키가 필요하므로 기본 키 (year, title) 및 info 속성 추가항목 읽기// GetItem.jsvar AWS = require("aws-sdk");var fs = require("fs");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();var table = "Movies";var year = 2017;var title = "The Big Wonny";var params = {  TableName: table,  Key: {    year: year,    title: title  }};docClient.get(params, function(err, data) {  if (err) {    console.error(      "Unable to read item. Error JSON:",      JSON.stringify(err, null, 2)    );  } else {    console.log("GetItem succeeded:", JSON.stringify(data, null, 2));  }});node GetItem.js항목 업데이트// UpdateItem.jsvar AWS = require("aws-sdk");var fs = require("fs");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();var table = "Movies";var year = 2017;var title = "The Big Wonny";var params = {  TableName: table,  Key: {    year: year,    title: title  },  UpdateExpression: "set info.rating = :r, info.plot=:p, info.actors=:a",  ExpressionAttributeValues: {    ":r": 5.5,    ":p": "Everything happens all at once.",    ":a": ["Larry", "Moe", "Curly"]  },  ReturnValues: "UPDATED_NEW"};console.log("Updating the item...");docClient.update(params, function(err, data) {  if (err) {    console.error(      "Unable to update item. Error JSON:",      JSON.stringify(err, null, 2)    );  } else {    console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2));  }});node UpdateItem.js- 지정된 항목에 대해 수행하고자 하는 모든 업데이트를 설명하기 위해 UpdateExpression을 사용- ReturnValues 파라미터는 DynamoDB에게 업데이트된 속성("UPDATED_NEW")만 반환하도록 지시원자성 카운터 증가시키기update 메서드를 사용하여 다른 쓰기 요청을 방해하지 않으면서 기존 속성의 값을 증가시키거나 감소시킬 수 있음 (모든 쓰기 요청은 수신된 순서대로 적용)실행 시 rating 속성이 1씩 증가하는 프로그램// Increment.jsvar AWS = require("aws-sdk");var fs = require("fs");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();var table = "Movies";var year = 2017;var title = "The Big Wonny";// Increment an atomic countervar params = {  TableName: table,  Key: {    year: year,    title: title  },  UpdateExpression: "set info.rating = info.rating + :val",  ExpressionAttributeValues: {    ":val": 1  },  ReturnValues: "UPDATED_NEW"};console.log("Updating the item...");docClient.update(params, function(err, data) {  if (err) {    console.error(      "Unable to update item. Error JSON:",      JSON.stringify(err, null, 2)    );  } else {    console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2));  }});node Increment.js항목 업데이트(조건부)UpdateItem을 조건과 함께 사용하는 방법조건이 true로 평가되면 업데이트가 성공하지만 그렇지 않으면 수행되지 않음// ConditionalUpdateItem.jsvar AWS = require("aws-sdk");var fs = require("fs");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();var table = "Movies";var year = 2017;var title = "The Big Wonny";// Increment an atomic countervar params = {  TableName: table,  Key: {    year: year,    title: title  },   UpdateExpression: "remove info.actors[0]",  ConditionExpression: "size(info.actors) > :num",  ExpressionAttributeValues: {    ":num": 3  },  ReturnValues: "UPDATED_NEW"};console.log("Attempting a conditional update...");docClient.update(params, function(err, data) {  if (err) {    console.error(      "Unable to update item. Error JSON:",      JSON.stringify(err, null, 2)    );  } else {    console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2));  }});node ConditionalUpdateItem.js다음과 같이 작성하면 아래와 같은 에러 메시지가 표시 됨The conditional request failed"영화에는 3명의 배우가 있는데 배우가 3명보다 많은지를 확인하고 있어 에러가 발생다음과 같이 수정하면 정상적으로 항목이 업데이트 됨ConditionExpression: "size(info.actors) >= :num",항목 삭제// DeleteItem.jsvar AWS = require("aws-sdk");var fs = require("fs");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();var table = "Movies";var year = 2017;var title = "The Big Wonny";var params = {  TableName: table,  Key: {    year: year,    title: title  },  ConditionExpression: "info.rating <= :val",  ExpressionAttributeValues: {    ":val": 5.0  }};console.log("Attempting a conditional delete...");docClient.delete(params, function(err, data) {  if (err) {    console.error(      "Unable to update item. Error JSON:",      JSON.stringify(err, null, 2)    );  } else {    console.log("DeleteItem succeeded:", JSON.stringify(data, null, 2));  }});node DeleteItem.js다음과 같이 작성하면 아래와 같은 에러 메시지가 표시 됨The conditional request failed특정 영화에 대한 평점이 5보다 크기 때문에 에러가 발생다음과 같이 수정하면 정상적으로 항목이 삭제 됨var params = {  TableName: table,  Key: {    year: year,    title: title  }};데이터 쿼리- 파티션 키 값을 지정해야 하며, 정렬 키는 선택 사항- 1년 동안 개봉한 모든 영화를 찾으려면 year만 지정, title을 입력하면 2014년 개봉된 "A"로 시작하는 영화를 검색하는 것과 같이 정렬 키에 대한 어떤 조건을 바탕으로 일부 영화를 검색할 수도 있음한 해 동안 개봉한 모든 영화// QueryYear.jsvar AWS = require("aws-sdk");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();var params = {  TableName: "Movies",  KeyConditionExpression: "#yr = :yyyy",  ExpressionAttributeNames: {    "#yr": "year"  },  ExpressionAttributeValues: {    ":yyyy": 1985  }};docClient.query(params, function(err, data) {  if (err) {    console.error("Unable to query. Error JSON:", JSON.stringify(err, null, 2));  } else {    console.log("Query succeeded.");    data.Items.forEach(function(item) {      console.log(" -", item.year + ": " + item.title);    });  }});node QueryYear.jsExpressionAttributeNames는 이름을 교체함. 이를 사용하는 이유는 year가 DynamoDB에서 예약어이기 때문. KeyConditionExpression을 포함해 어떤 표현식에서도 사용할 수 없으므로 표현식 속성 이름인 #yr을 사용하여 이를 지칭ExpressionAttributeValues는 값을 교체함. 이를 사용하는 이유는 KeyConditionExpresssion을 포함해 어떤 표현식에서도 리터럴을 사용할 수 없기 때문. 표현식 속성 값인 :yyyy를 사용해 지칭* 위의 프로그램은 기본 키 속성으로 테이블을 쿼리하는 방법. DynamoDB에서 1개 이상의 보조 인덱스를 테이블에 생성하여 그 인덱스로 테이블을 쿼리하는 것과 동일한 방식으로 쿼리 작업 가능. 보조 인덱스는 키가 아닌 속성에 대한 쿼리를 허용하여 애플리케이션에 더 많은 유연성을 부여함한 해 동안 개봉한 모든ㄴ 영화 중에 특정 제목을 지닌 영화year 1992에 개봉한 영화 중에 title이 "A"부터 "L"까지의 알파벳으로 시작하는 영화를 모두 조회합니다.// QueryTitle.jsvar AWS = require("aws-sdk");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();console.log(  "Querying for movies from 1992 - titles A-L, with genres and lead actor");var params = {  TableName: "Movies",  ProjectionExpression: "#yr, title, info.genres, info.actors[0]",  KeyConditionExpression: "#yr = :yyyy and title between :letter1 and :letter2",  ExpressionAttributeNames: {    "#yr": "year"  },  ExpressionAttributeValues: {    ":yyyy": 1992,    ":letter1": "A",    ":letter2": "L"  }};docClient.query(params, function(err, data) {  if (err) {    console.error("Unable to query. Error JSON:", JSON.stringify(err, null, 2));  } else {    console.log("Query succeeded.");    data.Items.forEach(function(item) {      console.log(        " -",        item.year + ": " + item.title + " ... " + item.info.genres + " ... ",        item.info.actors[0]      );    });  }});node QueryTtiel.js스캔테이블의 모든 항목을 읽고 테이블의 모든 데이터를 반환선택 사항인 filter_expression을 제공할 수 있으며 그 결과 기준이 일치하는 항목만 반환하지만 필터는 테이블 전체를 스캔한 후에만 적용됨// Scan.jsvar AWS = require("aws-sdk");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();var params = {  TableName: "Movies",  ProjectionExpression: "#yr, title, info.rating",  FilterExpression: "#yr between :start_yr and :end_yr",  ExpressionAttributeNames: {    "#yr": "year"  },  ExpressionAttributeValues: {    ":start_yr": 1950,    ":end_yr": 1959  }};console.log("Scanning Movies table.");docClient.scan(params, onScan);function onScan(err, data) {  if (err) {    console.error(      "Unable to scan the table. Error JSON:",      JSON.stringify(err, null, 2)    );  } else {    // print all the movies    console.log("Scan succeeded.");    data.Items.forEach(function(movie) {      console.log(        movie.year + ": ",        movie.title,        "- rating:",        movie.info.rating      );    });    // continue scanning if we have more movies, because    // scan can retrieve a maximum of 1MB of data    if (typeof data.LastEvaluatedKey != "undefined") {      console.log("Scanning for more...");      params.ExclusiveStartKey = data.LastEvaluatedKey;      docClient.scan(params, onScan);    }  }}node Scan.jsProjectionExpression은 스캔 결과에서 원하는 속성만 지정FilterExpression은 조건을 만족하는 항목만 반환하도록 조건을 지정. 다른 항목들은 모두 무시됨테이블 삭제// DeleteTable.jsvar AWS = require("aws-sdk");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var dynamodb = new AWS.DynamoDB();var params = {  TableName: "Movies"};dynamodb.deleteTable(params, function(err, data) {  if (err) {    console.error(      "Unable to delete table. Error JSON:",      JSON.stringify(err, null, 2)    );  } else {    console.log(      "Deleted table. Table description JSON:",      JSON.stringify(data, null, 2)    );  }});node DeleteTable.js#트레바리 #개발자 #안드로이드 #앱개발 #Node.js #백엔드 #인사이트 #경험공유 #데이터베이스 #DB #개발 #AWS #아마존 #NoSQL 
조회수 2128

JPassKit 적용중 오류 발생

서비스에서 ios wallet을 제공하려고 하니, 예전과는 다르게 서버단 통신을 통해 인증받는 절차가 추가로 생겼단다. 다만, 애플에서 제공하는 서버쪽 데모를 보면 ruby로 만들어져있다. 왜 하필 루비인가? swift도 아니고… 여튼 그걸 java로 porting하려니 이미 만들어 놓은 것이 있을 것 같아서 구글링했더니, jpasskit이 그나마 제일 fork도 많이 되고, 사용도 하는 것 같아서 lib dependency를 추가했다.<!-- PassKit --> de.brendamour jpasskit 0.0.8 개발을 완료했는데, Test Case에서 오류가 나타나기 시작했다.com.fasterxml.jackson.databind.JsonMappingException: Can not resolve PropertyFilter with id 'validateFilter'; no FilterProvider configured난 jackson filter를 바꾼 적이 없는데 왜 에러가 나는 것인가? 처음에는 jpasskit issue를 보고 jackson lib의 version 호환성 문제가 있는 것 같아서 아래처럼 dependency처리를 했다.<!-- PassKit --> de.brendamour jpasskit 0.0.8 com.fasterxml.jackson.core jackson-core 위의 오류가 해결된 것처럼 보여서 SNAPSHOT version을 만들었는데, 됐다안됐다한다. 예를 들어서 local profile에서 하면 되고, develop profile에서 하면 오류나고… 혹은 전체 junit을 모두 돌리면 에러가 발생하는데, 에러나는 class만 테스트 돌리면 성공하고 ㅠ.ㅠ그래서 해당 소스를 파보다가 문제점을 발견하였다.우리의 프로젝트에서는 pojo type인 jackson object mapper를 bean으로 등록해서 사용하고 있다. bean으로 등록하면 몇 가지 장점이 있는데, 자세한 설명은 이 글의 범위를 벗어나기 때문에 생략한다.@Primary @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new CustomObjectMapper(); initializeObjectMapper(objectMapper); return objectMapper; }그래서 Object Mapper는 singleton으로 재사용하고 있는데, jpasskit은 Object Mapper를 변조시키고 있다.public final class PKFileBasedSigningUtil extends PKAbstractSIgningUtil { private static final String FILE_SEPARATOR_UNIX = "/"; private static final String MANIFEST_JSON_FILE_NAME = "manifest.json"; private static final String PASS_JSON_FILE_NAME = "pass.json"; private ObjectWriter objectWriter; @Inject public PKFileBasedSigningUtil(ObjectMapper objectMapper) { this.addBCProvider(); this.objectWriter = this.configureObjectMapper(objectMapper); } ...protected ObjectWriter configureObjectMapper(ObjectMapper jsonObjectMapper) { jsonObjectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); jsonObjectMapper.setDateFormat(new ISO8601DateFormat()); SimpleFilterProvider filters = new SimpleFilterProvider(); filters.addFilter("validateFilter", SimpleBeanPropertyFilter.serializeAllExcept(new String[]{"valid", "validationErrors"})); filters.addFilter("pkPassFilter", SimpleBeanPropertyFilter.serializeAllExcept(new String[]{"valid", "validationErrors", "foregroundColorAsObject", "backgroundColorAsObject", "labelColorAsObject", "passThatWasSet"})); filters.addFilter("barcodeFilter", SimpleBeanPropertyFilter.serializeAllExcept(new String[]{"valid", "validationErrors", "messageEncodingAsString"})); filters.addFilter("charsetFilter", SimpleBeanPropertyFilter.filterOutAllExcept(new String[]{"name"})); jsonObjectMapper.setSerializationInclusion(Include.NON_NULL); jsonObjectMapper.addMixIn(Object.class, PKAbstractSIgningUtil.ValidateFilterMixIn.class); jsonObjectMapper.addMixIn(PKPass.class, PKAbstractSIgningUtil.PkPassFilterMixIn.class); jsonObjectMapper.addMixIn(PKBarcode.class, PKAbstractSIgningUtil.BarcodeFilterMixIn.class); jsonObjectMapper.addMixIn(Charset.class, PKAbstractSIgningUtil.CharsetFilterMixIn.class); return jsonObjectMapper.writer(filters); }확실해졌다. 위에서 상황마다 오류가 간헐적으로 발생하는 이유는 이와 같은 것이었다. jpasskit이 실행되기 전까지는 정상적으로 동작한다. 그러다가 jpasskit을 한 번 거치면 이미 등록되어 있는 object mapper bean의 설정이 바뀌게 된다. 즉, 우리가 설정한 custom configuration들이 무시되어버려서, 전혀 엉뚱한 곳에서 에러를 일으킨다.jpasskit에서 사용하는 object mapper는 특별한 설정이 필요한 것은 아니라, bean을 사용하지 않고 기본 object mapper를 생성해서 넘기는 식으로 수정하였다.private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); ... private byte[] createPKPassBinaries(PKPass pass, PKSigningInformation pkSigningInformation, InputStream thumbnail, InputStream thumbnail2x) throws Exception { return new PKFileBasedSigningUtil(OBJECT_MAPPER).createSignedAndZippedPkPassArchive(pass, createPKPassTemplate(thumbnail, thumbnail2x), pkSigningInformation); }All Clear.해당 내용은 jpasskit에 issue reporting하여 신규 release(0.0.9)가 예정중이다.#데일리 #데일리호텔 #기술스택 #스택도입 #후기 #일지 #JPasskit
조회수 422

매장 수익 극대화하기

매장/식당을 운영할 때 우리가 가장 많이 신경 쓰는 영역은 매출과 수익일 것입니다. 비즈니스가 앞으로 나아가려면 고객이 필요하고 이는 매출/수익으로 이어집니다. 매출은 비즈니스 라이프 스트림의 시작이며 사업을 유지하고 수익 내기 위해 필요합니다. 우리는 서로 다른 비즈니스 환경에 맞는 구체적인 매출 전략이 필요합니다. 고객을 유치하여 음식, 서비스 및 브랜드에 충실하게 만들거나 더 많은 고객을 수용하기 위해 식당을 확장 할 수도 있습니다. 레스토랑 비즈니스가 수익을 창출하고 고객을 다시 방문하게 만드는 요인에 대해 살펴 보겠습니다.저는 여기서 매출 증대 활동을 주요 활동과 지원 활동으로 나누겠습니다.매출 증대를 위한 주요 활동레스토랑 비즈니스의 핵심 비즈니스 모델은 제공되는 음식입니다. 그걸 잊지 맙시다. 저는 이 것이 많은 독자들에게 상기 될 필요가 없기를 바랍니다.1. 품질 및 고객 경험을 타협하지 마십시오.요식업에서 음식과 서비스의 질을 낮추는 것은 일으키고자 하는 변화에 대한 마지막 옵션 혹은 아예 고려하지 말아야 할 사항입니다. 사람들이 식당을 반복적으로 방문하는 유일한 이유는 음식과 경험입니다. 고객을 다시 오게 만든는 것은 광고가 아니며 충성도 높은 고객을 만드는 것은 눈에 띄는 거창한 광고 문구가 아닙니다. 우리는 레스토랑의 본질인 제품과 서비스에 집중해야 합니다.음식과 서비스의 질을 유지하기 위한 활동들:직원 회전율 평가요리사와 서버가 너무 많이 입퇴사하는 경우 음식과 서비스에 문제가 될 것입니다. 해당 현상을 발견했다면 문제를 해결하십시오!원재료/제품 소싱모든 제품 품질의 기본은 제조자 혹은 질에 달려있습니다. 식당 운영에서 재료의 신선도는 타협할 수는 없습니다 (소매점의 경우 제품의 품질). 어떠한 방법으로든 좋은 품질의 재료/제품을 찾으십시오 (합리적인 차원에서). 너무 비싸면 다른 식당과 공동구매하여 단가를 낮추십시오. 열심히 한 만큼 돌아옵니다.트레이닝 매뉴얼트레이닝 매뉴얼을 만들고 항상 음식 준비, 요리 지침 및 매장 운영에 대한 규칙을 세운 후 그에 따르도록 합니다. 제대로된 교육을 받지 않은 직원은 비즈니스에 있어 평생 고객을 잃는 손해를 안겨다 줄 수 있습니다. 그 동안 트레이닝의 효과를 무시했다면, 이제 사업의 트레이닝 과정을 다시 평가해 볼 때입니다. 따라야 할 일련의 규칙을 가지고 있으면 음식과 서비스의 일관성이 유지됩니다.2. 피드백 루프이는 일부 IT 스타트업의 문제처럼 들릴지 모르지만 건강한 피드백 루프는 고객의 참여를 이끌어 내고 그들의 목소리를 들어주는 좋은 방법입니다. 모든 사업은 스타트업처럼 성장할 수 있습니다. 양적 데이터와 정성적인 피드백에 모든 결정을 기반하세요. 성공한 스타트업 중 가장 성공적인 기업은 고객과의 건강한 피드백 루프를 가지고 있습니다. 이 것이 제품에 대한 시장의 반응을 파악하고 비즈니스의 방향을 재검증하는 방법입니다. 사업은 당신의 마스터 플랜에 달려 있지 않습니다. 비즈니스는 고객들에 달려있고 그들과 함께합니다. 오늘 고객에게 경험이 어땠는지 묻기 시작해 보세요. 그들이 무엇을 좋아하거나 싫어하는 것을 알게 되면 놀랄 것입니다. 당신은 그 결과에 따라 행동하기만 하면 됩니다.매출 증대를 위한 지원 활동주요 활동 이외에도 많은 지원 활동을 통해 매출이나 수익을 높일 수 있습니다. 이러한 활동에는 비용 절감, 효율성 증대, 고객 유치, 반복 방문 증가 등이 포함될 수 있습니다.1. 기프트 카드 프로그램기프트 카드 사용이 증가하고 있습니다. 소비자는 물리적 카드 또는 온라인 기프트 카드와 상관없이 기프트 카드를 계속 주고 받습니다. 고객에게 기프트 카드를 구입할 수있는 옵션을 제공하면 매출을 앞당길 수 있을 뿐만 아니라 충성 고객이 친구 및 가족에게 전달하여 잠재 신규 고객을 더 많이 확보 할 수 있습니다. 많은 소매 및 F&B 기업이 선불 형태로 수익을 늘리고 잠재 고객에게 제품/서비스를 이용해 볼 수 있는 기회를 제공하기 위해 기프트 카드 전략을 사용합니다. 기프트 카드의 장점은 고객에게 부여되는 구매의 자유입니다. 기프트 카드를 받으면 원하는 음식이나 서비스를 언제 구매할 지 자유롭게 선택할 수 있습니다.또 다른 매출 전략을 세우고 있다면 기프트 카드 및 프로모션 방법에 대해 생각해보세요.2. 전략적 구매 시점 프로모션우리가 계획보다 얼마씩 더 소비하게 만드는 요인은 충동적인 마지막 순간의 결정일 때가 많습니다. 저는 많은 독자들이 이를 경험했을 것이라고 생각합니다. 이는 상향 판매에 좋은 전략이며 때때로 일일 매출의 상당 부분을 차지할 수도 있습니다.많은 고객의 구매 결정은 상점내에서 이루어집니다. 그 결정은 곧 매출로 이어질 수 있습니다. 소형 보드나 아이패드를 계산대 옆에 설치하고 베스트셀러 물품이나 오늘의 할인 품목을 홍보해 보세요. 고객이 매장에서 알아채지 못했던 베스트셀러나 할인품목을 구매 시점에 발견하여 구매할 확률이 높습니다.3. 작업 효율 향상작업의 효율성에 영향을 미치는 많은 요소가 있습니다. 그것은 매장 구조 같은 작은 영역에서 발생할 수 있습니다. 고객에게 제품을 전달하기 위한 한 가지의 추가적인 단계는 고객의 만족도를 저하시킬 수 있습니다.식당/매장 평면도매 번 부엌이나 계산대가 항상 혼잡하다면 귀하의 레스토랑 평면도에 문제가 있을 수 있습니다. 식당/상점 운영은 부동산 비즈니스와 유사합니다. 바쁜 시간에 고객이 집중되는 통로와 전체 고객 트래픽을 처리할 방법을 잘 계획해야합니다. 레스토랑의 평면도를 재평가하고 bottle neck 현상이 어디에 있는지 확인하고 고쳐보세요. 전에 하루 100 명의 고객을 앉힐 수 있었다면 평면도를 개선하고 20 명의 추가적인 고객이 당신의 음식을 먹어 볼 수 있지 않을까요?스토리지(창고) 구조직원이 고객에게 맞는 신발을 찾는데 걸리는 시간이 오래 걸리나요? 창고에서 고객이 요구한 제품을 찾는 것이 어려운 일인가요? 귀하의 재고 관리 소프트웨어는 그 품목이 창고에 있다고 말해 주지만 도통 찾을 수가 없나요? 스토리지 재배치, 선반 재정렬, 올바른 레이블링 등으로 재구성해 보세요.주방 구조주방은 식당이나 스토리지보다 복잡한 영역입니다. 요리사가 음식의 품질을 통제하는 중요한 곳입니다. 복잡하게 설계 된 주방은 식당 운영의 효율성을 떨어뜨립니다. 직원/요리사들과 주방에 대한 피드백을 듣고 개선 할 수있는 방법에 대해 토론해 보세요. 당신이 그들이 하는 말을 듣은다면 놀랄 수 있습니다. 대화의 창을 열어보세요.상점 매출과 수익을 높이기 위한 몇 가지 방법을 제안했습니다. 일부는 귀하의 비즈니스에 적용 가능할 수도 있고 그렇지 않을 수도 있습니다. 비즈니스의 사장 또는 관리자로서 귀하의 중책은 직원 관리, 재고 주문 및 광고, 홍보만이 아닙니다. IT 스타트업의 핵심은 제품 그 자체이며 고객이 잘 만든 제품/서비스를 구매하듯 레스토랑이나 리테일 사업도 그 핵심은 음식과 제품, 그리고 서비스에 있습니다.#시프티 #고객가치 #핵심가치 #기업소개 #서비스소개
조회수 3698

PHP Codeigniter 환경에서 VUE 사용해보기

Overview이번에는 PHP Codeigniter 기반의 서비스에 VUE를 적용시키려고 고민했던 것들을 나누려고 합니다. VUE JS는 가상 DOM을 활용하여 실시간으로 반응 컴포넌트를 제작할 수 있는 프레임워크입니다. 또한, VUE-ROUTER 및 VUEX라는 컴페니언 라이브러리를 통해 url 라우팅 및 전역상태를 관리하기에도 탁월하죠. VUE와 다른 프레임워크와의 비교 부분은 여기를 참고해주세요. 브랜디의 관리자 서비스는 PHP Codeigniter 프레임워크로 제작되었습니다. 하지만 관리자 서비스의 규모가 점점 커지고 기능이 다양해지면서 “자주 사용하는 기능을 묶어 컴포넌트화하자!”라는 숙제가 남아 있었죠. 요즘 잠깐의 여유가 생겨 이때다 싶었습니다. 관리자 서비스에 VUE를 도입하기 위한 시도를 시작했는데요. 얼마 지나지 않아 문제점에 봉착했습니다. 바로 IE9.0…. 개발자의 숙적 IE가 또 한 번 발목을 잡았습니다. 임포트가 되지 않아….VUE를 좀 더 편리하게 사용하려면 JS의 모듈화가 필요했지만, ES2015에서는 import 혹은 require 구문을 지원하지 않아 불편하고, arrow 함수 또한 사용할 수 없습니다. 게다가 VUE의 JAX 탬플릿 구문을 사용할 수도 없었죠!! 뭔가 배보다 배꼽이 더 커질 것 같은 조짐이 보였습니다.결국 Webpack의 도움 없이 VUE를 적용하려던 시도는 여러 가지 난관을 만났고, Codeigniter 프로젝트 내부에서 Webpack을 사용하는 방법을 연구하기 시작했습니다. Webpack은 모듈 번들러입니다. Webpack의 메인 페이지를 방문하면 아래 네 개의 슬로건이 빙글빙글 돕니다.Bundle your scriptsBundle your imagesBundle your stylesBundle your assets아래의 이미지는 Webpack이 무엇을 하는 녀석인지 잘 설명해줍니다.Webpack은 실제로 번들러라고 광고하는것 처럼 Only Webpack 빌드만으로는 소스 파일들을 모아줍니다. 만약 webpack-dev-server로 실행하면 websocket을 통해 소스가 변경됐을 때 실시간으로 화면을 갱신해주는 개발 툴 제공 정도의 역할 밖에 없습니다. (…충분히 훌륭하잖아?)대부분의 기능은 엄청난 확장성을 가진 webpack의 설정으로 모듈로서 작동할 수 있죠. 예를 들면 Babel은 우리의 발목을 잡았던 IE를 위해 ES6로 작성된 js 문법을 IE에서 사용할 수 있는 ES5문법으로 너무나 쉽게 트랜스컴파일할 수 있습니다.하지만… 관리자 서비스는 위에서 언급했듯이 Codeigniter 기반입니다. 따라서 완벽히 VUE와 API서버를 분리하려면 로그인, 메뉴구성, 헤더, 푸터 등 PHP 기반으로 제작된 모든 기능들과 인증 등 기존 방식을 전부 새로 만들어야만 VUE를 온전히 사용할 수 있습니다.문제점들을 모두 해결하고 넘어가기엔 여유가 부족하기 때문에 조금씩 적용하자고 생각했습니다. 덕분에 webpack-dev-server의 실시간 소스 반영 기능을 포기해야만 했죠.(눈물) 우리의 서버는 node기반이 아닌 apache-php 기반이었기 때문입니다.자, 그럼 Codeigniter 프로잭트 하위에 웹팩을 포함시켜 Hello World까지 가는 짧은(?)여정을 시작해봅시다.Hello world로 가는 여정Node, npm 설치맥에서도 유사한 명령어로 제작할 수 있도록 CMD 위주로 진행하겠습니다. 먼저, 여기를 클릭해 Node를 설치합시다. 8.11.3 LTS버전으로 진행했습니다.맥에서는 Homebrew를 통해 간편하게~brew install node 설치 확인npm 잘 설치되었네요.web pack 폴더 생성 및 이동mkdir webpack cd webpack nom init으로 초기화npm init webpack, vue, babel 설치npm install -D webpack webpack-cli webpack-dev-server npm install -D vue-loader vue-template-compiler npm install -D babel-core babel-loader babel-preset-es2015 여기서 VUE는 설치하지 않습니다! 왜냐하면 VUE.js는 로딩만 하면 되고 필요하지 않습니다! (읭?) VUE는 Codeigniter view에서도 사용해야 하기 때문에 해당 view에서 import 해줍니다. 따라서 VUE 컴포넌트가 들어가는 시점에는 이미 전역에 vue.js 가 있습니다. 따라서 굳이 각 모듈마다 VUE를 import 했다가 webpack 설정에서 다시 vue.js를 제외할 필요는 없습니다.VUE와 template 태그를 로딩할 수 있는 로더도 설치하고, 트랜스컴파일을 위한 바벨, IE9를 지원하기 위한 es2015프리셋도 함께 설치합니다.webpack 빌드명령어 package.json의 script부분에 추가"scripts": { "build": "webpack --mode production", "build-dev": "webpack --mode development",   } 이제 VUE를 빌드할 명령어를 작성합니다. 위처럼 두 가지 명령어를 제작해두면, 추후 env를 통해 webpack.config.js를 분기시켜 원하는 환경으로 빌드할 수 있습니다. 또한 production 모드로 빌드할 땐 자동으로 옵티마이저 - uglify 내장 플러그인이 적용되어 익숙한 min.js형태로 빌드되며 development를 빌드할 땐 사람이 알아볼 수 있는 형태로 빌드되고, debugger 코드 또한 살아있습니다.weboack.config.js 작성const { VueLoaderPlugin } = require('vue-loader'); module.exports = {   entry: {     HelloWorld: './src/main.js'   },    module: {     rules: [       {         test: /\.vue$/,         loader: 'vue-loader',       },       {         test: /\.js$/,         loader: 'babel-loader',       }     ]   },    resolve: {     alias: {       'vue$':'vue/dist/vue.esm.js'     }   },    plugins: [     new VueLoaderPlugin()   ]  } webpack.config.js 가 없다면 생성한 후 위와 같이 작성합니다..babelrc 작성{     "presets": ["es2015"] } 테스트용 파일 작성1)main.js 작성import HelloWorld from './HelloWorld.vue' Vue.component('hello-world', HelloWorld); 2)HelloWorld.vue 작성 [removed] export default {   name: 'app',   data: () => {     return {       word1: 'Hello',       word2: 'World'     }   }  } [removed] 테스트 빌드npm run build-dev 빌드를 할 땐 기본적으로 ‘/dist/’ 하위에 소스코드가 떨어집니다. 자, 여기까지 진행하셨다면 폴더 구조는 다음과 같을 것입니다.지금까지 진행한 파일 모습입니다.뷰 컴포넌트가 잘 제작되고 등록되는지 확인하려면 기본 빌드 폴더인 dist 폴더에 Test.html을 작성해 브라우저로 열어봅시다.확인용 html 파일 작성<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>VUE Test</title>     <!-- VUE 플러그인 -->     [removed][removed] </head> <body>                     [removed][removed]     [removed]         new Vue({             el: '#vue'         })     [removed] </body> </html> 잘 나옵니다.정상적으로 VUE가 적용된 것을 확인합니다.코드이그나이터 설치이제 코드이그나이터 프로젝트 내부에서 VUE 컴포넌트를 출력해보기 위해 코드이그나이터 프로젝트를 생성합시다. 먼저 Codeigniter와 XAMPP를 다운로드 받습니다.Codeigniter 받으러 가기XAMPP 받으러 가기프로젝트 폴더 하위에 Codeigniter 프로젝트용 폴더를 생성합니다.mkdir codeigniter-with-vue-webpack cd codeigniter-with-vue-webpack 다운받은 Codeigniter를 해당 폴더에 압축 해제하면 Codeigniter 설치가 끝납니다.XAMPP 설치 및 DocumentRoot 변경XAMPP를 설치하고 DocumentRoot를 테스트 프로젝트 폴더로 설정한 뒤 아파치를 실행합니다.Codeigniter 프로젝트가 생성되었고, 서버 실행이 완료되었습니다. webpack 폴더를 Codeigniter 프로젝트 하위로 이동node-modules는 너무 크기 때문에 기본 파일만 복사하고, npm install로 설치합니다.Codeigniter에서 VUE를 사용하기 위한 webpack dist설정기존의 프로젝트에서 스크립트를 모아두는 폴더 하위로 빌드 결과 파일을 보내기 위하여 webpack 빌드 시 dist 폴더가 아닌 /application/scripts/vue/hello_world 하위로 빌드 결과 파일이 생성되도록 설정합니다.// 기존 module.exports = {   entry: {     HelloWorld: './src/main.js'   },    //... 생략 } // 변경후 module.exports = {   entry: {     '../../application/scripts/vue/hello_world/HelloWorld.js': './src/main.js'   },    //... 생략 } Codeigniter의 load->view 기능을 활용하여 파일 작성1)header.php// application/views/common/header.php <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>VUE Test</title>     <!-- VUE 플러그인 -->     [removed][removed] </head> 2)실제 view// application/views/vue/hello_world/vueTestPage.php <?php $this->load->view( 'common/header' ); ?> <body>                 [removed] [removed]     [removed]         new Vue({             el: '#vue'         })     [removed] </body> <?php $this->load->view( 'common/footer' ); ?> 3)footer.php// application/views/common/footer.php </html> 실제 프로젝트 구성과 유사하게 header, body, footer로 나누어 파일을 작성해봅니다. 실제로는 더 복잡하지만 이 정도만 나누겠습니다.Codeigniter 테스트용 컨트롤러 작성// application/controllers/Vue.php <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');   class Vue extends CI_Controller {      public function index()     {         $this->load->view('vue/vueTestPage');     }  } 정말 심플(?)한 테스트용 파일 작성이 모두 끝났습니다! 이제 잘 작동하는지 확인해볼까요?코드이그나이터에서 helloworld 출력짜잔이번엔 문제의 IE에서 확인해봅시다.IE9.0 환경에서 확인IE에서도 무사히 출력되는군요. 이제 코드이그나이터 환경의 프로젝트에서도 IE까지 지원하며 무사히 VUE를 사용할 수 있게 되었습니다! (시간이 없어서 가상머신에 IE9가 설치된 윈도우7까지 테스트하진 못했습니다!) 모든 작업이 완료한 후, 파일 폴더 구조는 아래와 같습니다.붉은 네모 부분이 실제로 제작하거나 수정한 파일들입니다.Conclusion여기까지가 Codeigniter 프래임워크 환경에서 webpack + vue를 사용하기 위한 웹팩의 설정 과정 및 테스트 결과였습니다. php 서버를 사용해야 하기 때문에 webpack-dev-server의 핫리로드 기능을 사용하지 못하는 건 매우 안타까운 일입니다. 하지만 짧은 시간에 신기술을 도입하면서도 수많은 리스크를 회피할 수 있다는 건 나쁘지 않은 선택이라 생각합니다.위의 웹팩설정을 조금만 활용한다면 다른 프레임워크 프로젝트에서도 무리없이 VUE를 사용할 수 있을 겁니다! 비슷한 고민을 하셨던 개발자님들… 집에 가기 전 말고 오전에 Webpack을 설치해보세요. 안 그러면 저처럼 집에 못갈 수도 있으니까요!참고.gitignore 작성, index.php 제거 등은 내용에 포함하지 않았으며, 아래의 링크로 자세히 알 수 있음.Codeigniter index.php 없애기글강원우 과장 | R&D 개발2팀kangww@brandi.co.kr브랜디, 오직 예쁜 옷만 #브랜디 #개발자 #개발팀 #인사이트 #경험공유 #PHP
조회수 1156

이혜민 핀다대표 “쇼핑하듯 쉽게, 금융상품 찾아드려요"

이투데이 청춘반란 시리즈의 6번째 인터뷰이(inverviewee)로 핀다(Finda) 이혜민 대표님이 소개되었습니다. 핀다와 핀다의 금융상품 정보 에 대해 더 깊게 알아보는 기회가 되시기를 바랍니다! 이투데이 기사 원문보기 260개 금융기관 7000여개 상품 정보 이해하기 쉽게 표준화…맞춤형 비교·검색 고객에 최적 상품 추천… 月 30만명 방문 똑부러진 목소리와 열정이 담긴 눈빛. 이혜민(35) ‘핀다’ 대표는 3차례의 창업 경험으로 잔뼈가 굵은 스타트업 대표답게 인터뷰 내내 뚜렷한 목표와 방향성을 제시했다. 창업 시장에서 산전수전 다 겪은 그가 선택한 네 번째 창업 아이템은 바로 ‘금융’이다. <이혜민 핀다 대표는 2일 이투데이와의 인터뷰에서 “단순한 금융 서비스를 제공하는 데서 더 나아가 개인 맞춤형 자산관리 서비스를 제공하는 게 목표”라고 말했다. 사진=이동근 기자 정보의 비대칭성 해소하고 금융도 쇼핑하듯 이용하자“정보 격차가 가장 심한 분야는 금융이라고 생각합니다. 30년 전이나 지금이나 어렵고 불친절한 금융 서비스를 누구나 쉽고 편하게 이용할 수 있게 만들고 싶었습니다.” 이 대표가 금융정보 서비스 앱 ‘핀다’를 창업하게 된 계기는 자신의 경험에서 나온 운명적인 선택이었다. 대출을 받으려고 은행을 찾았던 그는 창구에 앉자마자 머리가 백지 상태가 됐다. 당시 이렇다 할 수입이 없던 그에게 은행은 높고 두꺼운 벽처럼 다가왔다. 게다가 금융 지식이 없던 그는 은행원의 설명을 하나도 알아들을 수 없었다. 심지어 어떤 금융 서비스가 필요한지 감도 잡히지 않았다. 그는 “필요성을 느끼면 주위에 확인하는 걸 습관적으로 한다”며 “나만 필요한 게 아니라 모든 사람이 느낀다면 사업성이 있다고 생각하는데 마침 주위에 나와 비슷한 고민을 하는 사람들의 의견을 들을 수 있었다”고 말했다. 본능적으로 창업을 떠올렸다. 그는 곧바로 팀을 꾸리고 2015년 10월 금융 정보를 서비스하는 ‘핀다’를 설립한다. 핀다는 판매자와 구매자, 공급자와 수요자 간 금융 정보의 비대칭을 해소하기 위해 탄생했다. 금융 서비스도 쇼핑몰에서 옷을 구매하듯 구매자가 1분 안에 원하는 상품의 정보를 얻고 선택할 수 있도록 도와줘야 한다는 생각이 창업의 바탕이 됐다. 핀다는 국내 260여 개 금융기관의 7000여 개 금융상품 정보를 수집, 사용자들이 이해하기 쉽게 표준화해 제공하고 있다. 금융감독원의 오픈 API(응용프로그램 인터페이스)뿐 아니라 제휴 금융기관의 API를 통해 상품 정보를 직접 전달받는다. 제휴사는 신한은행, KEB하나은행, KB국민카드, 우리카드, 신한카드, 삼성카드, 현대카드, 케이뱅크 등 금융사와 렌딧, 어니스트펀드 등 핀테크사 31곳이다. 이를 통해 주택담보·신용·자동차·P2P 등 대출, 예·적금과 P2P투자 및 펀드 등 투자, 신용·체크카드, 보험상품 등 카테고리별로 상품 비교를 통해 고객에게 최적화된 상품을 추천해준다. 월 방문자 수는 30만 명을 기록 중이며, 지난해 4분기부터 매출이 발생하고 있다. 특히 지난해 11월에는 대화형 상담이 가능한 챗봇 기능을 도입했다. 챗봇에 들어가는 상품 추천 알고리즘과 대화 로직은 6개월의 개발 기간을 거친 순수 자체 기술이다. 이 대표는 “이달 정식 모바일 앱 출시에 앞서 오픈베타 버전을 내놨다. 현재 신용정보사와 기밀유지협약(NDA)을 검토 중으로 조만간 정식 앱 서비스를 시작할 수 있을 것으로 보인다”며 “앞으로 개인의 데이터를 토대로 맞춤형 금융서비스, 궁극적으로는 자산 관리 서비스를 제공하는 것이 목표”라고 말했다.  성공에 안주하지 않고 끊임없이 도전 이 대표는 2007년 STX에 입사해 해외영업을 담당했는데, 금액이 큰 대기업의 글로벌 사업인 만큼 호흡이 길었다. 일은 재미있고 배울 것도 많았지만 업무가 피부에 와닿지 않았다. 그는 5년차가 되던 2011년 고민 끝에 회사를 나와 창업 시장에 뛰어든다. 자신의 의사 결정이 곧바로 회사 경영에 반영되고 현실화될 수 있는 일을 찾기 위한 도전이었다. 잘나가던 대기업을 때려치우려니 주위의 만류도 많았다. 성공에 대한 확신도 없었다. 이 대표는 “내가 가장 취약한 부분, 악조건을 골라 창업해 보고 싶었다”며 “대기업에서는 항상 선택하는 입장에서 영업에 취약했고, 이 부분을 가장 어렵게 느꼈던 터라 발품을 팔고 영업하는 업종으로 창업을 결심했다”고 회상했다. 자본금이 넉넉지 않았던 그는 ‘로켓인터넷(Rocket Internet)’이라는 독일의 벤처 투자 및 육성 회사의 투자, 인큐베이팅을 받아 ‘글로시박스’라는 화장품 정기 배송 스타트업을 창업한다. 미국의 ‘버치박스(Birch Box)’에서 아이디어를 얻은 국내 최초 화장품 정기 배송 업체다. 창업 6개월 만에 손익분기점에 이를 정도로 빠르게 성장했고 스타트업으로선 꿈 같은 일인 해외 진출도 이뤄냈다. 이후 유아용품·유기농 식재료 정기 배송 서비스 ‘베베앤코’를 창업했다. 화장품에서 유기농 식재료로 내용을 바꾼 것이다. 이 대표는 “태풍이나 자연재해로 인해 식재료 수급이 어려웠고, 무엇보다 당시 유기농에 대한 인식이 그리 높지 않을 때라 사업을 성장시키기 어려워 결국 접었다”고 말했다. 이 대표는 세 번째 사업을 구상하던 중 미국 뉴욕의 워크스마트랩스라는 건강관리 관련 앱 개발회사를 알게 된다. 이 팀과 협업을 결정하고 건강관리 앱 회사 ‘눔’을 만든다. 뉴욕에 본사를 둔 눔에서 그는 한국 법인 대표를 맡는다. 사업 1년 만에 137만 명의 회원 유치에 성공, 건강관리 앱계의 ‘우버’로 불리면서 화려하게 재기한다. 4차례의 창업을 통해 이 대표는 본인만의 경영 철학을 구축했다. 그는 “대중이 공감할 수 있는지가 가장 중요하다”며 “사업을 시작할 때 더 나은 상황으로 만들 수 있다는 확신이 서야 한다”고 강조했다.#핀다 #CEO #인터뷰 #기업문화 #스타트업CEO #철학 #인사이트
조회수 1081

라이더소개#11. 국대 앞의 사나이, 데니

[라이더소개#11. '국대(떡볶이)' 앞의 사나이, 데니]데니을 소개합니다 :)Q. 간단한 자기소개 부탁해내 닉네임은 데니고,나이는93년생 닭띠,유학생이야. 현재 한국에 나와서 지금 이렇게 아띠인력거를 접하고, 일을 하고 있는6개월 차 라이더야.Q. 어떻게 아띠인력거를 시작하게 됐어?계기가 있어?맨 처음에 일을 시작하게 된 계기는,김난도 선생님의 책을 읽다가IJ가 자전거 고치는 모습을 보고서'아 이거 왠지 느낌있다'싶어서 시작하게 됐어. '재밌게 일하고 싶다' 그런 마인드가 나랑 약간 생각이 비슷하더라고.그때가 한국오기 며칠 전이었어.타이밍이 잘 맞았지.Q. 처음 라이딩 했을 때 어땠어?진짜 좋았어.진짜 재밌었어.첫 날 라이딩하고, '아 적성을 찾았구나'싶었어.(웃음) 처음에 온이랑 같이 나가서 빈 차로 따라다니는건 힘들어서 재미없었는데,처음으로 프리라이딩 했을 때는 진짜 재미있었어. 그 때 어떤 여고생들을 태웠었는데,같이 어우러지는 게 너무 좋았어.그 친구들은 아직도 기억나.얼굴도 기억나고.Q. 라이더를 하면서 가장 힘들 때는 언제야?진짜 춥거나, 아니면진짜 무겁거나.하루는 영하20도에 외국인 두분이 탔었는데,그 때는 진짜 춥고,진짜 무거웠던 날이었어.. 심지어 예약도 그거 하나밖에 없어서 좀 힘들었지..음. 근데 오히려 힘든 건,빈차로 계속 있을 때?멘탈적으로 그게 더 힘들지.Q. 가장 기억에 남는 손님은 어떤 손님이야? 기억에 남는 손님은 너무 많지~음, 어떤 누님들이 탄 적이 있는데 진짜 웃겼어.안국역에서 삼청동 수제비 집까지 태워드렸는데, 그 때 진짜 추운 날이었거든.차양 씌운 인력거를 타고있었고,너무 추워하시는 게 보여서 내가'춥죠?타실래요?제가 태워드릴게요.'하니까 '빨리 태워줘요!!'이러시는 거야.(웃음) 거기서부터 약간 웃긴 느낌이 났는데,태워드리고 나서는'수제비 같이 먹을래요?먹고가요!'하고 시크하게 물어보셔서 수제비도 같이 먹었어. 먹으면서는 몇 살인지 물어보시더니 그때부터 말을 놓으시더라고.(웃음) '맛있지?많이 먹어~'하시면서. 그리고 또 밥 먹고 나서는 자연스럽게 인력거에 타시더니'커피 마시러 가자~커피 사줄게!'이러시더라고.(웃음) 근데 그게 막 기분 나쁘지 않게, 정말 친 누나처럼 대해주셨어.그리고 서촌 아트갤러리까지 데려다 드리니까'우리 이제 헤어지는 거냐~'이러시면서 아쉬워하는 모습이 보였는데,그 때가 기억에 남아.그리고 또.. 생각하면 계속 나와!오늘같은 경우도 기억에 남지. 그림 그려주시는 분이랑 콜라보레이션해가지고 1시간 동안 같이 타면서 그림도 그리고.아,그것도 기억에 남는다.생일날 혼자서 타러 오신 남자 분!! 짠해서 기억에 남아 그 분...사진 찍어달라고 보통 핸드폰 주는데,그 분은 아이패드를 줘서 내가 막 사진 찍어드리고.. 일부러 오히려 당연한 척,아무렇지 않은 척하면서 태워드렸었어.(웃음)예약자분 성함이 중성적인 이름이어서 혹시 여자분 혼자면 외로울 테니까 조쉬(인형)도 챙겨가고 그랬는데..(웃음) 근데 그 때 마침 한 달에 한 번 헌법재판소 하늘공원이 오픈 되는 날이었어. 그 때 딱 오셔가지구 거기 갔었던 기억이 있어.그리고.. 케빈이랑 서촌에서 라이딩했을 때 유쾌하신 어머님들도 생각난다.사진 찍지마,찍지마 하셨는데 찍고 나니까 제일 환하게 웃고 계시ㄷ더라.(웃음) 초등학생 남자 꼬마 한 명도 기억나고... Q. 우리가3개 정도의 코스가 있잖아.어떤 코스를 제일 좋아해?아, 그건 어려운 질문이다..엄마가 좋냐,아빠가 좋냐지.다 좋아!근데 제일 안 좋아하는 걸 꼽으라면 오히려 제일 많이 하는 서북촌일 것 같아. 늘 하는거라서.그래서 가끔씩 히스토리코스를 하면 기분이 좋아.다 매력이 다른 것 같아.서북촌은 늘 하는거라서 시간관리가 칼같이 되는데,서촌은 혼자하면 시간관리가 잘 안돼.Q. 왜 인력거를 선택한 거야?미국에 있으면서 한국 사람들이 그리웠어.사람들을 많이 만나고 싶었어.그거에 최적화된 딱 맞는 일이잖아. 이야기도 많이 할 수 있고.그런 일을 찾고 있었지.Q. 대니의 개인적인 꿈은 뭐야?요새 내가 느끼는 건데 정해진 꿈이 없어. 그래서우선 지금은 꿈을 찾는 게 꿈이야.그리고 인력거 일을 하면서 느끼는 건데,이쪽의 일을 하는 게 나한테 맞는 것 같아. 이게 내 장점인 것 같은데 이걸 살릴 수 있는 일을 찾아봐야지.Q. 아띠의 자랑을 하자면?우선, '편하다'라는 거.정말 심플한 건데 엄청난 장점인 것 같아.그것 만큼 좋은 게 어디 있어. 일하면서 편한 사람이 얼마나 있겠어.그리고 힘든 것도 없어. 다른 데에서 일할 때는10분마다 시계보고 언제 퇴근하지~그랬는데, 여기서는 시계 보면'빨리 복귀 해야 되는데,더 타고 싶다!'이렇게 돼.'오늘 어떻게 시간 보내지'하면 벌써7시가 되어있고.(웃음)그리고 아띠는 남성미가 넘치지!(웃음)Q. 아띠가 어떤 모습으로 나아갔으면 좋겠어?지금의 이 모습을 잊지 않았으면 좋겠어.라이더가 많아지고 인력거도 많아지고 그러다 보면,지금 아띠의 분위기를 더 잘 유지해야 될 것 같아.Q. 너에게 아띠인력거란?뜻밖에 만난 행운?진짜 이걸 하게 될지 몰랐는데,진짜 잘한 것 같아. 6개월 정도 했는데,몇 년 뒤에 생각해도 정말 잘했다고 생각할 것 같아.Q. 미래의 아띠라이더들에게 한마디 한다면?만약에 돈을 벌 생각으로 하려 한다면 하지 말라고 하고 싶어.그런 생각이면 아띠를 할 수 없어.진짜 즐기려고 해야 할 수 있어.나는 항상 내가 재미있어야 사람들을 재미있게 해줄 수 있다고 생각하거든.진짜 즐겁게 일하고 싶은 사람만 오라고 하고 싶어.근데 후유증은 너무 빠져버리면 안 된다는 거야!(웃음)Q. 며칠 뒤면 미국으로 돌아가는데,기분이 어때?아쉽다~ 데니!괜찮아~ 언젠가 또 오겠지.만약 돌아와서 다시 라이딩을 하면 내가 처음 라이딩 하면서 느꼈던 감정을 또 느낄 수 있을 것 같아.그 때 저스틴,현아,나 이렇게 셋이서 경복궁 쪽으로 출근하면서 쫙 나갔는데 그 때 진짜 기분 좋았거든. 그리고 그 날 수학여행 온 애들이 단체로 있었는데,내가 혼자 신나가지고 손 흔드니까,'꺄!'하면서 진짜 말도 안 되는 반응이 나와가지고되게 기분 좋게 탔었어.(웃음)Q. 지금까지 아쉬웠던 점이 있을까?R2가 못된 게 진짜 아쉬워.이왕 하는 거R2는 찍어야 나중에 인력거 탔다고 할 수 있는데... 그리고 내가 아끼는 신발, 인력거 체인 때문에 더러운 거 묻었는데 어떻게 배상해줄 거야? 라이딩 하는 첫날에'이왕 타는 거 신발 멋있는 거 신고 타야지~' 했는데..첫날부터!!! (웃음)Q. 마지막으로 하고 싶은 말이 있으면 해줘나중에 돌아왔을 때 아띠가 많이 안 변했으면 좋겠어.정비사만 고용하지 말고,주기적으로 근육마사지 받을 수 있게 마사지사도 고용해서 번호표같은 거 뽑아서 마사지 받게 하면 좋을 것 같아!라이더들이 항상 풀컨디션으로 있을 수 있게.(웃음웃음)그리고 스포츠적으로 접근해서 라이더들 유니폼 맞춰서 등번호 제도 같은 거 도입하면 재미있을 것 같아.난42번.나중에 만든다면42번으로 만들어서 내 유니폼 걸어줘.내가 항상 국대 앞에 있는 자세로 동상도 세워서!(웃음)언제나 유쾌한 데니의 인터뷰였습니다!미국으로 조심히 돌아가길 바라며, 다시 학생으로 돌아가는 데니를 응원하며,인터뷰를 마칩니다:)#아띠라이더스클럽 #팀원소개 #팀원인터뷰 #팀원자랑 #기업문화 #조직문화 #사내문화
조회수 2143

와디즈 협업 이야기

스타트업에서 효율적으로 일하기저는 와디즈에서 시스템 운영을 담당하고 있습니다. 시스템 운영이 주 업무이지만 저의 JD에는 좀 생소해 보이는 업무도 하나 있습니다. 그건 다양한 툴을 활용해서 일을 좀 더 효율적으로 하도록 돕는 일입니다. 어떤 일이든 금방 지루해하는 성향 탓인지 예전부터 새로운 생산성 툴이나 협업 도구를 찾아서 테스트해보고 업무에 적용해보기를 좋아했습니다. 이전 회사에서는 취미로 했던 이런 일들을 와디즈에 입사 후에는 업무로 하게 되었습니다.스타트업들은 시간과 리소스가 부족합니다. 와디즈도 그렇죠. 그래서 조금이라도 효율적으로 일하기 위해 이런저런 도구를 테스트해보고 적용하곤 합니다. 업무 효율을 높이기 위해 도입한 도구들 중에서 리워드 펀딩 업무에서 잘 사용하고 있는 '스마트시트' 이야기를 해보고자 합니다. 와디즈가 사용하는 협업툴, 스마트시트와디즈 플랫폼에서 이루어지는 리워드 펀딩은 여러 담당자의 협업을 통해 투자자 분들을 만나고 있습니다. (1) 먼저 심사를 하고, (2) 펀딩이 매력적으로 보이기 위해 스토리를 만들며, (3) 펀딩 성공-종료 후 정산하는 업무까지 여러 담당자가 나눠서 진행합니다. 그러다 보니 관련 정보들을 공유하고 진행상황을 체크하는 일이 빈번하게 발생합니다. 이런 협업이 과거에는 구글 시트를 통해 이뤄지고 있었습니다. 엑셀과 달리 구글 시트는 여러 사용자가 실시간으로 편집할 수 있기 때문에 빠르게 정보를 공유하고 업데이트할 수 있죠. 하지만 리워드 펀딩 오픈을 위한 프로세스를 관리하기에 다소 불편한 부분들도 있었습니다. 구글 시트에 입력한 정보를 다른 담당자들에게 알리기 위해 메일을 보내거나 사내 메신저로 대화를 해야 했습니다. 또한 프로젝트가 늘어나면 텍스트가 많아 가독성이 떨어지기도 했죠. 그래서, 이런 불편함들을 덜어내기 위해 스마트시트라는 툴을 사용해보기로 했습니다.효율 1. 스마트시트 알림으로 커뮤니케이션 리소스 줄이기아래 시트는 펀딩 프로젝트를 성공적으로 오픈하기 위한 업무를 관리하는 시트입니다. 각 프로젝트를 담당하는 콘텐츠디렉터들이 메이커와 소통하며 프로젝트 오픈을 돕기 위해 사용하죠. 프로젝트 오픈 준비 협업을 위한 스마트시트위에 보이는 것처럼 스마트시트는 엑셀이나 구글 시트와 유사하게 생겼습니다. 하지만 구글 시트에 비해 스마트시트는 (1) 칼럼의 타입을 지정할 수 있고, (2) 칼럼의 값에 따라 시트를 공유받은 사람들에게 알람을 보낼 수 있다는 장점을 가지고 있습니다. 이 기능들을 활용해서 (1)‘현 진행상태’라는 dropdown list 타입의 칼럼을 만들고, (2) 선택한 값에 따라 관련된 사람들에게 알람이 가도록 했습니다.dropdown list 타입으로 만든 칼럼'6. 오픈' 상태 선택시 발송되는 알림 메일위 메일은 '현 진행상태'를 '오픈'으로 변경했을 때 받도록 해놓은 알림메일 입니다. 필요에 따라 조건을 더 추가해서 다양하게 알림을 만들 수 있습니다. 이렇게 알림 메일을 설정한 후 담당자 간 불필요하게 수동으로 발송했던 메일이 줄어들었고, 더 필요한 커뮤니케이션에 집중할 수 있게 되었습니다.효율 2. 필터와 조건부 서식을 적용하여 가독성 높이기메일 알림 기능 외에 데이터의 가독성을 높이기 위해 두 가지 기능을 활용했습니다. (1)값에 따라 자동으로 데이터의 포맷이 변경되는 조건부 서식 기능과 (2)내가 원하는 데이터만 모아서 볼 수 있게 해주는 필터 기능입니다.조건부 서식을 적용하기 위해서는 먼저 원하는 조건을 설정합니다. 그리고, 서식 지정을 원하는 칼럼을 선택하면 조건에 해당하는 모든 데이터에 서식이 반영됩니다. 진행상황의 단계에 따라 다른 배경색을 지정하거나 담당자에 따라 다르게 서식을 지정하는 등의 용도로 활용이 가능합니다.조건부 서식을 편리하게 관리할 수 있다조건에 따라 데이터에 서식을 적용해주는 조건부 서식과 달리 필터는 조건에 따라 원하는 데이터만 보여주는 기능입니다. 엑셀이나 구글 시트에도 필터 기능이 있기는 하지만 스마트시트에서는 각 필터에 이름을 지정해서 관리가 가능하도록 하여 편의성을 높였습니다.현 진행상태가 '오픈'인 것만 보이는 필터필터 상세 내용효율 3. 자동화 툴로 관리의 편의성 높이기위에서 살펴본 스마트시트의 자체 기능 외에도 Zapier라는 자동화 툴을 활용하면 다른 앱들과 연동을 할 수 있습니다. Zapier는 스마트시트와 Gmail, 구글 시트 및 슬랙이나 잔디와 같은 메신저와의 연동을 가능하게 해주는 마법 같은 툴입니다. 리워드 펀딩 관리 시트에서는 Zapier를 활용해서 펀딩 프로젝트에 콘텐츠디렉터(CD)가 지정되면 잔디 채팅방에 알림을 보내도록 설정을 했습니다.콘텐츠 디렉터 지정을 알리는 잔디방 알리미스마트시트를 사용하는 것은 겉으로 봐서는 구글 시트에 비해 큰 차이가 없을 수도 있습니다. 오히려 새로운 툴을 배우고 익숙해져야 하는 수고가 필요할 수도 있죠. 와디즈에서도 스마트시트 사용 초기에 비슷한 이슈가 있었습니다. 어떤 분은 스마트시트가 정말 효율적인지 진지하게 물어보기도 했었죠. 하지만 평소 ‘급변의 물살을 즐기며 앞서 나아가기’를 위해 노력하는 와디지앵들은 새로운 툴에도 금방 적응했습니다. 그리고, 다른 업무들에도 스마트시트를 사용하기 시작해서 이제는 대부분의 와디지앵들이 다양한 모습으로 스마트시트를 통해 협업하고 있습니다.이 글을 보시는 메이커분들이나 스타트업분들 중에 효율적인 협업을 위해 비슷한 고민을 하고 계시다면 스마트시트를 시작해보시면 어떨까요? #와디즈 #기업문화 #업무프로세스 #협업문화 #스마트시트 #인사이트 #꿀팁
조회수 1598

KT 채용 필수 정보! 실무자가 직접 말하는 KT 人사이드(경영지원 직무 편)

 기다리고 기다리던 2017년 KT그룹 하반기 신입사원 공개채용이 바로 오늘부터 시작됐습니다! (짝짝짝) 아마도 많은 취업준비생 여러분이 마음을 굳게 다지며 자기소개서 항목을 살펴보고 계실 것 같은데요. 여러분의 고민을 조금이라도 덜어드릴 수 있도록 이번에는 경영지원 직무를 맡고 계신 KT인들의 이야기를 준비했습니다. 전사적인 목표수립과 각 부서와의 커뮤니케이션으로 업무를 서포트하며, 기업이 나아갈 방향을 제시하는 역할을 하는 경영지원 직무! KT人이 말하는 경영지원 직무에 필요한 역량은 무엇인지, 그들이 말하는 취업 팁까지 함께 들어볼까요?^^  “KT 취업, 특별하지 않아도 자신에 대한 믿음이 있으면 할 수 있습니다.“- kt skylife 경영기획본부 기획조정실 황희진  Q. 현재 어떤 직무를 담당하고 계신가요?A. 저는 경영기획본부 기획조정실에서 근무하고 있습니다. 우선 경영기획본부는 사업에서 최대한의 가치를 창출해 낼 수 있도록 중∙장기 전략과 비전을 수립하고 매년 경영목표를 설정하여 진행 현황을 점검하는 일을 합니다. 또한 사업 추진에 필요한 예산을 편성∙조정하고 조직을 구성하여 원활한 사업운영을 지원하고 있습니다.현재 제가 하고 있는 업무는 첫째, '사업관리 및 조정' 업무인데요. 담당 부서와의 사업/예산을 협의하고 조정하는 일입니다. 또한 연초 발굴한 주요 사업 과제의 이행 현황을 관리합니다. 둘째, KT와 커뮤니케이션을 통해 그룹사 소식을 전하고 양사간의 시너지를 위해 지속적으로 소통하고 있습니다. 마지막으로 전사 업무보고를 총괄하며, 이사회 운영업무를 지원하고 있습니다. Q. kt skylife를 선택한 이유는 무엇인가요?A. 다양한 소재의 콘텐츠를 제공함으로써 삶의 질을 높여줄 수 있는 방송 산업은 여전히, 또 앞으로도 꾸준히 중요할 것이라고 생각했습니다. 특히 kt skylife는 국내 유일의 디지털위성방송 기업으로, 단순한 이익창출이 아닌 한반도 전체가 방송을 통해 문화를 누릴 수 있도록 꾸준히 노력하고 지원하는 회사입니다. 저도 이런 회사에서 한 명의 구성원으로 참여하고 싶었습니다.  Q. 회사에서 가장 보람 있었던 일은 무엇인가요?A. 특별한 일은 아니지만 매주, 매월 하고 있는 일에 보람을 느낍니다. 저는 매주 전 부서에서 행한 업무와 계획을 취합하여 정리하고 보고자료를 만드는 업무를 합니다. 또한 연초에 발굴한 과제들을 매월 수합하고 진행률을 분석해서 실, 혹은 유관부서에 공유하고 있습니다. 전사 부서들의 자료를 취합하여 정리하는 것이 쉽지 않지만, 이 자료가 임원회의 자료의 기초가 되기도 하고 어떠한 보고서를 만드는 데에 양분이 된다고 생각하면 제가 하고 있는 업무에 보람을 느낄 수 있었습니다. Q. 지원자에게 마지막으로 전하고 싶은 취업 팁은?A. 취업 팁으로 얘기하는 기업 및 직무분석 등 회사에 대한 공부도 좋지만, 그것보다 본인 스스로의 강점을 알고 자신 있게 어필하는 것이 더 중요하다고 생각합니다. 저는 평소 새로운 경험을 좋아해서 봉사활동, 인턴 등에 참여해 여러 사람들을 만나보려고 노력했습니다.이 부분을 제 무기라고 생각하고 kt skylife의 조직원으로서 업무를 배울 때나 회사생활에 있어서 어떻게 활용할 수 있을지를 자신 있게 이야기를 하였고, 그 점 덕분에 면접에 합격할 수 있었던 것이 아닌가 싶습니다. 특별하지 않더라도, 스스로에 대한 믿음과 자신이 있으면 된다고 생각합니다.  “KT는 Work Together를 지향합니다.”- kt submarine 경영기획본부 경영기획팀 이창하   Q. 현재 어떤 직무를 담당하고 계신가요?A. 저는 경영기획 직무를 담당하고 있습니다. 경영기획 직무는 시장 및 고객사의 변화에 능동적으로 대처하기 위해 외부 환경 분석을 통한 회사의 중장기 전략을 수립하고, 경영목표를 효과적으로 달성하기 위해 회사가 보유한 자원을 적재적소에 배치하는 Control Tower 역할을 수행합니다. 연간 경영 계획과 전략과제 수립 및 관리를 통해 사업부문별 방향성을 제시하며, 지속적인 실적 관리 및 분석을 통해 계획을 조정하고 보완할 수 있도록 전사적 차원의 대응책을 마련합니다. Q. 회사에서 가장 보람 있었던 일은 무엇인가요?A. KT그룹에서는 소통, 협업 및 임파워먼트를 체질화하기 위해 ‘1등 Workshop’을 시행하고 있습니다. 신규시장 환경 분석 및 진출 방안을 도출하는 주제로 1등 Workshop의 과제리더로 선정되어 Workshop 자료를 준비했던 경험이 가장 인상 깊었습니다. 전사적으로 참여하는Workshop이였기 때문에 참여하시는 분들의 시간을 소중하게 생각하고, 영업 및 시공 부서 등 관련 부서 담당자 분들과 사전 협의를 통해 구체적이고 실행력을 가진 결과물을 도출하고자 노력했습니다. 1등 Workshop을 통해 전략적 추진과제들이 선정되었고, 해당 과제들이 담당부서를 중심으로 원활하게 진행되고 있다고 생각될 때 가장 큰 보람을 느낄 수 있었습니다.   Q. 본인이 속해있는 회사 분위기는 어떤가요?A. 전사적으로 ‘Work Together’를 지향하고 토론 문화가 활성화되어 있습니다. 내가 문제점으로 생각하고 있는 일이 있다면, 전사토론회를 통해 자유롭게 의견 개진을 할 수 있고, 회사에서도 해당 문제를 해결할 수 있도록 적극 지원하고 있습니다. 사내 동호회도 활성화되어 있기 때문에, 다른 부서의 직원들과 쉽게 소통할 수 있고 평소 궁금했던 사업 내용들을 배울 수 있는 기회가 많습니다. Q. 하루 일과를 설명해주세요.A. 아침에 출근하면 해외 경쟁사의 뉴스를 검색하고 시장 동향을 파악∙분석합니다. 주요 고객사들이 해외에 있어 국내 언론 매체를 통해서는 동향 파악에 한계가 있기 때문에, 주로 해외 언론사들을 통해 경쟁사의 동향을 파악하고, 필요 시 영업부서와 공유를 통해 시장 환경에 능동적으로 대처할 수 있도록 준비합니다. 업무가 시작되면 메일함을 확인하고 주요 이슈들을 점검합니다. 연간 전망치에 따른 make-up 방안, 비용혁신 등 대응책을 마련하기 위해 고민하고, 사업부서의 의견을 경청하기 위해 회의에 자주 참석하게 됩니다. 회의 당시에는 이해가 되지 않는 내용도 많기 때문에 회의록을 반드시 작성하고, 회의가 끝나면 회의 중에 언급되었던 주요 내용들 중 실행방안이나 추진계획에 누락된 것이 없는지 다시 한 번 점검합니다.  “경영지원 업무의 필요조건은 신속하고 정확한 커뮤니케이션입니다.“- kt service 남부 경영기획총괄 경영기획팀 박순용   Q. 현재 어떤 직무를 담당하고 계신가요?A. 저는 경영기획총괄의 경영기획팀에서 근무하고 있습니다. 경쟁이 심해지고 있는 통신시장 속에서 회사의 경영 방향을 설정하고 이행하는 것을 경험해 보는 것이 저 자신의 발전에 도움이 될 것 같아 경영지원 직무를 선택하였습니다. 지금 저는 KPI 운영 업무를 맡고 있습니다. 구체적으론 각 KPI 지표의 운영관리 업무를 통해 각 부서 및 현장에 동기를 부여하는 업무를 수행 중입니다. Q. KT를 선택한 이유는 무엇인가요?A. 통신서비스를 제공하는 데에 한 축을 담당하는 회사라는 점이 가장 큰 동기라고 할 수 있었습니다. 사람과 사람을 이어주는 통신서비스에 관심이 있었던 찰나, KT의 고객과 제일 첫 번째로 만나는 중요한 역할을 하는 kt service의 채용공고를 보게 되었고 지원하게 되었습니다. 저는 현장과 고객 모두와 가까운 곳에서 일할 수 있는 회사에서 일하고 싶었고, 또한 통신서비스 분야에서 나만의 장점을 만들고 싶었기 때문에 kt service에 입사하였습니다.   Q. 하루 일과를 설명해주세요.A. 개인적으로 성공적인 업무의 필요조건은 여러 관련 부서와의 신속하고 정확한 커뮤니케이션이라고 생각합니다. 따라서 아침에 출근하면 가장 먼저 현재 진행되고 있는 업무의 진행 정도를 파악한 뒤에 관련 부서의 실무담당자들과 면담 또는 전화로 커뮤니케이션하는 것으로 하루를 시작합니다. 이후 업무에 따라 필요한 자료를 수합하여 정리한 뒤 이를 바탕으로 기획서 및 보고서를 작성합니다. 정기적인 회의를 통한 회사 전체적인 커뮤니케이션 역시 경영기획팀에서 담당하고 있습니다. Q. 지원자에게 마지막으로 전하고 싶은 취업 팁은?A. 본인의 스토리를 만들어가는 것이 중요하다고 생각합니다. 기회가 있을 때 꾸준히 경험하고 겪어두는 것이 훗날 저의 장점 중 하나가 되기도 했습니다. 또한 취업준비생 생활을 하다 보면 자신감을 잃는 경우가 자주 발생하지만 그럴 때일수록 스스로 긍정적으로 생각하는 것이 도움이 됩니다. 저 역시도 이러한 마음가짐으로 면접에 임한 것이 효과가 있었던 것 같습니다.  “KT 취업, 목표 설정과 목표달성을 위한 발판의 경험이 중요합니다.“- kt service 북부 경영기획총괄 인재경영팀 윤가윤   Q. 현재 어떤 직무를 담당하고 계신가요?A. 저는 kt service 북부 인재경영팀의 교육기획·운영 직무를 담당하고 있습니다. 변화의 물결 통신 서비스 시장에서 저희 회사가 중심이 될 수 있도록 전 직원의 교육을 총괄하여 체계화하고 운영하는 직무입니다. 저는 그 중 리더십 향상 교육과 일반직 직무역량 향상교육, 변화혁신교육 업무를 주로 담당하고 있습니다. Q. kt service를 선택한 이유는 무엇인가요?A. KT의 통신서비스에 대해 예전부터 관심이 많았던 저는 1년 동안의 KT 대외활동에서 얻은 저만의 경험이 지원동기가 되었습니다. 고객센터의 통화품질 및 서비스 개선 프로젝트와 KT 모바일 상품에 관한 이슈 및 동향 분석 프로젝트 등의 경험을 통해 KT에서 근무하고 싶다는 바람이 더욱 강해졌고, KT의 서비스를 고객 최전선에서 제공하는 kt service의 채용공고를 보게 되어 지원하게 되었습니다.   Q. 하루 일과를 설명해주세요.A. 신입사원인 저는 신속하고 명확한 업무처리를 위해 교육업무를 To do list로 작성하고, 중요도 및 업무의 우선순위를 정해 다음날의 업무를 어떤 식으로 진행할 지 생각한 뒤 당일에 이행합니다. 교육일정과 계획에 따라서 앞으로 진행할 교육에 필요한 자료를 수집하고, 기획서 및 보고서를 작성하여 교육이 원활히 운영될 수 있도록 하고 있습니다. Q. 지원자에게 마지막으로 전하고 싶은 취업 팁은?A. 본인의 목표를 설정한 뒤 목표를 이루기 위한 발판의 경험이 중요합니다. 경험이 쌓이다 보면 자신만의 색을 보여줄 수 있는 스토리가 될 수 있다고 저는 생각합니다. 기회를 얻기 위해 도전하는 진취적인 마인드를 가지고 실행에 옮기시기 바랍니다. 저 또한 이러한 마음가짐으로 임했기에 합격할 수 있었던 것 같습니다. 어느덧 여름이 지나고 하반기에 접어들었습니다. 본격적으로 하반기 채용 소식이 들려오고 있는 9월, 날로 심해지는 취업난으로 불안하고 초조한 마음이 드실 수도 있는데요. 급할수록 돌아가라는 옛말이 있듯이 마음을 편히 가지시고, 오늘 소개해드린 KT人들의 인터뷰 내용에 맞게 차근차근 준비하신다면 모두 취업 뽀개기 성공하실 수 있을 거라고 생각합니다! 요즘 하늘이 정말 높고 맑은데요. 고된 취업준비 생활에도 하늘 한 번 올려다보는 여유 꼭 가지시길 바랄게요. 안녕!#kt #kt공채 #기업문화 #조직문화 #직무정보 #업무환경 #사내복지 #kt일과 #kt일상 #구성원인터뷰 #취업정보
조회수 1746

Mac을 처음 쓰는 개발자에게

Overview애플(Apple) 제품을 한 번도 써본 적이 없습니다. 3주 전, 입사하고 받은 맥북(MacBook Pro)이 첫 애플 제품이었죠. 사실 개발 업무를 하면서 ‘한 번쯤은 애플 제품을 써 봐야겠다’는 생각을 하고 있었습니다. 단지 쉽사리 용기가 나지 않았을 뿐이었죠. 하지만 여러 개발 환경이 존재하는데도 개발자가 한 가지 환경만 고집하는 건 스스로의 잠재 능력을 좁히는 거라 생각했습니다. 그래서 이번 기회에 새로운 환경과 친해지려고 APM 웹서버 구성에 도전해봤습니다. (아자!) OS 설치 완료 후 환경Sierra 10.13apache 2.4php 5.6mysql 5.6 APM 설치 과정MAC 환경에서 APM 설치하려면 MAMP 방법도 있지만 기본적으로 apache, php가 설치되어 있으므로 패키지관리자 Homebrew를 이용하여 설치하겠습니다. 1.apache 설치 버전 확인$ httpd -v 명령어를 실행해서 아래와 같이 버전이 나오면 설치가 되어있는 상태입니다. $ httpd -v Server version: Apache/2.4.27 (Unix) Server built: Jul 15 2017 15:41:46 2.php 설치 버전 확인php -v 명령어를 실행해 아래와 같은 버전이 나오면 설치가 된 것입니다.$ php -v PHP 5.6.32 (cli) (built: Oct 27 2017 11:55:27)  Copyright (c) 1997-2016 The PHP Group  Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies 참고: MAC Sierra 10.13 버전에는 php7 상위 버전으로 설치되어 있습니다. Homebrew로 php5.6 하위 버전을 추가적으로 설치해야 합니다.3.Homebrew 설치Homebrew 명령어1)패키지 검색하기 -> $ brew search 패키지명 2)패키지 설치하기 -> $ brew install 패키지명 3)패키지 삭제하기 -> $ brew uninstall 패키지명 4)설치된 패키지 목록확인 -> $ brew list 5)패키지 정보보기 -> $ brew info 패키지명 6)패키지 업그레이드 하기 -> $ brew upgrade 패키지명 7)패키지 저장소 추가하기 -> $ brew tap homebrew/패키지명 8)패키지 저장소 삭제하기 -> $ brew untap homebrew/패키지명 9)패키지 링크 삭제하기 -> $ brew unlink 패키지명 가.설치파일 다운$ /usr/bin/ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)” 나. Homebrew wget 설치 (Apple에서 제공하지 않는 패키지를 설치하기 위한 것이다.) $ brew install wget다. 심볼릭 링크 연결 $ ls -l /usr/local/bin/wget ../Cellar/wget/1.19.2_1/bin/wget bin/wget -> ../Cellar/wget/1.19.2_1/bin/wget 라. 패키지 저장소 추가 $ brew tap homebrew/dupes $ brew tap homebrew/php $ brew update 4.php56 설치가. Homebrew php56 설치 $ brew install php56 –with-apache 나. Apache에 PHP 설정 수정하기 아파치에 php7 모듈이 연결되어 있어 주석 처리 후 설치한 php5 경로로 연결한다. $ vi /etc/apache2/httpd.conf LoadModule php5_module /usr/local/php5-5.6.31-20170817-164511/libphp5.so #LoadModule php7_module libexec/apache2/libphp7.so 다. apache 재시작 apachectl restart라. phpinfo 확인 phpinfo 확인5.mysql56 설치가. Homebrew mysql56 설치$ brew install mysql56나. mysql 시작$ /usr/local/Cellar/mysql@5.6/5.6.38/bin/mysql.server start다. mysql 버전확인$ /usr/local/Cellar/mysql@5.6/5.6.38/bin/mysql –version명령어를 실행해서 아래와 같이 버전이 나오면 설치가 되어있는 상태입니다.$ sudo /usr/local/Cellar/mysql\@5.6/5.6.38/bin/mysql --version  /usr/local/Cellar/mysql@5.6/5.6.38/bin/mysql  Ver 14.14 Distrib 5.6.38, for osx10.13 (x86_64) using  EditLine wrapper 6.가상호스트 설정로컬에 다수의 프로젝트를 세팅하기 위한 것이다. 가. httpd.conf 파일 수정Include /private/etc/apache2/extra/httpd-vhosts.conf <- 주석제거 $ vi /etc/apache2/httpd.conf  # Virtual hosts Include /private/etc/apache2/extra/httpd-vhosts.conf 나. httpd-vhosts.conf 파일 수정NameVirtualHost : 아파치 2.4 이전 버전일 경우 80 포트에서 이름 기반 가상 호스트를 사용하겠다는 의미로 반드시 적어줘야 한다.DocumentRoot : 해당 프로젝트 소스 경로ServerName : 해당 프로젝트 접속 도메인주소 $ vi /etc/apache2/extra/httpd-vhosts.conf NameVirtualHost *:80       DocumentRoot "/Users/comkjs/Sites/ex1"     ServerName ex1.brandi.co.kr     ErrorLog "/private/var/log/apache2/error_log"     CustomLog "/private/var/log/apache2/access_log" common               Options FollowSymLinks         AllowOverride All         Order allow,deny         Allow from all         Require all granted         DocumentRoot "/Users/comkjs/Sites/ex2"     ServerName ex2.brandi.co.kr     ErrorLog "/private/var/log/apache2/error_log"     CustomLog "/private/var/log/apache2/access_log" common               Options FollowSymLinks         AllowOverride All         Order allow,deny         Allow from all         Require all granted     7. hosts 설정해당 도메인으로 접속시 DNS 서버를 사용하기 이전 로컬에 지정된 IP로 맵핑된다.$ vi /etc/hosts ## # Host Database # # localhost is used to configure the loopback interface # when the system is booting. Do not change this entry. ## 127.0.0.1 localhost 255.255.255.255 broadcasthost  ::1             localhost   127.0.0.1 ex1.brandi.co.kr 127.0.0.1 ex2.brandi.co.kr Conclusion물론 오랫동안 맥북을 사용했던 개발자에겐 쉬운 내용일 수 있지만 MS와 리눅스에 익숙했던 저에겐 ‘두려움’이었습니다. 리눅스 구조와 명령어가 비슷해서 리눅스를 이용했던 이용자에겐 어렵지 않을 것입니다. 한 번 세팅해두면 환경이 바뀌지 않는 이상 잘 건드리지 않기 때문에 나중에 세팅을 바꾸는 일이 있으면 또 다시 볼 수 있도록 기술 블로그에 남겨둡니다. 분명 언젠가는 도움이 되지 않을까요. 글곽정섭 과장 | R&D 개발1팀kwakjs@brandi.co.kr브랜디, 오직 예쁜 옷만#브랜디 #기업문화 #조직문화 #업무환경 #인사이트 #경험공유 #Mac #개발자 #신입개발자 #조언
조회수 1740

안드로이드 스튜디오

안녕하세요. 크몽 개발팀 입니다.오늘의 포스팅 주제는 "안드로이드 스튜디오" 입니다.안드로이드 스튜디오는 구글이 직접 만든 안드로이드 앱 개발 도구를 말하는데요.안드로이드 스튜디오는 2013년 5월 개발자 컨퍼런스를 통해 프리뷰 버젼을 처음 공개하였습니다.1년 6개월 정도의 기간동안 베타버전이였지만  지난달 8일에  안정화된 정식버전 1.0이 공개되었습니다.안드로이드 개발자 사이트에 가시면 공식적으로 다운받아서 안드로이드 앱을 개발 할 수 있습니다.( Eclipse로 앱을 개발중인데 개발자 사이트에 배포중인 ADT가 내려가서 당황했던 기억이 나네요^^ ) 안드로이드 스튜디오는 IntelliJ 기반으로 만들어 졌는데요.IntelliJ는 워낙 유명한 개발도구인지라 많은 개발자분들이 알고 계실겁니다.Eclipse 와 같이 통합개발툴인데 안정성과 속도면에서 Eclipse보다 뛰어나기때문입니다.하지만 Eclipse가 안드로이드 초기부터 개발자들이 이용해 왔기 때문에 대부분의 개발들에게 익숙하고현재 나온 가이드 or Tip 들이 Eclipse에 기준이 되어있어서 여러부분에서 시행착오를 겪을거 같습니다.그래서 그런지 안드로이드 스튜디오 정식버젼이 나왔지만 아직은 익숙한 Eclipse에 손이가는데요.앞으로 구글에서 공식적으로 ADT에 대한 지원을 끊었으니 조만간 안드로이드 스튜디오로 갈아탈려고 합니다.Android 개발자 사이트 링크 : http://developer.android.com/index.html----------------------------------------------------------------------------------------새롭게 나온 안드로이드 개발도구 "안드로이드 스튜디오"에 대하여  소개하는  포스팅 해보았습니다.다음에는 안드로이드 스튜디오를 직접 사용해보고 각각의 특징들에 대해좀 더 자세히 설명해드리겠습니다. ^_^#크몽 #개발팀 #인턴 #인턴생활 #팀원소개 #업무환경

기업문화 엿볼 때, 더팀스

로그인

/