웹 개발 입문자를 위한 Vue.js 프레임워크 소개

누구나 쉽게 시작할 수 있는 Vue.js 프레임워크와 학습 자료 소개

Advertisements

들어가며

요즘 프런트엔드 개발에 관심을 갖는 분들이 점점 많아지고 있습니다. 컴퓨터 공학을 전공한 대학생 뿐만 아니라 비전공자, 퍼블리셔, 디자이너 분들도 점점 멋진 웹 화면을 개발하기 위해 스스로 정보를 찾아가며 웹 개발하는 법을 배우고 있는 것 같아요.

웹 개발을 위한 기초 HTML, CSS, 자바스크립트를 배우고 나면 제일 먼저 찾게 되는게 바로 프런트엔드 프레임워크입니다. React, Angular 처럼 널리 알려진 프레임워크 사이로 요즘 새롭게 떠오르는 쉽고 강력한 프레임워크가 있습니다. 바로 Vue.js 입니다.

이번 글에서는 Vue.js에 대해서 간단히 소개하고, 웹 개발 입문자도 쉽게 프레임워크를 배울 수 있는 자료들을 안내하려고 합니다.

Vue.js 프레임워크란?

먼저 Vue.js 프레임워크가 무엇인지 소개를 하자면 Vue.js는 웹 사이트를 만들 수 있는 웹 개발자들의 도구입니다.

웹 사이트를 만들기 위해서는 HTML, CSS, Javascript와 같은 웹 기술이 필요합니다. 이 3가지 웹 기술로도 요즘 저희가 많이 사용하는 페이스북, 네이버, 구글 등 여러 가지 유형의 사이트를 만들 수 있습니다.

그런데 왜 프레임워크를 사용해서 만들까요? 그 이유는 더 쉽고 빠르게 웹 사이트를 만들 수 있기 때문입니다. 정형화된 방식으로 미리 만들어진 기능들을 편하게 가져다가 다시 사용하기 때문에
백지상태에서 시작하는 것보다는 확실히 더 빠르게 일정 이상의 좋은 품질로 개발할 수 있죠.

화면을 쉽게 개발할 수 있는 프런트엔드 프레임워크는 2000년대 중후반부터 등장했습니다. 그리고 많은 프런트엔드 프레임워크를 거쳐 지금의 Vue.js에 이르기까지 수많은 프레임워크가 등장했죠. 그래서 요즘 웹 사이트를 개발한다고 하면 엄청나게 많은 도구의 선택지가 있습니다.

좋죠. 일단 선택지가 많으니 뭐든 잘 배워서 개발할 때 써먹으면 되니까요. 하지만, 반대로 생각해보면 정말 너무 많습니다. 네 저도 지금 4년 동안 회사에서 웹 개발을 해왔는데 배우는 걸 멈춰본 적이 없습니다. 맨날 새로운 게 튀어나오고 그러면 또 배우고..

그래서 요즘에는 이런 상황에 고통받는 웹 개발자들이 한 둘이 아닙니다. 제 주변만 봐도 그렇거든요. ‘아 또 나왔네……’라면서 한숨을 쉬는 개발자들이 있습니다. 저도 한숨까지는 아닌데 아 공부할게 하나 더 늘었구나라고 생각은 하죠 🙂

Vue.js 프레임워크는 이런 현재 상황에서 가장 쉽게 접근할 수 있는 프레임워크입니다. 요즘 업계에서 많이 사용되는 앵귤러, 리액트와 다르게 HTML, CSS, 자바스크립트 이외에 꼭 알고 있어야 하는 기술도 없으며 프레임워크 자체가 가볍고 쉬운 프레임워크를 지향하기 때문에 배우기가 쉽습니다.

또한 배우기가 쉽다는 점 때문에 더 많은 입문자들에게 관심을 받고 있다고 생각합니다. 그리고 기존에 프런트엔드 개발을 하지 않았던 다른 분야의 개발자들도 Vue.js로 쉽게 웹 개발을 시작하고 있습니다.

서적을 집필하면서..

책을 잠깐 소개하겠습니다.

Do it! Vue.js 입문서는 Vue.js 프레임워크를 처음 배우는 사람들이 쉽게 프레임워크를 배울 수 있도록 집중한 책입니다.

처음 출판사와 도서를 기획하고 목차를 구성하면서 어떻게 하면 이 쉬운 Vue.js 프레임워크를 더 쉽게, 빠르게, 재밌게 알려줄 수 있을까? 라는 고민을 했습니다. 작년에 패스트 캠퍼스인프런에서 강의를 하면서 검증했던 교재와 자료들을 중심으로 수업 중간중간에 수강생들이 이해하지 못하던 부분들, 특히 질문이 많았던 부분들을 어떻게 책에 잘 녹여낼지에 대한 고민을 가장 많이 했습니다. 생각해보면 이 책을 가장 필요로 하는 웹 개발 입문자, 퍼블리셔, 대학생, 실무자를 대상으로 수업을 진행했기에 수업에서 나온 피드백이 정말 소중했었죠.

처음에 초고를 쓸 때 그 내용을 책 안에 담는 게 쉬운 작업은 아니었습니다. 기술 서적을 처음 집필하는 입장에서 어떻게 써야지 독자들이 더 쉽게 읽을 수 있을지 감이 잘 안 왔었거든요. 그때 다행히 기술서 편집 경험이 많은 노련한 편집자님을 만나 요약된 정보 위주로 전달하는 블로그 글 형식에서 더 친절하고 쉽고 자세히 설명하는 글 형식으로 탈바꿈할 수 있었습니다.

