* 이 포스트는 "ES6 사용에 앞서" 알아본 내용을 정리하는 개인적인 포스트입니다!


[참고/출처]

* https://nodejs.org/

* http://blog.nekoromancer.kr/2016/01/26/es6-var-let-%EA%B7%B8%EB%A6%AC%EA%B3%A0-const/

http://chanlee.github.io/2013/12/10/javascript-variable-scope-and-hoisting/



ES6는 뭘까?


NodeJS를 공부하기 위해 http://www.nodejs.org 에서 샘플 소스를 옮겨적어봤다.

내용은



Webstorm에서 에러를 잔뜩 표시해준다 

뭔가 해서 살펴봤더니 처음보는 아이들 const.. => .. 얘네는 뭘까 ㅎ.ㅎ

그래서 찾아보니 2015년 6월에 공개된 자바스크립트(JS) 표준 ECMAScript 6 의 문법이라고한다.

지금은 2017년인데 처음봐..ㅎㅎ ECMAScript 6 의 특징들 (한글번역)



그래서 일단은 const 와 let에 대해 알아보기로한다.

아! Webstorm에서의 빨간줄은 File -> Setting-> Languages & Frameworks 에서 

Javascript를 선택한 후 Javascript language version 을 ECMAScript 6로 변경해주면 말끔히 사라진다 ㅎ.ㅎ




자바스크립트에서 변수의 범위(VAR) 와 호이스팅


[자세한내용보기] http://chanlee.github.io/2013/12/10/javascript-variable-scope-and-hoisting/


contst 와 let을 알기에 앞서 먼저 var에 대해서 알필요가 있다.

변수는 지역 범위(local scope)와 전역 범위(global scope) 둘 중 하나를 가진다.



1. 지역변수(local scope)


스크립트의 가장 큰 특징 중 하나는 다른 언어들과 달리 블럭 {} 수준의 범위를 가지고 있지 않다.

그 대신 함수 수준의 범위를 가진다.

예를 들어 



위에 같은 경우 함수안에서 선언된 name 변수는 지역범위를 가진다. 그러므로 함수밖에서 선언된 name 의 값은 

전역변수 mingcho.

그러나 아래와 같이 



블럭 안에서 값을 할당하면 전역변수의 값이 바뀐다. 블럭수준의 범위에 해당되지 않는다.

위와 같은 경우 if 문안에서 var name = "minyoung" 과 같이 변수를 다시 선언해도 name은 여전히 전역 변수이며 

전역변수의값은 블럭안에서 할당된 값으로 변경된다. (블럭수준 X / 블럭범위의 변수가 아님)

그러나 함수안에서 var name = "minyoung" 과 같이 선언될 경우 name은 전역변수가 아닌 지역변수로 간주된다.


또한, 함수안에서 사용하더라도 선언을 해주지 않았을 경우엔 전역변수로 간주된다.

그러니 함수안에서 지역변수를 사용하고 싶을 땐 항상 선언을 해주도록 하자.

지역변수는 함수내에서 전역변수보다 높은 우선 순위를 가진다.


2. 전역변수(global scope)


함수의 외부에서 선언된 모든 변수는 전역 범위를 가진다.

모든 전역변수는 window객체와 연결되어 window객체를 통해 모든 전역 변수에 접근이 가능하다.




만약 변수가 최초 선언 없이 초기화 되었다면, 이 변수는 함수 내에 들어있더라도 전역변수가 된다.

또한, 함수가 아닌 블럭 {} 내에서 선언될 경우에도 전역변수로 간주된다.


for문의 경우도 같다.



또한, setTimeout 안에서 선언된 모든 함수는 전역 범위에서 실행된다.

setTimeout안에서의 this는 window객체.


스크립트를 잘쓰려면 가급적 전역 범위에 변수를 생성하는 것을 피해야한다.

function name(){} 이런식으로 생성하는 함수역시 전역범위에 포함된다.



3. 변수 호이스팅


스크립트의 모든 변수선언은 호이스트 된다.

호이스트란, 변수의 정의가 그 범위에 따라 선언과 할당으로 분리되는 것을 의미한다.

즉, 변수가 함수내에서 정의되었을 경우 선언이 함수의 최상위로, 함수 바깥에서 정의되었을 경우 전역범위의 최상위로 

변경되는 것을 뜻한다.



