Atom 에디터 단축키 (Windows 기준)


Editor


Ctrl + Shift + P: 커맨드 팔레트 열기

Ctrl + P : 트리뷰 내 파일 찾기.  [eclipse: Ctrl + Shfit + F]

Ctrl + ,: 설정 뷰

Ctrl + .: 키 바인딩 보기 (단축키 작동 현황 보기)

Ctrl + K > 방향키: 패널 나누기

Ctrl + K > Ctrl + 방향키: 패널 전환

Ctrl + W: 창(패널) 닫기

Alt + \ or Ctrl + 0: Treeview 포커스 전환

Ctrl + \: Treeview 열기/닫기

Ctrl + K > Ctrl + B: Treeview 열기/닫기

Ctrl + Shift + L: 언어 선택

Ctrl + Shift + M: Markdown 프리뷰

Ctrl + Shift + U: 인코딩 설정

Ctrl + Alt + I: 개발자 콘솔 열기

Esc: 열린 기능 패널 닫기 및 취소

F11: 전체화면

Tree View (활성화 상태일 때)


A: 새로운 파일 생성

Shift + A: 새로운 폴더 생성

M or F2: 파일(폴더) 경로 및 이름 변경

Delete or Backspace: 파일(폴더) 삭제

D: 파일(폴더) 복사

J, K 커서 이동

H, L 선택 열기/닫기



Tab


Ctrl + T: 파일 파인더 열기 (탭 전환)

Ctrl + B: 열린 파일 보기 (탭 전환)

Ctrl + Tab: 다음 탭 전환

Ctrl + Shift + Tab: 이전 탭 전환

Ctrl + Pagedown, Pageup: 다음/이전 탭 전환

Crtl + Shift + T: 최근에 닫은 탭 다시 열기

Alt + 숫자: 열린 탭 전환



General Editing


Ctrl + /: 주석 토글

Ctrl + F: 찾기/바꾸기

Ctrl + Shift + F: 프로젝트 전체에서 찾기

Ctrl + E: 선택 영역을 찾기/바꾸기

Ctrl + G: 라인 번호로 커서 이동

Ctrl + R: 키워드로 이동

Ctrl + M: 블럭 매칭

Ctrl + J: 라인 조인

Ctrl + L: 라인 선택

Ctrl + D: 현재 단어 선택 (이후 전체 범위에서 같은 단어 선택)

Ctrl + Backspace, Delete: 단어 별 삭제

Ctrl + Shift + K: 현재 라인 삭제 [Eclipse Ctrl + d]

Ctrl + Shift + D: 현재 라인 다음 라인으로 복사 [Eclipse ctrl + alt + ↓]

Ctrl + [, ]: 들여쓰기

Ctrl + Alt + [, ]: 코드 폴딩 토글

Ctrl + Shift + Alt + [, ]: 전체 코드 폴딩 토글

Ctrl + ←, →: 단어 별 이동

Ctrl + ↑, ↓: 현재 라인 이동

Ctrl + Alt + ↑, ↓: 다중 커서 삽입

Ctrl + Enter: 현재 라인 밑으로 개행

Ctrl + Shift + Enter: 현재 라인 위로 개행

Ctrl + Space: 코드 힌트 보기

Shift + 방향키: 텍스트 선택

Shift + Ctrl + ←, →: 단어별 텍스트 선택



서론


 스프링에서는 총 3개의 컨테이너가 구동된다고 할 수있다. 컨테이너란 서버(정적리소스 관리)내에서 Client의 요청을 동적으로 처리하기 위한 웹 서버의 한 부분 이다.


(사진)Servlet Container 


본론




톰캣 서버를 처음 구동하면, 

1. Web.xml 파일을 로딩하여 서블릿 컨테이너가 구동된다.

2. 서블릿컨테이너는 web.xml 파일에 등록된 ContextLoaderListener객체를 생성 한다.

3. 이때 ContextLoaderListener는 applicationContext.xml 파일을 로딩하여 스프링을 구동하는데 이를 'Root 컨테이너'라고 한다.

4. 동시에 Service 구현 클래스나 DAO 객체들이 메모리에 생성된다.

5. Clinet가 서버에 요청을 하게 되면, 서블릿 컨테이너는 DispathcerServlet 객체를 생성하고,

6. Presnetation-layer.xml 파일을 로딩하여 두 번쨰 스프링 컨테이너를 구동한다. 이때 Controller 객체들이 메모리에 올라가게 된다.

 

(+ 추가사항) 

web.xml에서 <servlet><init-param> 과 

