올해들어서 완독한 가장 첫번째책인듯하다. 기술서적을 사 놓고는 필요한부분만 보고는 레퍼런스 형식으로만 보는게 어느덧 습관아닌 습관처럼 된거같다. 책을 한권사놓고 첨부터 끝까지 읽어보고 실습해보고 하는데 생각보다 시간이 많이 걸린다. 이 책을 처음 접한건 모 출판사의 페이스북 이벤트였다. 아는 형이 페이스북으로 열심히 도서이벤트를 참석하는데, 나한테도 추천을 해준적이있다. 얼떨결에 신청했는데 운이좋겠도 당첨이 됬었다. 

이 책을 읽게된 가장큰게기는 이책의 역자인 이종은님의 화상강의를 듣게되면서다. 화상강의 얘기는 나중으로 미루고 이책의 읽은 총평에 대해서 간략하게 쓰고자한다. 

OREILLY 라는 출판사의 책을 예전부터 봐았지만 읽기 어렵다는 선입견이 나에게는 있었던거 같다.  

이 책의 특징은 빠르고 간단하게 ReactNative 에대해서 기술을 하고있으며, 책을 읽기전에 갖추어야할 지식을 어느정도 알고 있으면 읽기가 편하며, 모르고 있으면 읽기가 어렵다. 나같은경우는 React도 어설프게 알고있는정도 였으므로 첨에 읽기가 쉽지는 않았으며 실습도 생각보다 막히는 부분이 많았던거 같다. 뭔가 대단한? 예제보다 간단한 예제들로서 ReactNative로 앱을 구성하는 방법을 기술하고 있다. 이 책을 좀더 쉽고 재밌게 읽는 방법은 역자의 화상강의를 듣는걸 추천한다. 

React Native 화상강의




블로그 이미지

클라인STR

,

아는사람 추천으로 구글애드센스를 블로그에 장착하기로 했다. 

포털을 검색해보니 생각보다 승인하기가 까다롭다는 글들이 많이보였다. 

올해3월 애드센스신청을 했었는데, 2차승인에서 거절을 당했다. 거절을 당했을 당시 궁금해서 승인이유에 대해서 구글에 매일을 보냈더니 아래와 같이 답장이 왔었던거 같다. 

원래 몇년전부터 블로그를 하다가 방치한 티스토리블로그가있었는데 방문자수가 많지는 않았지만 게시물이 적지않았기때문에 좀 아까웠었는데, 생각보다 통과가 녹록치는 않았다.

9월말경 일을 쉬고있는동안 다시한번 구글애드센스를 신청하였다.

2번정도 떨어지고 난 다음 생각한건 이전에 만들어났던 티스토리블로그중 게시글이 작은 계정으로 다시 신청하였다. 

구글애드센스 신청후기를 포털에서 검색해서 읽어보면 통과되기 위해서 포스팅하는 글의 방식이 여러가지가 나와있는데, 글을작성할때 1000자 또는 3000자 이상작성할것 사진이나 이미지가 들어가는 게시글보단 텍스트 게시물이 좋다거나, 하루에 게시물을 개수를 4~5개 유지하는것이 좋다는 글을 많이 봤었다. 처음에 몇개 는 1000자에준하게 글을 작성했었는데, 생각보다 힘이 들어서 관심있는 주제에 대해서 짧게 여러번 포스팅하였고, 구글애드센스를 신청한 후에도 게시글을 꾸준히 적었다. 

아래와 같은 게시글이 오면 구글애드센스에 광고를 게제할 수 있다. 


블로그 주제를 명확하게 하고 가능한 포스팅을 자주 꾸준히 올리는게 중요한거 같다. 

왜냐면 내 포스팅에서 글자수가 긴포스팅이 별루없기때문이다. 쓰기도 귀찮거니와 책의 내용을 발췌해서 쓰는것도 생각보다 힘들었기 때문이다. 


블로그 이미지

