첫번째 해결 방안

 

IE를 여신 후 보안 설정을 전부 체크합니다.

 

도구 -> 인터넷 옵션 (alt + T + O)

 

보안 탭 

인터넷 : 하단 보호 모드 사용 체크 

 

로컬인트라넷 : 하단 보호 모드 사용 체크

 

신뢰할 수 있는 사이트 : 하단 보호 모드 사용 체크

 

제한된 사이트 : 하단 보호 모드 사용 체크

 

 

 

 

두번째 해결 방안

 

코드상으로 Ignore하는 방법

 

->

const Capabilities = require('selenium-webdriver/lib/capabilities').Capabilities; let capabilities = Capabilities.ie(); capabilities.set('ignoreProtectedModeSettings', true);  capabilities.set('ignoreZoomSetting', true); 

 

와 같이 옵션을 작성후 빌드시 옵션을 넣어서 무시할수 있도록 

 

해당 방식은 사이드가 있어서 좀더 확인 후 포스팅 하겠습니다.

IE 버전입니다. 

 

트러블 슈팅 

 

현재 capabilities 가 동작하지 않는데 

1. 이그노어프로텍티드모드 세팅 true

2. 이그노어줌세팅 true

 

2개가 있는데 이유는 IE는 줌 100% , 보안에서 보호체크가 전부되어야 하기 때문이다.

이거를 코드상으로 무시를 하고 킬수가있는데 일단 코드상은 안되니

 

IE에서 직접 설정 후 코드를 돌려보시기 바랍니다.

 

