레이블이 Development인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Development인 게시물을 표시합니다. 모든 게시물 표시

2021년 9월 15일 수요일

@Async 사용할 때 주의해야 할 것

@Async is not a silver bullet (@Async는 은 탄환이 아니다)

  • private 메서드에는 적용이 안됨 (public만)
  • self-invocation(자가 호출)해서는 안됨 (같은 클래스 내부의 메서드를 호출하는 것은 안됨)
  • 리턴값에 대해서 void나 CompletableFuture<> 여야 함
참고
  • https://jeong-pro.tistory.com/187

2021년 3월 24일 수요일

MongoDB 명령어

백업

  • mongodump --host <host> --port <port> --username <username> --password <password> --db <database> --out <dirname>
복구
  • mongorestore --host <host> --port <port> --username <username>  --password <password> --db <database> <dirname>

2021년 1월 28일 목요일

JWT Claim Set

- iss: 토큰을 발급한 발급자 (issuer)
- sub: Claim의 주제(Subject)로 토큰이 갖는 문맥을 의미함
- aud: 이 토큰을 사용할 수신자(Audience)
- exp: 만료시간(Expiration Time)
- nbf: Not Before의 의미로 이 시간 이전에는 토큰을 처리하지 않아야 함을 의미함
- iat: 토큰이 발급된 시간(Issued At)
- jti: JWT ID로 코튼에 대한 식별자

2021년 1월 17일 일요일

[Spring Boot] Spring Boot 시작하기

Spring Boot 기초


1. Spring Boot?
- 스프링 프레임워크를 사용하는 프로젝트를 쉽게 설정할 수 있도록 해주는 서브 프로젝트


2. Spring Boot의 특징

- 단독으로 스프링 애플리케이션을 생성

- Tomcat, Jetty, Undertow 를 내장

- 빌드 구성을 단순화하기 위해 'starter' 종속성 제공

- 스프링과 3th party 라이브러리를 가능한 자동적으로 설정

- 상용화에 필요한 metrics, health checks, externalized configuration 같은 기능 제공

- XML 설정을 생성하지 않고 요구하지 않음


Spring Boot 시작하기


1. Spring Initializr 로 Spring Boot 프로젝트 생성


1.1. Generator