<context-param>

<param-name>contextConfigLocation</param-name> 정확히 이해해서 추가내용 쓰기

개요


일반적으로 프레임워크 기반의 웹프로젝트를 보면 아래 그림과 같이 2개의 레이어로 시스템을 나누어 개발한다.



위는 스프링의 프레임워크의 대략적인 구조를 나타낸 것이다. 특히 2-Layered 아키텍쳐에따라 컴포넌트를 분류 해 놓았다.


컴포넌트 설명


(클라이언트의 요청이 들어온 뒤 흐름에 따라 기술)

1.Dispathcer Servlet : 프론트 컨트롤러로써 클라이언트의 요청은 무조건 여기를 거친다.

2.Handler Mapping : 사용자의 요청에 따라 어느컨트롤러로 분기할지 맵핑을 시켜준다.

3.Controller : 기능마다 어느 비즈니스 로직을 태울지 관장하는 컨트롤러이다. 만약 스프링 프레임워크를 쓴다면 실질적으로 여기서부터 프로그래밍을 시작한다.

4.ServiceImpl : 서비스 인터페이스를 상속받아 작성한 비즈니스 로직을 구체적으로 기술 한 곳이다.

5. DAO는 직접 DB에 접근한뒤 DTO 객체에 담아온다.

6.View Resolver : 뷰 리졸버는 이제 다음 *.do URL로 분기할지 아니면, 어떤 jsp로 분기할지 관장하는 컴포넌트이다. 

 *책에서 실제로 구현을 해봣는데 prefix와 suffix를 붙여줘서 실질적인 파일 jsp 이름으로 맵핑시켜줬었다.

7. View : 클라이언트가 마주하는 화면으로써, jsp파일이나 html 페이지에 해당하는 부분이다.


상세


# src/main/resources 폴더에는 비즈니스 레이어에 해당하는 설정파일인 applicationContext.xml (AOP,JDBC등 설정) 파일이 있으며, /WEB-INF/config 폴더에는 프레젠테이션 레이어에 해당하는 설정파일인 presentation-layer.xml 이 있다. 

# DispatcherServlet이 생성되면 presentation-layer.xml 파일을 읽고, 스프링 컨테이너를 구동하면 Controller 객체들이 메모리에 생성된다. 하지만 Controller 들이 생성되기전에, src/main/resources 소스 폴더에 있는 applicationContext.xml 파일을 읽어 비즈니스 컴포넌트 들을 먼저 메모리에 생성해야 한다. 이때 사용하는 클래스가 스픵에서 제공하는 ContextLoaderListener 


->ContextLoaderListener는 다음 글에서 자세히설명 할것 



ps. 본 내용은 스프링 퀵스타트 책을보며 공부한내용을 요약 한 것 입니다.(루비페이퍼, 채규태 저)



Scenario


NodeJS의 npm 모듈중 passport를 쓰면서, 분명히 가이드라인대로 했는데 안되는 게 좀 있엇다. 다들 어이없는 이유로 안됬는데, 이런거땜에 1~2시간은 족히 소요되는 것 같다.

 

1.Passport 사용시 Client에서 서버로 요청까지는 보내지는데 authenticate 에서 passReqToCallback로 진입이 안되는 상황.


2.bcrypt.compareSync(password, this.local.password) 함수로 비밀번호 비교 하련는데, cannot read property 'password' of not undefined 라고 뜨는 상황


3.(가장 어이없음 주의**) req.flash를 사용헤 flash 메세지를 얻어오려는데 못얻어오는 상황.


Solution


1.Passport 사용시 Client에서 서버로 요청까지는 보내지는데 authenticate 에서 passReqToCallback로 진입이 안되는 상황.

->View 에서 보낼때 name과 passport의 usernameField,passwordField 가 일치해야한다.

ex)내가 오류났던 상황