위와 같은 경우 처음에 name의 값을 찍어봣을때 선언부가 아래있음에도 에러가 아닌 undefined라는 결과가 나온다.

이 경우 지역변수 name이 최상위로 호이스트 되었기 때문이다.

이 경우에 ES6의 const, let 과 다른 특성을 보여준다.


호이스트 되었을 때, 함수 선언은 변수선언을 덮어쓴다. 

즉 변수를 선언한 후 같은 이름의 함수를 선언할 경우 그 이름의 주인은 함수가 된다.

하지만 변수에 값이 할당될 경우에는 반대로 변수가 함수 선언을 덮어쓴다. 



const , let 의 사용


[자세한내용보기] http://blog.nekoromancer.kr/2016/01/26/es6-var-let-%EA%B7%B8%EB%A6%AC%EA%B3%A0-const/


contst 와 let은 var와 같이 변수의 선언에 사용되는 ES6용어이다.

다만 이들은 var보다 훨씬 엄격한 규칙을 가지고있다.


1. 중복선언 금지


var의 경우 



위와 같이 선언을 두번 해줘도 에러가 나지 않는다. 

하지만 const, let은 경우 위와 같은 경우 에러를 발생시킨다.


2. 호이스팅!?


var의 경우 선언을 해주기전에 값을 출력해도. 선언된 변수가 호이스팅 되므로 출력값은 "undefined"

하지만 const 와 let은 다르다. ERROR! 먼저 선언을 하고 사용하자.

이를 임시적 사각지대라고한다.



3. 함수범위 X , 블럭범위 O


위에서 살펴봤듯이 스크립트 변수는 함수수준의 범위를 가진다 .

그러므로 if 나 for문 등 블럭안에서 전역변수와 같은 이름의 변수를 선언할 경우 이는 전역변수로 간주!

그러나 const 와 let은 블럭범위(Block-scope)이다.

블럭안에서 선언하여 사용할 경우 블럭밖에서 선언된 변수와는 다른 변수로 간주되어 사용된다.


4. 임시적 사각지대(TDZ)


어떤 변수가 호출되었을 때 블록 안에 같은 이름의 변수가 없으면 상위 블록에서 선언된 같은 이름의 변수를 호출한다.

하지만 블록안에서 const 나 let으로 선언된 변수가 있다면 그 이름의 변수는 변수가 선언되기 이전까지 그 블록안에서는

정의 되지 않는 내용으로 간주된다.



5. let , const 의 적절한 사용


일반적으로, 값의 변경이 있는 경우는 let으로 

값의 변경이 되지 않는 경우는 상수 const로 사용합니다. 

단, 참조형의경우는 const로 사용하는 것이 바람직합니다.

@ ES6에서 var의 사용은 지양합시당


[펌] 출처 : http://recoveryman.tistory.com/187


1. 저장 엔진이란 무엇이며, 어떤 종류의 저장 엔진이 있는가?


1. 저장 엔진이란?


1.1 저장 엔진이란 무엇인가?

트랜잭션을 설명하기 전에 MySQL의 저장 엔진에 대해 알아 두어야 합니다.


MySQL의 기능은 크게 두 가지로 나눌 수 있습니다.


첫 번째는 접속 기능과 SQL 문의 내용을 사전에 조사하는 기능, 즉 데이터베이스의 상위 부분이고, 두 번째는 그 상위 부분의 지시를 받아 실제로 검색이나 파일을 조작하는 기능의 하위 부분입니다. 이 하위 부분을 '저장 엔진'이라고 합니다.


1.2 저장 엔진의 종류

MySQL에는 여러 가지의 저장 엔진이 있는데, 사용자는 목적과 자신의 취향에 따라 저장 엔진을 선택할 수 있습니다. 또한, A 테이블은 ◯ ◯ 저장 엔진, B 테이블은 Х Х 저장 엔진과 같은 방식으로 테이블별로 저장 엔진을 지정할 수 있습니다.


이처럼 사용자가 독립된 형태의 저장 엔진을 선택할 수 있는 것은 수많은 RDBMS 중에서도 MySQL만의 고유한 특징입니다.


MySQL의 주요 저장 엔진

저장 엔진 