iframe (IE의 경우는 swtichTo.frame('string') 이 되지않아

 iframe을 직접 찾아서 WebElement를 넘겨주어야 합니다.  (IE상의 이벤트 사이클 문제로 인함)

 

 

결과 코드 

 

 

 

 const _url = "https://www.naver.com/";    require('iedriver'); const webdriver = require('selenium-webdriver'); const {By,Util}  = webdriver; // 드라이버 빌드 // IE const Capabilities = require('selenium-webdriver/lib/capabilities').Capabilities; let capabilities = Capabilities.ie(); capabilities.set('ignoreProtectedModeSettings', true); capabilities.set('ignoreZoomSetting', true); capabilities.set('IgnoreZoomLevel', true); const driver = new webdriver.Builder().withCapabilities(capabilities).build();   const register_pc = false; (async () => {   try {     // 페이지 이동     await driver.get(_url);         // 윈도우 최대화  headless 옵션 사용시 는 의미없음     await driver.manage().window().maximize();     // input값 가져옴     let inputId = await driver.findElement(By.css('input#id'));     // ID 입력         await inputId.sendKeys('myID');     // password 값 가져옴     let inputpw = await driver.findElement(By.css('input#pw'));     // password 입력         await inputpw.sendKeys('mypw');     // login 버튼 가져와서 클릭          let loginBtn = await driver.findElement(By.css("input[type='submit']"));         await loginBtn.click();       // 최초 실행 PC일 경우 해당 페이지가 나타나기 때문에 존재한다면 등록 유무 선택     let page_ = await driver.findElements(By.css('fieldset.login_form a'));       if(!!page_){             // 등록 page_[0] 등록 안함  page_[1]             !!register_pc ?console.log("등록합니다.") :await page_[1].click();       }        await driver.sleep(2000);           // selenium-js 에서는 switchTo.frame을 통해서 프레임을 변경 한다.       console.log("프레임 변경");     await driver.sleep(5000);       await driver.switchTo().frame(await driver.findElement(By.id("minime")));     // 변경 후 프로필에 메일을 가져오고 클릭        let mail_profile = await driver.findElement(By.id('mail_count_profile'));       //  메일 클릭        //  화면 제어가 빠른 경우에 대한 sleep -> 추후 isContentsLoaded 또는 WebElement Condition 으로 변경         console.log(await mail_profile.getAttribute('href'));        await driver.sleep(1500);       await mail_profile.click();   //   // 기존 프레임으로 다시 돌아오는 경우 (page이동이없었을때)      //   //   await driver.switchTo().defaultContent();   //   // 임시 테스트용 Sleep      await driver.sleep(2000);     console.log(await driver.getTitle());     console.log(await driver.getCurrentUrl());     let newUrl = await driver.getCurrentUrl();     await driver.navigate().to(newUrl);   // // 가장 최상단 메일 의 Subject를 가져옴     let mailTitle = await driver.findElement(By.css('ol.mailList.sender_context li .subject'));   // // 셀레니엄 JS에서 getText는 innerText를 가져온다고 되어있습니다.    console.log(await mailTitle.getText());    // 페이지 뒤로가기    // await driver.navigate().back();         }    catch(err){     // Node Debug시 메시지가 너무길어 한글로 처음과 끝을 지정해서 보여지기 쉽게 처리      console.log("자동화 도중 에러 ",err  +  " 에러메시지 끝  ");   }   finally {         await driver.sleep(3000);         await driver.quit();   } })();   

 

 

 

저번에 UI 자동화에 대한 개요(?) 정도로만 시작했으며

 

이번에는 메일까지 접속해서 확인하도록 하겠습니다.

 

ID를 가져와서 입력하는 부분 및 PW를 가져오는 부분은 생략 하겠습니다.

 

전 포스팅에서 다루었기 때문에 

 

id와 pw를 입력해서 로그인 까지 하게되면

 

const _url = "https://www.naver.com/";  require('chromedriver'); const webdriver = require('selenium-webdriver'); const {By,Util}  = webdriver;   var driver = new webdriver.Builder() .forBrowser('chrome') .build();   const register_pc = false; (async () => {   try {     await driver.get(_url);           await driver.manage().window().maximize();     let inputId = await driver.findElement(By.css('input#id'));         await inputId.sendKeys('myID');     let inputpw = await driver.findElement(By.css('input#pw'));         await inputpw.sendKeys('mypassWord');     let loginBtn = await driver.findElement(By.css("input[type='submit']"));         await loginBtn.click();      let page_ = await driver.findElements(By.css('fieldset.login_form a'));    // 최초 실행 PC일 경우 페이지가 나타남        if(!!page_){             // 등록 page_[0]             // 등록 안함  page_[1]             !!register_pc ?console.log("등록합니다.") :await page_[1].click();       }               }    catch(err){     console.log("자동화 도중 에러 ",err  +  " 에러메시지 끝  ");      }   finally {         await driver.sleep(2000);         await driver.quit();   } })(); 

 

해당과 같이 코드를 작성후 node test.js 를 실행할시에 로그인 까지는 정상적으로 됩니다.

 

그후에 내 로그인 프로파일에 메일 이라는 부분을 클릭하여서 이동을 하여야 디는데 iframe 특성상

 

일반 DOM 과 분리되어있는 독립 document이기 때문에 클릭이 되지않습니다.

-> 정확히는 WebElement를 가져오지 못합니다.

해당 내용을 해결하기 위해서는 selenium-js에 있는 swtichTo 라는 API 를 사용하여야 합니다.

 

아래의 이미지는 네이버 로그인 프로필은 iframe으로 감싸져있음을 나타냅니다.

 

Native JavaScript 역시 iframe에 접근할 때는

window.frames["minime"].document.getElementById("mail_count_profile");

이와같이 사용합니다. 

[iframe] 

 

 

 

결과 코드

 

 

 const _url = "https://www.naver.com/";  // require 가 Builder보다 위에 있어야 함 공식 홈페이지  require('chromedriver'); const webdriver = require('selenium-webdriver'); const {By,Util}  = webdriver;  // 드라이버 빌드  var driver = new webdriver.Builder() .forBrowser('chrome') .build();   const register_pc = false; (async () => {   try {     // 페이지 이동     await driver.get(_url);         // 윈도우 최대화  headless 옵션 사용시 는 의미없음     await driver.manage().window().maximize();     // input값 가져옴     let inputId = await driver.findElement(By.css('input#id'));     // ID 입력         await inputId.sendKeys('id');     // password 값 가져옴     let inputpw = await driver.findElement(By.css('input#pw'));     // password 입력         await inputpw.sendKeys('pw');     // login 버튼 가져와서 클릭          let loginBtn = await driver.findElement(By.css("input[type='submit']"));         await loginBtn.click();       // 최초 실행 PC일 경우 해당 페이지가 나타나기 때문에 존재한다면 등록 유무 선택     let page_ = await driver.findElements(By.css('fieldset.login_form a'));       if(!!page_){             // 등록 page_[0] 등록 안함  page_[1]             !!register_pc ?console.log("등록합니다.") :await page_[1].click();       }     // selenium-js 에서는 switchTo.frame을 통해서 프레임을 변경 한다.        await driver.switchTo().frame('minime');     // 변경 후 프로필에 메일을 가져오고 클릭        let mail_profile = await driver.findElement(By.id('mail_count_profile'));       //  메일 클릭        //  화면 제어가 빠른 경우에 대한 sleep -> 추후 isContentsLoaded 또는 WebElement Condition 으로 변경        await driver.sleep(1500);       await mail_profile.click();     // 기존 프레임으로 다시 돌아오는 경우 (page이동이없었을때)        //   await driver.switchTo().defaultContent();     // 임시 테스트용 Sleep      await driver.sleep(2000);     console.log(await driver.getTitle());     console.log(await driver.getCurrentUrl());     let newUrl = await driver.getCurrentUrl();     await driver.navigate().to(newUrl);   // 가장 최상단 메일 의 Subject를 가져옴     let mailTitle = await driver.findElement(By.css('ol.mailList.sender_context li .subject'));   // 셀레니엄 JS에서 getText는 innerText를 가져온다고 되어있습니다.    console.log(await mailTitle.getText());    // 페이지 뒤로가기    // await driver.navigate().back();         }    catch(err){     // Node Debug시 메시지가 너무길어 한글로 처음과 끝을 지정해서 보여지기 쉽게 처리      console.log("자동화 도중 에러 ",err  +  " 에러메시지 끝  ");   }   finally {         await driver.sleep(2000);         await driver.quit();   } })();    

 

 

저는 네이버 알림을 켜놔서 새로운 기기 에서 로그인되었다는 창이 계속 나타나네요 

 

 

 

 

 

 

 

simple-ftp ( 파일 전송 X 다운로드 X)


사용불가



sftp(사용자가 가장 많음)


폴더 채로 전송시 잘되지 않음 sync 문제도 맞춰지지않음


json 파일은 읽어오지 못함


사용X


이클립스 Remote 보다 나은건 아직 못찾음


(파일다운로드 O 업로드 O 마우스 드래그로 가능 실시간 적용 , 권한 적용 여러 창 분할 가능)




더 좋은 remote 사용 툴 있으면 추천 좀 부탁드립니다.



공간 데이터 (Spatial Data) : 지구상에 있는 집, 도로 등을 점이나 선 등의 형태로 나타낸 위치 데이터를 말함


1차원 데이터를 위해 만든 B-Tree 인덱싱 방법으로 2차원 데이터를 저장하면 속도가 떨어지기 때문에 


위도,경도와 같은 공간 데이터 , 즉 2차원 데이터의 좌표 값을 데이터베이스에 저장할 때는 공간 인덱싱 방법 사용


공간 인덱싱은 데이터 베이스에서 2차원 공간 데이터를 빠르게 조회하기 위해 만든 2차원 인덱싱 방법으로


2차원 인덱싱 방법에는 R-Tree, R*Tree 등이 있음



Node.js를 알아가기 전에 동기 방식 과 비동기 방식 에 대한 정~~~말 간단한 예시를 보고 들어 가는게 좋을것 같아


가져왔습니다.



동기 입출력 (블로킹, Blocking IO) 방식 


파일 기능(읽기요청) -> 파일준비 -> 파일 처리 -> 데이터 처리 -> 다른작업 진행

var contents = file.read('a.txt');

******************대기*****************

doShow(contents);

var result = doAdd(10,10);



비동기 입출력(논블록깅 입출력, Non-Blocking IO) 방식

파일 기능(읽기요청) -> 파일준비 > 파일 처리 > 데이터 처리 

-> 다른작업 진행

file.read('a.txt',function(contents){

doShow(contents);

}

var result = doAdd(10,10);


|       Node Program                 |

|JavaScript C/C++                           |

| 노드 표준 라이브러리 |

| Node Standard library |

| 노드바인딩 |

| (Socket,http,etc) |

|스레드 풀 이벤트 루프  DNS crypto |

|libeio  libev    |

| V8 엔진 |

프로그램 실행시 V8엔진 위에서 실행됩니다. V8엔진 에서는 필요한 기능을 병렬로 실행하는 '스레드 풀'과

이벤트를 받아 처리하는 '이벤트 루프' 등의 기본 기능이 있으며 그 위에 네트워킹 기능을 담당하는 소켓(Socket)

,http 라이브러리 들이 있고 그 위에 표준 라이브러리가 구현되어있습니다.


결론 

특정 예시 [ 깍돌이의 오늘 저녁은 짜파게티위에 계란 후라이를 올려 먹을 생각입니다. ]

1. 짜파게티를 끓여야 함. [ 냄비에 물 올리고 끓으면 면넣고 섞어서 물 버리고 스프 로 섞기 ]

2. 계란후라이도 해야 함. [ 후라이팬에 불 달구고 기름 넣고 날계란 까서 뒤집어 주기 ]


이 두개의 작업이 있다고 하였을 때


동기 방식 


 후라이를 하든지 짜파게티를 끓이던지 하나를 정해야 합니다. 전자의 작업을 먼저 한다고 하였을 때 


1. 후라이팬을 꺼내 불 온도를 올립니다.

2. 온도가 올랐을때 기름을 붓고 날계란을 올립니다.

3. 익으면 뒤집어 줍니다.

[후라이 완료] - 예상 시간 60초


1. 냄비를 꺼내서 물을 넣고 끓입니다.

2. 끓었을때 짜파게티 사리를 넣습니다.

3. 익었을 경우 면을 섞고 물을 버립니다.

4. 스프를 넣고 섞습니다.

[짜파게티 완료] 예상 시간 150초


짜파게티 위에 계란을 올려 먹습니다.


-> 결과적으로 최소한 210초가 걸리게 되는 현상이 발생합니다.  하나씩 하나씩 스텝을 진행하여야 되기 때문입니다.


말로만 이렇게 하긴 했지만 프로그램적으로 봤을때는 짜파게티가 되기전 계란 후라이 작업에서는 펜딩되어있다고 보실


수 있기 때문에 매우 비효율적으로 보입니다. 


그러면 비동기가 짱짱일거 같지만 비동기가 매우 편리하고 좋지만 처리해야 할 작업도 많고


동기로 처리해야 하는경우가 있긴 합니다. 




비동기 방식  Node.js 의 논블로킹방식

(비동기는 실행순서가 늦는점을 이야기한거고 아래와 같은 예시는 논블로킹방식이 맞습니다.)


1. 후라이를 시작함과 동시에 냄비도 올리고 짜파게티도 시작합니다.

2. [후라이 완료] 60초 

3. [짜파게티 완료] 150초


짜파게티 위에 계란을 올려 먹습니다.


-> 결과적으로 동시에 따로 시작했고 후라이가 먼저 되었기 때문에 그걸 알려주게되며 전체 시간은 150초가 걸렸습니다.


위의 동기 방식을 더 쉽게 이야기하면 가스렌지가 1개 밖에 없어서 순차적으로 음식을만들어야 되는 점 


비동기 방식은 가스렌지가 2개라서 같이 진행 할수 있습니다.


어느정도 이해가 된 상태에서 비동기에 대한 포스팅은 다시 한번 자세하게 하겠습니다.








HTML5 까지의 기본 적이 역사(?) 에 대해 나열해 보았습니다.


HTML 등장시기 1991년 에 나왔으며 1993에 공식 발표 


HTML 1.0 - 1991년 10월 

HTML 2.0 - 1995년 11월

HTML 3.2 - 1997년 1월

HTML 4.0 - 1997년 12월

HTML 4.01 - 1999년 12월

HTML5 - 2008년 1월, 2014년 10월 현재 권고안 (Recommendation) 확정


p 태그로 감싸진 문장이 있다면 문단 (Paragraph)로 인식하게 됨 > 태그가 없는 경우에는 그냥 단순 텍스트로 표시합니다.


태그는 단독 사용형 태그와 시작 - 끝 형의 태그가 있습니다.


1. 단독 사용형  > img , hr , br 


2. 시작 - 끝 태그 영역형  html,body,head,title, div, p, h1~h5

<html> </html> 이런식


html 태그 - 이 문서는 HTML 로 마크업 되어 있다 라는 것을 알려주기 위한 태그 해당 태그 안쪽에는 다른 태그들이 들어가 제 역할을 수행하게 됩니다.

head 태그 - html 태그 앞에 붙으며  문서를 웹 브라우저가 읽어들일 떄 우선적으로 처리해야 하는 사항들이 들어가게 된다.

head 태그 안에는  <title>, <meta>,<link>,<script>,<style> 태그가 위치

<title> - HTML 문서를 웹 브라우저에서 열었을 때 웹 브라우저 의 제목 표시줄이나 탭의 제목으로 표시

// 과거에는 웹 사이트의 제목만을 넣어 두는 것이 일반적이였으나 

// 웹 접근성 향상을 위해 title 태그 내에 웹 사이트의 제목 뿐만 아니라 페이지의 제목도 넣어주는 것이 최근 추세 

// 과거 - 깍돌이 블로그

// 현재 - 깍돌이 블로그 - 블로그 개요

<meta> - HTML 문서에 대한 메타 데이터를 입력하는 태그입니다. 용도는 매우 다양합니다.

// 메타 데이터들을 입력함으로 검색엔진의 봇(bot)이 페이지 크롤링 (Crawling - 긁어 오는 작업)할 때 해당 페이지를 누가 작성하였고 

   어떤 정보들이 있으며 이 정보들에 대한 검색어 (Keyboard)는 무엇인지 등에 대해 봇에게 알려주는 역할을 합니다.

// http 헤더에 속성 값을 넣어 웹 브라우저에 전달하는 역할도 함

1) 페이지 작성자 : <meta> 태그에 name="author", content="작성자명" 속성을 사용합니다.


예) <meta name="author" content="Crestia">

* 여러 개의 항목을 넣어 쓸 수 있으며, 항목은 ','로 구분.


2) 페이지 검색어 : <meta> 태그에 name="keywords", content="검색어1, 검색어2, ..." 속성을 사용합니다.

예) <meta name="keywords" content="HTML 튜토리얼, CSS 스니펫, 개발 팁">

* 여러 개의 항목을 넣어 쓸 수 있으며, 항목은 ','로 구분.


3) 페이지 설명 : <meta> 태그에 name="description", content="간단한 설명" 속성을 사용합니다.

