반응형

스프링부트(springboot)로 카산드라 데이터 모니터링 하는 프로젝트 작업 중  java.lang.NoClassDefFoundError:org/springframework/data/cassandra/mapping/UserTypeResolver 과 같은 에러가 발생해 한참을 해맸다.



Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/data/cassandra/mapping/UserTypeResolver

at java.lang.Class.getDeclaredMethods0(Native Method)

at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)

.

.

생략

Caused by: java.lang.ClassNotFoundException: org.springframework.data.cassandra.mapping.UserTypeResolver

at java.net.URLClassLoader.findClass(URLClassLoader.java:381)

at java.lang.ClassLoader.loadClass(ClassLoader.java:424)

at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)

at java.lang.ClassLoader.loadClass(ClassLoader.java:357)


일단 해결은 pom.xml 의 <parent>부분의 버전을 수정하여 해결하였다.

<parent>

         <groupId>org.springframework.boot</groupId>

   <artifactId>spring-boot-starter-parent</artifactId>

      <version>1.5.6.RELEASE</version>

        <!-- <version>1.2.3.RELEASE</version> -->

              <relativePath/> <!-- lookup parent from repository -->

</parent>


버전의 1.5.6버전을 하위 dependency에서 사용하는 스프링부트 버전과 맞춰주니 해결되었다. (1.5.6-> 1.2.3)


<properties>

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

<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

<java.version>1.8</java.version>

<spring-boot.version>1.2.3.RELEASE</spring-boot.version>

<spring-data-cassandra.version>1.2.0.RELEASE</spring-data-cassandra.version>

<spring-cql.version>1.2.0.RELEASE</spring-cql.version>

<datastax.cassandra.version>2.1.7</datastax.cassandra.version>

</properties>


버전이 맞지않으면 예상치 못한 예외가 발생한다. 디텍팅하기도 너무 힘들뿐도로 원인파악이 너무 힘들기 때문에 메이븐 설정을 다른 프로젝트 등에서 가져다 


사용 할때는 버전을 꼭 참고하여 사용하도록 하자. 무작정 사용하는 ctrl+c, ctrl+v는 재앙을 가져올지니...

반응형
반응형

최근 작업중 unix date를 파싱해야는 경우가 있어서 아무렇지 않게


String unixDate = "1498906817.357"

String[] parseDate = unixDate.split(".");

String parsedDate = Long.parseLong(parseDate[0]);


다음과 같이 썼는데 파싱된 데이터에 값이 안들어있다는...


확인해보니 split의 인자로 들어가는  .(dot)이 정규식이기 때문이었다. 

정규식에서는 .(dot)은 무작위의 한글자를 의미하므로 모든 문자가 토큰이 되기 때문에 배열에 남는게 없게 되는 것이다.

그렇기 때문에 이를 피하기 위해서는 이스케이프(\\)를 문자앞에 써줘야 한다.



String unixDate = "1498906817.357"

String[] parseDate = unixDate.split("\\.");

String parsedDate = Long.parseLong(parseDate[0]);


뭔가 split 메서드를 사용해 parsing을 했는데 값이 정상적으로 나오지 않는다면 정규식을 의심하자.



[ 참고 ]

