블로그 이미지
윤영식
Full Stacker, Application Architecter, KnowHow Dispenser and Bike Rider

Publication

Category

Recent Post

2016. 10. 23. 22:59 Angular/Concept

Angular v2가 정식 릴리즈되었다. Angular v1 은 Two-way data-binding 이라는 독특한 특징으로 인해 많은 사용자 층을 확보했지만 장점 만큼이나 성능상의 단점도 존재했었다. 또한 처음엔 쉬운듯 하면서 좀 더 깊게 들어가볼려고 하면 학습곡선이 갑자기 껑충뛰기도 했다. 가장 많이 사용했던 Directive(지시자)가 대표적이다. 많은 개발자가 만들어 놓은 지시자를 쉽게 가져다 쓸 수는 있지만 직접 만들어 애플리케이션에 접목하려 할 때 첫 문턱을 만나게 된다. 그리고 jQuery사용에 익숙한 개발자에게 Angular v1 시점상의 차이로 Angular v1 방식의 개발패턴을 요구하기도 했다. 관성은 무섭다. 기존에 사용하던 방식을 버리고 Angular v1에 맞춰서 애플리케이션을 만들어 가기란 곤혹스럽다. Angular v2 또한 그런 인식의 전환을 요구할까? 그렇다 그리고 아니다. 






웹 애플리케이션 흐름

웹 애플리케이션 개발을 위해 우리가 사용하는 jQuery같은 라이브러리나 Angular, Backbone같은 프레임워크의 가장 1차적인 목적은 무엇일까? 나는 Data Projection이라 생각한다. 데이터를 화면에 출력하기 위해 DOM을 얼마나 쉽게 조작하고 상호 작용할 수 있느냐가 선택의 기준이라 생각한다. Data Projection을 일관되고 확장가능하고 배포가능하게 하는 방식으로 기술은 발전해 왔고, 현재는 화면에 대한 제어방식이 컴포넌트 기반 방식으로 발전해 오고 있다. 


Data Projection의 역사를 보면 초장기엔 Server Side Rendering 를 사용해 웹 애플리케이션을 개발했다. 예로 JSP, PHP, ASP 같이 서버 미들웨어서 데이터를 조회하고 HTML을 조작하여 결과 HTML을 브라우져에 전송하던 시대이다. 




1세대에는 AJAX가 나오고 다양한 라이브러리나 프레임워크가 나왔다. 이때는 데이터변경에 대한 DOM반영이 서버에서 클라이언트 개발자의 몫으로 넘어오게 되었다. 즉, 직접 DOM 을 얻어와서 특정 위치에 넣어 주어야 했고, DOM에서 발생하는 이벤트를 Listening해서 처리하고 DOM에 반영하는 모든 작업이 웹 개발자가 직접 코딩하던 단계였다. Java의 프레임워크 역사로 보면 Struts 로 비유할 수 있지 않을까 싶다. 




2세대로 넘어오게 되면 Model을 DOM 에 반영하는 방식은 자동화 된다. 여기에 대표적인 프레임워크가 Ember 와 Angular v1 이다. 이때 부터 Single Page Application (SPA) 개발이라는 용어가 나오게 된다. URI 변경에 대한 대응으로 Routing  개념이 나오고, Data Projection후 원하는 일부 DOM을 변경하는 역할이 프레임워크로 넘어갔고, 웹 개발자는 좀 더 애플리케이션 비즈니스 로직에 집중토록 만들었다. Java 프레임워크로 비유하자면 Struts와 Spring Framework 초기버전의 중간 지대 정도 쯤이라 생각한다.  이때부터 Frontend (프론트앤드)라는 직군이 웹 개발자와 분리되기 시작한 지점이라 생각한다. 이에 대한 자세한 설명은 태곤님이 작성한 "[번역] 프론트엔드 개발자는 왜 구하기 어렵나요?"를 참조하자. 2011년을 기점으로 2013년 웹 애플리케이션 프레임워크가 정착을 해가는 시기였고, 현재는 대부분의 스타트업이나 중견기업에서 2세대 웹 애플리케이션 프레임워크를 선택할 경우 프론트엔드 개발자와 백앤드 개발자를 구분하여 팀을 구성하고 있는 추세이다.