책 전체를 교정하는 과정에서 특정 부분은 최소 7번 이상 다시 썼던 것 같아요. 편집자님이 쉽고 자세한 설명을 요구했었기 때문이기도 했지만 제 스스로도 다시 읽었을 때 이상하다 싶은 부분들은 그냥 넘어가지 않고 몇 번이고 다시 고쳤습니다. 그렇게 전체 원고를 최소 8번 넘게 정독한 것 같습니다.

또한, 글로 쉽게 설명하기 어려운 부분들은 도형과 그림으로 풀어냈습니다. 그림과 도형 같은 경우에도 제가 한번 쓱 그리고 끝내는 것이 아니라 1차로 제가 작업한 그림을 개발 지식이 있는 전문 디자이너 분께 2차 작업을 맡겼고, 3차로 다시 디자이너 분과 논의하면서 도형을 다듬었습니다. 그리고 4차, 5차 작업을 편집자님, 개발을 모르는 기획자분께 검토 받으며 어느 관점에서 보든지 그 글을 쉽게 이해할 수 있는 그림으로 선정했습니다.

책 작업을 하는 내내 생각했던 1가지는 ‘내 스스로도 납득이 가지 않는 글은 책에 담지 않는다’ 였습니다. 그렇기에 글의 흐름, 단어 설명, 도형과 그림, 예제 코드 등 책의 모든 부분을 하나도 빠짐없이 꼼꼼히 읽고 검토했습니다.

그리고 그 검토 작업에 고맙게도 많은 분들이 도움을 주셨어요. 모든 집필/편집 과정을 함께해준 편집자님, 직관적인 그림과 도형을 그려준 디자이너 겸 개발자님, 전체적인 책의 오탈자와 구성 오류를 검토해준 기획자님, 그리고 베타 리딩과 기술 검수를 맡아준 개발자 두 분까지 합하면 벌써 이 책에는 저 혼자가 아닌 6명의 노력과 시간이 들어갔네요. 그 외에도 조판하는 회사의 직원과 이 책을 함께 검토해주는 출판사 직원까지 생각하면 정말 많은 분들이 좋은 책을 내기 위해 함께해주신 것 같습니다.

그래서인지 이번에 출간된 Do it! Vue.js 입문 책을 자신 있게 추천할 수 있습니다. 혹시 웹 개발을 시작하고 싶다면 Do it! Vue.js 입문 책으로 시작해보시는 건 어떨까요? 🙂

읽어주셔서 감사합니다.
저자 장기효 올림

P.S : 여러 명의 땀과 노력이 들어간 Do it! Vue.js 입문 도서는 아래 링크에서 구매하실 수 있습니다 🙂
Do it! Vue.js 온라인 구매 링크

Vue.js 학습 자료

성능 덕후를 위한 자바스크립트 코딩 패턴 (중급 이상)

이 글은 CodeSchool 의 Javascript Best Practices 를 듣고, 주요 내용을 정리한 글입니다.

Ternary Conditional (삼항 연산자)

  • 다음과 같은 예문이 있다.
var isArthur = true;
var weapon;

if(isArthur) {
  weapon = "Excalibur";
} else {
  weapon = "Longsword";
}
  • 삼항연산자를 이용하면 위의 if else 문을 아래와 같이 바꿀수 있다.
var weapon = isArthur ? "Excalibur" : "Longsword";
  • 또한 삼항 연산자를 다음과 같은 형태로도 사용이 가능하다.
// 두개 이상의 변수를 이용하여 값을 받는 경우
isArthur && isKing ? (weapon = "Ex", helmet = "Goose") : (weapon = "ln", helmet = "Iron")

// 즉시 실행함수로 값을 받는 경우
isArthur && isKing ? function () {
                                   // ...
                     }();
                     :
                     function () {
                       // ...
                     }();

Logical Assignment 1 (OR)

  • OR 연산자 : “falsy” 하지 않은 가장 첫번째 마주친 값을 갖는다.
  • 아래의 삼항 연산자를 OR 연산자를 이용하여 다음과 같이 줄일 수 있다.
// 삼항연산자 사용
function addSword(sword) {
  this.swords = this.swords ? this.swords : [ ];
  this.swords = push.(sword);
}

// OR 연산자 사용
function addSword(sword) {
  this.swords = this.swords || [ ];
  this.swords = push.(sword);
}

// OR 연산자 잘못 사용한 예
function addSword(sword) {
  this.swords = [ ] || this.swords;
  this.swords = push.(sword);
}
// 위의 경우 계속 new array 를 할당함.
  • OR 연산자의 잘못된 사용 예를 더 본다.
// 잘못된 OR 연산자 사용 예
var result1 = 42 || undefined; // undefined 를 절대로 마주치지 않는다.
var result2 = ["Sweet", "array"] || 0; // 0을 절대로 마주치지 않는다.
var result3 = {type: "ring", stone: "diamond"} || ""; // "" 를 절대로 맞추지지 않는다.

// 위를 고쳐보면,
var result1 = undefined || 42;
var result2 = 0 || ["Sweet", "array"]; // 0을 절대로 마주치지 않는다.
var result3 = "" || {type: "ring", stone: "diamond"}; // "" 를 절대로 맞추지지 않는다.