예) <meta name="author" content="Project Crestia의 블로그">


4) 인코딩 정보 : HTML5에서는 <meta> 태그에 charset="인코딩 셋" 속성을 사용하며, HTML 4.x나 XHTML 1.x는

http-equiv="Content-Type", content="text/html;charset=인코딩 셋" 속성을 사용합니다.

예) HTML5 : <meta charset="UTF-8">

HTML 4.x : <meta http-equiv="content-type" content="text/html;charset=UTF-8">

XHTML 1.x : <meta http-equiv="content-type" content="text/html;charset=UTF-8" />

* 주로 사용 되는 한국어 인코딩 셋 : UTF-8 (유니코드), EUC-KR (확장완성형)

* 주의 : 한 HTML 문서 내부에 여러 개의 인코딩이 들어갈 수 없음


5) 렌더링 엔진 지정 : <meta> 태그에 http-equiv="x-ua-compatible" content="IE=버전" 속성을 사용합니다.

예) Internet Explorer : <meta http-equiv="x-ua-compatible" content="IE=edge">

* 버전 속성

* edge : 항상 최신 버전의 렌더링 엔진으로 표시

* 9 : 9.0 렌더링 엔진

* 8 : 8.0 렌더링 엔진

* 7 : 7.0 렌더링 엔진

