고베그릴

메뉴 : 하이블렌딩 코크 * 2 (16,000원)  + 와규 모둠 (60,000원) + 비빔냉면(5,000원)

total : 81,000원

후기 

깍돌이 : 수도권에서 먹어본 최고의 고기 중 하나 

깍순이 : 가격에 걸맞는 맛 && 가격 대비 착한 맛



일이 바빠 포스팅 하기가 너무 힘들지만 그래두 열심히 하려고 하고있습니다. ㅜㅜ

 

지난 포스팅때 만들어 놓은 Naver Login  - selenium-JS ( iframe 대처 방안 - IE 버전) 이 있는데요

 

// naver 자동 로그인하여서 최근 메일 가져오기  - IE 

http://ipex.tistory.com/entry/webUI-Naver-Login-seleniumJS-iframe-%EB%8C%80%EC%B2%98-%EB%B0%A9%EC%95%88-IE%EB%B2%84%EC%A0%84?category=770641

 

해당 소스코드가 Windwos 10 에서 같은 드라이버와 같은 브라우저 버전 같은 npm Node.js 버전을 사용하여도

 

동작하지 않습니다.

 

??

 

일단 멈춰지는 소스코드는 await loginBtn.click(); 입니다.

여기서 클릭이 안됐는데 다음 DOM 찾고 객체 찾고를 반복 하다보니

 

되지않던 현상이였습니다.

 

관련 내용을 찾아 보니

 

셀리니엄 HQ에 이런 이슈가 있더군요

 

// 링크

https://github.com/SeleniumHQ/selenium/issues/4292

 

 

 

이슈는 역시 Closed 되어있고

 

셀레니엄팀에서 해줬을 거라고는 생각 하지 않습니다. 

 

(최신버전을 쓰고있는 저에게 되지않으니까요 Stable 버전 기준으로)

 

아래 글 내용들을 읽어 보니

 

결국 우회 처리로 요소를 클릭 하였습니다.

 

그 우회 처리란

  // login 버튼 가져와서 클릭          let loginBtn = await driver.findElement(By.css("input[type='submit']"));         await loginBtn.click(); 

 

기존에는 위와같이 await loginBtn.click() 이 동작하였지만 Windwos 10 에서는 동작하지가 않습니다.

 

그래서 사용하는 우회 방법은

 

Driver 모듈에 있는 executor를 이용하는 방법입니다.

 

일단 JS DOC을 한번 확인해보겠습니다.

 

 

보시면 2개가 있는데 Async 근 비동기방식이고 제가 펼쳐 놓은 이 executor는 동기 방식으로 차이는 없습니다.

 

자 보시면 (Script,... args) 라고 되어있습니다.

 

앞에 파라미터로는 스크립트가 들어갈 것이고 뒤에 arguments로는 WebElement가 들어가야 된다고 쓰여있네요

 

그럼 저 위에 동작하지 않는 login Btn 을 어떻게 클릭을 할것인가 하면

 