Logical Assignment 2 (And)

  • OR 연산자와는 다르게 두개의 “truthy” 값이 있으면, 마지막으로 확인한 truthy 값이 리턴된다.
  • “falsy” 값의 경우에는 OR 연산자와 동일하게 동작한다.
var result1 = "King" && "Arthur";
console.log(result1); //Arthur
var result2 = "Arthur" && "King";
console.log(result2); // King

Switch Blocks

  • 반복되는 if else 문과 switch 문의 차이점은, 순차적으로 모든 if 문을 도느냐. 아니면 해당하는 case 로 바로 가서 불필요한 연산을 줄이느냐의 차이이다.
var regimnet = 3;

if (regiment == 1) {
  ...
} else if (regiment == 2) {
  ...
} else if (regiment == 3) { // 앞 1,2 를 거쳐 3으로 온다.
  ...
}

switch (regiment) {
  case 1:
    ...
  case 2:
    ...
  case 3: // 3으로 바로 온다.
    ...
}
  • break 문을 사용하지 않고, 공통된 property 를 상위 case 에서 부터 순차적으로 접근하여 추가하는 방법도 있다.

Loop Optimization

  • 컴퓨터 메모리 관점에서 일반적인 for 문의 연산 순서를 보자.
treasureChest = {
  necklaces: ["A", "B", "C", "D"];
};

for (var i = 0; i < treasureChest.necklaces.length; i++) {
  console.log(treasureChest.necklaces[i]); 
} 
  • 위 for 문에서 메모리 연산이 필요한 부분은 다음과 같다.
    1. i 값 탐색
    2. treasureChest 객체 탐색
    3. necklaces 속성 탐색
    4. necklaces 속성의 배열 인덱스 탐색
    5. length 프로퍼티 검색 > 위의 연산을 최적화 해보자 : Cache the necessary values in the local variables
// 1. length property 를 한번만 접근 (기존 for 문은 반복시 마다 접근)
var x = treasureChest.necklaces.length;
for (var i = 0; i < x; i++) {
  console.log(treasureChest.necklaces[i]);
}
  • 위의 리팩토링으로 연산 수가 다음과 같이 줄어들었다.
  • 위 코드는 더 개선할 수 있다.

// 2. for 문의 초기 선언문 쪽에서 x 값을 선언하면, 전역 변수로 var x 를 선언하지 않아도 되어 메모리가 더 효율적이게 된다.
for (var i = 0, x = treasureChest.necklaces.length; i < x; i++) {
  console.log(treasureChest.necklaces[i]);
}
  • 주의할 점 : 자바스크립트는 {} 로 스코핑이 되어 있지 않기 때문에, 위의 for 반복문이 끝나면 x 값은 최종 값으로 할당되어 있다는 사실

  • 또 다른 개선 포인트

// 3. 각 반복 싸이클마다 treasureChest 객체의 속성에 접근을 할 필요가 없다.
var list = treasureChest.necklaces;
for (var i = 0, x = treasureChest.necklaces.length; i < x; i++) {
  console.log(list[i]); } 

모든 인덱스를 접근할 때에는 for loop 문이 좋고, 때로는 for in 보다 성능이 나은 경우가 있다. for in 은 prototype 에 접근하여 기존의 기 정의된 메서드까지 포함하여 출력하므로 비효율적

Performance (Script Loading)

  • Work Intensive javascript 는 body 마지막 태그 맨 위나 async 속성 이용하여 페이지 첫 로딩을 빠르게 한다.

Performance (Inheritance)

  • 자바스크립트에서 상속은 prototype 을 이용
  • 공통으로 쓰는 메서드는 모두 prototype 에 집어 넣는다.
function SignalFire(id, logs) {
  this.id = id;
  this.logs = logs;
  this.functionality1: function() {

  },
  this.functionality2: function() {

  },
  this.functionality3: function() {

  },
}
  • 위 함수의 경우 매번 객체를 생성할 때 마다 사용하지 않는 메서드들을 메모리에서 사용하는 낭비가 발생한다.
  • 따라서, 매번 객체 생성시 필요한 속성이나 메서드만 가져가도록 하고, 공통 메서드는 다음과 같이 prototype 으로 뺀다.
  SignalFire.prototype = {
  functionality1: function() {

  },
  functionality2: function() {

  },
  functionality3: function() {

  },
}

Performance (Indivdual DOM)

  • list 를 배열로 갖는 DOM 요소에 append 메서드를 이용하여 DOM 을 추가하면 전체 리스트가 reflow 된다. 이는 성능에 악영향을 준다.
  • 성능 향상을 위한 해결법은 Fragment 를 사용한다.
var fragment = document.createDocumentFragment();
fragment.appendChild(element);
list.appendChild(fragment);

Performance (Get rid of var redundancy)

  • var 지정어를 사용할 떄, 다음과 같이 코드량을 줄일 수 있다.
var a = 1;
var b = "hello";
var c = ["a","b","c"];

var a = 1,
b = "hello",
c = ["a","b","c"];

// 코드의 가독성이 높아지고, 간결하다.

Performance (String Concatenation)

  • 문자열의 길이에 따라 += 연산자와 join() 메서드의 성능차이가 발생한다.
  • 문자열이 짧을 떄 : += 연산자가 성능이 더 빠르다.
  • 문자열이 길고, 문자열이 배열안에 리스트 형태로 저장되어 있을 때 : join("\n") 메서드가 성능이 우월하다.