there are 12 characters with special meanings: the backslash \, the caret ^, the dollar sign $, the period or dot ., the vertical bar or pipe symbol |, the question mark ?, the asterisk or star *, the plus sign +, the opening parenthesis (, the closing parenthesis ), and the opening square bracket [, the opening curly brace {, These special characters are often called "metacharacters".

반응형
반응형


 안녕하세요. 오늘은 프로세스와 스레드에 대해서 알아보도록 하겠습니다. 많은 분들이 실제로 프로세스와 스레드를 알고 계시면서도 막상 물어보면 대답하기 막막해하시는 경우도 많이 있고 저도 실제로 프로세스&스레드에 대해서 명확히 설명하기 힘들어 했던 경험이 있어 이번 기회에 한 번 간단히 개념적인 부분에 대해서 정리하고 넘어가려고 합니다. 이제 막 2년차에 접어드는 현업 개발자지만 요즘 느끼는 것은 새로운 기술들에 관심을 가지는 것도 중요하지만 개발을 함에 필요한 '기본적인 내용들과 지식을 좀 더 단단히 쌓아야 겠다'는 생각이 많이 들곤 합니다. 포스팅 시작하도록 하겠습니다.



[ PROCESS ]

 먼저 프로세스란 간단히 설명해서 실행중인 프로그램에 대한 인스턴스를 프로세스라고 합니다. 실제로 프로세스가 생성되게 되면 해당 프로세스는 운영체제로부터 주소공간, 파일, 메모리 등을 할당받게 됩니다. 그리고 메모리 공간은 CODE, DATA, HEAP, STACK영역으로 나뉘어지게 됩니다. 실제로 프로세스가 처리해야 될 일을 각각의 메모리 영역들 위에서 처리하게 되게 됩니다.

프로세스는 다음과 같은 독립된 메모리공간을 프로세스별로 가지게됩니다. (스레드 설명할 때 설명하겠지만 스레드는 STACK 부분만 독립적으로 가지게 됩니다.) 그렇기 때문에 특정 PROCESS가 다른 PROCESS 메모리에 직접 접근하기 힘듭니다.


[ THREAD ]

 스레드란 프로세스 안에서 동작되는 여러 실행의 흐름이라고 보시면 됩니다. 간단히 말해서 프로세스 내부에서 실제로 일을 하는 녀석들을 스레드라고 합니다. 우리 몸으로 치면 몸은 프로세스 손,발은 스레드 정도가 되지 않을까요?(단순한 제 생각) 기본적으로 하나의 프로세스가 생성되면 하나의 스레드가 같이 생성이됩니다. 이를 메인 스레드라고 부르며, 스레드를 추가로 생성하지 않는 한 모든 프로그램 코드는 메인 스레드에서 실행이 된다고 생각하시면 됩니다. 또한 프로세스는 메인 스레드 외에도 여러개의 스레드를 가질 수 있는데요. 이를 멀티스레드라고 합니다.

 스레드의 경우에도 프로세스와 같이 메모리 공간을 할당 받게 되는데요. 프로세스가 각각의 독립적인 메모리 공간을 할당받는 반면에 스레드의 경우는 Stack영역만을 독립적으로 할당 받게 됩니다. 실제로 Code, Data, Heap영역은 프로세스의 공간을 공유받아 사용하게 됩니다. 이렇듯 프로세스 내에서 생겨나는 모든 스레드의 경우 Stack이외의 영역은 프로세스의 영역을 공유받아 사용하게 되고 이러한 이유로 인해 스레드간 Context Switching(아래에 간단히 설명)이 발생했을 경우 Stack 영역의 데이터들만 switching되면 되므로 프로세스 스위칭보다 훨씬 빠르게 진행이 됩니다. 스레드의 장점으로는 시스템의 Throughput(처리량)이 향상 되며, 자원 소모가 줄어들고 스레드간의 스위칭 시간이 줄어들면서 일을 처리할 때 응답 시간이 단축되는 점이 있습니다. 반면에 여러 개의 스레드를 사용할 때는 프로세스가 가지고 있는 메모리 영역의 자원 공유의 문제가 발생할 수 있고 디버깅이 힘들다는 점이 있습니다. 마지막으로 프로세스의 메모리 영역(Data, heap)을 공유함으로써 전역 변수와 동적 할당 딘 메모리 공간을 공유하게 되고 이를 통해 쓰레드간 통신이 쉽게 가능하게 됩니다.


[ THREAD가 스택을 독립적으로 할당하는 이유 ]

 스택은 함수 호출 시 전달되는 인자, 되돌아갈 주소 값 및 함수 내에서 선언하는 변수 등을 저장하기 위해 사용되는 메모리 공간입니다. 따라서 스택 메모리 공간이 독립적이라는 것은 독립적인 함수 호출이 가능하다는 것이고, 이는 독립적인 실행흐름을 가질 수 있다는 것입니다. 결과적으로 실행 흐름의 추가를 위한 최소 조건이 독립된 스택을 제공하는 것이라고 볼 수 있습니다.


[ Context  Switching 이란? ]

 프로세스를 이것저것 우선 순위에 따라 변경하기 위해서는 실제로 작업에 사용되는 프로세스 데이터를 레지스터와 메모리 사이를 왕복하며 값을 복사해야 합니다. 보통 cpu에 의해 프로세스가 일을 처리하게 되는데 스케줄링 방식에 따라 특정 프로세스가 일을 진행하고 있다가 다른 프로세스에게 cpu사용권을 넘겨주게 될 때 어디까지 작업을 했고 다음부터는 어디서부터 작업을 해야하는지에 대한 정보를 보관할 수 있는 곳이 필요하고 이러한 정보들을 프로세스에 맞게 변경해주고 처리하는 것을 말합니다. 실제로 CPU는 동시에 한 개씩만 스레드를 실행시킬 수 있는데 스레드가 여러개가 생성되게 되면 CPU는 각각의 스레드를 번갈아가며 실항하게 되는데, 이 때 이전 스레드의 문맥 정보(레지스터 값, 실행중인 스택 정보 등)을 백업받고 백업 받아놓았던 다음 스레드의 문맥정보를 로딩하는 과정을 거치게 됩니다. 이 과정을 Context Switchig이라고 합니다. 이러한 스레드가 많아질 수록 Context Switching에 많은 부하가 걸리기 때문(메모리와 레지스터 사이의 데이터 이동도I/O이다)에 잘 고려해서 사용해야 되겠습니다.  


오늘 포스팅은 여기까지 하도록 하겠습니다. 잘못된 부분이나 설명이 부족한 부분은 댓글로 남겨주시면 참고하도록 하겠습니다. 감사합니다.




반응형
반응형

 


 [ REST API 제대로 알고 사용하기 ]

 어느 날 뜬금없이 대학교 친구에게 전화가 왔습니다. 그러더니 ‘야, REST API가 정확히 뭐 어떤 거야?’ 하는 질문에 가슴에 비수가 날아와 꽂힌 듯한 느낌을 받았습니다 . 며칠 전 카톡으로 요즘 보통 웹서비스들은 ‘REST API형태로 서비스를 제공한다’고 아는 척을 조금 했던 기억이 머릿속을 빠르게 스쳐 지나갔고 그 순간 대충 얼버무리며 ‘아, 그거 REST하게 클라이언트랑 서버간에 데이터를 주고 받는 방식'을 말한다며 얼렁뚱땅 마무리 지었던 기억이 납니다.  실제로 REST API의 서비스를 직접 개발도 해보고 사용도 해봤는데도 막상 설명을 하자니 어려움을 겪었던 적이 있으셨을텐데요. 그래서 이번에 REST API에 대해 정리하게 되었습니다. 기본적인 REST API에 대한 내용 외에도 REST API를 설계하실 때 참고해야 할 몇 가지 TIP들에 대해 공유해보도록 하겠습니다. 


1. REST API의 탄생

   REST는 Representational State Transfer라는 용어의 약자로서 2000년도에 로이 필딩 (Roy Fielding)의 박사학위 논문에서 최초로 소개되었습니다. 로이 필딩은 HTTP의 주요 저자 중 한사람으로 그 당시 웹(HTTP) 설계의 우수성에 비해 제대로 사용되어지지 못하는 모습에 안타까워하며 웹의 장점을 최대한 활용할 수 있는 아키텍쳐로써 REST를 발표했다고 합니다.


2. REST 구성

쉽게 말해 REST API는 다음의 구성으로 이루어져있습니다. 자세한 내용은 밑에서 설명하도록 하겠습니다.

자원(RESOURCE) - URI

행위(Verb) - HTTP METHOD

표현(Representations)


3. REST 의 특징

1) Uniform (유니폼 인터페이스) 

: Uniform Interface는 URI로 지정한 리소스에 대한 조작을 통일되고 한정적인 인터페이스로 수행하는 아키텍처 스타일을 말합니다.


2) Stateless (무상태성) 