- Spring Initializr 사이트 접속 ( https://start.spring.io/ )

  ( 2021년 1월 설정 화면 )

- Project, Language, Spring Boot, Metadata등을 설정함
- Generate를 클릭함( 프로젝트 파일이 압축되어 다운로드됨 )

1.2. 프로젝트 Import
- 압축 해제 후 Eclipse나 IntelliJ를 통해 프로젝트를 Import (여기서는 IntelliJ를 사용)



- ( IntelliJ Idea 2020.3.1버전은 Gradle 프로젝트를 자동으로 인식해서 로드하는 것 같음 )

2. Gradle 설정

2.1. spring-boot-starter-web
- Spring MVC나 RESTful 같은 Web과 관련된 의존성들

2.2. spring-boot-starter-test
- Junit, Hamcrest, Mockito를 포함하는 테스트관련 의존성들

plugins {
	// 스프링부트 의존성 관리 및 애플리케이션 패키징을 위한 Gradle 플러그인
	id "org.springframework.boot" version "2.4.1"
	// 스프링부트 버전에 대해 의존성을 자동으로 가져옴
	id "io.spring.dependency-management" version "1.0.10.RELEASE"
	id "java"
}

group = "com.chakans"
version = "0.0.1-SNAPSHOT"
// 자바 버전 선언
sourceCompatibility = "11"

repositories {
	mavenCentral()
}
// 프로젝트와 의존 관계에 있는 라이브러리 정의
dependencies {
	implementation "org.springframework.boot:spring-boot-starter"
	implementation "org.springframework.boot:spring-boot-starter-web"
	testImplementation ("org.springframework.boot:spring-boot-starter-test") {
		exclude group: "org.junit.vintage", module: "junit-vintage-engine"
	}
}

test {
	useJUnitPlatform()
}

3. Application.java

3.1. @SpringBootApplication
- @EnableAutoConfiguration, @ComponentScan, @Configuration을 하나로 묶은 것이라 볼 수 있음
- 해당 어노테이션이 있는 package위치를 기준으로 ComponentScan을 수행함 ( 기준 package 위치 변경 가능 )
main 메소드 위치하는 곳임

4. index.html
- resources > static 하위에 index.html 파일 생성

- 서버 구동 후 http://localhost:8080/index.html로 확인 가능함

5. 서버 구동

2020년 11월 25일 수요일

TINC(Peer-to-Peer VPN) 설정 방법 in Ubuntu 18.04

소개

TINC는 터널링 및 암호화를 사용하여 인터넷상의 호스트간에 보안 개인 네트워크를 만드는 VPN데몬

준비사항

2대의 서버, Ubuntu 18.04

구성

A 서버 -------------------------------------- B 서버

설치

1. 각 서버에 Tinc 설치
$ sudo apt update && sudo apt install tinc

2. VPN 작업 디렉토리 생성
$ sudo mkdir -p /etc/tinc/sample/hosts

3. 설정 파일들 만들기
- 각 서버에 "tinc.conf" 파일 생성
$ sudo vim /etc/tinc/sample/tinc.conf

-- A 서버
-------------------------
 Name = tinc_a
 Device = /dev/net/tun
 AddressFamily = ipv4
 Interface = tun0
-------------------------

-- B 서버
-------------------------
Name = tinc_b Device = /dev/net/tun AddressFamily = ipv4 Interface = tun0
 ConnectTo = tinc_a
-------------------------
  • Name - VPN에 사용될 고유한 이름 
  • Device - 가상 네트워크를 위한 장치 정의
  • AddressFamily - IP 주소 형식
  • Interface - 네트워크 인터페이스명
  • ConnectTo - 연결하려는 tinc 데몬명
- 각 서버에 hosts 설정 파일 생성
-- A 서버
$ sudo vim /etc/tinc/sample/hosts/tinc_a
------------------------- Address = 172.17.0.2 Subnet = 100.100.100.100 -------------------------
-- B 서버
$ sudo vim /etc/tinc/sample/hosts/tinc_b

-------------------------
Address = 172.17.0.3
Subnet = 100.100.100.200
-------------------------

- 각 서버의 vpn hosts 설정 파일에 public key 추가
$ sudo tincd -n sample -K 4096

VPN 제어 스크립트 생성

-- A 서버

$ sudo vim /etc/tinc/sample/tinc-up

-------------------------
#!/bin/sh ip link set $INTERFACE up ip addr add 100.100.100.100 dev $INTERFACE ip route add 100.100.100.0/24 dev $INTERFACE
-------------------------
$ sudo vim /etc/tinc/sample/tinc-down
-------------------------
#!/bin/sh ip route del 100.100.100.0/24 dev $INTERFACE ip addr del 100.100.100.100 dev $INTERFACE ip link set $INTERFACE down
-------------------------

-- B 서버

$ sudo vim /etc/tinc/sample/tinc-up

-------------------------
#!/bin/sh ip link set $INTERFACE up ip addr add 100.100.100.200 dev $INTERFACE ip route add 100.100.100.0/24 dev $INTERFACE
-------------------------
$ sudo vim /etc/tinc/sample/tinc-down
-------------------------
#!/bin/sh ip route del 100.100.100.0/24 dev $INTERFACE ip addr del 100.100.100.200 dev $INTERFACE ip link set $INTERFACE down
-------------------------
- 실행 권한 변경
$ sudo chmod -v +x /etc/tinc/sample/tinc-{up,down}

서비스 등록

$ sudo vim /etc/systemd/system/tinc.service

-------------------------
[Unit]
Description=Tinc net sample
After=network.target

[Service]
Type=simple
WorkingDirectory=/etc/tinc/sample
ExecStart=/sbin/tincd -n sample -D -d3
ExecReload=/sbin/tincd -n sample -kHUP
TimeoutStopSec=5
Restart=always
RestartSec=60

[Install]
WantedBy=multi-user.target
-------------------------

$ sudo systemctl enable tinc.service
$ sudo systemctl status tinc.service

Host 파일 교환

-- A 서버

$ scp /etc/tinc/sample/hosts/tinc_a user@172.17.0.2:/tmp/
$ ssh -t user@172.17.0.2 sudo mv -v /tmp/tinc_a /etc/tinc/sample/hosts/

-- B 서버

$ scp /etc/tinc/sample/hosts/tinc_b user@172.17.0.3:/tmp/
$ ssh -t user@172.17.0.3 sudo mv -v /tmp/tinc_b /etc/tinc/sample/hosts/

테스트

-- A 서버 & B 서버

$ sudo tincd -n sample -D -d3
$ sudo ip a
$ ping 100.100.100.***

참고

  • https://www.linode.com/docs/guides/how-to-set-up-tinc-peer-to-peer-vpn/

2018년 3월 8일 목요일

RESTful API Design (검색API)

Global search
  • /search?q=word
Scoped search
  • /products/search?q=word

참고
  • https://apigee.com/about/blog/technology/restful-api-design-tips-search

2018년 1월 23일 화요일

Config Server

Config Server 목적

설정 파일을 환경별(local, dev,stage, real, 등)로 중앙에서 관리하기 위한 목적임

Config Server 만들기

  1. Spring initializr(http://start.spring.io) 접속
  2. "Search for dependencies"에 Config Server 입력
  3. "Selected Dependencies"에 넣기
  4. "Generate Project" 클릭
  5. "DemoApplication.java"에 @EnableConfigServer 어노테이션 붙임

Config파일 repository 설정

  1.  "application.properties"파일에 아래 설정파일위치정보 입력
    ===============================
    server.port=8888
    spring.cloud.config.server.git.uri=http://config-git-repository-address.git
    ===============================
  2. 설정파일 git repository에 push (파일명 구조는 변경 가능)
    {프로젝트명}-{환경별 명칭}.{yml|properties}

Config server 패키징

$ ./mvnw clean package 

Config server 실행

$ java -jar demo-0.0.1-SNAPSHOT.jar

브라우저에서 동작 확인

http://localhost:8888/{프로젝트명}/{환경별 명칭}

참고

  • http://blog.leekyoungil.com/?p=352

2017년 12월 11일 월요일

AngularJS & Angular의 url에서 hashtag(#) 제거

  • AngularJS인 경우 설정 (** html에 <base href="/"> 추가)

1
2
3
angular.config(['$locationProvider'], function ($locationProvider) {
    $locationProvider.html5Mode(true);
});
  • Angular인 경우 설정 (** html에 <base href="/"> 추가)

1
2
3
4
5
6
@NgModule({
    imports: [
        RouterModule.forRoot(LAYOUT_ROUTES, { useHash: false })
    ],
    ...
})
  • UrlRewriteFilter 설정 (Spring Framework, Gradle)

    • 의존성 설정
compile("org.tuckey:urlrewritefilter:${urlrewritefilter_version}")
    • Custom UrlRewriteFilter 생성 (url-rewrite.xml 위치를 변경을 위해)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tuckey.web.filters.urlrewrite.Conf;
import org.tuckey.web.filters.urlrewrite.utils.StringUtils;

import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.io.InputStream;
import java.net.URL;

/**
 * Subclass of {@link org.tuckey.web.filters.urlrewrite.UrlRewriteFilter}
 * that overrides the configuration file loading mechanism.
 */
public class UrlRewriteFilter extends org.tuckey.web.filters.urlrewrite.UrlRewriteFilter {

    private final Logger log = LoggerFactory.getLogger(UrlRewriteFilter.class);

    @Override
    protected void loadUrlRewriter(FilterConfig filterConfig) throws ServletException {
        ServletContext context = filterConfig.getServletContext();
        String confPath = filterConfig.getInitParameter("confPath");
        boolean modRewriteStyleConf = getModRewriteStyleConf(filterConfig.getInitParameter("modRewriteConf"));
        try {
            final InputStream inputStream = getClass().getClassLoader().getResourceAsStream(confPath);
            final URL confUrl = getClass().getClassLoader().getResource(confPath);

            if (inputStream == null) {
                log.error("unable to find urlrewrite conf file at " + confPath);
                // set the writer back to null
                if (isLoaded()) {
                    log.error("unloading existing conf");
                    destroyUrlRewriter();
                }

            } else {
                Conf conf = new Conf(context, inputStream, confPath, confUrl.toString(), modRewriteStyleConf);
                checkConf(conf);
            }
        } catch (Throwable e) {
            log.error("unloading urlrewrite conf file at " + confPath, e);
            throw new ServletException(e);
        }
    }

    private boolean getModRewriteStyleConf(String modRewriteConf) {
        boolean modRewriteStyleConf = false;
        if (!StringUtils.isBlank(modRewriteConf)) {
            modRewriteStyleConf = "true".equals(StringUtils.trim(modRewriteConf).toLowerCase());
        }
        return modRewriteStyleConf;
    }
}
    • Servlet Filter에 넣기
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private void initUrlRewriteFilter(ServletContext servletContext, EnumSet<DispatcherType> disps) {
    FilterRegistration.Dynamic urlRewriteFilter =
        servletContext.addFilter("urlRewriteFilter", new UrlRewriteFilter());

    urlRewriteFilter.setInitParameter("confPath", "url-rewrite.xml");
    urlRewriteFilter.setInitParameter("confReloadLastCheck", "-1");
    urlRewriteFilter.setInitParameter("logLevel", "WARM");

    urlRewriteFilter.addMappingForUrlPatterns(disps, true, "/*");
    urlRewriteFilter.setAsyncSupported(true);
}
    • url-rewrite.xml 작성 (위치: src/main/resources)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN" "https://www.tuckey.org/res/dtds/urlrewrite4.0.dtd">

<urlrewrite >
    <!-- default -->
    <rule match-type="regex">
        <condition type="request-uri" operator="notequal">
            ^.*\.(html?|htc|js|css|xml|map|json|ico|bmp|gif|jpe?g|png|svg|eot|woff|woff2|ttf|pdf|swf|txt)$
        </condition>
        <from>^/(.*)$</from>
        <to last="true">/index.html</to>
    </rule>
</urlrewrite>

참고

  • https://github.com/spring-io/sagan/search?utf8=%E2%9C%93&q=urlrewrite.xml&type=


2017년 12월 7일 목요일

Nginx로 Reverse-Proxy 구성

Reverse-Proxy란?
  • 사용자의 요청을 받아서 반대편 네트워크에 있는 웹 서버에 전달하는 역할을 함
  • 단순 요청 전달만 함
  • 로드밸런서로의 역할을 할 수 있음
Nginx로 Reverse-Proxy 설정
그림1) Nginx로 Reverse-Proxy 환경 구성도
  • 정적 리버스 프락시 서버 구성
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# cat /etc/nginx/sites-available/default
upstream sample_proxy {
    server 192.168.56.2:8080;
    server 192.168.56.3:8080;
}
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/html;

    index index.html index.htm index.nginx-debian.html;

    server_name _;

    location / {
        proxy_pass http://sample_proxy;
    }
}
    • upstream영역에 프락시 대상 호스트의 목록 입력
    • upstream은 proxy할 타겟 서버를 설정을 위해 사용
    • location / 에 대한 모든 요청에 대해서, sample_proxy로 중계한다는 의미
  • 로드 밸런싱 메서드
    • 라운드로빈(Round-robin)은 기본적인  메서드로 모든 서버에 동등하게 요청
      1
      2
      3
      4
      upstream sample_proxy {
          server 192.168.56.2:8080;
          server 192.168.56.3:8080;
      }
      
    • least_conn은 연결이 가장 작은 서버로 요청
      1
      2
      3
      4
      5
      6
      upstream sample_proxy {
          least_conn;
      
          server 192.168.56.2:8080;
          server 192.168.56.3:8080;
      }
      
    • ip_hash는 클라이언트 IP주소를 기준으로 요청을 분배한다. IP주소가 같다면, 동일한 서버로 요청
      1
      2
      3
      4
      5
      6
      upstream sample_proxy {
          ip_hash; 
      
          server 192.168.56.2:8080;
          server 192.168.56.3:8080;
      }
      
    • hash는 유저가 정의한 key나 변수 혹은 이들의 조합을 해시해서 분산
      1
      2
      3
      4
      5
      6
      upstream sample_proxy {
          hash $request_uri consistent;
      
          server 192.168.56.2:8080;
          server 192.168.56.3:8080;
      }
      
    • least_time메서드는 NginX Plus에서 지원, 평균 레이턴시와 연결을 기준으로 검사해서 로드가 적은 서버로 요청
      1
      2
      3
      4
      5
      6
      upstream sample_proxy {
          least_time header; 
      
          server 192.168.56.2:8080;
          server 192.168.56.3:8080;
      }
참고
  • https://www.joinc.co.kr/w/man/12/proxy

2017년 9월 28일 목요일

OffsetDateTime, ZonedDateTime, Instant

The javadocs say this:

  • "OffsetDateTime, ZonedDateTime and Instant all store an instant on the time-line to nanosecond precision. Instant is the simplest, simply representing the instant. OffsetDateTime adds to the instant the offset from UTC/Greenwich, which allows the local date-time to be obtained. ZonedDateTime adds full time-zone rules."

2017년 9월 20일 수요일

Tomcat 포트(80->8080, 443->8443) 라우팅 설정

iptables 설정
  • # iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
  • # iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8443
  • # netstat -ntl or iptables -t nat -L
  • # iptables restart
server.xml 변경
  • <Connector port="8080" proxyPort="80" protocol="HTTP/1.1"
               connectionTimeout="20000"
               enableLookups="false"
               redirectPort="443"
               URIEncoding="UTF-8" />
  • <Connector protocol="org.apache.coyote.http11.Http11NioProtocol"
           keyAlias="tomcat"
           port="8443" proxyPort="443" maxThreads="200"
           scheme="https" secure="true" SSLEnabled="true"
           keystoreFile="conf/keystore파일" keystorePass="키스토어비밀번호"
           clientAuth="false" sslProtocol="TLS" />
참고
  • http://devzeroty.tistory.com/entry/Tomcat-80-443%ED%8F%AC%ED%8A%B8-NonRoot-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C-%EB%9D%84%EC%9A%B0%EA%B8%B0

2017년 5월 23일 화요일

개인서명 SSL 인증서 생성


  • 준비
    • openssl
  • 개인키 생성
    • $ openssl genrsa -des3 -out server.key 2048
  • 인증요청서 생성
    • $ openssl req -new -key server.key -out server.csr
      • Country Name (2 letter code) [XX]: KR
      • State or Province Name (full name) []: Seoul
      • Locality Name (eg, city) [Default City]:
      • Organization Name (eg, company) [Default Company Ltd]: Company
      • Organizational Unit Name (eg, section) []:
      • Common Name (eg, your name or your server's hostname) []: company.com
      • Email Address []:
  • 개인키에서 패스워드 제거
    • $ cp server.key server.key.origin
    • $ openssl rsa -in server.key.origin -out server.key
  • 인증서 생성
    • $ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
  • 참고
    • https://zetawiki.com/wiki/%EB%A6%AC%EB%88%85%EC%8A%A4_%EA%B0%9C%EC%9D%B8%EC%84%9C%EB%AA%85_SSL_%EC%9D%B8%EC%A6%9D%EC%84%9C_%EC%83%9D%EC%84%B1

2016년 12월 5일 월요일

멀티 스레딩 첫번째

멀티 스레딩?
  • 한 프로세스를 여러 수행단위(스레드)로 나눠 처리하는 것을 말함
장점
  • 사용자에 대한 응답성이 향상됨
  • 자원을 공유하고 코드 공유의 이점이 있음
  • 자신이 속한 프로세스의 자원들을 공유하기 때문에 경제적임
  • 멀티 프로세서인 경우에 각 스레드가 병렬로 수행할 수 있음
단점
  • 멀티 스레드는 캐시나 TLB(변환 색인 버터)와 같은 하드웨어 리소스를 공유할 때 서로 간섭할 수 있음
  • 하나의 스레드만 실행 중인 경우 실행 시간이 개선되지 보단 오히려 지연될 수 있음
  • 멀티 스레드의 수행이 예측 불가함
  • 실행 순서가 보장되지 않음
  • 테스트 및 디버깅이 어려움
프로그래밍시 주의할 점
  • 컨텍스트 스위칭에 상당한 비용이 소모되기 때문에 너무 많은 스레드는 성능이 더 떨어짐
참고
  • https://ko.wikipedia.org/wiki/%EB%A9%80%ED%8B%B0%EC%8A%A4%EB%A0%88%EB%94%A9
  • http://codedragon.tistory.com/3525

2016년 11월 25일 금요일

Load Balancing 설명

Load Balancing : 웹 어플리케이션의 부하를 분산하는 방식임
  • Server Side Load Balancing
    • Switch(L4, L7)를 사용함
    • HA proxy - Open Source Software Loadbalancer임
    • 문제점
      • Switch가 처리할 수 있는 요청수에 한계가 있음
      • Switch장비를 설치하거나 설정이 어렵고 비싼 장비임 (HA proxy 역시 서버가 필요함)
      • Switch에 장애가 생기면, 접속 문제가 발생함 (이중화하여 Active – Standby로 동작하도록 세팅함)
그림1) Server Side Load Balancing
  • Client Side Load Balancing
    • Server Side Load Balancing의 문제점을 해결하고자 나옴 개념임
    • Switch를 거치지 않고 바로 서버로 요청하는 방식임
    • 즉, Switch에서 하는 분산 역할을 클라이언트 소프트웨어에서 처리하자는 것임
    • 자바에선 Ribbon을 이용함
      • 각 서버의 host정보를 일일이 설정이 필요함
      • Eureka를 함께 사용하면 따로 설정을 하지 않아도 됨
그림2) Client Side Load Balancing
참고
  • http://blog.leekyoungil.com/?p=259