var page = "";
for (var i = 0, x = newPageBuild.length ; i < x ; i++) {
  page += newPageBuild[i];
}

// join() 메서드 활용
page = newPageBuild.join("\n");

Namespacing

  • 팀 프로젝트 시 많은 양의 자바스크립트 코드를 작성할 때, 타 팀원이 작성한 전역변수가 overwrite 되는 경우가 발생한다.
  • 이를 막기 위해 namespacing 을 활용한다.
var a = ["Apple", "Banana", "Coil"];
var c = function () {
  console.log("this is not what I want.");
};

var nameSpace = {
a : "1",
b : 23,
c : function() {
  // ...
}
};

// HTML Element click event
onClick=nameSpace.c();

유럽 배낭여행에서 느낀 Offline Web App 의 무한한 성장가능성

10월 한 달간 유럽 배낭여행을 하면서 느낀 Offline Service 에 대해서 생각을 정리해보았습니다.

  • 초당 10MB 가 넘는 데이터를 무리 없이 제공하는 한국에 있다 보니 자연스럽게 인터넷이 느린 사용자의 입장에서 생각을 하지 않고, 한국의 빠른 인터넷 속도 기준으로 어플리케이션을 제작해왔다.
  • Software 분야에서는 한국이 결코 후진국이라는 말이 있고, 나 또한 그렇게 믿고 있었지만, 내가 경험하고 본 유럽의 현황은 사실 우리나라 보다 더 뒤처져 있는 것 같았다.
  • 느린 통신사 data 망과 길거리에서 찾아보기 힘든 Public Wifi 는 현지인들이 지하철에서 핸드폰보다는 책이나 신문을 더 보게 하고, 관광지에 놀러 온 여행객들은 Google Trips 처럼 offline 에서도 작동하는 앱을 사용하기보다, 언제나 그래왔듯이 꾸준히 지도를 펼쳐가며 방향을 잡고 주민들에게 물어보며 장소를 찾아가는데 한 몫을 한다.
  • 물론, Google Trips 앱이 나온 지가 얼마 되지 않았고, 사람들에게는 Google Map 보다 관광 지도로 보는 것이 더 편하고 익숙하겠지만. 대다수를 위한 서비스를 하기 위해서는, 그 대다수가 선호하는 방식을 알고 있어야 하고, 그 패턴을 분석해서 보다 더 나은 서비스를 제공할 수 있는 통찰력이 필요하다는 생각이 들었다. 그리고 이러한 안목으로 서비스를 개발해 나가는 것이 세상을 더 편리하게 하는 Software Engineer 가 함양해야 할 자세가 아닐까?
  • 어플리케이션 성능을 최대한 최적화 해서 빠른 사용자 경험을 제공한다고 하더라도, 인터넷이 느린 국가에서는 사실 그렇게 의미가 많지 않은 작업이라고 생각이 든다. 그렇기 때문에 구글에서도 Progressive Web App 이라는 새로운 Web Application 개념으로, 보다 더 많은 사용자들이 Offline Service 로 혜택을 볼 수 있게끔, Web 기술을 발전시켜 나가고 있는 게 아닐까 라는 생각이 들었다.
  • Offline Web Service Era 가 도래할만한 충분한 배경과 현실이 있는 세상이다. Offline Service 부분에 좀 더 집중해서 나처럼 배낭 여행하는 여행객들과 현지인들이 편하게 여행하고, 지하철에서도 충분히 자기가 원하는 서비스들을 offline 으로 제공받는데 도움이 되었으면 좋겠다.

To be continued after this backpacking trip..

크롬 플러그인의 content_scripts.js 분석

사이트 별로 다른 Content Script 적용

  • 사이트 마다 다른 스크립트 파일을 적용하려면 아래의 패턴을 적용한다.
    "content_scripts": [
    {
      "matches": ["http://www.google.com/*"],
      "css": ["mygooglestyles.css"],
      "js": ["jquery.js", "mygooglescript.js"]
    },
    {
      "matches": ["http://www.yahoo.com/*"],
      "css": ["myyahoostyles.css"],
      "js": ["jquery.js", "myyahooscript.js"]
    }
    ],
    

Content Script 의 jQuery 사용

  • content_script.js 에서 jquery로 DOM 을 접근하면, 크롬 익스텐션에서 정의한 popup 페이지에 대한 DOM 접근을 한다.
    "browser_action": {
    "default_popup": "popup.html"
    },
    "content_scripts": [
    {
      "matches": ["http://*/*","https://*/*",""],
      "js": ["js/jquery.js","js/content_script.js"]
    }
    ]
    
    <br /><a href="http://js/jquery.js">http://js/jquery.js</a>
    <a href="http://js/content_script.js">http://js/content_script.js</a>
    
    
    <div id='product_name'>Injecting Product Name....</div>
    <!-- ... -->
    
    
    // content_script.js
    function onWindowLoad() {
    console.log("팝업 페이지의 DOM 접근 : ", $("#product_name").text());
    // 위 결과는 위 html 파일에서 product_name 아이디의 태그 값인 Injecting Product Name.... 이 된다.
    }
    
    window.onload = onWindowLoad;
    
  • manifest.json 파일의 js 속성을 위처럼 jquery.js, content_script.js 로 지정하면 content_script 에서 $ 연산자 사용이 가능하고, ajax 콜도 가능하다.