클라인STR

,

회사에서 테스트 자동화를 위해서 id부여를 위해서 Selenium을 처음으로 설치하여 사용해 보았다.

Selenium이란 어플리케이션을 위한 테스트 자동화 툴이다. 자세한건 구글링을 참조하시라..

https://github.com/seleniumhq/selenium



현재 사용중인 자바프로젝트에 설정을 추가하여 환경을 구성해보기로 하였음


1.pom.xml에 Selenium 관련 디펜던시를 추가한다.

https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java


<!-- Selenium -->
<dependency>
   <groupId>org.seleniumhq.selenium</groupId>
   <artifactId>selenium-java</artifactId>
   <version>3.7.1</version>
</dependency>


2. WebDriver 다운로드 받는다.

  - FireFox, Internet Explorer, Safari, Chrome 다양한 브라우저를 지원한다.

  - http://docs.seleniumhq.org/download/ 접속하여 테스트 하고 싶은 브라우저의 드라이브를 다운로드 받는다.


3. Test 코드를 작성한다. Spring4 환경에서 테스트 하였으며, JUnit을 활용하였다.

  


4. 네이버가 실행되는걸 확인할수 있다.

블로그 이미지

클라인STR

,

어제 오후 친구에게 한톡의 카톡을 받았다. 중소기업 청년 취업 소득세 감면 법이 개정되어서 아는지인이 소득세감면 신청을 했다는 얘기였다. 

혹시나 .... 해서 신청을 해보았다.

사진은 클릭하면 크게 보실수 있습니다.

국세청 홈택스 -> 신고/납부 -> 종합소득세  선택한다.



종합소득세화면에서  경정청구 작성버튼을 선택한다.


경정청구서 작성화면에서 귀속연도를 선택하고 다음버튼을 눌른다.




소득세액증명내역이 표시된다. 다음이동 버튼을 선택한다.



귀속년도 조회버튼을 선택하면 기본정보내역이 조회된다. 

휴대폰번호와 주소전화번호는 필수값이니 반드시 입력한다.

전자우편번호를 입력한경우 경정청구 결과를 우편으로 받을수있으니 꼭 입력하도록 하자.


 총급여 부분을 복사해서 웹브라우저 스크롤을 내린다음, 아래스샷 을 참고하여 계산버튼을 선택한다.





중소기업 취업청년 감면대상 총급여액 (100%) 수정란데 총급여부분을 붙여넣고 계산하기를 누르면 자동계산된다. 적용하기 버튼을 누르면 원래 페이지에 계산값이 반영된다. 




적용된 납부세액이 하면에 나타나고 환급받을 계좌정보를 입력하고 신고서 작성완료 버튼을 선택한다. 


신고내역란에 정정 청구이유는  세액감면 - 중소기업  취업청년에 대한 소득세 감면(조특별$30) 선택한다. 



최종신고내역이 나타나고 신고서 제출하기를 누르면 정상적으로 접수가 완료된다. 


그리고 하루뒤 결과가나왔는데 ....



처리가 취하되었다고 통보를 받았다. 

관할세무서 담당자와 확인해서 알게된 점은 

법이개정되더라도 소급적용은 되지 않는다고 했으며, 입사일이 34세인 2016년 에 입사한 이력이 있어서, 향후 5년 세금감면 (90%) 받을수 있다는 안내를 받았다.

경정청구신청 및 결과에 대한 내용을 우편으로 전달받을 수 있다. 

친절하게도 전화로 궁금하게 물어봤던 신청내역에 대해서 정리 및 의견까지 같이 정리해주셨다.

중소기업 감면을 신청받기 위해서는 현재 재직중인 직장 혹은 재직했었던 직장에 '중소기업 취업자 감면신청서'  제출해야되며 신청서를 제출받은 회사는 관할 세무서에 중소기업 취업자 소득세 감면 대상 명세서를 제출해야 한다. 회사 관할 세무서에서 해당 법인의 중소기업 여부를 판단하여 감면 대상자로 승인 판정이 나야 감면 적용이 가능하다.