특징 

 MyISAM 

 MySQL 5.1까지의 기본 엔진. 트랜잭션을 지원하지 않는다. 

 InnoDB 

 MySQL 5.5 이후의 기본 엔진. 트랜잭션을 지원한다. 

 ISAM 

 MySQL의 기본이 되는 저장 엔진. 예전 형식으로, MySQL 5.0부터는 설치되지 않는다. 

 MEMORY 

 데이터를 모두 메모리상에 보관하며, 동작이 빠르다.

 MERGE 

 MyISAM의 여러 개의 테이블을 하나의 테이블처럼 다룬다. 


여기서는 처음부터 기본 엔진으로 설정되어 있는 InnoDB를 그대로 사용하겠습니다. 사실은 MySQL 5.1까지는 MyISAM이 기본 엔진으로 설정되어 있었습니다. 이 MyISAM은 당시의 InnoDB에 비하면 처리 속도가 매우 빨랐으나 안타깝게도 트랜잭션을 지원하지 않았습니다.


그래서 당시에는 트랜잭션을 사용하지 않을 때에는 MyISAM을, 사용할 때에는 InnoDB를 이용하기도 했습니다. 그러나 지금은 InnoDB의 처리속도가 많이 향상되었기 때문에, 여기서는 MyISAM은 사용하지 않겠습니다.


저장 엔진을 보다 효율적으로 사용하려면 저장 엔진별로 세심한 튜닝이 필요하고, 새로운 저장 엔진에 대한 연구도 필요합니다. 하지만 여기서는 기초를 확실히 하는 것을 목표로 하고 있기 때문에, 현시점에서는 InnoDB만 사용해서 설명할 것입니다. 단, 저장 엔진의 기능은 점점 진화하고 있습니다. MySQL을 사용하는 이상, 목적에 최적화된 저장 엔진이 있다면 그 엔진을 사용하는 것이 효율적입니다. 미래에 대비하여 여기에서는 저장 엔진을 변경하는 방법만 기억합시다.


MyISAM과 InnoDB는 어떻게 읽을까?

읽는 방법은 개인마다 다르지만, 일반적으로 MyISAM은 '마이아이삼', InnoDB는 '이노디비'라고 불리고 있습니다.



2. 저장 엔진 설정하기


2.1 저장 엔진 확인하기

그럼 지금까지 사용했던 테이블의 저장 엔진을 확인해 보겠습니다. 테이블의 상세한 정보를 표시할 때에는 SHOW CREATE TABLE 명령을 사용합니다.


SHOW CREATE TABLE tb;



저장 엔진은 'ENGINE=Х Х'를 통해 확인할 수 있습니다. 앞의 예에서는 테이블 tb에 InnoDB가 사용되고 있다는 것을 알 수 있습니다. 테이블을 만들 때 저장 엔진을 별도로 지정하지 않으면 기본 설정인 InnoDB가 선택됩니다.


MySQL 콘솔창 사용 팁 - 쌍반점(;) 대신 \G 사용하기

앞의 예에서 SHOW CREATE TABLE;과 같은 명령을 실행하면 1행에 표시하는 데이터가 많아서 외관상 보기가 매우 불편합니다. 이럴 때 명령문의 마지막에 쌍반점(;) 대신 \G를 사용해봅시다. 이때, G는 반드시 대문자를 사용합니다.


\G를 사용하면 다음과 같이 칼럼별로 알아보기 쉽게 표시됩니다.



SELECT 명령과 같이 표시할 칼럼이 많거나 표시할 항목이 길 때 사용하면 편리합니다. 꼭 기억해 두기 바랍니다.



2.2 저장 엔진 변경하기

테이블의 저장 엔진은 나중에 변경할 수도 있습니다. 여기에서는 InnoDB가 설정된 테이블 tb1A의 저장 엔진을 MyISAM으로 변경해 보겠습니다.


저장 엔진을 변경할 때에는 ALTER TABLE 명령을 사용합니다.


저장 엔진을 MyISAM으로 변경하기

ALTER TABLE 테이블_이름 ENGIN=MyISAM;



'Query OK'라고 표시되어도 저장 엔진이 변경되지 않는 경우가 있습니다. 반드시, SHOW CREATE TABLE tb1A;를 실행해서 MyISAM으로 변경 되었는지 확인합니다.





2. 트랜잭션이란 무엇인가?


3. 트랜잭션이란?

트랜잭션을 설명할 때 자주 등장하는 예가 '입출금 처리'입니다.