3세대는 2세대의 과도기를 거쳐 2세대의 장점을 흡수 하면서 성능상의 이슈를 해결하고, 점점 복잡해 지고있는 웹 애플리케이션을 보다 직관적이고 쉽게 개발할 수 있게 노력하고 있다. 대표적인 프레임워크로는 Facebook의 React와 Google의 Angular v2 (이하 Angular)이다. Angular는 Component기반 개발 방식으로 표준인 Web Components를 지원하며 Typescript를 기본 언어로 채택했다. Typescript는 Type 시스템을 제공하기 때문에 개발단계에서 버그의 가능성을 쉽게 찾을 수 있도록 도와준다. React와 Angular에 대한 장단점은 손창욱님의 "React보다 Angular v2에 더 주목해야 하는 이유"를 참조하자. Java의 Spring Framework이 성숙하면서 Annotation 같은 기능이 추가되듯, Angular v2 프레임워크는 Java의 Spring 프레임워크 최신버전과 비유할 수 있다. 



Angular v1에 대한 개발 및 컨설팅을 3년 가까이 하면서 올해 초 Angular v2를 공부하고 기존 v1 코드를 v2 코드로 전환하면서 코드 베이스는 50%가량 줄었고, 반응속도는 30%가량 개선되었다. 8명 프론트앤드 개발자와 컨버전을 진행하면서 이구동성으로 말하는 것은 "코드가 직관적으로 변했다. 코드량이 현저히 줄었다. Typescript의 타입체킹으로 인해 실수를 최소화 할 수 있었다" 이다. 



Angular v2 왜 배워야 하는가?

Angular를 왜 배워야 하는가? 답하자면 안배워도 된다. 단순 홈페이지나 업무 화면이라면 쉽고 더 빨리 만들 수 있는 워드프레스나 서비스를 이용하거나 DOM 핸들링 라이브러리나 플러그인을 사용해 개발하는 편이 낫다. 하지만 솔루션의 복잡한 요구사항을 지속적으로 반영해야 하고 DOM제어가 복잡해 질 가능성이 높다면 jQuery, React 같은 라이브러리 보다는 Angular 같은 프레임워크를 선택하는 것이 좋다. 그리고 최근에는 ES2015 표준이 확정되었고 최신 브라우져에 대부분 기능이 구현되고 있다. 2세대와 3세대 Data Projection의 가장 큰 개발 방식의 차이는 ES2015의 이해에서부터 시작한다.  즉, ES2015 문법을 잘 알고 사용하면 좀 더 쉽고 간단하게 코드 베이스를 유지하면서 오류를 최소화할 수 있다. 예로 -> 펑션은 this에 대한 오류를 방지하고, Set/Map등 Collection은 Java의 Collection과 유사한다. 



Angular v2 시작하면 초기에 배워야 하는 것들이 갑자기 늘어난다. 이것은 2세대와 3세대의 개발 패턴이 바뀌었음을 시사한다. ES2015 문법은 그대로 TypeScript에 녹아 있고, Type System과 Annotation 기능이 녹아 들어 더욱 편리한 개발을 가능토록 한다. 따라서 ES2015의 Syntax와 개념을 이해해야 한다. 그리고 Typescript를 다시 공부해야 한다. 또한 요즘 인기를 누리고 있는 Reactive Programming을 표방한 대표적인 라이브러리인 RxJS를 Angular가 근간으로 사용하고 있다. 따라서 RxJS 에 대한 개념과 사용법을 익혀야 한다. 그런후 Web Components 란 무엇인지 알아야 하고, Angular 프레임워크의 아키텍쳐를 구성하는 개념인 Change Detection 동작원리, Dependency Management, Modulization 을 알아야 하고, 다음으로 주변의 Tooling System으로 SystemJS (Webpack), Gulp 등을 알아야 한다. 