블로그 이미지

클라인STR

,


Intellij SVN 소스를 커밋할일이 생겼는데, 한번도 사용해본적이없어서 사용한 방법을 기록해 본다.


Subversion -> Update Directory 선택한다.


Update Directory 화면이 뜨고 OK를 선택한다. 


svn 인증정보를 요청한경우 User name 과 Password 정보를 입력하고 OK를 선택한다. 


Files Merged with Conflicts 화면이 이 나타나며 Merged 또는 Conflicts난 소스 리스트가 나타난다.  

Merge 버튼을 선택한다.


3개의 분할된 영역이 나타난다. 왼쪽이 현재 내가 가진 소스 버전이고 오른쪽이 서버의 소스버전이며 가운데영역이 실제 merged될 결과를 표시하는 영역이다.



붉은색으로 표시된 화살표 모양을 클릭하면 반영하고자하는 소스 내역이 가운데 Result 영역으로 합쳐진다. 충돌내역을 잘 확인하고 적용 버튼을 선택한다.


Subversion -> Commit Directory 를 선택한다.


Commit Change 화면에서 commit 내역을 확인하고 Commit 버튼을 선택한다. 


Code Analysis 창이 뜨고 Commit 을 선택하면 Commit이 완료된다.


참고 : https://okky.kr/article/279048

블로그 이미지

클라인STR

,

1. Messages.properties 파일 생성하기

resources 폴더 밑에 messages.properties 파일을 생성한다. 
파일은 messages_언어.properties

2.Spring에 MessageSource 설정하기

Config.java

@Configuration
@EnableWebMvc
@ComponentScan(
basePackages="com.example.app"
)
public class Config extends WebMvcConfigurerAdapter{
@Bean
public MessageSource messageSource(){
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasenames("messages/messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor(){
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
return localeChangeInterceptor;
}
@Bean(name = "localeResolver")
public LocaleResolver sessionLoacleResolver(){
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setDefaultLocale(Locale.ENGLISH);
return localeResolver;
}
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(localeChangeInterceptor());
}
}

WebMvcConfigurerAdapter 상속받은 Config.java MessageSource 설정을 진행한다.

3. 사용하는 방법

@Autowired
private MessageSource messageSource;

MessageSource를 사용하기위해 DI(Dependency Injection) 하여 사용한다.

MessageSource Method 인자 설명

String getMessage(String code, Object[] args, String defaultMessage, Locale locale);

code : 프로퍼티에서 설정한 key 값 
args : key에 해당하는 value값에 {0}, {1} 등으로 매핑되는 값 
defaultMessage : key 값을 찾지 못할 경우 표출될 값 
locale : 지역코드 값

사용예

String message = messageSource.getMessage("com.button", null, locale);



블로그 이미지

클라인STR

,

Lombok이란?

개발이야기 2018. 10. 30. 17:56

Lombok이란?

Lombok(롬복) 은 자바에서 @Getter, @Setter 같은 annotation 기반으로, 기존 DTO, VO, Domain Class 작성할 때, 멤버 변수에 대한 Getter/Setter Method, Equals(), hashCode(), ToString()과 멤버 변수에 값을 설정하는 생성자 등등을 자동으로 생성해 주는 라이브러리이다. 추가로 일반적인 Class에서 Log와 같은 명령어를 간단하게 사용 할 수 있도록 도와준다.





기능