예를 들어, 박진영의 계좌에서 윤종신의 계좌로 10만원을 송금한다고 했을 때, '박진영의 계좌 잔고에서 10만원을 감산'하고, '윤종신의 계좌 잔고에 10만원을 가산'하는 처리가 이루어집니다. 만일, '박진영의 계좌 잔고에서 10만 원을 감산'하는 시점에 오류가 발생했다면 어떻게 될까요? '윤종신의 계좌 잔고에 10만원을 가산'하는 처리는 이루어 지지 않은 채 박진영의 계좌에 있던 10만 원만 어디론가 사라지고 마는 것입니다. 이는 입출금 처리에서 절대로 있어서는 안 되는 사태입니다.


그래서, '10만 원의 감산'과 '10만 원의 가산'을 '분할할 수 없는 하나의 처리'로 취급해서, 만일 10만 원의 가산이 실패하면 10만 원의 감산도 취소하도록 합니다. 이렇게 하면 적어도 10만 원이 사라지는 일은 피할 수 있습니다.


이처럼, 여러 단계의 처리를 하나의 처리처럼 다루는 기능을 트랜잭션(transection)이라고 합니다. 트랜잭션의 실행 결과를 데이터베이스에 반영하는 것을 커밋(commit)이라 하고, 반영하지 않고 원래 상태로 되돌리는 것을 롤백(roll-back)이라고 합니다.


Excel 등의 컴퓨터 처리에 익숙하다면, 무엇이든지 ctrl + z 로 되돌릴 수 있다고 생각하기 쉽습니다. 그러나 데이터베이스 세계에서는 트랜잭션을 사용하지 않으면 일단 한번 변경된 데이터는 원래 상태로 되돌릴 수 없다고 생각해야 합니다.




3. 트랜잭션을 시작하는 방법


4. 트랜잭션 사용하기

트랜잭션의 기능을 직접 체험해 보겠습니다. 이번에는 지금까지 수없이 등장했던 매출정보 테이블 tb의 모든 레코드를 대담하게 삭제해 보겠습니다. 그러고 나서, 그 처리를 되롤려(ROLLBACK) 보겠습니다.


4.1 실행 전 주의사항

만일, 중요한 데이터가 삭제되어 버렸는데 원래 상태로 되돌릴 수 없다면 곤란하겠죠? 그렇기 때문에, 트랜잭션을 테스트할 때에는 반드시 잃어버려도 곤란하지 않을 데이터를 사용하기 바랍니다. 그리고 DROP 등 몇 가지 명령은 롤백이 되지 않으니 주의해야 합니다.


또한, 저장 엔진이 MyISAM인 테이블에서는 트랜잭션 기능을 사용할 수 없습니다. 테이블 tb의 저장 엔진이 InnoDB로 되어 있는지 확인하고 실행하도록 합니다.


4.2 트랜잭션 시작하기

먼저, 테이블 tb에 있는 데이터를 표시해 보겠습니다.



데이터가 있는 것을 확인했으면 트랜잭션을 시작해 보겠습니다. 트랜잭션을 시작할 때에는 START TRANSACTION이라는 명령을 실행합니다.


트랜잭션 시작하기

START TRANSACTION;


또는, BEGIN이나 BEGIN WORK를 입력해도 됩니다. 다음과 같이 'Query OK'라는 메시지가 표시되는 것을 확인합니다.



이 메시지가 표시되지 않으면 트랜잭션이 작동하지 않는 것입니다.


그럼, 테이블 tb의 모든 레코드를 대담하게 삭제해 보겠습니다.


DELETE FROM tb;



WHERE 등으로 조건을 설정하지 않았기 때문에 테이블 tb의 모든 데이터가 삭제되었습니다.


실제 이 시점에서 테이블의 일부 기능에 록(lock)이 걸립니다. 즉, 잠금 처리가 됩니다. 따라서 다른 세션에서 INSERT 등의 명령을 실행할 수가 없습니다. 예를 들어, 이 상태에서 명령 프롬프트를 하나 더 실행하여, MySQL 콘솔창에서 테이블 tb에 INSERT 명령을 실행해 봅시다.


이때, 트랜잭션을 실행한 MySQL 콘솔창에서 COMMIT;이나 ROLLBACK; 명령을 실행할 때까지 INNSERT 명령은 실행되지 않습니다.