TLS / SSL 소개 및 Tomcat 에 HTTPS 적용하는 방법

TLS / SSL 소개

  • TLS : Transport Layer Security
  • SSL : Secure Sockets Layer
  • 웹 브라우저와 웹 서버 간의 통신을 안전하게 보장하는 기술이다.
  • 데이터를 보낼 때 데이터를 암호화하고, 데이터를 받을 때 암호화된 데이터를 복호화 하는 식의 기본 구조를 갖는다.
  • 이 통신 구조는 양방향 이기 떄문에, 웹 브라우저와 웹 서버 모두 데이터를 내보낼 때 암호화를 진행한다.

TLS / SSL 인증

  • 웹 브라우저에서 암호화된 연결로 웹 서버와 통신하려고 하면, 웹 서버에서 브라우저에게 몇가지 증명서(Certificate)를 요구한다.
  • 이 증명서는 클라이언트 인증 (Client Authentication) 이라고 하며, 개인 사용자 간 보다는 B2B 형태에서 더 많이 사용된다.
  • 대부분의 SSL-enabled 웹 서버 는 클라이언트 인증을 요구하지 않는다.

Certicates 인증서

  • SSL 를 구현하려면 웹 서버에 Certificate이 있어야 하는데, 이 Certificate 은 암호화된 연결을 수용하는 외부 인터페이스를 보장해준다.
  • 이러한 SSL 설계 방식은 “서버에서 어떤 형태로든 내가 생각했던 상대방이 맞다” 라는 것을 서버에서 증명하는 것이다

따라서, Certificate 을 해당 인터넷 주소에 대한 Digital Passport 로 볼 수 있다.

  • Certificate 은 암호화되어 발급되는데, 최초 발급자 말고는 사실 발급하기가 매우 힘들다.
  • 방문자 브라우저에서 해당 사이트를 접근하면 보통 경고가 뜨는데, 이때 Certificate Authorities 라는 신뢰되는 3rd 파티에 서명하면 경고가 뜨지 않는다.
  • Java 에서는 상대적으로 단순한 keytool 커맨드라인 툴을 제공하고, 명령어로 self-signed Certificate 을 생성할 수 있다.
  • Self-signed Certificates 는 사용자가 간단하게 생성한 인증서이기 때문에 테스트 시나리오에 적합하고, 실제 상용제품에는 적합하지 않다.

SSL 구동시 팁

  • SSL 로 웹 사이트를 구성할 때는 모든 사이트 자원들울 SSL 로 제공해야 한다. 이렇게 하면 해커들이 자바스크립트 파일 등에 악성 컨텐츠를 넣을 수가 없어 보안을 우회할 수가 없다.
  • 웹 사이트의 보안을 강화하고 싶으면 HSTS header 를 사용하는 것도 고려해봐야 한다.
    • HSTS header : 브라우저에서 항상 HTTPS 통신으로 사이트를 접근하게 한다.

Tomcat 에서 인증서 설정하기

Certificate Keystore 준비하기

  • Tomcat 에서 수용하는 keystore 타입은 JKS, PKCS11 또는 PKCS12.
    • JKS : Java 표준 키스토어 형식. JDK 에 포함된 keytool 커맨드 라인툴로 생성 가능
    • PKCS12 : 인터넷 표준 형식. Open SSL 이나 Microsoft Key-Manager 로 조작 가능
  • keystore 의 목록들은 alias 의 문자열 값으로 구분할 수 있다. 대부분은 대소문자 구분을 하지 않지만, PKCS11 형식은 대소문자 구분을 한다.

  • OpenSSL 을 이용하여 당신의 CA로 서명된 Certificate 을 PKCS12 keystore 에 임포트하려면 아래 명령어를 사용한다.
    openssl pkcs12 -export -in mycert.crt -inkey mykey.key
    -out mycert.p12 -name tomcat -CAfile myCA.crt
    -caname root -chain
    
  • JKS keystore 를 새로 생성하려면 아래 명령어를 커맨드창에서 실행한다.
    Windows:
    &amp;quot;%JAVA_HOME%\bin\keytool&amp;quot; -genkey -alias tomcat -keyalg RSA
    
    Unix:
    $JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA
    
  1. 위 명령어의 결과는 실행한 위치의 홈 디렉토리 아래에 .keystore 라는 이름의 새로운 파일을 생성한다.
  2. 만약 다른 위치나 파일이름을 지정하고 싶으면, -keystore 변수를 사용한다. (변경된 위치 또한 server.xml 에 반영해줘야 함)
    Windows:
    &amp;quot;%JAVA_HOME%\bin\keytool&amp;quot; -genkey -alias tomcat -keyalg RSA
    -keystore \path\to\my\keystore
    
    Unix:
    $JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA
    -keystore /path/to/my/keystore
    
  3. 위 명령어를 실행하면 비밀번호를 입력하라는 창이 나오는 데 default 값은 changeit 으로 되어 있다. 원하는 비밀번호로 변경이 가능하고, 이 또한 server.xml 에 반영해줘야 한다.

  4. 비밀번호를 입력하고 나면, 회사 / 이름 등에 대한 일반적인 정보를 입력하라고 한다. 이 정보는 이후 사용자가 암호화된 페이지 접근시에 표시된다.
  5. 마지막으로, 인증서(Certificate) 에 대한 key password 를 입력한다. 별도로 비밀번호를 입력하지 않고 엔터를 치면 위 1번에서 사용한 keystore 의 암호와 동일하게 입력된다.