@어노테이션설명세부기능
@Getter @SetterGetter, Setter 메소드 자동생성– AccessLevel : 해당 접근 제한자를 설정
– lazy : 동기화를 이용하여 최초 1회만 호출
@ToStringToString 메소드 자동생성– exclude : 출력하지 않을 필드명 입력 
– includeFieldNames : 필등명 생략 여부 설정
– callSuper : 상위 클래스 toString호출 여부 설정
@EqualsAndHashCodeequals, hashcode 메소드 자동생성-
@Data@ToString, @EqualsAndHashCode, @Getter, @Setter, @RequiredArgsConstructor 자동생성-
@valfinal 키워드 대신 사용하는 변수 선언 class-
@NonNull해당 값이 Null 일경우 NullPointerException을 발생-
@Cleanup자동 리소스 관리 : close() 메소드를 귀찮음 없게 안전하게 호출-
@EqualsAndHashCodehascode 와 equals 메소드를 생성– of : 포함 할 필드, – exclude : 제외 할 필드
@NoArgsConstructor인자 없는 생성자 생성-
@RequriedArgsConstructor필수 인자만 있는 생성자 생성(다른 생성자가 없을 때에만 만들어짐)-
@AllArgsConstructor모든 인자를 가진 생성자 생성-
@Value불편 클래스를 쉽게 생성-
@BuilderBuilder API 처럼 사용 할 수 있도록 지원-
@SneakyThrowsException 발생시 체크된 Throable로 감싸서 전달-
@Synchronized메소드에서 동기화 Lock을 설정-
@Log종류별 로그를 사용할 수 있도록 한다.– 기본 변수명 : Log
(Config 파일 만들어서 명칭 변경 가능)
– 로그 종류 : @Log, @Slf4j, @CommonLog, XSlf4j, JBossLog 등

Ex) Code

@Data
@ToString(exclude = {"name", "address"}, includeFieldNames = false, callSuper = true)
@EqualsAndHashCode(of = {"name", "address"}, exclude = {"gender", "phone"})
public class LombokGsonSampleInfo {
private String id;
@Getter(AccessLevel.PRIVATE) @Setter(AccessLevel.PUBLIC)
private String name;
@NonNull
private String email; // 메소드의 인자가 null일 경우 Exception을 출력 한다
// (java.lang.NullPointerException)
private String address;
private String gender;
private Phone phone;
}


IntelliJ 설치방법

Maven > pom.xml > dependency 추가

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
<scope>provided</scope>
</dependency>


plugins 에서 Lombok 플러그인을 설치한다.



Setting > Build, Execution, Deployment > Comipler > Annotation Processors > Enable annotation processing 체크해야 롬복이 정상적으로 동작한다. 

참고 : https://projectlombok.org/


블로그 이미지

클라인STR

,

1. 드래그 구현

마우스를 누른 상태에서 움직이면 선택한 요소가 함께 이동하는 것을 드래그라고 한다. 이런 드래그 기능을 구현하기 위해서는 다음의 3가지 마우스 이벤트를 사용하면 된다.

mousedown - 드래그할 객체를 선택할때 사용
mousemove - 객체를 드래그할 때 사용
mouseup - 드래그를 종료할 때 사용 


mousedown  발생하면 
드래그할 요소지정, 마우스 포인트와 요소 좌측상단 사이의 거리 저장
document 객체에 mousemove와 mouseup 이벤트를 등록한다
이벤트 전파를 중지.


mousemove 발생
드래그 할 요소 위치를 이동, 이 때 앞서 저장한 마우스 포인트와 요소 좌측 상단 사이의 거리값을 사용.
이벤트 전파를 중지.

mouseup 발생
드래그 중이 아닌 것으로 지정
이벤트 전파 중지

가장 먼저 할 작업은 드래그로 이동하길 원하는 요소에 mousedown 이벤트 핸들러를 등록하는 것이다. mousedown 이벤트가 발생하면 해당 요소를 드래그 할 것이라고 표시하게 된다. 이때 마우스 포인터와 드래그 요소의 좌측 상단 사이의 거리를 저장해야 한다. 그 이유는 마우스를 움직일 때 알맞게 요소를 이동시키기 위해서 이다. 그 이유는 마우스를 움직일 때 알맞게 요소를 이동시키기 위해서 이다.