: REST는 무상태성 성격을 갖는다. 다시 말해 작업을 위한 상태정보를 따로 저장하고 관리하지 않는다. 세션 정보나 쿠키정보를 별도로 저장하고 관리하지 않기 때문에 API 서버는 들어오는 요청만을 단순히 처리하면 된다. 때문에 서비스의 자유도가 높아지고 서버에서 불필요한 정보를 관리하지 않음으로써 구현이 단순해진다.


3) Cacheable (캐시 가능) 

: REST의 가장 큰 특징 중 하나는 HTTP라는 기존 웹표준을 그대로 사용하기 때문에, 웹에서 사용하는 기존 인프라를 그대로 활용이 가능하다. 따라서 HTTP가 가진 캐싱 기능이 적용가능하다. HTTP 프로토콜 표준에서 사용하는 Last-Modifyed태그나 E-Tag를 이용하면 캐싱 구현이 가능하다.


4) Self-descriptiveness (자체 표현 구조) 

: REST의 또 다른 큰 특징 중 하나는 REST API 메시지만 보고도 이를 쉽게 이해 할 수 있는 자체 표현 구조로 되어 있다는 것이다.


5) Client - Server 구조 

: REST 서버는 API 제공, 클라이언트는 사용자 인증이나 컨텍스트(세션, 로그인 정보)등을 직접 관리하는 구조로  각각의 역할이 확실히 구분되기 때문에 클라이언트와 서버에서 개발해야 할 내용이 명확해지고 서로간 의존성이 줄어들게 된다.


6) 계층형 구조 

: REST 서버는 다중 계층으로 구성될 수 있으며 보안, 로드 밸런싱, 암호화 계층을 추가해 구조상의 유연성을 둘 수 있고 PROXY, 게이트웨이 같은 네트워크 기반의 중간매체를 사용할 수 있게 한다.



4. REST API 디자인 가이드

! REST API 설계시 가장 중요한 항목은 다음의 2가지로 요약할 수 있습니다.

첫 번째, URI는 정보의 자원을 표현해야 한다.

두 번째, 자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE)로 표현한다.

다른 건 다 잊어도 위 내용은 꼭 기억하시기 바랍니다.


4-1  REST API 중심 규칙

1) URI는 정보의 자원을 표현해야한다. (리소스명은 동사보다는 명사를 사용)

GET /members/delete/1

 

위와 같은 방식은 REST를 제대로 적용하지 않은 URI입니다. URI는 자원을 표현하는데 중점을 두어야 합니다. delete와 같은 행위에 대한 표현이 들어가서는 안됩니다.


2) 자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE 등)로 표현

 위의 잘못 된 URI를 HTTP Method를 통해 수정해 보면

DELETE /members/1

로 수정할 수 있겠습니다. 회원정보를 가져올 때는 GET, 회원 추가시의 행위를 표현하고자 할 때는 POST METHOD를 사용하여 표현합니다.

 

회원정보를 가져오는 URI

GET /members/show/1     (x)

GET /members/1          (o) 

 

회원을 추가할 때

GET /members/insert/2 (x)  - GET 메서드는 리소스 생성에 맞지 않는다.

POST /members/2       (o)

 

**[참고]HTTP METHOD의 알맞은 역할 **