이렇게 열거해 보니 참으로 배울 것이 많다. 다시 말하지만 안 배워도 된다. 하지만 자신의 근육을 한단계 업그레이드 시키기 위해 고통스러운 인내의 시간은 필요하다. 배워야 하는 기준은 두가지 정도로 이야기 해본다. 


첫째, 서비스 버전업을 위해 요구사항이 계속 증가하고 있는가?

둘째, 더 적고 직관적인 코드 베이스를 유지하면서 성능을 높이고 싶은가?


 

프론트엔드 개발자 직군이 새롭게 자리잡게된  5년기간 동안 많은 부분이 기존의 백앤드 개발 패턴과 유사해 지고 있다. 모듈 의존성 관리, 빌드 시스템, 프레임워크의 발전은 Java개발자들이 초장기 프레임워크 없이 개발하다 Struts를 만났을 때 기쁨에서 Spring을 만나 자유를 얻었지만 여전히 배워야 할 것들은 더욱 증가했음을 알것이다. 그러나 어쩌겠는가 우리는 더 게을러 지고싶다는 욕구가 있고 프레임워크가 그것을 만족시켜줄것이라는 희망을 품고 있는 한 배움과 진보는 계속될 뿐이다. 



참조


posted by 윤영식
2013. 11. 15. 04:42 My Projects/BI Dashboard

자바기반 서버 환경 구축을 위한 기반 기술 설정에 대하여 알아보자. 우선 빌드환경인 Maven과 Spring Framework을 설치하고 간단히 RESTful 호출 테스트를 해보자 



1. Eclipse 플러그인 설치 

  - Eclipse Juno를 다운로드하여 설치 및 JDK1.6 사용

  - Sublime text 사용에 익숙하다면 http://eclipsecolorthemes.org/ 플러그인을 설치후 에서 Sublime Theme으로 바꾸어 사용한다 

  - Eclipse Marketplace에서 

    + STS (Spring Tool Suite - juno 4.2)를 설치

    + Maven (Maven Integration for Eclipse - juno and newer)를 설치

    + Git 사용한다면 EGit - Git Team Provider를 설치

    + SVN 사용한다면 Subversive - SVN Team Provider 설치 (참조1, 참조2)

       > "Help/Install New Software..."에서 

       > SVN Connector - http://community.polarion.com/projects/subversive/download/eclipse/3.0/juno-site/ 통해 설치

          Mac의 HL 부분은 unselect 

       > SVN Kit 1.7.8 선택한다. 

      


  

2. Spring MVC 프로젝트 구성

  - Maven으로 Simple project를 만든다. jar 배포 프로젝트로 만듦

  - 프로퍼티에서 Project facets에서 "Dynamics Web Module"를 선택하고 "Further configuration available..."에서 webapp 설정

  - webapp를 설정하였으면 src/main 밑으로 강제 이동시킴 

    

  - 프로퍼티에서 Deployment Assembly에서 add... 하여 Maven Denpendencies... 라이브러리가 WEB-INF/lib에 포함되도록 설정

    (참조)

    


  - pom.xml 에서 <packaging>jar</packaging>에서  <packaging>war</packaging>로 바꾼다 

  - 하기 의존성 라이브러리를 추가한다 

    + Spring Framework : v3.2.0

    + JDK : v1.6

    + JUnit : v4.11

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.ysyun</groupId>

<artifactId>DashboardTest</artifactId>

<version>0.0.1-SNAPSHOT</version>

<packaging>war</packaging>


<properties>

<spring.version>3.2.0.RELEASE</spring.version>

<junit.version>4.11</junit.version>

<jdk.version>1.6</jdk.version>

</properties>


<dependencies>


<!-- Spring 3 dependencies -->

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-core</artifactId>