* 6 : 6.0 렌더링 엔진 (쿼크 모드)

6) 모바일 기기 화면 설정 : <meta> 태그에 name="viewport" content="설정 내용" 속성을 사용합니다.

예) <meta name="viewport" content="width=device-width, initial-scale=1.0">

* 설정 내용 항목

* width : 페이지의 너비. 일반적으로 device-width (기기 화면 너비)로 사용함.

* initial-scale : 페이지를 불러왔을 때 초기 화면의 크기. initial-scale=1.0로 해 놓으면 100%.

* maximum-scale : 최대 화면 크기. maximum-scale=1로 해놓으면 100%가 최대값.

* user-scalable : 사용자 줌 가능 여부 설정. user-scalable=no로 설정하면 페이지 줌 불가능

* 여러 개의 항목을 넣어 쓸 수 있으며, 항목은 ','로 구분.


7) 페이지 새로 고침 간격 지정 : <meta> 태그에 http-equiv="Content-Type" content="초" 속성을 사용합니다.

예) <meta http-equiv="refresh" content="20">

body 택 - head 태그 뒤 쪽으로 <body> 태그가 나옵니다. 해당 태그에는 문서의 본문 내용들이 들어가게 됩니다. 

<img> <br> <hr>같은 단독 태그가 아닌 경우 />로 막아야 합니다. 