POST, GET, PUT, DELETE 이 4가지의 Method를 가지고 CRUD를 할 수 있다. 

| POST | POST를 통해 해당 URI를 요청하면 리소스를 생성합니다. |

| GET | GET를 통해 해당 리소스를 조회 합니다. 리소스를 조회하고 해당 도큐먼트에 대한 자세한 정보를 가져온다. |

| PUT | PUT를 통해 해당 리소스를 수정 합니다. |

| DELETE | DELETE를 통해 리소스를 삭제합니다. |

다음과 같은 식으로 URI는 자원을 표현하는데에 집중하고 행위에 대한 정의는 HTTP METHOD를 통해 하는 것이 REST한 API를 설게하는 중심 규칙입니다.



4-2 URI 설계시 주의할 점

1) 슬래시 구분자(/)는 계층 관계를 나타내는 데 사용

EX )  * http://restapi.example.com/houses/apartments

         * http://restapi.example.com/animals/mammals/whales


2) URI 마지막 문자로 슬래시(/)를 포함하지 않는다 

: URI에 포함되는 모든 글자는 리소스의 유일한 식별자로 사용되어야 하며 URI가 다르다는 것은 리소스가 다르다는 것이고, 역으로 리소스가 다르면 URI도 달라저여한다. REST API는 분명한 URI를 만들어 통신을 해야하기 때문에 혼동을 주지 않도록 URI 경로의 마지막에는 /를 사용하지 않는다.

http://restapi.example.com/houses/apartments/ (X)

http://restapi.example.com/houses/apartments  (0)


3) 하이픈(-)은 URI 가독성을 높이는데 사용 

: URI를 쉽게 읽고 해석하기 위해, 불가피하게 긴 URI경로를 사용하게 된다면 하이픈을 사용해 가독성을 높일 수 있다.


4) 밑줄(_)은 URI에 사용하지 않는다. 

: 글꼴에 따라 다르긴 하지만 밑줄은 보기 어렵거나 밑줄 때문에 문자가 가려지기도 한다. 이런 문제를 피하기 위해 밑줄 대신 하이픈을 사용하자(가독성)


5) URI 경로에는 소문자가 적합하다. 

: URI 경로에 대문자 사용은 피하도록 하자. 대소문자에 따라 다른 리소스로 인식하게 된다. RFC 3986(URI 문법 형식)은 URI 스키마와 호스트를 제외하고는 대소문자를 구별하도록 규정하기 때문이지요.

(*RFC 3986 is the URI (Unified Resource Identifier) Syntax document)


6) 파일 확장자는 URI에 포함시키지 않는다.

http://restapi.example.com/members/soccer/345/photo.jpg (X)

REST API에서는 메시지 바디 내용의 포맷을 나타내기 위한 파일 확장자를 URI 안에 포함시키지 않는다. Accept header를 사용하도록 합시다.

GET / members/soccer/345/photo HTTP/1.1 Host: restapi.example.com Accept: image/jpg



4-3 리소스간의 관계를 표현하는 방법

: REST 리소스 간에는 연관 관계가 있을 수 있고 다음과 같은 표현방법으로 사용하자.

/리소스명/리소스 ID/관계가 있는 다른 리소스명

ex) GET : /users/{userid}/devices  (일반적으로 소유 ‘has’의 관계를 표현할 때)

만약에 관계명이 복잡하다면 이를 서브 리소스에 명시적으로 표현하는 방법이 있다. 예를 들어 사용자가 ‘좋아하는’ 디바이스 목록을 표현해야 할 경우 다음과 같은 형태로 사용될 수 있다.

GET : /users/{userid}/likes/devices (관계명이 애매하거나 구체적 표현이 필요할 때)



4-4 자원을 표현하는 Colllection과 Document

: Collection과 Document에 대해 알면 URI 설계가 한 층 더 쉬워집니다. DOCUMENT는 단순히 문서로 이해해도 되고, 한 객체라고 이해하셔도 될 것 같습니다. 컬렉션은 문서들의 집합, 객체들의 집합이라고 생각하시면 이해하시는데 좀 더 편하실 것 같습니다. 컬렉션과 도큐먼트는 모두 리소스라고 표현할 수 있으며 URI에 표현됩니다. 예를 살펴보시도록 하겠습니다.

http:// restapi.example.com/sports/soccer

위 URI를 보시면 sports라는 컬렉션과 soccer라는 도큐먼트로 표현되고 있다고 생각하시면 됩니다. 좀 더 예를 들어보자면

http:// restapi.example.com/sports/soccer/players/13

sports, players 컬렉션과 soccer, 13(13번인 선수)를 의미하는 도큐먼트로 URI가 이루어지게 됩니다. 여기서 중요한 점은 컬렉션은 복수로 사용하고 있다는 점입니다. 좀 더 직관적인 REST API를 위해서는 컬렉션과 도큐먼트를 사용하실 때 단수 복수도 지켜주신다면 좀 더 이해하기 쉬운 URI를 설계하실 수 있을 것 같습니다.
 


5. HTTP 응답 상태 코드