4. 커밋 또는 롤백 사용하기


4.3 테이블의 내용 확인하기

자, 이제 테이블 tb에는 아무 레코드도 남아 있지 않을 겁니다. 확인해 보겠습니다. 트랜잭션을 실행한 MySQL 콘솔창에서 확인합니다(이 시점에서는 다른 MySQL 콘솔창에서 SELECT를 실행하면 레코드가 남아 있는 것처럼 보입니다).


SELECT * FROM tb;



'Empty set'이라고 표시되었습니다. 레코드가 남아 있지 않다는 의미입니다. 과연 레코드를 원래대로 되돌릴 수 있을까요?


롤백을 실행해서 원래 상태로 되돌리기

그럼, ROLLBACK 명령을 사용해서 레코드를 원래대로 되돌려 보겠습니다.


롤백(되돌리기)

ROLLBACK;



이제 DELETE 명령의 결과는 반영되지 않습니다. SELECT 명령으로 결과를 확인해 보겠습니다.



데이터가 무사히 복원되었습니다.


트랜잭션은 ROLLBACK;을 실행한 시점에 확정됩니다. 다시 한번 테스트를 하려면 반드시 START TRANSACTION;으로 트랜잭션을 시작해야 합니다.


만일, ROLLBACK; 대신 COMMIT;을 사용하면 레코드를 삭제한 결과가 반영되어 모든 레코드가 영구적으로 삭제되고 맙니다.


커밋(반영하기)

COMMIT;




5. 자동 커밋 기능이란 무엇인가?


5. 자동 커밋 기능

일반적으로는 MySQL에서 명령을 실행하면 그대로 반영됩니다. 즉, 사용자가 의식하지 않아도 모든 명령이 자동으로 COMMIT되는 것입니다. 특히, MySQL 5.1까지 기본 엔진이었던 MyISAM에서는 트랜잭션 기능이 없기 때문에 모든 명령은 커밋(반영)됩니다.


이처럼, 명령을 실행하면 그대로 반영하는 기능을 자동 커밋 기능이라고 합니다. 이 자동 커밋 기능의 기본 설정은 ON입니다. 그러나 저장 엔진이 InnoDB인 경우, START TRANSACTION(또는 BEGIN)을 실행하면 COMMIT 명령을 할 때 까지 커밋(반영)되지 않습니다. 그 덕분에 ROLLBACK 명령도 가능해진 것입니다.


자동 커밋 기능은 사용자가 강제로 OFF로 설정할 수 있습니다. 자동 커밋 기능을 OFF로 설정하면 SQL 문을 실행해도 곧바로 반영되지 않기 때문에, COMMIT과 ROLLBACK 기능을 사용할 수 있습니다.



5.1 자동 커밋 기능을 OFF로 설정하기

그럼, 자동 커밋 기능을 OFF로 바꿔보겠습니다.


자동 커밋 기능을 OFF로 하려면, 다음과 같이 SET AUTOCOMMIT=0;이라는 명령을 실행합니다.


자동 커밋 기능을 OFF로 설정하기

SET AUTOCOMMIT=0;



이제 명령을 실행해도 자동으로 반영되지 않게 되었습니다. 그럼, INNSERT 명령을 실행해 보겠습니다.


INSERT INTO tb VALUES('test', 555, 555);



내용을 확인해 봅시다. SELECT * FROM tb;를 실행해 보니 추가한 레코드가 표시되는군요.



과연, 롤백을 실행하면 어떻게 될까요?


ROLLBACK;


SELECT * FROM tb;를 실행해 보면 추가한 레코드가 표시되지 않습니다.



명령이 자동으로 반영되지 않는다는 것을 확인했습니다. 실제로 변경한 데이터를 확정하려면 COMMIT;을 실행해야 합니다.


이쯤 되면 자동 커밋 기능을 OFF로 설정하면 언제든지 명령을 되롤릴 수 있어서 더 좋다 라고 생각하는 분이 있을 것입니다. 그러나 자동 커밋 기능을 OFF로 설정한 상태에서 작업하다가, 만일 COMMIT을 하지 않고 MySQL을 종료하면 그 작업 내용은 반영되지 않으니 주의해야 합니다.



5.2 OFF로 설정한 자동 커밋 기능을 ON으로 바꾸기