말그대로 앞에는 스크립트 ( 클릭 스크립트를 넣을것이고) 뒤에는 가져온 WebElement ( loignBtn 을 넣어서 확인합니다.)

 

 

         await driver.executeScript('return arguments[0].click()",loginBtn);  

단순합니다. 우측에 놓은 element 가 arguments로 넘어오게 되고 1개만 넘겼으니 [0]으로 첫번째 값을 가져오면 됩니다.

 

가져온 후에 click 을 하는 스크립트로 return 을 넣어주면 driver executor에서 해당 반환된 스크립트를 브라우저로

 

인젝션하게 되어 실행을 합니다.

 

해당 이슈에서도 그렇고 여러 Win10 분들은 이와 같은 방안으로 우회를 하고 있는 것으로 보여집니다. 

 

win 10에서 네이버 로그인시 DOM 도 제대로 못가져오는 경우가 있는데

 

이에 대해서는 다음 포스팅때 작성 하도록 하겠습니다.

 

감사합니당

 

 

 

 

안녕하세요 노드에서 파일 작업을 하여야 하는 경우가 생겼는데 예전에 한번 썻었지만 기억도 나지않고


예전에 사용했던 경우는 그냥 단순 파일 쓰는 작업만 해서 이번에는 폴더가 있는지 체크해서 없으면


해당 폴더를 만든후에 -> 폴더를 만들고 해당 폴더 안에 파일을 작성하는 것을 포스팅 하려고합니다.


노드버전은 LTS버전인 10.6 기준입니다.


우선 기본적으로 알아야 할 것이 있습니다.


__dirname;


개인변수명 작성시에 preFix로 __로 지양 해야 겠네요 

File System 에 대한 내용은 전부 docs 에 너무 잘되어있기 때문에 다른점은 참고 하셔도 될것 같습니다.


/* Node.js docs 10.6.0 Documentation - File System */

https://nodejs.org/dist/latest-v10.x/docs/api/fs.html



const fs = require('fs');

const _path = __dirname;

console.log(_path);


결과는 현재 폴더 트리의 위치가 나타나게 됩니다. __dirname을 알고 있어야 어느 폴더로 이동하여서


노드가 실행 되어도 문제가 되지 않을것 같습니다.




const fs = require('fs');

const currPath = __dirname+"/_test_/";
let version =currPath+'Fixed/';


let arr = ['linearlayout','button','datepicker'];

let contents_ =['content','tea','test','b','e','t','set','s','hg'];

let writeFile = (filename,contents)=> {
            
    fs.open(filename,'w',(err,fd)=>{
            if(err) throw err;
            console.log('file Open - :',filename.split('/')[filename.split('/').length-1]);
           fs.writeFile(fd,contents.join(','),(err)=>{
                        if(err) throw err;
                    console.log(filename + ' - write\n');
                });
    });
};
try{

       if(!fs.existsSync(version)){
                console.log(version.split('/')[version.split('/').length-1]+" 폴더가 없습니다.생성합니다.");
              fs.mkdir(version,0700,function(err){
                        if(err) throw err;
                    for(let i=0;i<3;i++){
                            writeFile(version+arr[i]+'.txt',contents_);
                    }
            });
        }
       else{
                console.log(version.split('/')[version.split('/').length-2]+" 폴더가 존재합니다.");
                    for(let i=0;i<3;i++){
                            writeFile(version+arr[i]+'.txt',contents_);
                    }
        }

}
catch(err){console.error(err);}

finally{
        console.log('File System Working Clean');
}
       






JavaScript의 Scope는 Block(블록 { } ) 이 아닌 Function(함수)에 의해 정해집니다.


우선 scope에 대한 간단한 예시 입니다. 


scope(유효범위) 란 ?


JavaScript 뿐만 아니라 모든 프로그래밍 언어에서도 통용되는 말이며


block Scope라 함은 

{

  변수 선언 

}

시 block 을 나가면 선언된 변수가 block 안에서만 생존 하는 것을 말합니다.

JavaScript는 기본적으로 block Scope가 아니라 Function Scope 입니다.

function a(){

변수 선언! (A)

    {  

     변수 선언 !(B) 

   }



// 변수 A와 B둘다 살아있음

}



이와 같이 변수를 선언해도 펑션안에서는 어떻게든 살아서 있기 때문에 접근도 가능합니다.

기본적인 block Scope는 C 언어를 보면 알수 있습니다.



블록 안에서 선언된 변수 들은 블록 안에서 끝나지 않고 Function(함수) 단위로 가게 됩니다.


그에 해당 하는 테스트 샘플 코드입니다.





function foo()
{
		console.warn('__Before__');	
		typeof first ==='number' ? console.log('first exist') : console.error('first not exist');
		typeof Internal==='function' ? Internal() : console.error('not exist');
		/*
			first not exist  'number'로 비교하였지만 undefined로 호이스팅(끌어올리다) 
			Internal exist   'function' 으로 비교하여 참조 의 호이스팅이 되는점 확인 -> 실제 함수 사용까지 가능)

		*/
		var first = 1;
		function Internal(){console.log("Internal exist");}

		console.warn('__after__');
		typeof first ==='number' ? console.log('first exist') : console.error('first not exist');
		typeof Internal==='function' ? Internal() : console.error('not exist');

		/*
			first exist 
			Internal exist 
		*/
		if(first===1){var third = 3;};

		typeof third==='number' ? console.log('third exist') : console.error('third not exist');
		
		/*
			third exist  var third 선언은 if(first===1) 분기를 타고 블록(block) 안에 선언되었지만 밖에서도 참조가 가능
		*/

}
foo();






Hoisting ?

코드 실행 전의 변수와 함수 선언을 해당 범위의 맨위로 이동 시키는 JavaScript 의 매커니즘 


고려해야 할 조건이 있습니다.


1. 변수 할당은 함수 선언보다 우선 

2. 함수 선언은 변수 선언보다 우선 

-> 하지만 함수 선언이 변수 할당을 넘어 서진 않습니다.



관련 참고 사이트 // 설명이 잘 되어있습니다. 

https://scotch.io/tutorials/understanding-hoisting-in-javascript






이런느낌으로 알고 지나가는게 좋을 것 같습니다.


펑션은 호이스팅으로 참조까지 가능하지만


변수(var)는 undefined로 호이스팅이 되는점









C언어는 절차 지향 언어라고 할수 있다. 해당 내용은 절차지향에 대한 이야기 일뿐


자바스크립트와는 많은 관련이 있진 않습니다. C를 하다 넘어 왔기 때문에


자바스크립트도 절차지향으로 보여 잘못생각하였던 부분에 대한 설명입니다.






#include 
using namespace std;


int main(void)
{
	printf("CPP Test\n");

	show(); //show 식별자를 찾을수 없습니다. 에러 
	return 0;
}

 void show() 
{
	printf("Show Call");
}

const int OpenResult(int flag) 
{


}



// 해당 호출이 불가능해지기 때문에


// 실제 사용시에는

// 이 처럼 코드 상단에 미리 선언을 하고 원형을 하단에 작성한다.C 의경우


#include 
using namespace std;

// 절차 선언 
void show();
int main(void)
{
	printf("CPP Test\n");

	show();
	return 0;
}

 void show() 
{
	printf("Show Call");
}


의 형태로 지원되어야 한다. 절차지향




자바스크립트 또한 그럴것이라 생각 하였지만 실제 JS에서 유효범위는 생각과는 달랐다.










function external(){

typeof Internal ==='function'  ?  console.log("Internal  exist") : console.log("Internal  not exist");

function Internal (){};

typeof Internal ==='function'  ?  console.log("Internal  exist") : console.log("Internal  not exist");

window.Internal === undefined ? console.log('Internal is not window exist' ) : console.log('Internal window exist');

window.external === undefined ? console.log('external is not window exist') : console.log('external window exist');
}

external();




결과


Internal  exist

Internal  exist

Internal is not window exist

external window exist



1번째에


typeof Internal ==='function 부분에서 exist로 넘어가는것으로 보아


절차적으로 코드가 생성되는것으로 보였지만 


자바스크립트의 유효범위는 블록이 아니라 함수에 의에 정의된다고 할수있다.


여기까지보면 뭔가 큰 차이가 안 느껴져서  자바스크립트의 Scope Chain 은 Function 이라는 예제를 하나 더 들수 있다.

C의 경우




void show() 
{
	printf("Show Call");

	for (int i = 0; i < 5; i++)
	{
		int b = 10;

	}
	printf("B is %d", b);
}

// 와 작성시 이미 printf b 에서 컴파일 하기도전에 validation 에 걸립니다. b가 정의되어있지 않습니다. 
// C,C++에서는 Scope Chain 은 Block Scope를 가진다는 것을 알수 있습니다. 

JavaScript 의 경우


function show()
{
   for (var i=0;i<5;i++)
   {
			var b = 10;
   }
console.log("B is ",b);
}
show();


// 결과
// B is  10



자바 스크립트의 Scope Chain 은 위와 같이 Function 을 가지게됩니다.


이에 대해서 JS 작성시 실수하였던 점이





   for(var i=0;i<10;i++)
  {   
        for(var j=0;j<10;j++)
        {
              for(var i=0;i<5;j++)
              {
               }

         }

        
  }
       









해당 식의 코드를 한번 짤일이 있었는데 디버그 하다가 애를 먹었던적이 있습니다.


처음 i 0 ~을 돌다가 3번째 for문에서 i가 4인 채로 끝나기 때문에  자기 밖으로나가면 i2가 된상태로 돌아야하지만


i4인채로 끝나서


첫번째 포문에서 i 0 1,2,3 부분이 건너 뛰고 바로 4로 넘어가는 현상이 생겼습니다.


js에서는 function Scope Chain 을 가지기 때문에 해당 부분에 유의 하여야 합니다.


최근 ES스펙이 오름에 따라서 let변수가 해당 C,C++의 block scope 를 가지게 도와주지만 해당 내용은 뒤에 작성하도록 하겠습니다.













규카츠의 타게루(カツのタケル 日本橋店)

메뉴 : 규카츠(1,100엔) + 맥주(600엔-추측)

total : 1700엔

후기 

깍돌이 : 맥주와 조화가 너무 좋다

깍돌이 친3 : 환상의 맛


윤밀원

메뉴 : 족발(27,000원) + 막국수(9,000원)

total : 36,000원

후기 

깍돌이 : 족발 소스가 진짜 맛있다. 막국수

깍순이 : 족발의 느끼함을 밑 반찬이 잡아준다. (개인적으론 칼국수가 제일 맛있다.)




flex Box 모델


기존에 사용하던 inline inline-block , table 등이 아닌 flex라는 모델이 CSS3에서 도입되었습니다.


flex에서 가장 좋았던 점은 세로 수직 정렬이든 여러 정렬등이 너무 편리하게 동작할수 있다는 점이고


flex박스에 장점은 동적은 변경 가능한 순서를 지정하고 사용할 수 있는 공간내에서 자동으로 너비와 높이를 지정 할 수 있습니다.


이제부터 flex display 로만 화면을 구성해볼겁니다.


아래의 화면도 전부 flex로 구성되어있으며  아래 화면에 대한 html 코드 리뷰를 하고 


다음 포스팅부터는 flex의 속성 하나하나 훑어볼 예정입니다.


기준은 Chrome을 기준으로 하겠습니다.  IE에 대한 트러블 슈팅은 따로 ..









<!DOCTYPE html>
<html>
<head>
      <meta charset="utf-8">
      <title> CSS3 FlexBox </title>
<head>
<style>
/* padding 및 border를 width 와 height 에 포함한다.  margin X  > box-sizing:border-box */
*{
      box-sizing:border-box;
      
}
html,body{
   display:-webkit-flex;
   display:flex;
  
   
   flex-wrap:wrap;
   -webkit-flex-wrap:wrap;
   
   width:100%;
   height:100%;
   padding:0;
   margin:0;
}

header{
   width:100%;
   height:80px;
   background-color:#DAD9FF;
}

div#bodyLayout{
   display:flex;
   
   width:100%;
   height:calc(100% - 180px);
}