마지막으로 응답 상태코드를 간단히 살펴보도록 하겠습니다. 잘 설계된 REST API는 URI만 잘 설계된 것이 아닌 그 리소스에 대한 응답을 잘 내어주는 것 까지 포함되어야 합니다. 정확한 응답의 상태코드만으로도 많은 정보를 전달할 수가 있기 때문에 응답의 상태코드 값을 명확히 돌려주는 것은 생각보다 중요한 일이 될 수도 있습니다. 혹시 200이나 4XX관련 특정 코드 정도만 사용하고 계시다면 처리 상태에 대한 좀 더 명확한 상태코드 값을 사용하실 수 있기를 권장하는 바입니다.

상태코드에 대해서는 몇 가지지만 정리하도록 하겠습니다.



200 - 클라이언트의 요청을 정상적으로 수행함

201 - 클라이언트가 어떠한 리소스 생성을 요청, 해당 리소스가 성공적으로 생성됨(POST를 통한 리소스 생성 작업시)


400 - 클라이언트의 요청이 부적절 할 경우 사용하는 응답 코드

401 - 클라이언트가 인증되지 않은 상태에서 보호된 리소스를 요청했을때 사용하는 응답 코드 (로그인 하지 않은 유저가 로그인했을 때 요청 가능한 리소스를 요청했을 때)

403 - 유저 인증상태와 관계 없이 응답하고 싶지 않은 리소스를 클라이언트가 요청했을 때 사용하는 응답 코드 (403 보다는 400이나 404를 사용할 것을 권고. 403자체가 리소스가 존재한다는 뜻이기 때문에)

405 - 클라이언트가 요청한 리소스에서는 사용 불가능한 Method를 이용했을 경우 사용하는 응답 코드


301 - 클라이언트가 요청한 리소스에 대한 URI가 변경 되었을때 사용하는 응답 코드 (응답시 Location header에 변경된 URI를 적어 줘야 한다.

500 - 서버에 문제가 있을 경우 사용하는 응답 코드


[ 글을 마치며 ]

그래서 'REST API가 정확히 뭐 어떤 거야?'라고 다시 묻는 다면 'HTTP METHOD와 자원을 표현하는 URI를 이용해 서비스의 데이터에 접근하는 것' 라고 제 나름의 정의를 내려보았습니다. 물론 비전공자인 친구에게는 추가적인 설명이 필요할 것 같습니다. 


RESTFul한 API를 설계하실 때 도움이 될 만한 내용들을 제 나름의 우선순위를 가지고 정리해 보았습니다. 정리를 하면서 다시 한 번 느낀 것은 정확히 알지 못하면 '설명할 수 없다'는 것입니다. 누군가가 그런 말을 하였습니다. '당신이 어떤 것을 할머니에게 설명해 주지 못한다면, 그것은 진정으로 이해한 것이 아니다.' 저 문구를 항상 가슴 깊이 새기고 앞으로 무엇인가 새로운 지식을 학습해 실무에 적용할 때에도 '대충'이 아닌 '정확한 이해'를 바탕으로 문제를 해결해 나가도록 해야겠다'는 다짐과 함께 글을 마무리 짓도록 하겠습니다.


마지막으로 REST API는 정해진 명확한 표준이 없기 때문에 REST API를 사용함에 있어 '무엇이 옳고 그른지'가 아닌 개발하는 서비스의 특징과 개발 집단의 환경과 성향 등이 충분히 고려되어 설계되어져야 할 것입니다

 

 

긴 글 읽어주셔서 감사합니다.


[ Reference ]

- 일관성 있는 웹 서비스 인터페이스 설계를 위한 REST API 디자인 규칙(한빛미디어)

https://ko.wikipedia.org/wiki/REST

http://blog.remotty.com/blog/2014/01/28/lets-study-rest/

https://yangbongsoo.gitbooks.io/study/content/restc758_c774_d574_c640_c124_acc4.html

http://spoqa.github.io/2012/02/27/rest-introduction.html


#NHN엔터테인먼트가 만드는 IT 서비스를 소개하고, 개발 경험을 공유하는 기술 커뮤니티 이고 해당 페이지에 게시한 글입니다.

많은 구독부탁드립니다:)

https://www.facebook.com/toast.nhnent/?fref=ts 


반응형
반응형



@QueryParam ? @PathParam?

흔히 API설계하실 때 특히 GET 방식의 URI 만드실 때 쿼리 파라미터로 설계할지 패스파라미터로 설계하실지 고민들하실텐데요.


저또한 많이 고민하다가 관련해서 열띤 토론?을 나눈 stackoverflow글이 있어 공유합니다.



---------------------------------------------------------------------------------------------------------------------------------------


This is what I do.

If there is a scenario to retrieve a record based on id, for example you need to get the details of the employee whose id is 15, then you can have resource with @PathParam.

GET /employee/{id}

If there is a scenario where you need to get the details of all employees but only 10 at a time, you may use query param

GET /employee?start=1&size=10

This says that starting employee id 1 get ten records.

To summarize, use @PathParam for retrieval based on id. 

User @QueryParam for filter or if you have any fixed list of options that user can pass.


[ 자세한건 참고 : StackOverflow]