OFF로 설정한 자동 커밋 기능을 원래대로 되돌리는 방법입니다. 다음 명령을 이용해서 자동 커밋 기능을 원래의 기본 설정으로 되돌려 놓습니다.


SET AUTOCOMMIT=1;


자동 커밋 기능의 설정 상태를 확인하려면?

자동 커밋 기능의 현재 설정 상태를 확인하려면 SELECT @@AUTOCOMMIT 명령을 실행하니다. ON이면 '1', OFF면 '0'으로 표시됩니다.





5.3 트랜잭션을 이용할 수 있는 범위

트랜잭션으로 모든 명령을 롤백으로 되돌릴 수 있는 것은 아닙니다. 예를 들어, 다음과 같은 명령은 자동 커밋 됩니다.


* DROP DATABASE

* DROP TABLE

* DROP

* ALTER TABLE


앞의 명령은 트랜잭션을 실행해도 원래의 상태로 되돌릴 수가 없으니 주의해야 합니다.




저장 엔진을 자윫게 선택할 수 있다는 것은 MySQL의 커다라나 매력중의 하나 입니다. 현재 사용할 수 있는 저장 엔진은 SHOW ENGINES \G 명령으로 확인할 수 있습니다. 여기서의 환경에서 사용할 수 있는 트랜잭션은 InnoDB뿐인 것을 확인할 수 있을 겁니다.




체크!

★ 저장 엔진에 대해 이해했다.

★ 트랜잭션을 시작할 수 있다.

★ 명시적으로 커밋 또는 롤백을 실행할 수 있다.

★ 자동 커밋 기능을 이해하고 설정할 수 있다.

★ 롤백을 실행할 수 없는 명령이 있다는 것을 알고 있다.

'BACK-END > MYSQL' 카테고리의 다른 글

[MYSQL] MYSQL 트랜잭션 활용하기  (0) 2016.10.13


리눅스 서버간의 파일 복사 , scp


오늘은 리눅스에서 서로 다른 서버간에 파일을 복사하는 명령어 scp 를 알아보자.


scp 명령어를 이용하면 서로다른 서버간에도 파일 복사, 폴더 복사가 모두 가능하다.

오늘은 파일들을 tar.gz로 압축한 후 압축 파일을 가져오는 방법으로 scp 명령어를 사용해 보도록하자.


먼저 이동시키고자 하는 파일들이 있는 폴더로 이동해서 파일들을 압축시킨다.


tar cvzf  파일명.tar.gz ./*



ex)


[user@111.111.111.111 home]# tar cvzf mingcho.tar.gz ./*

//위를 설명하면 ./* 현재경로(home) 하위에 있는 모든 파일들을 mingcho.tar.gz 란 이름으로 압축파일을 생성하라는 의미이다.



압축파일이 생성됐으면 이제 파일들을 이동 시킬 서버의 경로로 이동한다.


scp -P 포트번호 계정@서버주소:원본경로 목적파일명



ex)


[user@222.222.222.222 home]# scp -P 22 mingcho@111.111.111.111:/home/mingcho.tar.gz /home/mingcho2.tar.gz


//22번포트로 111.111.111.111 번 서버의 mingcho계정으로 접속해서 /home 하위에 있는 mingcho.tar.gz 란 

파일을 현재 222.222.222.222 서버의 /home하위에 mingcho2.tar.gz 란 이름으로 복사한다.



이렇게 명령어를 날리면 목적서버 계정의 패스워드를 물어본다.


[user@222.222.222.222 home]# scp -P 22 mingcho@111.111.111.111:/home/mingcho.tar.gz /home/mingcho2.tar.gz

mingcho@111.111.111.111's password : 



여기에 패스워드를 입력하여 인증에 성공하면 복사가 완료된다.

복사가 된 파일을 압축을 풀려면 아래와 같이 풀어주면된다.


tar -zxvf 파일명.tar.gz



ex)


[user@222.222.222.222 home]# tar -zxvf mingcho.tar.gz 




여기에 압축파일이 아닌 폴더로서 전체로 복사 하고 싶을 경우엔 ( -r 옵션 ) 을 사용하면 된다.


scp -r -P 포트번호 username@원격서버주소:해당경로폴더/ 로컬저장소위치



ex)


[user@222.222.222.222 home]# scp -r -P 22 mingcho@111.111.111.111:/home/dir /home/dir







+ Recent posts

티스토리 툴바