JavaScript 0.45 KB

  1. -----------------view---------------------  
  2.       <div>
  3.         <label>Id:</label>
  4.         <input type="text" name="id"/>
  5.       </div>
  6.       <div>
  7.         <label>Password:</label>
  8.         <input type="password" name="password"/>
  9.       </div>
  10.  
  11.  
  12.  
  13. -----------------------server------------------------------
  14.   passport.use('login',new LocalStrategy({
  15.     usernameField:'email',
  16.     passwordField:'password',
  17.     passReqToCallback : true
  18.   },



2.bcrypt.compareSync(password, this.local.password) 함수로 비밀번호 비교 하련는데, cannot read property 'password' of not undefined 라고 뜨는 상황

->아주 단순했다 this.local.password를 this.password 로 바꿔주니 잘 동작했다.



3.(가장 어이없음 주의**) req.flash를 사용헤 flash 메세지를 얻어오려는데 못얻어오는 상황.

https://stackoverflow.com/questions/38136792/typeerror-req-flash-is-not-a-function

이유를 알고나서 정말 어이가 없었는데.

passReqToCallback:true 를 쓸때 나는 띄어쓰기가 상관 없는줄 알았다. 왜냐하면 다른필드도 띄어쓰기를 안해도 상관 없었으니까.

그러나 passReqToCallback : true 무조건 이런식으로 띄어쓰기를 해주어야한다.

명심하자

passReqToCallback^:^true

Scenario


몽고 DB에서 파일 형식 JSON Array를 꺼내와서, EJS단에서 꺼내서 쓸려고 했다.

서버에서 EJS로 보낸 JSON을 자바스크립트 파일에 담으니 자꾸 

ex)

<Script>

var fileArrys = <%= board.files%>

<script>


Invalid or unexpected token 이라는 에러가 뜨는 것이었다





Solution


다행히도 나와 비슷한 오류를 겪고있는 사람들이 스택오버플로우에 많았다.


JavaScript 0.10 KB

  1. var initData = JSON.parse('<%-JSON.stringify(list)%>');
  2. //or
  3. var initData = <%-JSON.stringify(list)%>;


이렇게 써서 간단히 해결!!

Scenario


 스프링으로 개발하다보면, URL 뒤에 /value=hi&id=nana0303

이런식으로 string을 쓰면 서버측에서 HandlerMethodArgumentResolver 등록해놨다면 바로바로 맵에서 Parameter 들을 꺼내 쓸 수 있엇다.

그래서 nodejs에서도 /down/value=hi&id=nana0303  이런식으로 보낸뒤 (나는 당연히 JSON 형식으로 갈꺼라 생각)

router.get('/download/:Params', function(req, res){

req.params.Params.storedname

}

서버에서 이렇게 꺼내쓰면 될 줄알았다. 하지만 params 은 긴 스트링으로 인식 되는 것이었다.



Solution


역시 NodeJs에서는 querystring 이라는 모듈로 제공 하고 있었다.

다음과 같이 쓰면 내가 원하는 결과를 얻을 수 있엇다.

JavaScript 0.26 KB

  1. var querystring = require('querystring');
  2. //file down
  3. router.get('/download/:Params', function(req, res){
  4.     var Params = querystring.parse(req.params.Params);
  5.     console.log("path: %s",JSON.stringify(Params, null, " "));
  6.     res.download('./'+downPath+Params.storedname, Params.originFileName);
  7. });




개요


 스프링을 공부하고 회사에서도 스프링을 다룬다. 그러나 스프링의 심오함은 파도파도 끝이 없는 것 같다. 결정적으로 새로운 언어의 학습 필요성을 느낀 때가 있엇다. 

 Cloud 서비스 및 빅데이터 강의를 연수원에 있을때 들은 적이 있는 데, 강사님과 Back-End와 Front-End에 대해서 이야기를 나눈 적이 있엇다.

 강사님 왈 "한국에서는 백엔드 하면 무조건 JSP,Servlet(스프링) 인데 이미 외국은 노드제이에스 파이썬 장고로 많이 넘어갔어요. 미리미리 준비해두세요." 이런식으로 말씀 하신게 기억이난다.

 그 이후로 nodejs에 대해 조금 스터디를 하고 싶어졌고 하둡 생태계처럼 nodejs도 생태계가 존재하는 것이었다.



그래서 MEAN STACK 이 뭔데??


일단 이 그림부터 보고 가는 게 좋겠다.

 다음과 같은 프로그램의 앞글자를 따서 약자로 쓴 것 인데, 여기서 주목할 만한점은 모든 데이터를 JSON 형태로 주고받는 다는 것이다.

 특히 가히 충격점인점은 DB인데, document 기반(추후 따로 올려야겠다)이다. (몽고디비는 BSON이라고 불리는 바이너리 제이선으로 저장함) 이라는 것이다. RDB의 형식을 파괴하고, 무려 이름은 No-SQL 이다.! 

 물론 오래전부터 주목받았겠지만, 최근에 알게된 나는 JSON으로 프론트에서 디비까지 데이터 변형없이 주고받는게 너무 신선했다. 


장 단점


- 장점

  • 일단 4가지 언어의 공통점은 JavaScript의 뿌리를 가진다. 한 가지 언어로 프론트부터 백단까지 구성!!
  • 굉장히 간단하다. 스프링에 비한다면 가히 폭팔적인 생산성이라고 할 수 있겠다.(코드 짜는 속도가 완전 빠름)
  • 빠르다. 일단 NodeJs가 NonBlocking,Single-Thread를 추구하므로 단점도 있긴 하지만 빠르다. 또한 DOM기반 Jquery에 비해 AngularJS가 훨 씬 빠르다. (물론 어떻게 쓰느냐에 따라 많이 다르다)


- 단점

  • AngularJs는 진입장벽이 확실히 높다. 개인적으로 Jquery는 굉장히 직관적이어서 selector개념만 익힌뒤, 원하는 기능을 왠만하면 다 만들어 낼 수 있엇다. angularjs는 뷰단에서 프레임워크를 구성하기 때문에, 그리고 바인딩 개념때문에 확실히 초반진입장벽이 있다.
  • 한국은 아직까지 JAVA가 대세. 말 그대로 어쩔 수 없는 것 같다. 아직까지 자바공화국 한국에서는 nodejs 기반 프로그래밍은 스타트업에서 쓰이는 정도이다. (나도 자바로 취직을 했다. MEAN stack은 스터디 개념)
  • MongoDb에는 트랜젝션이 없다. 이 부분에서는 좀더 스터디를 하면서 채워나가야 겠다.

결론


 나는 회사원보다는 개발자가 되고싶다. 

언어는 90년대부터 시작해서 굉장히 많이 변해 왔다. 목수나 기술자에게 생산성이 높은 툴이 나온다면, 주저하지 않고 사용법 정도는 익혀놔야 할 것이다. 개발자에게는 더욱 중요 하다. 








Scenario: 페이징을 할경우 밑에 숫자가 뜨게된다. 만약 Ajax를 쓰지 않을 경우, 서버에서 nowPage 라고 선택된 페이지를 넣어주고 클라이언트에서 받아서 if문에 i와 now page를 찍어주면 활성화된 페이지 번호에 class="active" 를 써주면 된다.

그러나 ajax로하면 비동기로 하기때문에(페이지를 분기하는게 아님), 리플부분만 갱신해주고 page 번호는 다시 안찍어주기떄문에 복잡해졌는데, 단순하게 jquery로 클릭한 부분에 대해서 Active하는 방법을 알 수있엇다

(boot strap 기준)


Solution:

jQuery 0.42 KB
  1.     $(function(){
  2.      var pageBtn = $("ul > li");    //  ul > li 이를 pageBtn 으로 칭한다. (클릭이벤트는 li에 적용 된다.)
  3.       pageBtn .find("a").click(function(){   // pageBtn 에 속해 있는  a 찾아 클릭.
  4.       pageBtn .removeClass("active");     // pageBtn 속에 (active) 클래스를 삭제.
  5.       $(this).parent().addClass("active"); // 클릭한 a에 (active)클래스를 넣는다.
  6.      })
  7.     });




ex) Ajax로 페이지가 분기하지 않고 비동기적으로 댓글내용을 페이징함, 밑에 번호들도 클릭시 active되게 바꿔줌.


Scenario:

AWS에서 EC2에 Ubuntu Tomcat7 웹 프로젝트를 올려서 배포를 하려고 했다.

Window 환경에서 배포를 했을때는 잘 돌아갔는데

Ubuntu 환경으로 변하니 오류가 해결이 안되는 것이었다.

Tomcat7 로그를 확인해보니 다음같은 오류가 계속났다.

Error initializing mybatis. Cause:org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.datasource.DataSourceException: There was an error configuring JndiDataSourceTransactionPool. 

Cause: javax.naming.NamingException: Could not create resource factory instance [Root exception is java.lang.ClassNotFoundException: org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory]



Solutions

Mybatis 쪽에서 오류가 나는건가 하고 내 코드를 열심히 뒤져봤지만,

문제는 

The cause is a issue in the Ubuntu build/package process for Tomcat7. If I understand the issue correctly, Apache builds tomcat-dbcp.jar from binary files, while Ubuntu builds packages only from source. The Ubuntu project ends up needing to change the Java package name, which tends to break things for us poor users. The gory details may be found at the Ubuntu issues list.

The solution I found is to name the data source factory when I define the resource. In one case, I have a META-INF/context.xml file that contains:

이런 이유에서 나는 것 이었다.




factory="org.apache.commons.dbcp.BasicDataSourceFactory" 

단순히 이 한 줄을 context.xml 파일내 Resource에  추가하니 해결 되었다.

이것때문에 몇날을 고생했는지.. ㅠㅠ 

심지어 윈도우로 EC2를 다시구성해야되나 고민했엇다.



Scenario: 클라이언트에서 jsp를 쓸 수 없었고, 세션 정보도 불러올 수 없고, json을 통해서만 서버와 통신 할 수 있었다.

어떤 자료구조를 날리기 위해 List<Map<>>을 Json 으로 바꿔서 날려야만 했고, 받을때도 Json을 받아야만 했다. 엄청 삽질 해서 겨우 해냈다.


Solutions:


1 Json to List<Map<>>


Java 0.42 KB
  1. import org.codehaus.jackson.JsonGenerationException;
  2. import org.codehaus.jackson.map.JsonMappingException;
  3. import org.codehaus.jackson.map.ObjectMapper;
  4.  
  5.     public static String getQuestion() throws JsonGenerationException, JsonMappingException, IOException{
  6.         ObjectMapper objectMapper = new ObjectMapper();
  7.  
  8.         String json = objectMapper.writeValueAsString(questionPool);
  9.  
  10.         System.out.println(json);
  11.        
  12.         return json;
  13.     }



2.List<Map<>>  to Json

Java 0.84 KB
  1.         import org.codehaus.jackson.map.ObjectMapper;
  2.         import org.codehaus.jackson.node.ObjectNode;
  3.         import org.codehaus.jackson.type.TypeReference;

  4.         ObjectNode sessionNode =  (ObjectNode) obj.get(JsonAdaptorObject.TYPE.META);
  5.        
  6.        
  7.         //wow... Tostring 으로 하면 "" 이 붙어서 json list로 인식못함
  8.         // astext 한방에 되버림. tostring을 할경우 더블 쿼테이션이 "" 붙어버려서 망해버렷엇음
  9.         String json = sessionNode.get("quesMapList").asText();
  10.        
  11.         List<HashMap<String, Object>> queList;
  12.         ObjectMapper MAPPER = new ObjectMapper();
  13.  
  14.        
  15.         //""이 붙는 상황에서 고쳤다.
  16.         //astext로 바꾸고 json 형태를 Map List 로 으로 바꿨음
  17.         try {
  18.             System.out.println(">>start");
  19.             queList = MAPPER.readValue(json, new TypeReference<List<HashMap<String, Object>>>() {});
  20.             System.out.println(queList.get(0).get("qNum"));
  21.         } catch (IOException e1) {
  22.             // TODO Auto-generated catch block
  23.             e1.printStackTrace();
  24.         }


+뷰단에서 스트링값으로 온 Jason 값 처리

Sever단에서 String으로 처리해서 Client 단으로 보내야 했기때문에, 다음과 같이 Jason 데이터로 전달되었다.

"[{\"qNum\":\"1\",\"question\":\"아침 9시까지 그린카를  타고 가산동으로\",\"missFlag\":\"true\"},{\"qNum\":\"2\",\"question\":\"목적지 주변에서 미션을  찾으세요\",\"missFlag\":\"ing\"},{\"qNum\":\"3\",\"question\":\"3번쨰 목적지로 가서 QR 코드를 찾아보세요\",\"missFlag\":\"false\"},{\"qNum\":\"4\",\"question\":\"4번째 미션.\",\"missFlag\":\"false\"},{\"qNum\":\"5\",\"question\":\"5번째 미션.\",\"missFlag\":\"false\"}]"


이것을 파싱해주기위해 다음처럼 정규식을 이용해 replace함

JavaScript 0.63 KB
  1. //콜백 펑션임
  2. function(resMIS000){
  3.             //제이선 -> String 시에는 stringify, 제이선 파싱시에는 parse
  4. //          alert(JSON.stringify(resMIS000).replace(/\\/g, ""));
  5.             //Client 단에서 String jason을 파싱해주기 위해서 \과 대괄호를 제거 해주기위해 다음과 같은 정규식적용
  6.             var jsonString = JSON.stringify(resMIS000.body.misList).replace(/\\/g, "").replace(/"\[/g,"\[").replace(/\]"/g,"\]");
  7.             fn_setStatus(JSON.parse(jsonString));
  8. }
  9.  
  10. function fn_setStatus(data) {
  11.     $.each(data, function(idx, val){
  12.         console.log(val.question+" "+idx);
  13.         fn_setTag(idx, val);
  14.     });
  15. }


+ Recent posts