Tomcat Configuration 파일 변경하기

  • 톰캣은 SSL 통신 구현방법에는 JSSE, APR 2가지가 있다.
    • JSSE : Java 런타임에서 제공.
    • APR : OpenSSL 엔진을 기본값으로 사용.
  • 여기서 JSSE connector 를 정의하는 방법은

1

2

  • APR 을 사용하려면

3

  • Configuration 을 위한 최종 단계는 $CATALINA_BASE/conf/server.xmlConnector 를 설정하는 것이다.

4

  • 위 절차를 모두 마치면 브라우저에서 https://localhost:8443/ 를 입력했을 때 Tomcat 기본페이지를 볼 수 있다.

Atom 필수 플러그인 리스트 (Can’t live without it)

Atom Editor 는 무엇인가요?

  • Github 에서 제작한 hackable 코드 에디터로 뛰어난 접근성과 현대적이고 유용한 기능들을 제공하는 것이 특징
  • 개인적으로 필요한 기능들에 대해 추가적으로 제작할 수 있고, 이를 패키지로 배포하여 서로 공유할 수 있다.

atom_editor

Atom Editor 를 쓰게된 계기?

  • 오픈소스로 관리되고, 100% 무료인 Code Editing Tool
  • 코드 개발과 소스 관리에 특화된 Github 이 지원하고 있는 Editing Tool

Github has a lot of resources to put in the process of developing an application. It has the ability to create a stable product fast and improve it over time.

  • 테마부터 코드 동기화까지 모두 개인화가 가능한 맞춤형 툴
  • Chrome 요소 검사로 에디팅 툴을 접근할 수 있는 것도 장점

Atom 의 유용한 플러그인 리스트

Seti UI

  • Backbone.js 의 제작자 Addy Osmani 도 추천하는 코드 테마. 색깔 조합이 수려해서, 개인적으로 코딩할 때 질리지 않는 colorful 한 테마다.

seti ui

Beautify

  • 들여쓰기나 코드 간격이 일정하지 않은 복잡한 코드를 보기 좋게 정리해준다.

beautify

Pigments

  • CSS 파일의 #FF530D 형태의 컬러 값을 직관적으로 표시해준다.
    pigments

Code peek

  • 선택한 함수가 정의되어 있는 파일을 자동으로 열어 대조해준다. (이클립스의 Alt+마우스 왼쪽 클릭 과 동일한 기능)

color peek

Highlight selected

  • 선택한 코드를 강조해주는 유틸리티

highlight selected

Auto close HTML

  • HTML 태그 이름만 입력하면 시작 및 종료 태그를 알아서 붙여준다.

auto close html

Package sync

  • 서로 다른 컴퓨터 간에 Atom Package 를 동기화 시켜준다. 다른 컴퓨터에서 작업환경을 동일하게 구성할 때 유용하다

package sync

Minimap

  • 전체 코드의 프리뷰 기능을 제공하고, 툴의 오른쪽에서 코드 전체 윤곽을 확인하거나 위치를 확인하기 편리하다
    minimap

Minimap cursorline

  • 현재 선택한 라인이 Minimap 에서 어디에 위치하는지 구체적인 Line Highlighting 지원

Color Picker

  • CSS 스타일 작성시 색상 팔레트를 에디팅 위에서 볼 수 있어 쉽게 변경할 수 있다.

color picker

Emmets

  • Emmets 에서 제공하는 특정 Syntax 로 반복적인 코드를 쉽게 작성할 수 있다. 예를 들어, ul&gt;li*3&gt;p 는 아래와 같은 결과

emmet

Linter

  • HTML, CSS, Javascript, TypeScript 등의 코드를 분석하여 문법 및 유효성을 검증해주는 유틸리티

linter

Fuzzy Finder

  • 단축키 Ctrl-TCmd-T 로 파일을 쉽게 찾고 연다.

fuzzy finder

Sort Lines

  • 선택한 라인의 내용을 알파벳 순서로 정렬해준다.

sort lines

WakaTime

  • 프로젝트에서 사용한 언어, 작업 시간, 로그인 타임 등을 분석해서 가시화 해주는 그래프 유틸리티

wakatime

 

Legacy 웹 사이트에 Progressive Web App 적용하기 (Part I)

Why did I start to work on this project?

  • 배경 : 팀내에서 고객과의 질의응답 채널로 포탈 사이트를 운영하고 있다.
  • 현상 : 포탈 사이트가 개발된지 약 2년이 된 것 같은데 (소스를 보니 2014년에 만들어진 것으로 추정), 시대를 역행하는 Non Responsive Design 과 고객 Q&A에 Notification 기능이 없어 수시로 사이트 접속하여 게시글과 댓글을 모니터링 해야하는 불편함이 있었다.
  • 계획 : Mobile 에서도 간단한 게시글 확인 및 알람 기능을 추가하여 사용성을 늘리기로 결정했고, Progressive Web 의 몇가지 기능들을 넣어보기로 결정했다.

What is Progressive Web App?

  • 구글에서 최근에 밀어붙이는 웹앱으로 Responsive Design, App Like, Re-engagable, Installable, Safe, … 등의 특징과 함께 빠른 로딩과 높은 사용자 경험을 제공하는 것이 특징이다.
  • Mobile 에서만 지원되었던 Push 알림, Mobile Icon, 앱 설치 배너 등을 웹 어플리케이션에서 지원하기 때문에, 일반 웹 개발로 Mobile Application 의 Appy 한 느낌을 낼 수 있다.
  • 자세한 내용은 Google Web Fundamental 참고