2016년 10월 21일 금요일

Public, Protected, Private 차이 설명

  • 접근 제어자
구분제어자설명
접근권한public모든 클래스에서 접근이 가능함
protected동일 패키지에 속하는 클래스와 하위 클래스 관계의 클래스에 의해 접근이 가능함
private클래스 내에서만 접근이 가능함

  • 접근 권한
종류클래스하위 클래스동일 클래스모든 클래스
(default)OXOX
publicOOOO
protectedOOOX
privateOXXX
  • 출처
    • http://hyeonstorage.tistory.com/176

2016년 4월 5일 화요일

Thead Safe란?

Thead Safe

  • 멀티 스레드 프로그래밍에서 일반적으로 어떤 함수나 변수, 혹은 객체가 여러 스레드로부터 동시에 접근이 이루어져도 프로그램의 실행에 문제가 없음을 뜻함.
  • 즉, 하나의 함수가 한 스레드로부터 호출되어 실행 중일 때, 다른 스레드가 그 함수를 호출하여 동시에 함께 실행되더라도 각 스레드에서의 함수의 수행 결과가 올바로 나오는 것으로 정의함
참고
  • https://ko.wikipedia.org/wiki/%EC%8A%A4%EB%A0%88%EB%93%9C_%EC%95%88%EC%A0%84