http://stackoverflow.com/questions/11552248/when-to-use-queryparam-vs-pathparam

-------------------------------------------------------------------------------------------

[ 결 론 ]

결국에는 특정 정보를 가지고 올 때는  PATH PARAMETER를 데이터에 특정 조건(필터)를 주거나 SORT를 해서 가지고 오고자 할 경우에는 쿼리파라미터를 사용하면 좀 더 깔끔하게 API 를 설계하실 수 있을 것 같습니다.

감사합니다.

 




반응형
반응형



 안녕하세요. 오늘은 ENUM을 JSP에서 받아 사용하는 방법에 대해 포스팅하려고 합니다. 많은 분들이 공통적으로 자주 사용하는 코드 값들이나 타입들을 ENUM에 넣어서 주로 사용하실 텐데요. ENUM을 값 그대로 가져와서 JSP에서 쓸 수 있는 좋은 방법이 있어 포스팅을 하려고 합니다. 저 또한 최근에 ENUM값을 JSP에서 사용해야 하는 기능 개발 건이 있었는데 오늘 포스팅 하는 내용을 통해 쉽게 해결할 수 있었습니다.


먼저 ENUM을 어떻게 JSP에서 사용할 수 있었는지에 대해 간단한 절차를 적어보도록 하겠습니다.1. 사용하고자 하는 ENUM 클래스를 작성합니다.2. web.xml에 Context-param으로 해당 enum 클래스를 등록해 줍니다.3. EnumContextListner를 web.xml에 등록해 줍니다.4. EnumContextListner 클래스를 작성합니다.5. JSP에서 Context-param으로 등록한 ENUM을 가져다가 사용합니다.


1. 사용하고자하는 ENUM 클래스를 작성합니다.해당 내용은 포스팅을 위해 번호와 이메일을 임의로 작성하였습니다. 잘린 부분은 get,set메서드이기 때문에 생략하도록 하겠습니다.



2. web.xml에 Context-param으로 해당 enum 클래스를 등록해 줍니다.위에서 작성한 SmsServiceType 클래스를 Context-param의 param-value에 등록해 줍니다. 간단히 Context-param에 대해 설명하자면 보통 사용자의 요청(ex, www.nr.com/dongbeom)이 웹서버를 거쳐 웹 어플리케이션 서버(탐캣)에 들어왔을 경우 그에 해당하는 servlet을 생성하게 됩니다. Context-param은 사용자의 요청에 의해 생성되는 모든 servlet에서 Context-param으로등록 된 값을 사용할 수 있도록 하는 존재로 쉽게 전역 변수의 역할과 비슷하다고 생각하시면 될 것 같습니다.

밑의 그림에서는 Context-param의 이름이 enumServletContextConfig이고 com.nhncorp.echo.eme.model.SmsServiceType의 클래스를 값으로 가지고 있는 컨텍스트를 정의하고 있습니다.




3. EnumContextListner를 web.xml에 등록해 줍니다.
리스너는 컨텍스트에 정의되어 있는 것들을 모든 서블릿과 필터가 공유할 수 있도록 해줍니다.밑의 그림에서 EnumContextListener 클래스를 listener-class로 등록하고 있는 것을 볼 수 있습니다. 보통 컨텍스트의 값과 리스너들은 클라이언트에서 요청이 들어오지 않아도 web.xml이 읽혀질 때 호출되게 됩니다. (서버가 시작되는 시점에도 호출되게 됨)



4. EnumContextListner 클래스를 작성합니다.해당 클래스에 대해 간단히 설명하자면 web.xml에서 등록한 Context-param의 값들을 다 가져와서 MAP과 LIST로 만들어 JSP에서 사용할 수 있도록 ServletContext에 set을 해주는 역할을 합니다. 또한 loadEnum이라는 메소드를 보시면 ENUM 을 맵과 리스트로 만들어 Collections.unmodifiableMap, Collections.unmodifiableList로 변환해 read-only MAP과 LIST로 변경해 주는 작업도 진행 합니다. (혹시나 ENUM 값을 다른 곳에서 초기화하거나 값을 변경하는 불상사를 막을 수 있음)





5. JSP에서 Context-param으로 등록한 ENUM을 가져다가 사용합니다.

위와 같은 과정을 거치면 모든 JSP에서 해당 ENUM 값을 가져다가 사용할 수 있습니다. 사용하는 방

법에 대한 가이드를 참고 하셔서 사용하시면 됩니다.

[ 참고 가이드 ] 
1) web.xml에 리스너 등록 
2) web.xml의 context-param으로 enumServletContextConfig를 등록. value값에 사용할 enum클래스명을 기입 
3) jsp에서 등록한 enum을 ${enum명(소문자시작)} 형식으로 호출할 수 있다. ex) ${day.MONDAY} 
4) enum.values()의 경우 ${enum명 + List} 형식으로 호출할 수 있다. ex) ${dayList}


저 같은 경우에는 list형태로 다음과 같이 사용하였습니다. ${smsServiceTypeList}