마우스가 이동하면 요소의 좌측 상단을 마우스 이동한 거리에 비례해서 이동시켜 주어야 하는데, 드래그할 요소를 선택할 때 마우스 포인터와 요소 좌측 상단사이의 거리를 저장하지 않는다면 비례해서 이동할 수 없을 것이다.

실제로 드래그 기능을 어떻게 구현하는지 SimpleDragSource 모듈을 통해서 살펴보자.

1.1 단순 드래그를 지원하는 SimpleDragSource 모듈 작성하기

이번 절에서는 다음과 같은 코드만 실행하면 관련 요소를 드래그할수 있도록 해주는 SimpleDragSource를 만들어 보기로 한다.

var drag  = new ajax.dnd.SimpleDragSource("car");


dnd.js


  
        ajax.dnd = {};
        ajax.dnd.SimpleDrag = function (elementid) {
        this.element = document.getElementById(elementid);  //드래그 가능하게 할요소구함
        this.dragging = false; //현재 드래그 중인지 여부 표시
        this.selected = false; //현재 마우스 다운 상태인지 표시
        this.diff = null;         //마우스 위치와 객체 위치
        
        this.mouseDown = ajax.Event.bindAsListener(this.doMouseDown, this);
        this.mouseMove = ajax.Event.bindAsListener(this.doMouseMove, this);
        this.mouseup = ajax.Event.bindAsListener(this.doMouseUp, this);
        
        ajax.Event.addListener(this.element, "mousedown",this.mouseDown);
        //드래그할 요소에 mousedown 이벤트 등록
       }
       
       ajax.dnd.SimpleDrag.prototype = {
       
         doMouseDown : function(e) {
            var event = window.event || e;
            if(!ajax.Event.isLeftButton(event))           return;
         this.selected = true; //드래그 하기 위해 선택한 상태로 표시
         
         //드래그할 요소와 마우스 포인터 사이의 거리를 구해서 저장
        var elementXY = ajax.GUI.getXY(this.element);
         var mouseXY = ajax.Event.getMouseXY(event);
         this.diff = {
            x: mouseXY.x - elementXY.x,
            y: mouseXY.y - elementXY.y
            
            };
            
          ajax.Event.addListener(document, "mousemove", this.mouseMove);
          ajax.Event.addListener(document, "mouseup" , this.mouseUp);
          //document에 mousemove와 mouseup 핸들러 추가
          ajax.Event.stopEvent(event);
         
         },
         
        doMouseMove: function(e) {         //mousedown 처리 후, mousemove 발생하면 호출
           if(!this.selected) return false; //선택된 상태가 아니면 이동시키지 않음
         
         if(!this.dragging) {
            this.dragging = true;
            ajax.GUI.setOpacity(this.element, 0.60);  
            }
            // 첫 번째 mousemove 발생시 드레그 상태로 변경하고, 요소를 투명하게 처리
            
           var event = window.event || e;
           var mouseXY = ajax.Event.getMouseXY(event);
           var newXY = {
              x: mouseXY.x - this.diff.x,       //마우스 위치에서 라인 25에서 저장한 거리 값을 빼서 요소의 새로운 위치를 구함
              y: mouseXY.y - this.diff.y
            }
           ajax.GUI.setXY(this.element, newXY.x, newXY.y); //위치변경
           
           ajax.Event.stopEvent(event);
        },
        
        doMouseUp: function(e) {        // mousedown 처리 후, mouseup 발생하면 호출
            if(!this.selected) return;
            
            this.selected = false;  //선택되지 않은 상태로 변경하고 앞서 구한 마우스와의 거리 값도 없앰
            this.diff = null;
            
            var event = window.event || e;
            if(this.dragging) {
                this.dragging = false;
                ajax.GUI.setOpacity(this.element, 1.0); //드레그 중이었으면 드레그 상태 아니라고 표시하고, 요소를 불투명하게 처리
            }
            
            ajax.Event.removeListener(document, "mousemove", this.mouseMove);
            ajax.Event.removeListener(document, "mouseup" , this.mouseUp);
            ajax.Event.stopEvent(event);
        }
      }  