2016년 3월 29일 화요일

Grunt - The JavaScript Task Runner

Grunt는 무엇?
  • Javascript를 사용한 Task Runner
  • 반복적인 작업을 스크립트를 통해서 수행하는 자동화 도구
  • 여러 가지 JS 및 CSS 파일을 합치고 최소화, 배포 폴더로 복사하는 과정들을 스크립트를 작성하여 자동화 시킴
  • Grunt와 Grunt 플러그인들은 npm(Node.js Package Manager)을 통해 설치되고 관리
Grunt의 장점
  • Javascript/Node.js 기반의 빌드 툴. Javascript 및 Node.js는 활발하게 유지 보수되며 성장하고 있서 안정성 및 전망에서 많은 기대를 할 수 있음.
  • Javascript 어플리케이션에서 사용되는 다양한 기능들(jshint, minify, uglify, less)을 안정적인 플러그인으로 제공
  • 작성 및 유지보수가 쉬운 빌드 스크립트를 제공
  • 커뮤니티가 크고 활발
설치
  1. nodejs 설치 ( https://nodejs.org/ )
  2. nodejs관련 환경변수 추가
    • PATH -> "nodejs설치 경로"추가 ( C:\Program Files\nodejs\ )
    • NODE_PATH -> "prefix 값 + \node_modules" 추가 ( C:\Users\...\AppData\Roaming\npm\node_modules )
  3. Grunt설치 ( > npm install -g grunt-cli 실행 )

패키징 전 준비해야 할 파일
  • Gruntfile.js : 설정을 위해 사용되거나 Task들을 정의하고 Grunt플러그인들을 읽어들임
  • package.json : 필요한 Grunt플러그인들을 정의하여 "npm install"시 읽어들여 설치함
참고
  • http://xinics.tistory.com/99

2016년 3월 11일 금요일

메모리 캐시 ( Memcached, Redis )

1. Memcached


분산 메모리 캐싱 시스템.
DB에 저장된 데이터를 메모리에 적재하여 응답속도를 높여 동적 웹 어플리케이션의 성능을 높이기 위한 용도로 사용하기도 함.
데이터를 작은 단위의 key-value형태로 저장.

맴캐시드를 사용하지 않았을 때는 분리되어 있는 메모리에 대해 각 서버에 할당된 캐시 크기만큼만 사용하기에 효율적이지 않음.
맴캐시드를 사용하면, 결합되어 각 서버는 전체 캐시 크기만큼 사용할 수 있음. 즉, 메모리 운용이 효율적이라는 것임.






2. Redis

in-memory data structure store.
데이터베이스, 캐시, 메시지 브로커로 사용할 수 있음.
key-value형태로 저장.
string, hasheds, lists, sets, sorted sets과 같은 데이터 구조를 지원.
Global Cache 방식


* Global Cache방식은 네트워크 트래픽이 발생하기 때문에 Java Heap 영역에서 조회되는 Local Cache가 성능이 낫지만 WAS 인스턴스가 증가하게 되는 경우, Cache에 저장되는 테이터 크기가 커지기 때문에 Redis방식 유리


3. 참고
http://blog.naver.com/windfalcon1/220400294140
http://ojava.tistory.com/70