nav {
   display:flex;
   width:10%;
   height:100%;
   background-color:#4641D9;
   color:white;
}

article{
   display:flex;
   width:90%;
   height:100%;
   background-color:#FFD9EC;
   border : solid 3px black;
   overflow-y: auto;
}
footer{
   width:100%;
   height:100px;
   background-color:orange;
}

</style>
   <body>
         <header>
               header 태그입니다.
         </header>
         <div id="bodyLayout">
            <nav>
               <ul>
                  <li>nav Tag</li>
               </ul>
            </nav>
            
            <article>
               flex 테스트 본문입니다.
            </article>
         </div>
      
         <footer>
                  footer 입니다.
         </footer>
      <script>
         window.addEventListener('load',function(){
                console.warn('onLoad flexBox Test')
         });   
         
         window.addEventListener('unload',function(){
                 alert("unLoad flexBox Test");
         });   
         /*
            load = 페이지를 전부 다 읽어 들인 후 발생
            unload = 페이지로부터 빠져나갈때 빨생  
            
            
         */
   
      </script>

   </body>
</html>



flex-wrap :  body랑 html 에 해당 flex-wrap:wrap


을 지정한 이유는 기존의 inline-block 이나 inline, block 을 통해서 적용시 였으면


header가 100%로 잡혀있고 div는 기본 block 형식이니 화면을 꽉채울거라 생각 했지만