아직까지 업무도중에 reduce를 쓸일이 없어서 reduce랑 reduceRight 가 몇번 건드리긴 했는데


제대로 해본적이 없다 보니 reduce에 대해 자세하게 알아보기로했다.


매번 return map forEach 만 사용했는데 


https://jsperf.com/native-map-reduce-vs-for/2


reduce가 엄청나게 파워풀하고 map filter forEach 를 전부 해결할수있는 만능 이라는것도  알게되면서


reduce에 대한 포스팅을 하려고합니다.

알아야 하는 JavaScript 


1. JavaScript Event Loop 에 대해 설명


2. JavaScript 에서의 비동기 처리 과정


3. Hoisting 이란


4. Closure 란


5. this 에 대해서 설명


6. Promise 에 대해 설명


알아야하는 front-end


1. 브라우저의 동작 원리 설명


2. Document Object Model (DOM)

Event bubbling and Capturing 설명

Event delegation


3. CORS 에 대한 설명


4. 크로스 브라우징 예시 


5. 웹 성능과 관련된 Issue


6. 서버사이드 렌더링 (SSR) 과 클라이언트 사이드렌더링 (CSR) 


7. CSS Methodology


8. normalize .css    vs reset.css


&& 이외 

1. 페이지 로드를 줄일 수 있는 방법을 나열 