포스팅은 여기서 마치고 이번 포스팅을 진행하다보니 이번 포스팅을 이해하기 위해 필요한 기본적인 내용들에 대해서(web.xml, servletContext.xml, applicationContext.xml 등등)는 아직 포스팅이 많이 안된 것 같은데 시간 나는 대로 다시 한 번 개념을 정리할 겸 포스팅하도록 하겠습니다.


감사합니다.





반응형
반응형

 


 안녕하세요 이번 포스팅에서는 Xss Filter에 대한 간단한 개념과 이번에 작업을 하다가 헤맸던 JSP에서 폼의 타입이 enctype ="multipart/form-data"일 때 XSS FILTER가 적용되지 않았던 문제에 대해 알아보고자 합니다. Xss Filter를 기존에 써봤다는 가정 하에 포스팅을 진행하겠습니다. ( 기본적인 XSS Filter를 적용하는 법에 대한 설명은 포함되어 있지 않음을 미리 말씀드립니다. )



 ▶ XSS Filter란???


 Xss Filter란 사용자들의 악의적인 스크립트 공격(ex, <script> alert("melong"); </script> )등을 막기 위해 사용하는 filter로 안정적인 웹서비스를 위해서는 필수적인 요소입니다. XSS는 Cross-Site Scripting를 의미한다. 보통 해당 filter를 사용하기 위해서는 web.xml에 필터를 정의해주고 거기에 해당하는 url을 매핑해주고 filter 클래스를 작성해주면 된다.( 이에 대한 내용은 생략합니다.) 



 ▶ 작업 중 문제 발생 ( JSP에서 form의 타입이 enctype="multipart/form-data"일 경우 XSS Filter를 타지 못함)


 보안팀으로부터 페이코 앱 고객센터의 문의를 넣는 페이지에 xss filter가 적용되어 있지 않아 보안에 취약하다는 메일을 한 통 받았습니다. 메일을 받고 가장 먼저 확인한 것은 "web.xml에 해당 문의를 넣을 때의 url이 XSS Filter url에 매핑이 되어있는가" 였습니다. 이를 확인한 결과 해당 url이 XSS Filter에 잘 매핑되어 있는 것을 확인 할 수 있었습니다. 여기서 되게 의아했습니다. 그래서 제가 직접 페이코 앱에서 스크립트( <script> alert("N"); </script> )를 제목 부분에 넣어 문의를 넣어 보았습니다.




 1:1 문의에 들어가서 문의를 넣고 내 문의 보기를 누르자 alert창이 뜨는 것을 볼 수 있었습니다. 도대체 왜 xss filter에 매핑이 되어 있는데 해당 스크립트의 내용이 안 걸러지는지 의아했습니다. 

                                                                           


 


 그림(보안상의 이슈로 모자이크 처리)을 보면 아시겠지만 /~/app/mail/addInquiry.nhn이 문의를 넣을 때 요청되는 url이고 잘 mapping되어 있는 것을 확인하실 수 있습니다. 잘 매핑은 되어 있는데 왜 필터링이 안될까하는 의문과 함께 filter와 wrapper클래스를 디버깅해 본 결과 폼에 의해 전송되는 값들을 제대로 호출해오지 못하는 점을 발견 하였습니다. 그래서 검색을 해본 결과 

 


 그림에서 보는 것과 같이 form 타입을 multipart/form-data로 폼을 넘길 경우 xss filter에서 해당 폼의 request의 값들을 제대로 읽어오지 못하는 것을 알 수 있었습니다. 해당 페이지가 기본적인 제목, 내용을 입력 받고 첨부파일 기능 또한 있는 페이지 이기 때문에 폼의 타입이 multipart/form-data일 수 밖에 없었습니다. 따라서 해당 타입으로 폼이 전송될 때 파일첨부 이외의 값들에 대해 XSS Filter를 통해 스크립트와 악의적인 공격들을 막아주어야하는데 XSS Filter가 폼의 값들을 제대로 읽어들이지 못하고 있었습니다. 문제는 multipart/form-data형식의 경우에는 파라미터를 읽을 때 getPart()와 getParts()라는 메소드를 사용하는데 해당 사용하고 있는 filter 클래스를 보면  getParameter와 getParameterValues()로 요청으로 부터 넘어온 값들에 대해 filter를 적용하는 것을 확인할 수 있었습니다. (밑의 그림)



 ▶ 문제 해결 방법


 위와 같이 form의 타입이 enctype="multipart/form-data"일 경우 XSS Fitler를 타지 못하는 문제를 해결 하기 위해서 XSS Filter 전에 "MultipartFilter"를 적용해 주어 먼저 multipartFile에 대해 필터를 적용해 주고 XSS Filter를 타게 해주어야 합니다. 


 


 그림(혹시나 해서 특정 부분은 모자이크 처리)과 같이 XSS 필터 위에 multipartFilter를 적용한 것을 보실 수 있습니다. 여기서 주의 사항은 multipartFilter에 url에 매핑을 시켜줬다고 해서 XSS Filter에서 url을 제거하면 안됩니다. ( 두 필터 모두에 url이 매핑되어 있어야함!!!! 저는 mutipartFilter에 매핑시켜줬으니까 xss에는 안해도 되나하고 안했다가 많은 시간을 낭비했다는 ㅠ,ㅠ) 이로 인해 form의 타입이 enctype="multipart/form-data"여도 XSS Filter가 잘 작동하는 것을 확인 할 수 있었습니다.



 ▶ multipartFilter를 XSS Filter위에 적용하기 전 requerst를 받아오는 모습과 적용 후 request 비교