flex의  경우 flex-wrap 이 기본(default)이 nowrap 으로 되어있다보니


지정을 안할시에는 이와같이 나타납니다. 위의 코드를 받아서 지워보시고 확인해 보시면 됩니다.


nowrap 은 한정된 영역내에서 자동으로 너비와 높이를 잡아 주게 되며


flex-wrap 을 wrap 으로 지정하게되면 맨 처음 사진과같이 넘치면 아래줄로 넘기게됩니다.


그래서

width 기준 


[ Header 100% ]

[ nav 10% article 90% ]

[ footer 100% ]


을 가지게됩니다. 또한 * {

box-sizing:border-box; 부분은 왜 했을까 할수도있는데요 

}


article을 보시면 border 에 3px가 들어가있습니다. border-box가 아닌 일반 박스모델에서 는 width 90% 를 하였어도 border를 지정하면 해당값을 제외 하고 계산하기때문에 넘쳐서 아래로내려가는 현상이 발생합니다.



box-sizing을 지우니 해당과같이 아래의 border가 덮여지게됩니다.


이것을 해결하기 위해 width 에 border를 포함하는 방법이 box-sizing: border-box입니다. 모든 레이아웃에


적용하기 위해서 *{ }를 지정하였습니다.



지정하게되면 이와같이 사이즈에 포함 시키기 때문에 문제가 발생하지않습니다.