<version>${spring.version}</version>

</dependency>


<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-web</artifactId>

<version>${spring.version}</version>

</dependency>


<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-webmvc</artifactId>

<version>${spring.version}</version>

</dependency>


<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>${junit.version}</version>

<scope>test</scope>

</dependency>

</dependencies>

<build>

<finalName>DashboardTest</finalName>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.0</version>

<configuration>

<source>${jdk.version}</source>

<target>${jdk.version}</target>

</configuration>

</plugin>

</plugins>

</build>

</project>



3. RESTful 테스트 하기 

  - Controller 추가하기 : RESTful uri 설정

package com.lge.dashboard;


import org.springframework.stereotype.Controller;

import org.springframework.ui.ModelMap;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;


@Controller

@RequestMapping("/")

public class HelloController {

 

@RequestMapping(value="/welcome", method = RequestMethod.GET)

public String welcome(ModelMap model) {

 

model.addAttribute("message", "Maven Web Project + Spring 3 MVC - welcome()");

 

//Spring uses InternalResourceViewResolver and return back index.jsp

return "index";

}

 

@RequestMapping(value="/welcome/{name}", method = RequestMethod.GET)

public String welcomeName(@PathVariable String name, ModelMap model) {

 

model.addAttribute("message", "Maven Web Project + Spring 3 MVC - " + name);

return "index";

 

}

 

}

  - web.xml 설정 : spring dispatcher를 설정한다 

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"

id="WebApp_ID" version="3.0">

<display-name>Counter Web Application</display-name>


<servlet>

<servlet-name>mvc-dispatcher</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>


<servlet-mapping>

<servlet-name>mvc-dispatcher</servlet-name>

<url-pattern>/</url-pattern>

</servlet-mapping>


<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>

</context-param>


<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

</web-app>

  - mvc-dispathcer-servlet.xml 스프링 환경설정 

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="

        http://www.springframework.org/schema/beans     

        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

        http://www.springframework.org/schema/context 

        http://www.springframework.org/schema/context/spring-context-3.0.xsd">

 

<context:component-scan base-package="com.lge.*" />

 

<bean

class="org.springframework.web.servlet.view.InternalResourceViewResolver">

<property name="prefix">

<value>/WEB-INF/pages/</value>

</property>

<property name="suffix">

<value>.jsp</value>

</property>

</bean>

 

</beans>

  - WEB-INF/pages폴더를 만들고 index.jsp 파일 생성 

<html>

<body>

<h2>Hello World!</h2>

 

<h4>Message : ${message}</h1>

</body>

</html>

  - 전체 설정 정보 

    

  - Tomcat v7.0 설정이 되었다면 Run As 에서 "Run on Server"로 DashboardTest 컨텍스트 추가하여 Tomcat 기동

    /<contextName>/welcome/<value> 넣어서 호출하면 하기와 같이 나온다 

    

  - maven Goal에 대한 명령을 수행할 경우 

Goal은 ant의 target과 같은 개념으로, mvn의 경우 pre-defined goal을 가지고 있다.

mvn compile : 컴파일 수행

mvn package : jar 파일로 패키징

mvn test : JUnit 테스트 수행

mvn install : local repository (PC내의 디렉토리)에 해당 jar 파일을 저장 

mvn deploy  : remote repository (Nexus)에 jar 파일 저장

mvn clean : 컴파일 내용 모두 삭제

mvn build : 위의 예제는 일반적은 spring-java 코드로 build goal을 제공하지 않는다. 

(Eclipse에서 run as하면 나와서 헷갈리게 만드는데) build goal을 지원하는 프로젝트를 만들거나 또는 pom.xml안에 인위적으로 build goal을 지정해줘야 한다. 보통 clean install 등 여러 명령을 스페이스로 구분하여 파라미터를 줄 수 있다 

  - 만들어진 pom.xml 파일 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.ysyun</groupId>

<artifactId>DashboardTest</artifactId>