Non Responsive to Responsive Design

  • 기존에 적용된 UI Framework 은 반응형이 지원되지 않는 Bootstrap 이다. 무슨 이유에서인지 모르겠으나 반응형 지원을 하지 않고, 철저히 PC 기준으로만 사이트를 제작하였다. 아마도, 모바일에서의 화면 Layout 까지 고려하기에는 시간이 빠듯했거나, 요구사항 자체가 Mobile 에서도 볼 수 있게 해달라는 요청이 없었기 때문인 것 같다.
  • Boostrap 외에도 jstree, jquery-ui, jquery-remodal, jquery-multifile, NHN Smart Editor 등의 외부 라이브러리들을 가져다가 화면을 구성해놓았다.

레거시 사이트 UI

1365 * 600 해상도 PC 화면

pc_login
PC 로그인 페이지
  • 그냥 로그인 기능만 되면 문제 없어보이는 UI…

 

pc_main
PC 게시판 목록
  • 전체적으로 균형은 잘 잡혀 있어 보인다.

 

pc_list
PC 트리 선택 후 게시판 이동
  • 왼쪽 트리를 펼쳐 게시판 목록을 펼친다.

 

pc_viewpost
PC 게시글 조회
  • 게시판 질의 응답 기능에만……. 충실한 화면 Layout 과 UI

iPhone 6 브라우저 화면

1
Mobile 로그인 페이지
  • 로그인 페이지는 그럭저럭 봐줄만 하다.

 

2
Mobile 게시판 목록
  • 모바일에서 보는 게시판 페이지는 거의 재앙에 가깝다.

 

3
페이지 확대해서 트리 선택
  • 페이지를 이동하려면 왼쪽 트리를 클릭해야 하는데, 페이지 확대를 해서 저 작은 리스트를 클릭해야 페이지 이동이 된다… 참 난감하다.

 

4
Mobile 에서 게시글 조회
  • 게시글 조회 시 게시글과 답변 모두 확대 하지 않고는 보기가 거의 불가능하다.

 

Re-designing UI & UX with Critical User Journeys

  • 지난 6월 Google Campus 에서 진행된 UI & UX 워크샵에서 배운 “Critical User Journeys” 기법을 이번 사이트에 적용 해보았다.
  • Critical User Journeys : 사용자의 입장에서 해당 서비스를 사용할 때 모든 동작에 대해 UI 와 Layout 을 고려하고 이를 기반으로 UI Design 을 가다듬는 것.
  • UI 개선을 위해 가장 첫 번째로 해야할 질문들 (The very first thing to do is ask these questions)
  1. Who is using your website? 누가 사이트를 사용하는가?
  2. When are they using their website? 사용자들은 사이트를 언제 사용하는가?
  3. Why are they using the website? 사용자들은 왜 사이트를 사용하는가?
  4. Where are they using the website? 사용자들이 사이트를 어디에서 사용하는가?
  • 사이트를 사용하는 유저 입장에서, 로그인 절차부터 게시판 및 기타 기능들을 사용할 때 까지 위의 질문들을 염두에 두고 다음과 같이 개편하였다.
  1. Mobile First Design
  2. 버튼에 아이콘을 추가하여 직관화
  3. 글쓰기 / 글읽기 / 답글달기 할 때 보여지는 기능들의 우선순위를 정하여 UI 컴포넌트 재배치
  4. 게시글 정보를 중요도 순으로 다시 배치하고 간결하게 표현
  5. 댓글에 자신의 사진을 표시하여 책임감 및 흥미 부여 (화장실에 담당자 사진 걸어놓는 것과 동일한 목적)
  6. 전체적인 Tone & Manner 를 맞추기 위해 기존 jsTree 라이브러리 제거 후 Collapsible 과 Collection 으로 트리 구현

개선된 사이트 UI

15인치 노트북 PC에 최적화된 화면

new_pc_login
PC 로그인 페이지
  • MaterializeCSS 의 기본 Login Template 을 적용했다.

 

new_pc_list
PC 게시글 목록
  • UI 의 전체적인 느낌을 통일하기 위해 왼쪽 jstree 라이브러리를 걷어내고, collipsible & collection 조합으로 왼쪽에 트리를 구현하였다.

 

new_pc_viewpost
PC 게시글 조회
  • 글 수정 / 삭제 / 목록 등의 버튼에 아이콘을 이용하여 직관적인 표시를 하였고, 답글과 댓글 영역을 명확히 분리하였다. 댓글 리스트는 우선순위 기준으로 정보를 재배치 및 계정에 프로필 사진을 추가하여, 댓글 구분이 쉽도록 하였다.

 

new_pc_delete
게시물 삭제시 권한 확인 팝
  • 기존 화면의 불필요한 영역을 차지하는 ID & PW 를, 게시글을 삭제할 때 확인하도록 변경했다.

 

iPhone 6 브라우저 화면

new_mobile_login
Mobile 로그인 페이지
  • PC Login 화면에서 크기만 작아진다.

 

new_mobile_main
Mobile 메인 페이지
  • 로그인 후 메인화면, 모바일에서는 폴더 트리를 Global Navigation 으로 뺐다.

 