1-1 이미지맵 

여러개의 이미지를 띄우지 않고 한개의 이미지에 사용되는 이미지들을 넣어 놓고 사용합니다.

login.png,logout.png,user.png을 따로 부르는것이 아닌 loginPage.png 라는 곳에 다 넣어 놓고

이미지를 픽셀로 짤라서 불러오는 방식을 사용합니다. 

2. CSS 애니메이션과 자바스크립트 애니메이션의 장단점을 설명하시오


3. 간단한 슬라이드쇼 페이지를 어떻게 개발할지 설명해보시오.





미나미야마

메뉴 : 철판치즈돈가스(13,000원) + 짬뽕라멘(9,000원)

total : 22,000원

후기 

깍돌이 : 수프가 무제한이 너무 좋았고 숙주는 좀 짜지만 돈가스는 맛있다.

깍순이 : 짬뽕이 주인공이닷




기존에 작성은 한적 있지만

 

새 서버로 옮기는 바람에 Node를 다시 설치 하여야 할 일이 생겼습니다.


노드 프로젝트를 통채로 가져왔기 때문에 


package.json 이랑 package-lock.json 은 그대로 있는 상태에서


Node를 재설치 후에 동작을 확인해보겠습니다.


우선 node.js 공식 홈페이지 접속 


https://nodejs.org/en/



메인 메뉴에서  DOWNLOADS 후  하단 


을 선택 합니다. 


저는 CentOS7 이기 때문에 엔터프라이즈 리눅스 메뉴를 선택


그리고 가이드대로 설치 합니다.


On RHEL, CentOS or Fedora, for Node.js v8 LTS:

curl --silent --location https://rpm.nodesource.com/setup_8.x | sudo bash -

Alternatively for Node.js 10:

curl --silent --location https://rpm.nodesource.com/setup_10.x | sudo bash -

Then install:

sudo yum -y install nodejs


현재 LTS버전인 8 (stable)  은 위에 LTS버전인 current 버전은 아래의 setup_10.x로 설치합니다.


설치 후  아래의 명령 yum -y install nodejs로 node를 설치합니다. node -v 로 버전 확인



설치가 잘됐습니다.


npm init으로 package.json 에 맞게 세팅 해주고


nodemon pm2같은 모듈은 제가 -g로 설정하여서 pakcage.json 에 없다보니


다시 재설치를 하였습니다.







+ Recent posts