<version>0.0.1-SNAPSHOT</version>

<packaging>war</packaging>

<url>http://maven.apache.org</url>


<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<spring.version>3.2.0.RELEASE</spring.version>

<junit.version>4.11</junit.version>

<jdk.version>1.6</jdk.version>

</properties>


<dependencies>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-core</artifactId>

<version>${spring.version}</version>

</dependency>


<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-web</artifactId>

<version>${spring.version}</version>

</dependency>


<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-webmvc</artifactId>

<version>${spring.version}</version>

</dependency>


<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>${junit.version}</version>

<scope>test</scope>

</dependency>

</dependencies>

<build>

<finalName>DashboardTest</finalName>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.0</version>

<configuration>

<source>${jdk.version}</source>

<target>${jdk.version}</target>

</configuration>

</plugin>

</plugins>

</build>

</project>



4. Spring 에 대한 Enterprise 환경 설정 원칙 

  - Enterprise Spring Best Practices

  - Bean Post Processors를 등록하는 어노테이션

RequiredAnnotationBeanPostProcessor – (@Required)

CommonAnnotationBeanPostProcessor – (@PostConstruct, @PreDestroy, @Resource, etc.)

AutowiredAnnotationBeanPostProcessor – (@Autowired, @Value, @Inject, etc.)

PersistenceAnnotationBeanPostProcessor – (@PersistenceUnit, @PersistenceContext, etc.)

  - annotation-config 지시자 설정

<context:annotation-config/>

  - 애플리케이션 컴포넌트 scanning 지시자 설정

<context:component-scan base-package="com.gordondickens.enterprisespring" use-default-filters="false">

<context:exclude-filter 

   expression="org.springframework.stereotype.Controller"

   type="annotation"/>

</context:component-scan>

  - 스캐닝 원칙 

+ Component scanning should ONLY be configured in the bootstrap config file, not in every XML config file

+ Do NOT also include the <context:annotation-config/> directive, it is automatically included by component scan

+ Do NOT start scanning from “com” and/or “org”, as this will scan ALL sub packages in all of the project and jars for candidates!

+ Be as specific as possible with the packages

+ Do NOT cross application boundaries with component-scan

  + Create an applicationContext-services.xml for scanning services

  + Create an applicationContext-persistence.xml for persistence and entity beans

  + Create an applicationContext-webmvc.xml for persistence and entity beans

  + Create an applicationContext-webservice.xml for web service beans

  + Import these references into the applicationContext-bootstrap.xml to these elements


Why separate the discovery files into layer specific configuration?

  + Unit testing is easier as discovery of beans is more specific

  + Allows the project to be separated into multiple Jar/Wars

  + Lowers risk of widely scoped discovery issues, overscanning and beans being replaced by multiple scanners



<참조>

  - Eclipse Theme 사용방법

  - STS + myBatis + RESTful 설정 및 테스트

  - Eclipse Juno기반 Spring MVC with maven으로 만드는 과정

  - Maven Console 기반 webapp RESTful 서비스 만드는 과정

  - AngularJS + SpringMVC 샘플 프로젝트

  - Eclipse에서 Maven 개발환경 설정

  - Spring에서 Enterprise 환경 설정 원칙

posted by 윤영식
2013. 1. 11. 09:52 Languages/Java

1) Korea Spring User Group의 세미나 자료  


1. Spring MVC를 손쉽게 테스트하기 (백기선) : 동영상 , 발표 자료

2. RESTful API(including Mobile) with Spring 3.1 (윤성준) : 동영상발표 자료

3. Spring 3.1에서 Ehcache 활용전략  (김흥래) : 동영상발표 자료

4. SpringFramework in Scala (석종일) : 동영상발표 자료

5. Type-safe querying using Querydsl (김영한) : 동영상발표 자료



2) 내 관심 사항

  - 테스트하기 

  - RESTful API 만들기 

  - Ehcache 활용전략

posted by 윤영식
prev 1 next