box-sizing을 따로 작성하도록 하며 border-box는 border와 padding만 계산하고 margin 은 계산하지 않기 때문에


margin 에 대한 처리는 따로 해주어야 합니다.


이후 포스팅은 분홍 부분에다가 관련 코드를 작성 하도록 하겠습니다.


이외에 flex 에 대한 설명이 있는 사이트가 있는데 링크 남깁니다.

* 너무 잘되어있어서 이거보다 자세히 설명은 .. 

// flex 설명 

https://css-tricks.com/snippets/css/a-guide-to-flexbox/

http://www.beautifulcss.com/archives/2812 

// flex 구버전 사용

https://css-tricks.com/using-flexbox/


앞서 UI 자동화에 대한 기본적인 개요 및 네이버 자동 로그인을 IE 11과 Chrome(66 Stable)로 테스트 해보았습니다.


이제 제대로 업무에 적용하기에 앞서 자동화가 이루어지기 위해서 빠지지 않는 webDriver에 대해 조사해보았습니다.



Selenium WebDriver

Selenium webDriver(셀레니엄 웹드라이버) 는 많은 브라우저(FireFox,Edge,InternetExplorer,Chrome...) , 운영체제 및 프로그래밍언어(ruby,js,C#,JAVA,Python .. ) 등을 지원하며 웹 응용 프로그램들의 테스트 를 단순화 함과 동시에 가속화를 도와주는 툴입니다.

해당 Selenium WebDriver 가나오기전 있었던 Selenium Remote Control(RC) 버전이 있었습니다.

해당 제품의 구동 방식은 이와 같습니다.

[Chrome]


Chrome 바이너리가 실행 되고 Remote Controller를 통해서 해당 Chrome에 메시지를 전달하고 다시 받고 다시 전달 하는 방식을 취득하였으며 지원되는 브라우저도 적었으며 RC구현으로 인해 OS의 제약도 많았습니다. 


또한 해당 메시지 방식을 취득 하다 보니 실제 사용자의 동작으로 보이지 않는 경우도 있었습니다.


이러저러한 문제점으로 인해 Selenium WebDriver(2.0) 이 webDriver + Selenium1.0 으로 나오게 되었으며


Selenium WebDriver 의 장점이 있습니다. 


1. 다채로운 프로그래밍 언어 지원

    기존의 Selenium IDE와는 다르게  Java,PHP,Perl,Ruby,Python,C#,JS 등을 지원합니다.

2. 매우 단순한 사용 법

    기존의 RC사용법은 RC실행 + 드라이버 세팅  + Selenium 세팅 및 스크립트가 따로 가야 하지만

    WebDriver는 StandardAlone으로  내부적으로 한번에 스크립트를 사용하여 제어합니다.

3. 실제 사용자 동작을 예뮬레이션 합니다.

    동작 내용을 확인해 보면 아실수 있겠지만 WebElement 등을 클릭할때 마우스로 인한 포커싱이 되는 모습을 확인 

    이가능합니다.

4. 기존보다 스크립트 실행 속도가 빠릅니다.

    - 해당은 제가 기존을 사용하지 않아서  확인을 못해봤습니다.

5.  API 지원

    WebDriver API 를 통해서 어렵지 않게 개발등이 가능합니다.

 (JS로 하는에 손쉬운거 같진 않지만)


chromedriver.exe가 하는 역할은  selenium에서 webdriver명령을 보낼때 크롬을 제어 하는 방법 을 제공해주는데


이를 크롬 57버전까지는 자동화 확장 기능을 사용하여 크롬과 통신을 원할하게 하였지만


크롬 58 버전 부터는 확장 기능을 제거하고 WebSocket 통신을 사용하고 원격 디버깅을 지원하는 크롬의 dev tool api 에서 모든것을 제어하는 방법으로 바뀌었습니다.


그러므로 자동화 실행시에는 위의 크롬은 현재 자동화 테스트 소프트웨어로 인해 제어되고 있습니다. 라는 메시지가 나타납니다.


설명이 매우 부실해보이지만.. 필요하면 더 추가하겠습니다.


Selenium 관련하여 이슈 트래킹 사이트가 있습니다.


안되 는 것이 있을 경우 이슈트래킹에서 


확인 해보시기 바랍니다.


https://github.com/SeleniumHQ/selenium/issues



또한 최근에(?) 만들어지는 Selenium 개발자가 직접 프로젝트를 합쳐서 만드는 4.0 Alpha 버전에 대한


지원 레밸 정의입니다.


대충 보면

이슈를 재기해도 고치진 않을것이고 fix되지 않은 API 에 대한 보장은 해주지 않겠지만

최선을 다해서 내부적으로 이슈를 찾아서 고칠 것이며  selenium 은 플랫폼 API 와 호환 API 를 릴리즈 한다.

Support Level Definitions

  • supported: A selenium-webdriver release will be API compatible with the platform API, without the use of runtime flags.

  • best effort: Bugs will be investigated as time permits. API compatibility is only guaranteed where required by a supported release. This effectively means the adoption of new JS features, such as ES2015 modules, will depend on what is supported in Node's LTS.

  • unsupported: Bug submissions will be closed as will-not-fix and API compatibility is not guaranteed.






해당 에러는 줌 레벨 문제로 나타나는 에러인데 IE 드라이버로 실행할 때 만 나타나는 현상입니다.


원시적인 방법

보기 -> 확대/축소 - 100% 지정





아래와같이 코드상으로 무시할수 있습니다. IgnorezoomLevel 을 통한 


// 관련 유사 에러 링크 

http://ipex.tistory.com/entry/webUI%EC%9B%B9%EC%9E%90%EB%8F%99%ED%99%94-Error-WebDriver-NodeJS-Instantiate-IE-Driver-with-Capabilities-introduceFlakinessByIgnoringProtectedModeSettingsignoreSettings




+ Recent posts