SimpleDrag  클래스의 생성자에서 드래그할 요소에 mousedown 이벤트 핸들러를 등록한다. 사용자가 드래그할 요소에서 mousedown 이벤트를 발생 시키면 doMouseDown 함수가 호출된다.

doMouseDown 함수는 드래그 요소가 선택되었다는 것을 나타내기 위해 this.selected 변수 값을 true로 할당한다. 그런 뒤, 마우스 포인터와 드래그 요소 사이의 거리를 구해서 this.diff에 저장한다. 마지막으로 document 객체에 mousemove 이벤트 핸들러와 mouseup 이벤트 핸들러를 등록하고 이벤트 전파를 중지시킨다.

이제 사용자가 마우스를 이동하면 doMouseMove 함수가 호출된다. doMouseMove 함수는 드래그 요소를 선택한 이후(즉, mousedown 이벤트 발생 이후) 처음 마우스를 이동한 경우, 드래그 상태임을 표시하기 위해 this.dragging 변수 값을 true로 지정한다. 이때 요소를  토명하게 함으로써 이동 중임을 시각적으로 알 수 있게 하였다. 이후 mousedown 이벤트가 발생하면 this.dragging 값이 true 이므로 ,
    if(!this.dragging) {
            this.dragging = true;
            ajax.GUI.setOpacity(this.element, 0.60);  
            }
라인은 더이상 실행되지 않는다.

doMouseMove 함수는 this.dragging 값을 판단한 후, 마우스 포인터의 위치를 구한다. 마우스 포인터의 위치로부터 this.diff에 저장된 값을 빼서 드래그 요소의 새위치를 구한다. 그런 뒤 요소를 새로운 위치로 이동한다.

마우스를 이동하다가 버튼을 떼면 doMouseUp 함수가 호출된다. doMouseUp 함수는 현재 드래그 중인지의 여부를 판단한다. 그 이유는 마우스 버튼을 누른 뒤, 마우스를 이동하지 않으면 마우스가 드래그 중이지 않았으므로 이동과 관련된 마무리 처리를 할 필요가 없기 때문이다. 드래그 중이었다면 this.dragging의 값을 false로 지정해서 드래그 중이 아닌 상태로 변경하고, 드래그 중에 요소를 투명하게 설정했으므로 요소를 불투명하게 변경한다.

마지막으로 document 등록했던 mousemove 이벤트 핸들러와 mouseup 이벤트 핸들러를 등록한다. 만약 이 두 이벤트 핸들러를 제거하지 않으면, 드래그 중인지에 상관업이 마우스가 이동되거나 버튼을 뗄 때마다 이 두 이벤트 핸들러가 호출되어 불필요하게 자원을 소모하게 된다.

SimpleDrag.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="SimpleDrag.aspx.cs" Inherits="SimpleDrag" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>제목 없음</title>
    <script type="text/javascript" src="ajax.js"></script>
    <script type="text/javascript" src="dnd.js"></script>
    <script type="text/javascript">
    window.onload = function() {
        var drag1 = new ajax.dnd.SimpleDragSource("car");
        var drag2 = new ajax.dnd.SimpleDragSource("navi");
    
    }
    </script>
    <style type="text/css">
    #navi {
        position: absolute;
        background-color: #aaa;
        left:200px top:90px;
        width: 150px; height: 80px;
       }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <img src="car.jpg" id="car"/>
    자동차 이미지를 생각해봅시다.
        <div id="navi">
     플로팅 메뉴<br/>
     메뉴1<br/>메뉴2
     </div>
        </form>
</body>
</html>

실행결과


드래그 후


출처 : Ajax/최범균님의 AjaxProgramming 다시읽기




블로그 이미지

클라인STR

,