먼저 multipartFilter 적용 전 request



다음 web.xml에 multipartFilter를 적용한 후



 request로 넘어오는 값들이 확연히 다른 것을 보실 수 있습니다. multipartParameters를 까보게 되면 해당 페이지에 기입한 여러 값들이 정삭적으로 잘 넘어오는 것을 확인할 수 있었습니다. 이로 인해 제목이나 본문에 스크립트가 들어간다고 해도 XSS Filter를 통해 잘 처리 할 수 있었습니다.

 




반응형
반응형

 JSP/SERVLET 파트에서 SERVLET이 동작하는 흐름에 대해서 알아봤다. 컨테이너에서 서블릿이 초기화되고 그 해당 서블릿이 어떻게 DispatcherServlet에 의해 처리되어 뷰를 반환하게 되는지에 대해 살펴보도록 하겠다.


  DispatcherServlet에 대해 간단히 설명하자면, DispatcherServlet은 Controller로 향하는 모든 웹 요청의 진입점이며 웹 요청을 처리, 결과 데이터를 Client에게 제공하는 역할을 한다.네 맞습니다. DispatcherServlet은 우리가 각각 분리하여 만든 Model 파트와 Controller파트 View 파트를 조합하여 브라우저로 출력해주는 역할을 수행하는 클래스이며 DispatcherServlet으로 인해 web.xml의 역할을 획기적으로 축소시켜 주었다.

예전 DispatcherServlet이 있기전에는 모든 사용자의 요청 url을 일일이 해당 요청을 처리하는 servlet과 매핑시켜주는 작업을 지정해 주었어야만 했다.예를 들어, 기본URL/happy, 기본URL/contents, 기본URL/subject 등의 요청이 들어왔을 때 이에 해당하는 서블릿과의 매핑 작업을 web.xml에 모두 정의해주고 사용했어야 했던 만큼 web.xml 도 복잡해지고 손수 작업에 필요한 서블릿 정의와 매핑작업을 해줘야 했기 때문에 여간 귀찮은 일이 아니였다.

하지만 지금은 web.xml에

이렇게 DispacherServlet을 정의해주고 모든 URL에 대해 매핑을 해주게 되면 DispatcherServlet이 요청 url에 해당하는 컨트롤러를 찾아 매핑해주게 된다. 얼마나 고마운 일인가. 위의 소스코드에 대해 이해가 안가시는 분은  http://blog.naver.com/kim3zz/220273028176 servlet 매핑에 대한 설명 부분을 참고하시길 바란다.


DispatcherServlet은 이렇게 web.xml 을 획기적으로 축소시켜주었고 개발자에게 요청에 따른 컨트롤러를 일일이 매핑해야하는 번거로움 또한 덜어주었다. 이제 그럼 DispatcherServlet이 어떻게 동작하는지에 대해 알아보자.

[ 그림 1 ] 사용자가 특정 URL을 요청하게 되고 웹서와 컨테이너를 거쳐 해당 요청이 DispatcherServlet을 타게 된다.

[ 그림 2 ] DispatcherServlet은 요청에 대한 정보를 HandlerMapping에게 보내 요청을 처리할 수 있는 Controller을 찾아 DispatcherServlet에게 다시 반환하게 됩니다. HandlerMapping은 클라이언트 요청을 어떤 Controller가 수행할지의 여부를 결정해 주며 스프링의 디폴트 전략에 의해 BeanNameUrlHandlerMapping이 설정되어 있어 따로 설정을 하지 않아도 요청 url과 동일한 이름을 갖는 Controller을 찾아 매핑시켜 주게 된다.

[ 그림 3 ] DispatcherServlet은 해당 컨트롤러에게 요청에 대한 처리를 부탁하고 컨트롤러는 요청을 처리한 후에 응답받을 ModelAndView를 리턴하게 됩니다.

[ 그림 4, 5 ] ViewResolver는 컨트롤러가 반환한 ModelAndView를 받아 해당 view가 존재하는지 검색하게 됩니다. 해당 View가 있다면 전처리 과정을 거쳐 해당 View를 반환해 줍니다.

InternalResouceViewResolver를 보시면 name="prefix"와 "suffix"를 보실 수 있는데 컨트롤러가 던지 view 앞에 붙여지는 것이 prefix이고 뒤에 붙여지는것이 jsp가 되게 됩니다. 예를 들어 컨트롤러가 "board"라는 뷰 스트링 객체를 던졌다면 리졸버를 통해 /WEB-INF/views/board.jsp 가 되어 해당 뷰에서 요청이 보여지게 됩니다.

다음에는 web.xml에서는 어떠한 작업들이 이루어지는 지에 대해 살펴보도록 하겠습니다.

ref :https://kisukpark.wordpress.com/2013/08/29/spring-mvc-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90/http://egloos.zum.com/springmvc/v/504151




반응형

+ Recent posts