어도비 포토샵은 자체 스크립트를 이용하여 다양한 기능을 수행할 수 있는 툴을 지원합니다. 언어는 자바 스크립트 이며 작성된 자바스크립트를 포토샵에서 실행하는 방법과 Extend Script Tool Kit 을 이용하여 실시간으로 작성한 스크립트를 포토샵으로 전송하여 실행 결과를 확인할 수도 있습니다.
본 블로그를 통하여 간단한 포토샵 스크립트 교육을 진행할 예정이므로 관심 있으신 분들을 하나씩 따라오는것도 좋을 것 같습니다.
먼저 포토샵에서 스크립팅을 하기위하여 기본적인 환경을 살펴 보겠습니다.
Adobe Photoshop CS5 이상
Adobe Extend Script Tool Kit (CS5 이상의 Creative Suite 를 설치하면 자동으로 설치가 됩니다.)
위의 그림과 같은 화면을 보실수 있는데요. 일반적인 개발 환경과 유사한 구조 입니다. 좌측 하얀 공간은 텍스트 에디팅이 가능한 창으로 실제 개발이 이루어 지는 공간입니다.
우측은 실행 중 값을 확인하거나 결과를 보기위한 콘솔 창이고요. 아래쪽은 잘 몰라도 간단한 개발에 큰 지장이 없는 창들 입니다.
중요한 것은 상단인데, 상단 좌측의 드롭다운 메뉴를 선택하면 현재 프로그램에서 연결 가능한 어도비 제품명칭이 나타납니다. 저처럼 Photoshop 을 실행중인 상태에서 드롭다운으로 포토샵을 선택하면 아래와 같이 됩니다.
초록색 링크 아이콘이 보인다면 이제 작성한 스크립트를 이용하여 포토샵에 보낼 준비가 되었다는 뜻이죠.
스크립트 동작을 테스트하기 위하여 아래와 같이 입력을 해봅시다
그런 다음 F5 키를 누르거나 상단 메뉴바에 있는 재생 버튼을 눌러보세요.
그럼 아래와 같이 팝업창이 나타나는데요, 바로 포토샵 프로그램에서 경고 창이 나타나게 됩니다.
이 경고창을 이용하여 간단하게 현재 작성중인 코드의 중간 값 또는 결과 값을 확인하실 수 있습니다.
값을 확인하기 위한 또다른 방법으로 자바스크립트 콘솔 창을 이용하는 방법입니다. 경고창의 경우 사용자가 [OK] 버튼을 누르기 전까지 스크립트 진행이 중단되어 흐름이 끊긴다는 특징이 있지만 자바스크립트 콘솔의 경우 값을 출력한 뒤 계속 스크립트가 진행이 되므로 좀더 유연하게 값을 확인 할 수 있습니다.
작성하는 방법은 아래와 같습니다.
"hello!" 부분에 출력하고 싶은 변수나 값을 적어 넣으면 아래와 같이 우측 콘솔 창에 결과가 나타나게 됩니다.
첫번째 줄에 요청했던 값이 출력이 되었고 두번째 줄에는 전체 스크립트에 대한 결과가 나왔습니다. undefined 라고 하면 딱히 출력할 결과가 없다는 뜻이 됩니다.
간단한 코드 샘플을 보여드리기 위해 이미지를 하나 열었습니다.
이름도 유명하긴 바로 그 검입니다.
포토샵에는 위의 이미지가 열려있는 상태에서 스크립트를 아래와 같이 작성해 봅시다
var cDoc = app.activeDocument
$.writeln(cDoc.name)
$.writeln(cDoc.width)
$.writeln(cDoc.height)
$.writeln(cDoc.layers.length)
그런 다음 실행을 해보면 아래와 같이 우측에 값이 나오게 됩니다.
위의 코드에서 var 라는 것은 variable 의 약어로 변수를 의미합니다. cDoc 라는 변수를 선언한다는 뜻이고요.
cDoc 라는 변수에 "=" 우측의 값을 적용한 것이죠. 우측의 값은 바로 현재 열려 있는 창을 말합니다.
app 라는 것은 포토샵을 의미하고요. activeDocument 는 현재 활성화된 창을 말합니다. (대소문자에 주의 하세요~)
그 다음 줄부터 cDoc 는 스크립트가 실행되던 순간 활성화 되어있는 창을 의미하게 됩니다.
위에서 배웠던 자바스크립트 콘솔창에 프린트를 하는 명령을 이용하여 현재 활성화된 창의 이름과, 가로크기, 세로크기, 그리고 레이어의 갯수를 출력하도록 해보았습니다.
이와 같이 스크립트 툴킷을 이용하여 개발을 하게되면 실행중인 값을 확인하며 개발을 할 수 있기 때문에 빠르고 정확한 코딩이 가능하게 됩니다. 또한 레퍼런스도 잘 되어 있는 편이어서 개발이 한결 수월해 지게 됩니다.
다음 시간에는 오브젝트 모델 뷰어를 통하여 필요한 명령어를 찾는 방법을 소개해 보겠습니다.
궁금하신 내용은 뎃글 부탁드립니다.
뎃글, 공감 은 블로그 작성자에게 큰 힘이 된답니다. 도움이 되었다 생각되시면클릭!! 부탁드려요~
함수는 단순하게 만드는 것이 좋지만 경우에 따라서는 아주 복잡하게 만들어 지는 경우도 있습니다.보통 스크립트 언어에는 기본적으로 제공되는 함수가 많이 존재 합니다. 특히 자바스크립트나 엑셀에서 사용하는 비주얼 베이직에서는 아주 유용한 많은 함수가 사전에 제공되므로 빠르고 쉽게 코딩을 할 수 있습니다.
예를 들면
String.indexOf("찾는글자") 와 같은 함수는 String 이라는 문자열 안에서 "찾는글자" 가 있는지 검사한 후 있으면 발견된 위치를 돌려주고 없으면 -1 을 돌려주는 함수 입니다.
Folder.getFiles("*.png") 라는 함수는 Folder 안에 있는 모든 파일 중에서 확장자가 ".png" 인 파일을 모두 찾아서 배열로 돌려 줍니다. 배열은 뒤에 다시 설명하겠습니다.
판단
컴퓨터를 이용해서 무엇인가를 시키기 위해서는 반드시 판단을 해주는 로직이 들어가게 되어 있습니다. 판단 로직이 없다면 사실상 포토샵의 액션보다 나을게 없습니다. 액션에서는 판단을 할 수 있는 구조가 없기 때문에 스크립트가 더욱 막강해 지게 됩니다.
판단 로직은 대부분의 언어에서 if 라는 이름으로 합니다. 다만 언어마다 작성하는 규칙에는 차이가 있습니다.
자바 스크립트에서는 아래와 같이 작성됩니다.
if (value > 10) {
myfunction()
}
엑셀 비주얼 베이직 스크립트라면 아래와 같이 작성이 됩니다.
if (value > 10) then
myfunction()
end if
판단을 해주는 로직은 if 뒤에 나오는 내용이 참인지 거짓인지를 판단하여 참이면 그 다음의 내용을 실행하도록 합니다. 예를 들면 현재 이미지의 가로가 세로보다 길다면 가로 사이즈를 720 으로 리사이즈 하고 세로가 길다면 세로를 720 으로 리사이즈 할 수 있습니다.
이미지의 가로 길이가 1920이 아니라면 오류 메시지를 출력하도록 할 수 있습니다.
레이어셋 안에 있어야 할 필수 레이어가 존재하지 않는다면 파일명에 "error" 를 붙여 저장할 수도 있겠습니다.
판단 로직을 잘 이용하면 아주 복잡한 연산과 판단도 가능해 집니다. 판단 로직안에 또다른 판단 로직이 들어갈 수 있기 때문입니다.판단 로직을 통하여 참이 아닌경우에 수행해야 할 동작이 있다면 아래와 같이 else 라는 명령으로 수행을 시킬수 있습니다.
참 / 거짓에 대하여 각각 실행해야 할 구문을 정의하려면
if (value > 10) {
myfunction()
}else{
yourfunction()
}
판단 조건이 좀더 여러가지 경우를 포함한다면
if (value > 10) // value 의 값이 10 보다 크다면
{
myfunction()
}else if (value < 5) // value 의 값이 5보다 작다면
{
yourfunction()}
else // 위에 제시한 두가지 조건에 해당이 되지 않는다면
{
anotherfunction()
}
하나의 문장으로 한개 이상의 판단을 수행하는 것도 가능합니다.
if (value > 10) && (value < 100) // value 라는 변수의 값이 10 보다 크고 100 보다 작다면
{
myfunction()
}
else
{
yourfunction()
}
if 구문안에 또다시 if 구문이 들어오는 것도 가능합니다.
if (value > 10) && (value < 100) // value 라는 변수의 값이 10 보다 크고 100 보다 작다면
{
if(value2 != "png") {
myfunction()
}
}
else
{
yourfunction()
}
반복위에 말한 것처럼 코딩, 즉 개발을 하는 궁극적인 목적중에 하나 입니다.
컴퓨터는 1번을 시키건 1000 번을 시키건 투정부리지 않습니다.
특정 폴더안의 모든 파일 또는 폴더, PSD 파일 내의 모든 레이어, 엑셀에 있는 모든 셀 등이 주로 대상이 됩니다.
반복은 for 라는 명령으로 진행이 됩니다.
포토샵의 자바스크립트에서는 아래와 같은 형식으로 문장을 작성해야 합니다.
for (int i = 0; i < 100; i ++) // i 라는 변수를 생성하고 0 부터 99 까지 반복 실행을 합니다. 이때 i 는 반복할 때마다 1 씩 증가 됩니다.
{
myFunction( i )
}
엑셀 비주얼 베이직에서는 아래와 같이 정의 합니다. (동작은 동일 합니다)
for i = 0 to 99
myFunction(i)
next
예를 들어 특정 폴더안의 모든 파일을 대상으로 어떤 것을 해야 한다면 이런식으로 작성이 됩니다.
var cFolder = Folder("d:\\asd\\")
// d 드라이브의 asd 라는 폴더를 cFolder 라는 변수에 저장.
// 이후에 나오는 cFolder 는 해당 폴더를 가리킵니다.
var cFiles = cFolder.getFiles("*.png") // cFiles 라는 변수에 위에 정의한 cFolder 안의 모든 png 파일을 찾아서 저장합니다.
for (int i = 0; i < cFiles.length; i++) // 변수 i 에 0 부터 위에서 찾은 모든 png 파일의 개수 만큼 반복하며 아래의 내용을 수행합니다.
{
myFunction( cFiles[ i ] ) // myFunction 이라는 사용자 정의 함수에서 각각의 파일을 입력으로 하여 무엇인가 일을 수행합니다.
}
배열
위에서 언급하지는 않았지만 배열의 개념을 잘 알아야 합니다.
자동화를 위해서는 빠질 수 없는 개념이기 때문인데 여러개의 정보 뜨는 데이터가 하나의 변수안에 묶에 있는 경우라고 보면 됩니다. 집합이라고 할수도 있겠고 묶음이라고 할수도 있겠습니다.
보통 배열 안의 데이터들은 동일한 타입의 값을 갖지만 그렇지 않은 경우도 있습니다.
배열은 보통 다음과 같이 정의 되며 사용됩니다.
변수를 선언하고 이 변수를 배열로 사용하는 경우
var sizeList = #{ }
sizeList 라는 변수를 만들고 이 안에 값들을 저장할 것이라고 선언해주는 구문 입니다.
변수 선언시 배열로 지정하여 사용하지 않고 바로 그냥 배열을 만들어 사용하는 경우
var myPos = [ 1920, 720 ]
var myPos = [ 1920, 720 ]
처음부터 값을 넣어서 배열을 선언하는 경우
var sizeList = #{ 640, 800, 1024, 1280, 1920}
var sizeList = #{ 640, 800, 1024, 1280, 1920}
처음 선언할때는 비어있는 배열을 선언하지만 이후 값을 채워 넣는 경우
var sizeList = #{ } sizeList.push(640) // 배열에 640 이라는 값을 넣습니다. 비어있었기 때문에 첫번째 값이 됩니다.
sizeList.push(800) // 배열에 800 이라는 값을 넣습니다. 첫번째 값이 이미 있기 때문에 두번째 값으로 들어가게 됩니다.
sizeList.push(1024) // 배열에 세번째 값으로 1024 를 집어 넣습니다.
var sizeList = #{ } sizeList.push(640) // 배열에 640 이라는 값을 넣습니다. 비어있었기 때문에 첫번째 값이 됩니다.
sizeList.push(800) // 배열에 800 이라는 값을 넣습니다. 첫번째 값이 이미 있기 때문에 두번째 값으로 들어가게 됩니다.
sizeList.push(1024) // 배열에 세번째 값으로 1024 를 집어 넣습니다.
이미 정의된 배열의 값을 변경하는 것도 가능합니다.
var sizeList = #{ 640, 800, 1024, 1280, 1920}
sizeList[ 2 ] = 2560 // 배열의 3번째 값인 1024 를 2560 으로 변경합니다.
var sizeList = #{ 640, 800, 1024, 1280, 1920}
sizeList[ 2 ] = 2560 // 배열의 3번째 값인 1024 를 2560 으로 변경합니다.
자바 스크립트는 0 부터 시작되기 때문에 2 는 3번째 값을 의미 하게 됩니다. 햇갈리는 부분이죠.
배열은 또다른 배열을 품을 수 있는데 이런 경우 2차원 , 3차원 배열로 이야기 할 수 있습니다.
2차원 배열은 아래와 같이 생겼는데 저의 경우에는 가로세로 사이즈나 x y 좌표를 저장할 때 자주 사용합니다..
var pointList = #{ [25,30], [35,40], [45,50] }
var pointList = #{ [25,30], [35,40], [45,50] }
2차원 배열의 값을 이용할 때는 다음과 같이 사용합니다.
var pointList = #{ [25,30], [35,40], [45,50] }
var myPosX = pointList[0][0] // 배열의 첫번째 값 의 첫번째 값인 25 이 myPosX 라는 변수에 저장이 됩니다..
var myPosY = pointList[0][1] // 배열의 첫번째 값의 두번째 값인 30 이 myPosY 라는 변수에 저장이 됩니다..
var pointList = #{ [25,30], [35,40], [45,50] }
var myPosX = pointList[0][0] // 배열의 첫번째 값 의 첫번째 값인 25 이 myPosX 라는 변수에 저장이 됩니다..
var myPosY = pointList[0][1] // 배열의 첫번째 값의 두번째 값인 30 이 myPosY 라는 변수에 저장이 됩니다..
삭제논리적 사고코딩은 기본적으로 컴퓨터에게 명령을 하는 것이므로 논리적인 글 작성이 필요합니다.논리적이라하면 문장의 흐름에 오류가 있으면 안된다는 의미인데요. 무엇인가 시작이 되었다면 종료가 되어야 하고 판단 로직이 들어가면 정확히 판단할 수 있는 기준이 제시되어야 합니다.
예를 들면 "이미지의 크기가 크다면 " 과 같은 기준은 컴퓨터가 처리 할 수 없습니다.
일단 어느정도의 크기가 큰것인지 작은것인지를 알수 없어 크기의 기준이 가로 인지 세로인지 아니면 용량인지, bit 수 인지 알 수 없기 때문입니다.
그래서 컴퓨터에게 판단을 시킬때는 "이미지의 가로 픽셀 수 가 960 보다 크다면" 과 같이 명확한 기준을 주어야 합니다.코딩을 해보면 이런식입니다.
잘못된 코드
if (image == big)
{
myFunction()
}
잘 된 코드
preference.unit = unit.PIXEL // 환경 설정의 유닛의 단위를 pixel 로 설정해준다.
//GUI 디자인과정에서는 대부분 유닛이 pixel 이겠지만
//그렇지 않은 사용자에게서는 cm 또는 inch 가 반환되어 오류가 날수 있다.
var maxSize = 960 // 판단 기준이 되는 사이즈를 지정 합니다.
var imageWidth = myDoc.width // 다큐먼트의 가로 크기를 가져와서 imageWidth 라는 변수에 지정
if (imageWidth > maxSize) { // 이제 사전에 설정한 최대 크기와 imageWidth 를 비교하여 더 큰지를 확인
myFunction()
}
사실 처음부터 논리적 사고를 바탕으로 코딩을 시작하면 좋겠는데 이부분은 여러번의 오류를 겪으며 실력이 쌓이는 것이 당연한 부분이므로 두려워 말고 코드를 작성하기 시작하면 됩니다.
코드를 작성할 때는 명확하게 어떤 동작을 시킬 것인지를 먼저 잘 생각해보는 것이 빠르고 정확하게 코딩을 하는데 큰 도움이 됩니다.
예를 들면 포토샵에서 레이어 이름으로 이미지를 저장하는 스크립트를 만든다고 하면 다음과 같은 방식으로 개발할 내용을 먼저 정리를 합니다.
파일이 저장될 경로를 설정하자 : PSD 파일의 경로에 저장
파일이 저장될 포멧을 지정 : png 파일로 지정
png 파일의 옵션을 설정
현재 최상위에 보여지는 모든 레이어를 변수로 설정먼저 모든 레이어를 hide 상태로 변경
레이어셋을 포함한 전체 레이어를 반복하여 탐색
레이어의 타입이 레이어셋인지 레이어인지 확인
- 레이어의 타입이 레이어일 경우 해당 레이어를 Show 시킨뒤 지정된 경로에 레이어의 이름으로 파일 저장
- 저장이 완료 되었으면 다시 Hide 시키자.
- 레이어의 타입이 레이어 셋인 경우
- 저장될 폴더 하위에 레이어 셋과 동일한 명칭의 폴더를 생성하자
- 생성된 경로를 이미지가 저장될 경로로 변경해 주자
- 레이어 셋 안의 레이어를 다시 탐색하자
- 탐색된 레이어의 타입이 레이어인지 레이어 셋인지 확인. (이하 동일), 이 부분이 depth 가 깊어지면 반복될 수 있으므로 재귀 함수로 별도로 만들 것
-모든 레이어의 저장이 완료 되었으면 다시 모든 레이어를 Show 상태로 변경
PSD 파일 닫기
이런 식으로 개발 내용을 정리 하였다면 이제 본격 적으로 코딩을 시작합니다.
현재 다큐먼트를 변수에 설정하고 PSD 파일이 있는 경로를 확인
var cDoc = app.activeDocument;
var savePath = cDoc.path + "\\"; // savePath 라는 변수에 현재 PSD 파일의 경로를 저장합니다.
PNG 파일의 옵션을 설정해 봅니다.
var psOption = new PNGSaveOptions()
psOption.embedColorProfile = true;
psOption.formatOptions = FormatOptions.STANDARDBASELINE;
psOption.matte = MatteType.NONE;
psOption.quality = 100;
psOption.PNG8 = false; //24 bit PNG
psOption.transparency = true;
psOption.interlaced = true;
요런 세세한 설정 값들은 레퍼런스를 참고 하는 방법과 인터넷이나 미리 만들어논 코드에서 따오는 것이 좋습니다.
현재 PSD 파일의 최상위 레이어를 모두 배열로 변수에 담아 줍니다. 그리고 모든 최상위 레이어를 숨김처리 합니다.
var tempLayers = cDoc.layers
for (var i = 0 ; i < tempLayers.length; i++)
{
tempLayers[i].visible = false
}
이제 레이어를 돌면서 레이어 셋인지 레이어인지 판단을 해봅니다.
모든 상위 레이어를 돌면서 레이어 셋인지 아닌지 판단
for (var i = 0 ; i < tempLayers.length; i++){
if (tempLayers[i].typename == "LayerSet")
{
}else{
}
}
이제 여기에 레이어 일경우 파일로 저장하는 기능을 넣어 보면 이렇게 됩니다.
for (var i = 0 ; i < tempLayers.length; i++)
{
if (tempLayers[i].typename == "LayerSet")
{
}else{
tempLayers[i].visible = true; // 현재 레이어를 보이도록 설정
cFile = File(savePath + tempLayers[i].name + ".png"); // 저장할 경로 뒤에 레이어 명을 붙여서 저장하기 위한 파일을 생성함 (아직 실제 파일이 생성되지는 않음)
cDoc.saveAs(cFile, psOption,true, Extension.LOWERCASE); // PS 에서 save as 하는 것과 동일합니다. 위에서 작성한 png 옵션을 이용하여 저장해주죠
tempLayers[i].visible = false; // 저장하고 나면 다시 레이어를 보이지 않도록 설정합니다.
}
}
레이어 셋일 경우 레이어 셋의 이름으로 폴더를 생성하고 depth에맞게 저장될 수있도록 준비를 해봅시다.
for (var i = 0 ; i < tempLayers.length; i++){
if (tempLayers[i].typename == "LayerSet") {
dPathName = savePath + tempLayers[i].name + "\\"; // 기존 저장 경로에 레이어 셋의 이름을 추가하여으로 새로 만들 경로 명칭을 정의 합니다.
ff = new Folder(dPathName) ; // 신규 생성할 경로를 폴더로 설정합니다.
ff.create(); // 위에 정의한 폴더를 실제로 생성합니다.
}
}else{
tempLayers[i].visible = true; // 현재 레이어를 보이도록 설정
cFile = File(savePath + tempLayers[i].name + ".png"); // 저장할 경로 뒤에 레이어 명을 붙여서 저장하기 위한 파일을 생성함 (아직 실제 파일이 생성되지는 않음)
cDoc.saveAs(cFile, psOption,true, Extension.LOWERCASE); // PS 에서 save as 하는 것과 동일합니다. 위에서 작성한 png 옵션을 이용하여 저장해주죠
tempLayers[i].visible = false; // 저장하고 나면 다시 레이어를 보이지 않도록 설정합니다.
}
}
레이어일 경우 그냥 저장하면 되는데 레이어 셋일 경우에는 하위 구조를 다시 탐색을 해야 합니다.
하위 구조를 탐색하기 위한 함수를 만들어 보겠습니다.
위에서 작성한 탐색 구조와 완전히 동일합니다.
재귀 함수를 만들껀데요. (재귀 함수는 반복해서 자신을 호출할 수 있도록 개발된 함수를 말합니다. 좀 개념이 어려운데 아래 코드를 보고 잘 생각해보면 이해가 될 수도 있습니다)
레이어 구조를 탐색하며 레이어면 이미지로 저장하고 레이어 셋이면 다시 탐색을 시키는 함수 입니다.
원래는 하나로 만들면 되는데 PS 스크립트 문제인지 두개로 나누어서 서로 호출하도록 해야 정상 동작이 되네요.
좀 이상하지만 어쨌든 이렇게 만들게 되면 explorerLayerSet 이라는 함수가 호출이 될 때 파일이 저장될 경로과 레이어 셋을 함수의 인자로 입력을 받게 됩니다.
입력된 레이어셋 안에서 레이어를 만나면 입력된 경로에 이미지로 저장하고 레이어 셋을 만나면 경로를 생성한 후 explorerLayerSet2 라는 함수를 호출합니다.
explorerLayerSet2 은 구조적으로 explorerLayerSet 과 완전히 동일한 함수인데요 마찬가지로 레이어 셋을 탐색하게 되며 레이어셋 안에서 레이어를 만나면 이미지로 저장하고 레이어 셋을 만나면 explorerLayerSet 을 다시 호출하게 되죠. depth 가 아주 많아도 계속해서 서로 호출하며 마지막 depth 까지 탐색을 하며 레이어만 저장을 하게 됩니다.
function explorerLayerSet (cPath, lSet){
var dLyrs = lSet.layers
for (var k = 0 ; k < dLyrs.length; k++)
{
if (dLyrs[k].typename == "LayerSet")
{
dLyrs[k].visible = true ;
ePathName = cPath + dLyrs[k].name + "\\";
ee = new Folder(ePathName);
ee.create();
explorerLayerSet2 (ePathName, dLyrs[k]);
dLyrs[k].visible = false;
}else{
dLyrs[k].visible = true;
dFile = File(cPath + dLyrs[k].name + ".png");
cDoc.saveAs(dFile, psOption,true, Extension.LOWERCASE);
dLyrs[k].visible = false;
}
}
lSet.visible = false;
}
function explorerLayerSet2 (cPath, lSet)
{
var cLyrs = lSet.layers
for (var m = 0 ; m < cLyrs.length; m++)
{
if (cLyrs[m].typename == "LayerSet")
{
cLyrs[m].visible = true
ePathName = cPath + cLyrs[m].name + "\\"
ee = new Folder(ePathName)
ee.create();
explorerLayerSet (ePathName, cLyrs[m])
cLyrs[m].visible = false
}
else
{
cLyrs[m].visible = true
cFile = File(cPath + cLyrs[m].name + ".png")
cDoc.saveAs(cFile, psOption,true, Extension.LOWERCASE)
cLyrs[m].visible = false;
}
}
cLyrs.visible = false;
}
이제 작성된 함수를 원래 작성하고 있던 코드에 삽입해 봅니다.
for (var i = 0 ; i < tempLayers.length; i++)
{
if (tempLayers[i].typename == "LayerSet")
{
dPathName = savePath + tempLayers[i].name + "\\"; // 기존 저장 경로에 레이어 셋의 이름을 추가하여으로 새로 만들 경로 명칭을 정의 합니다.
ff = new Folder(dPathName); // 신규 생성할 경로를 폴더로 설정합니다.
ff.create(); // 위에 정의한 폴더를 실제로 생성합니다.
tempLayers[i].visible = true;
explorerLayerSet(dPathName, tempLayers[i]); // 바로 요 부분이 하위 뎁스를 계속해서 탐색할 수 있도록 개발한 함수를 끼워 넣는 부분입니다.
tempLayers[i].visible = false;
}
else
{
tempLayers[i].visible = true; // 현재 레이어를 보이도록 설정
cFile = File(savePath + tempLayers[i].name + ".png"); // 저장할 경로 뒤에 레이어 명을 붙여서 저장하기 위한 파일을 생성함 (아직 실제 파일이 생성되지는 않음)
cDoc.saveAs(cFile, psOption,true, Extension.LOWERCASE); // PS 에서 save as 하는 것과 동일합니다. 위에서 작성한 png 옵션을 이용하여 저장해주죠
tempLayers[i].visible = false; // 저장하고 나면 다시 레이어를 보이지 않도록 설정합니다.
}
}
아 이제 개발이 다 되었습니다.
이렇게 하면 PSD 파일에 있는 모든 레이어를 탐색하며 각 레이어를 파일로 저장하는 동작을 수행하게 됩니다.
전체 코드를 보면 이렇습니다.
//파일이 저장될 포멧을 지정 → png 파일로 지정//png 파일의 옵션을 설정
var psOption = new PNGSaveOptions()
psOption.embedColorProfile = true;
psOption.formatOptions = FormatOptions.STANDARDBASELINE;
psOption.matte = MatteType.NONE;
psOption.quality = 100;
psOption.PNG8 = false; //24 bit PNG
psOption.transparency = true;
psOption.interlaced = true;
var cDoc = app.activeDocument //파일이 저장될 경로를 설정하자 → PSD 파일의 경로에 저장
var savePath = cDoc.path + "\\" //현재 최상위에 보여지는 모든 레이어를 변수로 설정
var tempLayers = cDoc.layers //먼저 모든 레이어를 HIde 상태로 변경
for (var i = 0 ; i < tempLayers.length; i++)
{
tempLayers[i].visible = false //레이어셋을 포함한 전체 레이어를 반복하여 탐색
}
for (var i = 0 ; i < tempLayers.length; i++)
{ //
if (tempLayers[i].typename == "LayerSet") //레이어의 타입이 레이어셋인지 레이어인지 확인
{
dPathName = savePath + tempLayers[i].name + "\\" // 기존 저장 경로에 레이어 셋의 이름을 추가하여으로 새로 만들 경로 명칭을 정의 합니다.
ff = new Folder(dPathName); // 신규 생성할 경로를 폴더로 설정합니다.
ff.create(); // 위에 정의한 폴더를 실제로 생성합니다.
tempLayers[i].visible = true;
explorerLayerSet(dPathName, tempLayers[i]); // 바로 요 부분이 하위 뎁스를 계속해서 탐색할 수 있도록 개발한 함수를 끼워 넣는 부분입니다.
tempLayers[i].visible = false;
}
else
{
tempLayers[i].visible = true; // 현재 레이어를 보이도록 설정
cFile = File(savePath + tempLayers[i].name + ".png"); // 저장할 경로 뒤에 레이어 명을 붙여서 저장하기 위한 파일을 생성함 (아직 실제 파일이 생성되지는 않음)
cDoc.saveAs(cFile, psOption,true, Extension.LOWERCASE); // PS 에서 save as 하는 것과 동일합니다. 위에서 작성한 png 옵션을 이용하여 저장해주죠
tempLayers[i].visible = false; // 저장하고 나면 다시 레이어를 보이지 않도록 설정합니다.
}
} // 여기부터는 레이어 셋일 경우 하위 뎁스를 계속해서 탐색하는 함수 입니다.
function explorerLayerSet (cPath, lSet)
{
var dLyrs = lSet.layers
for (var k = 0 ; k < dLyrs.length; k++)
{
if (dLyrs[k].typename == "LayerSet")
{
dLyrs[k].visible = true;
ePathName = cPath + dLyrs[k].name + "\\";
ee = new Folder(ePathName);
ee.create();
explorerLayerSet2 (ePathName, dLyrs[k]);
dLyrs[k].visible = false;
}
else
{
dLyrs[k].visible = true;
dFile = File(cPath + dLyrs[k].name + ".png");
cDoc.saveAs(dFile, psOption,true, Extension.LOWERCASE);
dLyrs[k].visible = false;
}
}
lSet.visible = false;
}
function explorerLayerSet2 (cPath, lSet)
{
var cLyrs = lSet.layers
for (var m = 0 ; m < cLyrs.length; m++)
{
if (cLyrs[m].typename == "LayerSet")
{
cLyrs[m].visible = true;
ePathName = cPath + cLyrs[m].name + "\\";
ee = new Folder(ePathName);
ee.create();
explorerLayerSet (ePathName, cLyrs[m]);
cLyrs[m].visible = false;
}
else
{
cLyrs[m].visible = true;
cFile = File(cPath + cLyrs[m].name + ".png") O
cDoc.saveAs(cFile, psOption,true, Extension.LOWERCASE)
cLyrs[m].visible = false
}
}
cLyrs.visible = false
}
이 정도는 어느정도 훈련된 디자이너라면 개발자가 아니어도 충분히 작성할 수 있는 어렵지 않은 코드 수준이라고 생각됩니다.
어렵지 않고 길지 않은 코드이지만 디자이너의 시간은 비약적으로 늘어나게 만들어 주는 코드라고 할 수 있습니다.
코딩을 하려면 앞서 이야기 했지만 무엇을 개발할 것인가를 명확히 하는 것이 중요합니다.
애메모호한 목표는 코딩을 더욱 어렵게 만들게 됩니다. 현재 본인이 가장 귀찮게 반복해야 하는 업무가 무엇인지 정확히 파악이 되었다면 컴퓨터에게 일을 시킬 준비를 해보세요. 어렵지 않습니다.
아도이노는 DIY 인 들에게 없어서는 안될 단물 같은 장치이다. 물론 요즘은 프로그래밍 교육용으로도 사용되고 미디어 아티스트들에게도 자주 사용되는 놀라운 장치이다. 간단한 코딩 만으로 하드웨어 지식이 거의 없더라고 다양한 레퍼런스를 이용하여 손쉽게 무엇인가 로지컬하게 동작하는 장치를 만들어 낼 수 있기 때문이다.
이번에 도전하게 된 것은 Arduino Nano 를 이용하여 RC 카 구동을 위한 무선 송수신기를 제작하는 것이다.
보통은 RC 카를 구성하는 송신기 (트랜스미터, Transmitter) 와 수신기 (리시버, receiver) 를 세트로 구입하여 모터와 ESC 에 연결하여 사용하는 것이 일반적이지만 직접 만들어 보는 것도 재미있을 것 같아 도전을 하게 되었다. RC 카의 차체와 모터 등은 기성품을 이용하여 가지고 놀기에도 좋아야 하며 송수신기 모듈만 아두이노를 이용하여 만드는 것을 목표로 하고 있다.
먼저 첫번째 시간으로 수신기 만들어 보자
필요한 부품
Arduino nano (atmega328p, 16MHz)
NRF24L01 SMD 버전
10 uF 전해콘덴서
점퍼용 선들
모터 / 서보 / ESC 연결용 2핀, 3핀 소켓 (만능기판 장착용, 2.54mm)
만능기판(양면) 8 * 24
SMD to DIP Adapter socket (1.27mm to 2.54mm, SOP14 규격) : 10개에 1 달러 미만
아두이노 나노에 대한 설명은 넣어두고 무선 연동을 위한 NRF24L01 보드가 필요하다.
해당 보드는 알리익스프레스에서 개당 1000원 미만으로 구입할 수 있다. 보통 무선 연동은 트랜스미터와 리시버가 각각 역할을 분담하는 형태로 모듈이 만들어져 있는데 이 제품은 하나의 제품이 송신과 수신을 할수 있는 제품으로 일명 트랜시버 라고 부르기도 한다. 2.4GHz 대역을 사용하여 신호의 정확도가 좋다고 한다.
이번 DIY 를 위하여 SMD 타입을 구입하였는데 일반 보드는 4x2 형태의 핀 배열을 가지고 있어 브래드 보드를 통한 테스트가 쉽지 않은 반면 SMD 타입은 1열로 핀이 배열되어 있어 약간의 꼼수를 부리면 사용이 간편한 장점이 있다.
NRF24L01 보드에 꼭 필요한 부품이 있으니 바로 10uF 전해 콘덴서
NRF24L01 보드에 꼭 필요한 부품이 있으니 바로 10uF 전해 콘덴서이다. 처음 이 프로젝트를 도전하였을때 상당히 많은 실패를 경험했는데 결과적으로는 이 전해콘덴서를 연결하지 않은 부분과 정확한 3.3V 를 인가하지 않은데서 기인했다고 생각된다. 지금은 단 한번의 실패도 없이 잘되는 것을 생각하면 정말 어의가 없지만 거의 2개월 정도를 이 문제 해결을위해 소모하였다. 이 글을 보는 당신도 도전할 생각이 있다면 반드시 10uF전해 콘덴서를 미리 준비해놓자. 47uf 도 100uf 도 1uf 도 아닌 반드시 10 uf 로 준비하자. 알리에서 사면 몇푼 하지도 않을 뿐더러 무료배송인 판매자도 많다. 전해 콘데서는 극성이 있는 제품이다. 띠 무늬가 있는 부분이 - 극 (GND) 다른 부분이 아두이노의 3.3V 또는 NRF24L01 의 +부분에 연결이 되어 있어야 한다.
사진에 제일 위층에 얹어진 검정색 PCB 보드가 NRF24L01 보드이다. 뒤쪽에 초록색으로 보여지는 보드는 작업의 편의 성을 위하여 붙인 것으로 원래는 14 pin Attiny84 smd 타입을 일반 만능기판에 연결할 수 있도록 사용하는 아답터 보드인데 이것을 반을 자르면 7핀을 이용하는 NRF24L01 보드의 확장용 보드로 사용이 가능할 것 같아 납땜하여 붙여서 사용해보았고 아주 만족스러운 호환성을 보여주었다.
아래와 같은 형태의 보드인데 반을 자른 후 NRF24L01 칩을 납땜하여 붙여주면 1열로 된 핀 배열 구성이 가능하게 되어 브래드 보드에서 바로 테스트가 가능하다. 참고로 NRF4L01 은 총 8개의 연결핀이 있는데 위에서 봤을때 가장 오른쪽 핀은 사용할 필요가 없는 핀 이므로 아래 아답터 보드를 반으로 자른후 좌측부터 7개의 단자와 납땜을해서 붙이면 정확하게 딱 맞는 결과물을 얻을 수 있다.
보통 고가의 프로그램들에는 자신들만의 스크립트 언어를 가지고 있는 경우가 흔히있으며 대부분 이 스크립트를 통해 일반적으로 구현하기 어려운 여러가지 것을을 손쉽게 구현할 수 있게 되는 경우가 많다. 고가의 프로그램이 고가인 이유가 스크립트가 이유인 경우도 많다.
90%이상의 포토샵 유저가 포토샵 스크립트라는 것이 있다는 것을 알지 못할 것이다. 하지만 adobe 는 나름의 스크립트 언어를 지원하고 있고 이를 위해 extend script tool kit 이라는 스크립트 언어 저작 프로그램을 별도로 제품 패키지에 끼워넣어 팔고 있으니 개발사 입장에서는 분명 중요하게 생각하고 있는 듯 하다. 3D 프로그램의 양대산맥이었던 Maya 에도 mel 이라는 스크립트를 지원하고 있고 매우 강력한 것으로 알고 있다.
오늘 내가 이야기 할 것은 바로 3DS MAX 가 지원하는 max Script 이다.
3D max가 그렇게 엄청난 가격에 팔림에도 불구하고 많은 사람들이 울며 겨자먹기로 구입을 해서 사용하는 것으로 알고 있다. 과연 이들 중 이 프로그램의 가치를 충분히 얻어내고 있는 사람들이 얼마나 있을까. 말하자면 맥스에 들어있는 무수히 많은 엄청난 기능들과 효과들을 얼마나 사용하고 있을까 궁금하기도 하다. 그중에 max script 가 단연 1순위라고 생각되지만 말이다.
우선 나는 맥스 스크립트를 찬양하는 사람 중 한명일 것이다.실제로 나의 업무량을 1/10 도 안돼게 줄여준 고마운 녀석이기도 하고 이를 통해 얻은 시간에 보다 가치있는 많은 것을 할 수 있게 되었기 때문이다.
내가 회사에서 하는 업무 중 맥스 스크립트가 사용되지 않는 업무는 거의 없다고 생각도 든다. 맥스 스크립트는 참으로 다재다능 하므로 3D 모델링 작업을 하는데만 사용되는 것이 아니기 때문이기도 하다.
내가 맥스 스크립트로 하는 업무를 분야별로 간단하게 나열해보면,
*3D 모델링 자동화 *3D 맵핑 자동화
*웹지도 연동 *대량의 3D max파일(또는 object) import / export *대량의 파일을 원하는 조건에 맞도록 copy / rename / delete ... (내 컴퓨터 파일관리) *이미지 분석 및 수정 (rename, resize, crop, save as, ...) *이미지 합성 (diffuse + occlusion + lightmap ...) *지원되지 않는 포멧 (ex>arcGIS '*.shp') 불러오기. *작업내역 및 필요한 내역 텍스트파일로 저장(txt, csv, ....)
뭐 더 있겠지만 그냥 생각나는 데로 적어보면 위와 같은데, 대충 봐도 참 다양한 일을 하고 있다. 깨알같이 나처럼 사용하는 사람도 많지는 않겠지만 어찌되었든 참 고마운 녀석임에는 틀림이 없다. 위의 내용중 어느 하나도 적당히 손으로 대신 하기가 쉽지 않은 것들이다. 왜냐하면 단순업무면 손이 엄청나게 많이 가거나 일일이 신경을 써서 해야 하는 작업들이기 때문이다.
간단히 export 만 하더라도 회사에서 특정시기에 많게는 한번에 3만개 이상의 obj 파일을 고유의 이름으로 export 를 해야하는데 이것을 일일이 손으로 한다는 것은 사실상 어려운 일이다. script 가 이런것을 지원해주지 않았다면 export select 를 단축키 지정해서 하더라도 아마 1달 정도는 출근해서 야근까지 해가며 퇴근한느 순간까지 화장실도 가지 않고 일일이 저장을 했어야 했을 것이다. 그리고 손가락 관절염에 걸려 1,2 년만에 이바닥을 떠나게 될지도 모른다.
최근 max script 에 관심을 보이는 국내 유저들이 많이 보이고 있는데 쉽게 포기하지말고 다양한 방면으로 접근해서 업무를 손쉽게 할 수 있는 좋은 결과를 얻었으면 좋겠다. 사실 맥스 스크립트 만큼 프로그래밍 하기 쉬운 언어도 없다. java script 를 이용하는 photoshop script 는 정말 까다롭기 짝이 없다. 레퍼런스도 그다지 훌륭하지 않거니와 open 되어 있는 기능도 상다히 제한적이어서 초보 스크립터가 작성하기에는 정말 불편한 녀석이니까. 반면 맥스 스크립트는 대소문자도 관계가 없고 줄바꿈이나 탭, 띄어쓰기, 다이얼로그 생성, 각종 UI 생성, function 생성, 변수 및 데이터 형 관리 뭐하나 까다롭지 않고 손쉽게 접근할 수 있게끔 되어있다. 그리고 무엇보다 레퍼런스가 참으로 훌륭하다.
블로그에 max script 와 관련한 내용을 좀 담아 보려고 준비를 했었는데 이런저런 핑계로 미루고 있던 참이었다.
맥스에 이미 좋은 레퍼런스가 포함되어 있으므로 강좌 씩이나 할 필요도 능력도 없겠지만 알아두면 맥스 스크립트 코딩에 도움이 될만한 정보들을 기재해 보려고 한다.
마이크로 소프트 엑셀은 수많은 기능과 자동화된 연산 처리, 편리한 템플릿 가공, 다양한 그래프 드을 이용한 데이터의 시각화 외에도 아주 많은 유용한 기능을 제공하여 사무 업무의 표준 프로그램이 되었다. 나는 디자이너이지만 후배들에게 포토샵이나 일러스트만큼이나 중요한 프로그램이라고 자신있게 말할 수 있는 것이 바로 엑셀이다. 회사에서 작성되고 확인되는 거의 모든 수치를 다루는 문서는 바로 엑셀이기 때문이다.
견적서도, WBS 같은 일정표도, 데이터 분석 결과도 모두 엑셀이며 지금은 전자문서로 대체되긴 했지만 각종 결재 서식이나 양식역시 워드보다 엑셀을 많이 사용했었다.
본 포스트를 보신 후 도움이 되었다 생각되시면 공감클릭!! 부탁드려요~
엑셀 전문가 하면 다양한 기능을 사용하는 것도 있지만 무엇보다 엑셀에서 지원하는 강력한 기능인 함수의 사용 여부로 판가름 할 수 있겠다. 엑셀에서 각종 지원 함수를 이용하면 엑셀이 더이상 문서가 아닌 하나의 프로그램이 되기 때문이다. 엑셀 지원 함수를 이용한 기능은 너무나도 다양하기 때문에 여기서 다루지는 않을 것이고 따로 찾아보는 것이 좋을 것이다. 관심이 있다면 학원을 잠시 다니는 것도 추천한다.
그럼 여기서 이야기 할 주제는 무엇인가 하니, 바로 VBA 라고 하는 프로그래밍 언어에 대하여 작성할 예정이다.
VBA 란 Visual Basic for Application 의 약어로 마이크로 소프트에서 제공하는 office 제품군에서 사용할 수 있는 visual basic 언어를 말한다.
visual basic 은 하나의 프로그래밍 언어로 문법이 다른 언어와 약간 차이가 있지만 막상 배우려고 보면 아주 쉽게 습득할 수 있는 언어이며 인터넷에 아주 많은 레퍼런스가 널려 있어 새로 개발을 할때에도 참고할 만한 자료가 아주 많은 괜찮은 개발 언어이다.
이 포스트를 보는 분이 이런 글 보자고 들어온 것은 아닐 것 이므로 바로 본론으로 들어가자.
엑셀( 다른 office 제품군 포함)에서 VBA 를 작성하기 위하여 먼저 개발창을 열어야 한다.
alt + F11키를 누르면 아래와 같은 창이 나타난다.
좌측 상단에는 현재 엑셀에 열려있는 문서와 각 문서가 포함하고 있는 워크시트 (엑셀 창 하단에 보이는 탭) 이름이 보여지는 창이 하나 있고 아래는 복잡한 테이블... 별로 알필요 없음. 우측은 회색 공간이 있다. 회색 공간에 창이 하나 떠 있는데 이는 필자가 좌측 트리뷰에서 Sheet1(Sheet1) 로 표시된 부분을 더블클릭한 상태이다.
이 하얀색 텍스트 에디터에 VBA 를 작성하여 각종 자동화 작업을 할 수 있다.
VBA 에서는 어떤 목적을 위하여 수행하는 기능을 묶어서 실행을 시키게 되는데 바로 아래와 같은 형태로 정의한다.
Sub setText()
수행할 명령어
End Sub
여기서 setText 는 사용자가 원하는 기능의 명칭을 적으면 되며 실제 수행하는 기능은 "수행할 명령어" 부분에 입력하면 된다.
Sub setText()
Cells(1, 1).Value = "DIY"
Cells(2, 1).Value = "Dev."
Cells(3, 1).Value = "Design"
End Sub
요렇게 입력하고 F5 키를 누르면 엑셀 창의 Sheet1 에 아래와 같이 자동으로 작성이 된다.
위의 코드가 의미하는 것을 살펴보면
Cells 는 엑셀 화면의 칸들을 의미한다. Cells( rowIndex, columnIndex) 의 순서로 셀을 지정하게 되는데 rowIndex 는 행번호 즉 좌측에 세로로 보이는 숫자를 말하고 columnIndex 는 열을 의미하며 위에 보이는 알파벳에 해당되는 번호다. 물론 VBA 에서는 알파벳으로 기재를 하지 않고 숫자로 기재를 해야 한다. VBA 에서 가로 세로 열을 앞에 말한바와 같이 지칭할때는 항상 앞자리가 행, 뒷자리가 열 임을 기억하자.
참고로 코드 실행을 위하여 F5 를 누를 때 키보드의 커서가 Sub 와 End Sub 사이에 이어야 해당 기능이 실행이 된다.
엑셀 VBA 를 공부하면서 알아가야 할 것이 많겠지만 우선 다음과 같은 것들을 고민해보아야 한다.
무엇을 위해 VBA 를 사용할 것인가?
VBA 를 배우면 내가 하는 실무 (또는 생활) 에 당장 도움이 되는 것은 어떤 것일까?
엑셀을 이용하면서 가장 시간 낭비라고 생각했던 것은 무엇이었는가?
막연히 공부해야 겠다는 생각으로 시작한 스크립팅 공부는 생각보다 진도가 빠르게 나가지 않는다. 당장 1분이라도 내 시간을 아껴 줄 수 있는 부분을 빨리 찾아 직접 만들어 보는 것이 가장 빠른 학습방법이 된다. 아래 몇가지 예를 들어 볼테니 본인에게 해당되는 사항이 있다면 엑셀을 열고 Alt + F11 을 눌러 바로 코드를 작성해 보자.
위에 예시를 든 케이스 외에도 VBA 로 할 수 있는 작업은 무궁무진하다. 하지만 어려운 것부터 시작한다면 첫걸음을 떼기 어려우니 간단한 작업부터 도전해 보자.
VBA 관련 첫번째 포스트는 여기서 마무리를 할텐데 이 주제에서 다룰 내용은 아래와 같다.
1. 각종 VBA 명령어와 사용법
2. 알아두면 유용한 코드들
3. 완성된 코드 샘플
필자는 디자이너지만 프로그래밍을 접하면서 업무의 질이 많이 달라졌다. 개발직군이 아니라고 개발을 등한시 하지 말고 적극적인 자세로 접하도록 해보자. 어느 순간 개발자가 와서 이것 좀 해줄 수 있을까 하고 개발 의뢰를 할 것이다. 그럴때가 우리에게 채무자가 아닌 채권자의 입장이 될 수 있는 절호의 찬스일 것이다.
세상에 VBA 만큼 쉬운 프로그래밍이 없으니 걱정말고 시작하자. 개발자 아닌 디자이너, 기획자, 일반 사무직 분들.
내가 작성하는 내용만 다 따라와도 엑셀 붙잡고 머리 터지게 숫자 계산하는 업무시간이 1/10 으로 줄어들 것이다.
궁금한 내용이나 질문은 뎃글을 남겨주면 답변해 드리겠습니다.
뎃글, 공감 은 블로그 작성자에게 큰 힘이 된답니다. 도움이 되었다 생각되시면 클릭!! 부탁드려요~
아파트 고층에 살면 여러가지 장점이 있게 마련인데 그중의 제일은 아무래도 전망이 좋다는 점일 것이다. 물론 우리아파트는 최근에 바로 앞에 고층 아파트가 들어왔기 때문에 그 장점 하나가 사라져 버렸다.
반대로 아파트 고층에 살면 가장 큰 단점중에 하나가 창문을 닦기 어렵다는 점일 것이다. 1층이나 주택에 살때는 생각날때마다 창문을 닦으면 그만이지만 고층에 살다보면 거의 불가능에 가까운 일중에 하나다. 요즘처럼 먼지가 많은 시즌이 되면 점차 창문에 얼룩이 가득해지고 맑은 날도 흐린날처럼 느껴 질 정도로 창문이 더러워지기도 한다.
뎃글, 공감 은 블로그 작성자에게 큰 힘이 된답니다. 도움이 되었다 생각되시면 클릭!! 부탁드려요~
길다란 밀대 같이 생긴 창문 닦이를 사서 창문을 닦으려고 해본적도 있으나 스파이더맨이 아닌 이상 사실상 닦이는 부분은 얼마 안된다. 마트에서 1만원이 넘게 주고 샀지만 딱한번 바깥유리를 닦는데 도전을 하고 그냥 쳐박혀 있다가 손잡이 부분이 녹이 슬어 결국 제대로 사용해보지도 못하고 버리게 되었다.
요즘에는 유리에 붙여놓고 전기를 연결하면 스스로 움직이면서 유리를 닦아주는 기계도 나왔기 때문에 아파트 유리 닦는것이 본인의 일생의 도전 과제라면 시도해 볼만도 한데 수십만원이나 되는 금액을 지불하면서 까지 유리 닦는데 투자를 하고 싶지는 않았다. 그리고 막상 샀는데 잘 안닦이면 어쩌라고..
문득 초등학교때 책받침 아래에 자석을 두고 윗면에는 클립을 놓은뒤 아래 자석을 움직이면 클립이 마치 마법처럼 혼자 움직이는 놀이를 하곤 했었던 생각이 났다. "맞아!" 바로 이렇게 하면 되지... 하고 집에 있는 자석을 가져다가 테스트를 해보았다. 물론 다 실패했다. 집에 있는 자석 중에서 가장 강력한 손바닥 만한 스피커 자석도 결국 유리창의 두께를 넘어서 맞은편의 자석을 붙들고 있지는 못하였다. 아니 정확히는 붙들고 있기는 했지만 이내 떨어지고 말았다. 17층인 우리집에서 벽돌 만큼이나 무거운 자석이 떨어지기라도 한다면 정말 대 참사가 일어나고 이 아파트를 떠나야 할지도 모르기 때문에 실험 이후로 실제 유리를 닦는데 사용해보지는 않았다.
그런데 바로 이런 원리를 이용한 제품이 시중에 나와있는 것을 발견 하였다. 물론 후기를 봐야겠지.
이런 류의 제품들의 후기에는 잘 떨어진다거나 생각처럼 안된다는 글들이 좀 있었지만 대부분은 긍정적인 내용이었다. 여기 저기 검색 중에 나의 사랑 알리에서 적당한 제품을 발견하였다. 2만원 정도 금액을 지불하고 받은 제품.
배송에는 약 40일 정도 소요되었다.
박스는 위와 같이 생겼다. 뭐 별다를건 없고 제품이 세모 형태여서 전진할 때 저항이 좀 덜할 것 같은 느낌적인 느낌이 있다.
참고로 알리에서 Magnetic window cleaner 로 검색하면 동일한 제품이 검색되며 구입전 자신의 유리창 두께에 맞는 옵션을 선택해야 한다. 나의 경우에는 15mm to 24mm 인 제품을 구입하였는데 지원하는 두께에 따라 당연히 자력에도 차이가 있을 것으로 보이고 가격도 차이가 난다.
정확한 유리의 두께를 모르겠으면 아래의 그림을 참고하여 측정해보는 것도 좋을 것이다.
유리의 두께 = A - B - C
가운데 플라스틱으로 공간을 확보해 주기 위한 부속물이 있다.
이 플라스틱 없이 양쪽의 제품이 달라 붙는 일이 없도록 초 집중해야 한다. 붙었다가는 큰일 남.
여분의 솜이 들어있다. 이 솜부분이 물을 머금고 유리창의 더러움을 1차로 닦아 주게 된다.
일단 물로 충분히 적혀 주자.아래 사진에 보이는 검은 부분은 스폰지 인데 물을 머금고 있는 역할을 한다.
닦는 동안 아래쪽 청소포가 마르지 않도록 물기를 제공해야 하므로 충분히 물을 채워주자.
본게임 전에 충분히 적셔 주는 것이 중요하다. 언제나.
한쪽은 끝이 달려있고 손잡이가 없으며 다른 한쪽은 끈이 없고 손잡이가 있다.
당연히 끈이 달려있고 손잡이가 없는 쪽이 바깥쪽이다.
당연한 것 임에도 꼭 반대로 붙인뒤 움직이는게 왜 이렇게 어렵냐고 투덜대는 분 분명 있음.
아래쪽을 보면 앞부분에 젖은솜이 유리창의 때를 문질러주고, 중간 쯤에 실리콘 와이퍼가 달려 있어 더러운 물을 깨끗히 닦아내 주게 된다. 뭐 다른 제품에도 있는 일반적인 구조임
요건 창문 바깥쪽인데 아래쪽의 생김은 동일하다. 말하자면 동시에 앞뒤를 닦는 것인데 뭐 비슷한 제품들 다 동일한 방식으로 되어 있는 듯 하다.
청소포가 더러워 졌다면 하얀색 핀을 빼고 여분의 솜으로 갈아 끼운 후 사용하면 되겠다.
박스 뒤에는 친절한 설명이 적혀있다. 뭐 어려울 것은 없는 설명이다.
그런데 아래 1번 처럼 손목에 끈을 걸어서 바깥 부분이 아래로 추락하는 것을 방지하라고 되어 있는데 좋은 방법은 아니다. 끈이 아주 길지는 않기 때문에 우리집의 경우 유리창을 다 닦을 수 없었다. 아마 이 제품 개발한 분은 창문이 매우 작은 집에 살고 있는 듯하다. 우리 아파트가 큰것도 아닌데.
저렇게 하고 닦다보면 바보가 된 느낌이 든다. 창틀에 끈이 걸려서 더 가지도 못하고 바둥바둥 데다가 결국 한쪽 끝은 닦지 못하게 될 수 있으니 그냥 안전 난간에 끈을 묶자.
4번 5번은 세제를 묻히고 거품을 내라는 내용인데 비오는날 청소를 한다면 거품을 내지 않고 물로만도 청소가 잘 되는 것을 확인하였다.
참고로 3번과 5번같은 행동은 하지 않는 것이 좋다. 달라 붙기라도 하면 정말 난감한 상황이 벌어지게 된다.
아래쪽 1, 2 번은 거품을 칠하는 방법인 것 같은데 물만 이용해도 그냥 좌우로 이동하면서 닦아주면 잘 닦인다. 아래쪽 4번은 도대체 어떻게 하라는 건지 모르겠다.
뎃글,공감은 블로그 작성자에게 큰 힘이 된답니다.클릭!! 부탁드려요~
청소 시작해보기
시작하기 전 바로 요렇게 안전 난간에 끝을 묶으면 되는데 가능하면 닦을 유리창의 중심부에 묶어주는 것이 좋다. 가능한 짧은 길이로 끈을 맞추어 놓아야 만약의 경우 떨어지더라도 아래층 유리를 박살 내는 불상사가 없을 것이다. 가운데 묶고 대각선 끝까지 살짝 여유가 있는 정도면 충분하다.
유리의 안쪽은 방충망 청소하느라 물이 좀 묻었고 아침에 비가 왔기 때문에 바깥쪽 역시 완전히 젖은 정도는 아니었지만 살짝 촉촉한 느낌? 유리가 너무 바짝 마르면 잘 안밀리니 비오는날 시도 하는 것을 추천한다.
원래 좀 젖어야 매끄럽고 편한 법이다.
유리창 앞뒤로 딱 붙은 상태. 떨어질 생각을 않는군.
위쪽부터 좌우로 지그재그로 내려오는 중간에 한장 찍어보았다. 아래쪽 물때가 위쪽에는 전혀 없는 것이 보이는지 어쩌는지 모르겠지만 실제로 아주 잘 닦였다. '거울인줄...'
닦고 나면 이렇게 솜 부분이 시꺼멓게 되어 버린다. 잘 닦였나보다. 사진이 좀 뽀얗게 나왔는데 실제로는 좀더 더러웠음
암튼 위에서 잠깐 이야기 했는데 절대로 저 중간 부품없이 양쪽 청소기가 달라붙는 일이 없도록 주의 해야 한다. 바닥에 내려놓을 때에서 특히 신경 써서 둘이 떨어 뜨려 놓아야 한다.
구입하고 궁금한 마음에 열어서 보다가 바닥에 내려놓는 사이 두녀석이 똭 붙어 먹는 일이 생겼었는데 정말 이걸 버려야 하나 하고 엄청나게 고민을 하였다. 사람의 힘으로 떼어내는 것은 불가능한 수준임을 명심하라. 실수로 그 사이에 손가락 끝이라도 찝히는 날에는 생각만 해도 끔찍한 일이 일어날 것이라 장담한다.
참고로 난 어마어마 하게 큰 드라이버와 온갖 공구를 이용하여 둘을 떼어 놓는데 결국 성공하긴 했지만 결코 쉬운일이 아니었음을 여러분께 알린다.
대부분의 자석을 이용한 양면 유리 닦기 제품이 비슷한 것 같은데 가능하면 비오는날 청소하기를 권장한다. 마른 유리에서는 덕덕덕 하며 부드럽게 밀리지가 않는다. 떨어질까 불안 스럽기도 하고. 무엇보다 아래층으로 물을 떨어뜨려 이불이라도 널어놓은 집에 폐를 끼치면 아니 되겠다.
뭐 꼭 이제품이 아니어도 비슷할 것 같은데 위에서 언급했던 것 처럼 내가 구입한 제품의 경우 유리 두께를 고를 수 있는 제품이었고 24mm 유리까지 커버할 수 있는 제품을 구입하였다. 다른 제품은 8mm 까지 커버하는 제품인데 아파트 외부 샤시는 보통 15mm 이상되는 두꺼운 유리를 사용하므로 굳이 몇천원 아끼려고 8mm 제품을 구입하는 실수는 없기를 바란다. 가능하면 정확한 두께를 측정한 뒤 자신의 유리에 맞는 제품을 구입하는 것이 중요하다고 볼 수 있겠다.
뎃글,공감은 블로그 작성자에게 큰 힘이 된답니다. 도움이 되었다 생각되시면클릭!! 부탁드려요~