new_mobile_list
Mobile 게시글 목록 페이지
  • 게시글 목록은 다음과 같이 표시된다. 테이블 cell 의 더 세부적인 css 스타일링으로 가독성을 높이는 작업이 더 필요한 것 같다.

 

new_mobile_tree
Mobile 네비게이션 바
  • Global Navigation Bar 를 이용하여 페이지 간 이동을 한다.

 

new_mobile_viewpost
Mobile 게시글 조회
  • Mobile 에서 유용하게 사용할만한 보기 & 댓글 기능에 주안점을 두고, 가독성을 높이는데 주력했다.

 

Back-End Service Analysis

기술 및 기법

  • 기존의 시스템은 Spring FW 3.4 로 구성이 되어 있었고, 다음과 같은 기술 및 기법 들을 쓰고 있었다.
  • Spring Security : 권한 관리를 위한 스프링 기술스택
  • Controller Annotation in bean.xml : base.package 에 지정된 패키지 안에 해당되는 모든 @Controller 에 대해 처리해준다.
  • ControllerAdvice Annotation in bean.xml : 위와 동일한 성격으로, 여기서는 Controller 에서 발생하는 에러 케이스 들에 대한 Exception 처리를 지정해주었다.
  • Multipart Resolver in beans.xml : 파일 또는 이미지를 Client 에서 Stream 방식으로 서버로 보낼 때, Stream 형식으로 받아 처리해줄 수 있는 Resolver
  • JDBC Template in applicationContext.xml : 스프링에서 DB 연결시 사용하는 전형적인 스프링 JDBC 연결방법
  • DataSource Transcation Manager in applicationContext.xml : 스프링에서 제공하는 다양한 Transaction Manager중의 하나
  • DBCP DataSource in applicationContext.xml : DB와 어플리케이션을 효율적으로 연결하는 커넥션 풀을 제공. 일정 커넥션을 유지하다가 필요하면 사용하고 반납하여 재사용하는 형태

문제점

  • 기존 레거시 시스템의 가장 큰 문제점은 특정 주기 간격으로, 서비스가 올라가 있는 Tomcat 을 주당 2회 정도 계속 재시작을 해줘야 했다.
  • 그 이유를 진단하기 위해 아래 쿼리를 넣었고
show status like `%connect%`;
  • 진단 결과는 다음과 같았다.

“페이지 마다 수행되는 쿼리에 대해서 커넥션이 닫히지 않고, 계속 커넥션 수가 누적된다.”

Back-End Service Refactoring

안티패턴 1

  • 위와 같은 문제점을 해결하기 위해 구현된 Spring 로직을 분석한 결과, 다음과 같은 안티패턴을 발견했다.
@Controller
public class BoardController extends ExceptionControllerAdvice {

private BoardService getBoardService() {
ApplicationContext context = new GenericXmlApplicationContext(&quot;applicationContext.xml&quot;);
return context.getBean(&quot;boardService&quot;, BoardService.class);
}

// ...
}
  • 위의 안티패턴은 해당 컨트롤러가 수행이 될 때 마다, ApplicationConext 를 매번 생성하여 메모리 낭비 및 DB 커넥션 수를 불필요하게 늘리게 된다.
  • 해결책 : ApplicationContext는 WAS (Web Application Server) 에 Spring Container가 올라가는 최초에만 생성되고, 이후에는 생성된 Context 를 공유하는 형식으로 바꿨다.
@Controller
public class BoardController extends ExceptionControllerAdvice {

@Autowired
private BoardService boardService; // Application Context 에서 생성된 BoardService 를 참조한다.

// ...
}

안티패턴 2

  • Controller.java 에서 해당 URL에 관한 로직을 처리 후 URL redirect 을 다음과 같이 한 안티패턴이 발견되었다.
@RequestMapping(value = &quot;replyBoard&quot;, method = RequestMapping.POST)
public String replyBoard(
HttpSession session,
@RequestParam(&quot;folder&quot;) String folder,
@RequestParam(&quot;subCategory&quot;) String subCategory, ... ) throws UserException {
ModelAndView mv = new ModelAndView;
mv.addObject(&quot;folder&quot;,folder);
mv.addObject(&quot;subCategory&quot;,subCategory);
// ...

return &quot;redirect:/viewPost?folder=&quot;+folder+&quot;&amp;subCategory=&quot;+subCategory;
}
  • ModelAndView 를 사용하여 redirect 를 할 경우에는 ModelAndView 에 추가된 Object 변수들이 redirect 시에 자동으로 붙지 않는다. 따라서, 이를 아래와 같이 Model model 을 이용하면,
@RequestMapping(value = &quot;replyBoard&quot;, method = RequestMapping.POST)
public String replyBoard(
HttpSession session,
@RequestParam(&quot;folder&quot;) String folder,
@RequestParam(&quot;subCategory&quot;) String subCategory, Model model ) throws UserException {
model.addObject(&quot;folder&quot;,folder);
model.addObject(&quot;subCategory&quot;,subCategory);
// ...

return &quot;redirect:/viewPost&quot;;
}

// URL 결과 : `viewPost?folder=&quot;folder&quot;&amp;subCategory=&quot;subCategory&quot;`
  • 위처럼 Model 을 이용하여 View에 데이터를 넘겨주면, redirect 시에 자동으로 변수가 붙게되는 이점이 있다.

Progressive Web App Native Feature 적용은 Part 2 에서 이어집니다…