[์นด์นด์˜ค๋ทฐ] ๋ณด๋“œ ์ž๋™ ๋ฐœํ–‰ 5๋‹จ๊ณ„, ์ž๋™ ๋ฐœํ–‰ (์˜ค๋ฅ˜๊ฐ€ ์ข…์ข… ๋ฐœ์ƒํ•˜๋Š” ์ฝ”๋“œ)
๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๋””์ง€ํ„ธ ๊ฟ€ํŒ

[์นด์นด์˜ค๋ทฐ] ๋ณด๋“œ ์ž๋™ ๋ฐœํ–‰ 5๋‹จ๊ณ„, ์ž๋™ ๋ฐœํ–‰ (์˜ค๋ฅ˜๊ฐ€ ์ข…์ข… ๋ฐœ์ƒํ•˜๋Š” ์ฝ”๋“œ)

by ์ผ์ƒ์„ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค 2022. 5. 17.

์ง€๋‚œ 3์›” ๋ง์— ๋กœ๊ทธ์ธ๊นŒ์ง€๋งŒ ์ž‘์—…ํ•˜๊ณ , ๊ทธ ์ดํ›„ ์ž‘์—…์— ๋Œ€ํ•ด ์˜ค๋ž˜ ๊ฑธ๋ ธ์Šต๋‹ˆ๋‹ค. ์ž‘์—…์„ ํ•˜์—ฌ ์ž๋™๋ฐœํ–‰์„ ํ–ˆ๋Š”๋ฐ๋„ ๋ณด๋“œ๊ฐ€ ์ €ํ’ˆ์งˆ์ด ๊ฑธ๋ ธ์Šต๋‹ˆ๋‹ค ๊ทธ๋ž˜์„œ ๋…ธ์ถœ์ˆ˜๊ฐ€ 1/1000์œผ๋กœ ์ค„์–ด์„œ ์†์ƒํ•˜์ง€๋งŒ, ๋‹ค ์ž˜๋˜๊ธฐ ์œ„ํ•œ ๊ณผ์ •์ด๋ผ ์ƒ๊ฐํ•˜๋ฉฐ ์ด๋ ‡๊ฒŒ ์ €๋ ‡๊ฒŒ ์‹œ๋„ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋กœ ์ €๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์•„๋‹ˆ๋ผ ๊ทธ๋ƒฅ ์ง€๋‚˜๊ฐ€๋‹ค ํ•ด๋ณด๋Š” ์œ ์ €์ž…๋‹ˆ๋‹ค. ์†Œ์Šค์ฝ”๋“œ๊ฐ€ ๊ทธ์ € ๋ชฉ์ ์ด ๋Œ์•„๊ฐ€๊ธฐ ์œ„ํ•จ์ด๋ผ ๊น”๋”ํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ์ž˜๋ชป๋œ ๋ถ€๋ถ„์ด ๋งŽ์„ ์ˆ˜ ์žˆ๋Š” ์  ์ธ์ง€ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค. 

๊ฐœ๋ฐœ ํ™˜๊ฒฝ

Mac OS : OS ver 12.3.1

 

[์นด์นด์˜ค๋ทฐ] ๋ณด๋“œ ์ž๋™ ๋ฐœํ–‰ 3๋‹จ๊ณ„. nodeJS๋กœ selenium ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉํ•˜์—ฌ ์นด์นด์˜ค๋ทฐ - ์ฑ„๋„ ์ž๋™ ๋กœ๊ทธ

python๋„ ์ข‹์ง€๋งŒ nodejs๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณด๋“œ๋ฐœํ–‰์„ ์ž๋™ํ™” ํ•˜๋ ค ํ•ฉ๋‹ˆ๋‹ค. ์˜ค๋Š˜ ๋‚ด์šฉ์—๋Š” ๋กœ๊ทธ์ธ๊นŒ์ง€๋งŒ ๊ธฐ์žฌํ•˜๊ณ , ์˜์ƒ์€ ๋ง›๋ณด๊ธฐ๋กœ ์ƒ˜ํ”Œ ์˜ˆ์ œ๋กœ ๊ณต๊ฐœ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค ์ดˆ๋ณด์ž๋Š” ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์ง€๋งŒ ์ตœ๋Œ€ํ•œ ๋งŽ์€

odaily.tistory.com


1.  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ ์–ธ

const {google} = require("googleapis"); //๊ตฌ๊ธ€ ๋ฌธ์„œ ๋กœ๋”ฉ์„ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
const creds = require("selenium-webdriver/metal-hope-xxxxxx-xxxxxxxxx.json"); //๊ตฌ๊ธ€ key
const config = require("selenium-webdriver/config"); //๊ธฐ๋ณธ ์„ค์ • ํŒŒ์ผ
const webdriver = require('selenium-webdriver'); //์ž๋™ํ™”๋ฅผ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
const mecab = require('mecab-ya'); // ์ œ๋ชฉ์„ ๊ธฐ์‚ฌ ์ œ๋ชฉ๊ณผ ์ผ์น˜ํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•œ ํ•œ๊ธ€ ๋ถ„๋ฆฌํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
const dateUtil = require("date-utils"); //ํƒ€์ž„ ์œ ํ‹ธ

1-1. googleapi๋ฅผ ์‚ฌ์šฉํ•œ ์ด์œ  ๐Ÿ’ก

์ฐธ๊ณ ๋กœ ์‹ค์ œ ๋ฐ์ดํ„ฐ๋Š” ๊ธฐ์‚ฌ๊ฐ€ ๋ˆˆ์œผ๋กœ ๋“ค์–ด์˜ค๋Š” ํŽธ์ด ์ข‹์•„์„œ ์ €๋Š” ๋‰ด์Šค ๊ธฐ์‚ฌ ๋ฐ ๋ธ”๋กœ๊ทธ, ํ‹ฐ์Šคํ† ๋ฆฌ๋Š” google spread sheet ์—๋‹ค๊ฐ€ ๋ถˆ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค. api๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด metal-hope...json ํŒŒ์ผ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.  

 

[์นด์นด์˜ค๋ทฐ] ๋ณด๋“œ ์ž๋™ ๋ฐœํ–‰ 2๋‹จ๊ณ„. ๊ตฌ๊ธ€ ์•ฑ ์Šคํฌ๋ฆฝํŠธ๋กœ ๋ณธ์ธ ํ‹ฐ์Šคํ† ๋ฆฌ ํฌ์ŠคํŒ… ๊ธ€ ๊ฐ€์ ธ์˜ค๊ธฐ(OPEN API)

๊ตฌ๊ธ€ ์Šคํ”„๋ ˆ๋“œ์‹œํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ค„ ์•„๋Š” ๋ถ„์ด๋ฉด ๋ˆ„๊ตฌ๋‚˜ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! 1๋‹จ๊ณ„. ํ‹ฐ์Šคํ† ๋ฆฌ API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์•ฑ์„ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ํ‹ฐ์Šคํ† ๋ฆฌ API ์•ฑ ๋“ฑ๋ก ์‚ฌ์ดํŠธ : https://www.tistory.com/guide/api/manage/regist

odaily.tistory.com

 

[์นด์นด์˜ค๋ทฐ] ๋ณด๋“œ ์ž๋™ ๋ฐœํ–‰ 2๋‹จ๊ณ„. ๊ตฌ๊ธ€ ์•ฑ ์Šคํฌ๋ฆฝํŠธ๋กœ ๋ณธ์ธ ๋„ค์ด๋ฒ„ ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŒ… ๊ธ€ ๊ฐ€์ ธ์˜ค๊ธฐ(OP

๋„ค์ด๋ฒ„ ๋ธ”๋กœ๊ทธ๋Š” ์ž๊ธฐ ๋ธ”๋กœ๊ทธ ์ฝ˜ํ…์ธ ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์ด ๋˜๋Š” ์ค„ ์•Œ์•˜๋Š”๋ฐ, ์ „์ฒด ๋ธ”๋กœ๊ทธ์—์„œ ํŠน์ • ๋‹จ์–ด๋ฅผ ๊ฐ€์ง€๊ณ  search ํ•˜๋Š” open API๊ฐ€ ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์šฐ์„  ๋ธ”๋กœ๊ทธ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ฑ™๊ฒจ

odaily.tistory.com

์ถ”ํ›„ description๋„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ์œ„ ํฌ์ŠคํŒ… ๊ธ€์„ ์กฐ๊ธˆ ์ˆ˜์ •ํ•˜์—ฌ ๋ณธ๋ฌธ๋„ ๊ฐ€์ง€๊ณ  ์™”์Šต๋‹ˆ๋‹ค.

1-2. config ํŒŒ์ผ์ด๋ž€?

json ํ˜•ํƒœ๋กœ ๋œ ์„ค์ • ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.  ์ €๋Š” ๋„ค์ด๋ฒ„๋‰ด์Šค, ๋‹ค์Œ ๋‰ด์Šค, ํ‹ฐ์Šคํ† ๋ฆฌ(๋‚ด ๋ธ”๋กœ๊ทธ), ๋„ค์ด๋ฒ„(๋‚ด ๋ธ”๋กœ๊ทธ), ์œ ํŠœ๋ธŒ ์ฝ˜ํ…์ธ ๋กœ ๊ตฌ์„ฑ์„ ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ํ˜น์‹œ๋‚˜ ์ฝ˜ํ…์ธ  ๋ฌธ์ œ๋‚˜ ์ด์Šˆ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด ์ „๋ถ€ OPEN API๋กœ ๋กœ๋”ฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์„ค์ •์— ๋”ฐ๋ผ ํ”Œ๋žซํผ๋ณ„ ๋ณด๋“œ ๋ฐœํ–‰์„ ์œ„ํ•œ ์ฝ˜ํ…์ธ  ์‚ฌ์šฉ ์œ ๋ฌด, ์˜ˆ์•ฝ ์„ค์ • ์œ ๋ฌด, ์˜ˆ์•ฝ ๋ฐœํ–‰ ์‹œ๊ฐ„, ์นดํ…Œ๊ณ ๋ฆฌ type์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐœํ–‰ ์‹œ๊ฐ„(time)์„ ์…‹ํŒ…ํ•œ ๊ฐœ์ˆ˜๋งŒํผ ๊ธฐ์‚ฌ๊ฐ€ ๋ณด๋“œ๋กœ ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค. ๋‹จ, isReserved : true๋กœ ์„ค์ •๋œ ๊ฒฝ์šฐ์—๋งŒ ์˜ˆ์•ฝ ๋ฐœํ–‰๊ณผ ์‹œ๊ฐ„ ์ง€์ •์ด ๋ฉ๋‹ˆ๋‹ค. ex) 18,20,23 ์ผ ๊ฒฝ์šฐ 3๊ฑด์˜ ๋ณด๋“œ๊ฐ€ 18์‹œ, 20์‹œ, 23์‹œ ์‹œ๊ฐ„์— ์˜ˆ์•ฝ ๋ฐœํ–‰์œผ๋กœ ์—…๋ฐ์ดํŠธ๋จ

{
    "kakaoview" : {
        "id" : "์นด์นด์˜ค์•„์ด๋””",
        "pw" : "๋น„๋ฐ€๋ฒˆํ˜ธ",
        "channelID" : "์ฑ„๋„ID",
        "bodytext" : "๋ณด๋“œ ๋ณธ๋ฌธ ๋‚ด์šฉ "
    },
    "google" : {
        "googlesheet" : "๊ตฌ๊ธ€ ์Šคํ”„๋ ˆ๋“œ ์‹œํŠธ ๋ฌธ์„œ ID",
        "navernews" : "Sheet ๋ฒ”์œ„ Sheet!B3:C",
        "daumnews" : "Sheet ๋ฒ”์œ„ Sheet!B3:C",
        "tistory" : "Sheet ๋ฒ”์œ„ Sheet!B5:C",
        "naverblog" : "Sheet ๋ฒ”์œ„ Sheet!B3:C",
        "youtube" : "Sheet ๋ฒ”์œ„ Sheet!B3:C"
    },
    "navernews": {
      "type": "naver",
      "isUsed": false ,
      "isReserved" : true,
      "time" : "18,20,23",
      "cate1" : "newsnow",
      "cate2" : "issuecutating"
    },
    "daumnews": {
        "type": "daum",
        "isUsed": false,
        "isReserved" : true,
        "time" : "22,23",        
        "cate1" : "newsnow",
        "cate2" : "lifestory"

    },
    "tistory": {
        "type": "tistory",
        "isUsed": false,
        "isReserved" : true,
        "time" : "18,19,20,21,22",
        "cate1" : "career",
        "cate2" : "lifestory"

    },
    "naverblog" : {
        "type": "naverblog",
        "isUsed": false,
        "isReserved" : true,
        "time" : "14",
        "cate1" : "hobby",
        "cate2" : "tech"
    },
    "youtube" : {
        "type": "youtube",
        "isUsed": true,
        "isReserved" : true,
        "time" : "23",
        "cate1" : "hobby",
        "cate2" : "contentscurating"

    }
}

1-3. ์‚ฌ์šฉํ•  ๋ณ€์ˆ˜ ์„ ์–ธ 

By = webdriver.By
until = webdriver.until
Key = webdriver.Key

const driver = new webdriver.Builder().forBrowser('chrome').build();
const configJson = JSON.parse(JSON.stringify(config));

let client ;
let category1 ='newsnow'; //์ดˆ๊ธฐ๊ฐ’ ์ผ๋ถ€๋กœ ์…‹ํŒ…
let category2 ='issuecutating';  //์ดˆ๊ธฐ๊ฐ’ ์ผ๋ถ€๋กœ ์…‹ํŒ…
๋ฐ˜์‘ํ˜•

2. ํ•จ์ˆ˜ ๊ตฌํ˜„

2-1. ๊ตฌ๊ธ€ api ์ธ์ฆํ•˜์—ฌ ์—ฐ๋™ํ•˜๋Š” ์ฝ˜ํ…์ธ  ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜

async function init(){
    return new Promise( async function(resolve) {
        client = new google.auth.JWT(
            creds.client_email, 
            null, 
            creds.private_key,
            [
            'https://www.googleapis.com/auth/spreadsheets',
            'https://www.googleapis.com/auth/spreadsheets.readonly'  
            ]
        );

        await loadingData();

        sleep(2000);

        resolve(true);
    });
}


async function loadingData(){
    await client.authorize(function(err,tokens){

        if(err){
            console.log(err);
            return;
        }else {
            console.log('>> google auth ok!!');
        }
    });
}

์ฑ„๋„๋ณ„๋กœ ์ฝ˜ํ…์ธ ๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ, ๋ณด๋“œ ์ˆ˜๋ฅผ ๋ช‡ ๊ฐœ ๋ฐœํ–‰ํ• ์ง€ ๋ชฐ๋ผ config file์— Time ๊ธฐ์ค€์œผ๋กœ ์Šคํ”„๋ ˆ๋“œ์‹œํŠธ ๋ฒ”์œ„๋ฅผ ์„ค์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์Šคํ”„๋ ˆ๋“œ์‹œํŠธ์˜ ๋‹จ์ ์€ ํ•œ ๋ฒˆ์— ๋กœ๋”ฉ์ด ์•ˆ๋˜์–ด #NAME์™€ ๊ฐ™์ด ์ œ๋Œ€๋กœ ๊ฐ’์„ ๋ชป ๊ฐ€์ ธ์˜ค๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿด ๊ฒฝ์šฐ๋Š” ํ•œ ๋ฒˆ ๋” retry ํ•˜์—ฌ ๊ฐ€์ ธ์˜ค๊ฒŒ ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ง„์งœ ์˜ค๋ฅ˜๊ฐ€ ์žˆ์ง€ ์•Š๊ณ ์„  ํƒ€์ด๋ฐ ์ด์Šˆ๋„ ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ  ์ž˜ ๊ฐ€์ ธ์™€์ง‘๋‹ˆ๋‹ค.

async function getContent(cl, cate1,cate2, rangeVal, uploadCnt){
    return new Promise( async function (resolve,reject) {

            category1 = cate1;
            category2 = cate2; //career

            const sheets = await google.sheets({version: 'v4'});

            let rangeValue = rangeChange(rangeVal, uploadCnt);

            const request = {
                spreadsheetId : configJson.google.googlesheet ,
                range : rangeValue,
                valueRenderOption: 'FORMATTED_VALUE',
                auth: cl
            };

            sleep(2000);            
            
            try {
                let response = ( await sheets.spreadsheets.values.get(request)).data;
                // TODO: Change code below to process the `response` object:

                sleep(2000);
              
                //๋กœ๋”ฉ ์‹คํŒจ์‹œ ๋กœ๋”ฉ ๋ ๋•Œ๊นŒ์ง€ ๋‹ค์‹œ spreadsheet ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
                let tempData = JSON.parse(JSON.stringify(response.values));
                while(tempData[0][0] == "#NAME?" || tempData[0][0] == "#ERROR!" || tempData[0][0] == "๋กœ๋“œ ์ค‘..." )
                {
                    console.log(">> retry getContent");
                    response = ( await sheets.spreadsheets.values.get(request)).data;

                    sleep(2000);

                    let tempData = JSON.parse(JSON.stringify(response.values));
                    if(tempData[0][0] != "#NAME?"  && tempData[0][0] != "#ERROR!"  || tempData[0][0] == "๋กœ๋“œ ์ค‘...")
                        break;
                }

                console.log(">> data result : " , tempData);
                resolve(response.values);

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

    });
}

function rangeChange(rangeval,uploadcount)
{
   let start =  rangeval.split(":");
   startnum = start[0].substr(start[0].length-2,start[0].length);

   startnum = startnum.replace("B","");
   startnum = startnum.replace("F","");

   let lastnum = parseInt(startnum) + uploadcount - 1;

   rangeval = rangeval + lastnum;

   console.log(">> data Range :  " , rangeval );

   return rangeval;

}

2-2. ์นด์นด์˜ค ๋กœ๊ทธ์ธํ•˜๋Š” ํ•จ์ˆ˜ 

configํŒŒ์ผ์— ๊ผญ ID/PW ์„ค์ •ํ•ด์•ผ ์ •์ƒ์ ์œผ๋กœ ์ž…๋ ฅ์ด ๋ฉ๋‹ˆ๋‹ค.

async function kakaoLogin(){
    return new Promise( async function(resolve,reject) {
        try {
            let inputId = await driver.findElement(By.css('input#id_email_2')); 
            inputId.sendKeys(configJson.kakaoview.id); 

            resolve(true);

        } catch (error) {
            console.log("kakao ID error : ",error);   
            reject(err);
        }

        try {
            let inputpw = await driver.findElement(By.css('input#id_password_3')); 
            inputpw.sendKeys(configJson.kakaoview.pw, Key.ENTER);
            
            resolve(true);
            
        } catch (error) {
            console.log("kakao PW error : ", error);   
            reject(err);
        }
    });

}

 

2-3. ๋ณด๋“œ ์ƒ์„ฑ

๋ณด๋“œ ์ƒ์„ฑ์ด ๋„ˆ๋ฌด ๊ธธ์–ด์ ธ์„œ.. ์ข€ ๋‚˜๋ˆˆ๋‹ค๊ณ  ๋‚˜๋ˆด๋Š”๋ฐ ์˜ ๋ณผํ’ˆ์ด ์—†์ง€๋งŒ, ๊ฒฐ๋ก ์ ์œผ๋ก  ์„ค์ • ํŒŒ์ผ์— ์‹œ๊ฐ„(time) ์ž…๋ ฅํ•œ ๋งŒํผ ๋ณด๋“œ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
๊ตฌ๊ธ€์—์„œ ์ฝ˜ํ…์ธ  ๋ถˆ๋Ÿฌ์˜จ ๊ฒƒ์„ ํŒŒ์‹ฑ ํ•˜์—ฌ ๋„˜๊ฒจ์ค๋‹ˆ๋‹ค.  ์ƒ๊ฐํ•ด๋ณด๋‹ˆ ๋‘ ํ•จ์ˆ˜๋Š” ๊ตณ์ด ๋‚˜๋ˆŒ ํ•„์š”๊ฐ€ ์žˆ์—ˆ๋‚˜ ์‹ถ๋„ค์š”.

async function boardcreatebyPlatform(isUsed, type, cate1, cate2, range, isreserved, time){
     if(isUsed){
        console.log(">> " + type + " site!!---------------");
        let content =  await getContent(client,cate1,cate2,range,uploadSplit(time));
        
        console.log(">> " + type + " loading success!");    
        sleep(2000);

        await createBoard(type, content, isreserved, time);
        sleep(2000);
    }
}
async function createBoard(chflag, content, isReservation, time){

    let data = await JSON.parse(JSON.stringify(content));
    console.log(">> " , chflag , " data : " ,  data, "length : " , data.length);

    let timeArr = await time.split(",")

    for(i=0; i<timeArr.length; i++){
        let bool =  await newBoard(chflag, data[i][0],data[i][1],isReservation,i+1,timeArr[i]);
        sleep(2000);

        if(bool){
            console.log(">> create borad : ",  i + 1 , "๋ฒˆ์งธ ์ƒ์„ฑ ์™„๋ฃŒ -----------------");
        }
        
    }
}

์‹ค์ œ ์ฝ˜ํ…์ธ  ์ฑ„์›Œ ๋„ฃ๋Š” ํ•จ์ˆ˜ : newBoard()

๋ณด๋“œ ํƒ€์ดํ‹€, ๋ณธ๋ฌธ ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ๊ณ , ๋ทฐ ํ˜•ํƒœ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ๋งํฌ ์ง์ ‘ ์ž…๋ ฅ ํƒญ์—์„œ ๊ตฌ๊ธ€ ๋ฌธ์„œ์—์„œ ๋ฐ›์•„์˜จ ๋งํฌ๋ฅผ ๊ฒ€์ƒ‰ํ•˜์—ฌ ๋‹ด๊ณ , ์ฝ˜ํ…์ธ  ํƒ์ƒ‰์— ์ œ๋ชฉ๊ณผ ์œ ์‚ฌํ•œ ๊ธฐ์‚ฌ๋ฅผ ๋ถˆ๋Ÿฌ์™€ ๋‹ด์•„๋ด…๋‹ˆ๋‹ค. ์ œํ•œ์ด 10๊ฐœ๊นŒ์ง€์ธ๋ฐ ์‹ฑํฌ๊ฐ€ ์•ˆ ๋งž์•„์„œ ๋‹ด์„ ๊ธฐ์‚ฌ ์ˆ˜๋ฅผ ๋‚ฎ๊ฒŒ ์ง€์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๋ทฐ ๋ชจ์–‘ / ์ฝ˜ํ…์ธ  ๋‹ด๊ธฐ

๋ทฐ ๋ชจ์–‘์„ ์„ ํƒํ•˜์˜€์ง€๋งŒ, ๊ฐ„ํ˜น ์ธ๋„ค์ผ์ด ์—†๋Š” ๊ธฐ์‚ฌ๊ฐ€ ๊ฒ€์ƒ‰๋ผ์„œ ๋ทฐ์— ๋งž์ง€ ์•Š๋Š” ๊ธฐ์‚ฌ๊ฐ€ ๋‹ด๊ฒจ ํŒ์—…์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿด ๊ฒฝ์šฐ ๋‹ค๋ฅธ ๋ทฐ ํ˜•ํƒœ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค. (๋‹จ, ์†Œ์Šค์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ์–ด ๋ฐœํ–‰ ์‹œ ์ข…์ข… ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.)

async function newBoard(chflag, title, newLink, isReserve, nCnt, uploadTime ){
    return new Promise((resolve) => {
         setTimeout(async()=>{

            console.log(">> " + chflag + " create board  ----------------------------------");
            let sendTitle = getTitle(title,chflag);

            let txtTitle = await driver.findElement(By.css('#boardTitle')); 
            let boardContent = await driver.findElement(By.css('#boardCmt')); 

            sleep(2000);

            let idx = selectView(nCnt,chflag);
            console.log(">> view select ", idx);

            let view = await driver.findElement(By.css('#mainContent > div.editor_board > div > div.area_editor > div:nth-child(3) > div.edit_template > ul > li:nth-child(' + idx +') > button > span'));            
            view.click();
            
            sleep(2000);

            boardContent.sendKeys(configJson.kakaoview.bodytext, Key.ENTER );
            txtTitle.sendKeys(sendTitle);

            console.log("sendtitle : ", sendTitle);

            driver.wait(until.elementLocated(By.css('#mainContent > div.editor_board > div > div.area_contents > div.tab_g.tab_type2 > ul > li:nth-child(2) > a')), 40000).then( async function(){

            let tab = await driver.findElement(By.css('#mainContent > div.editor_board > div > div.area_contents > div.tab_g.tab_type2 > ul > li:nth-child(2) > a'));
            tab.sendKeys(Key.ENTER);

                driver.wait(until.elementLocated(By.css('#mainContent > div.editor_board > div > div.area_contents > div.cont_tab > form > div.item_form.type_search > div > input')), 40000).then( async function(){

                    let link = await driver.findElement(By.css('#mainContent > div.editor_board > div > div.area_contents > div.cont_tab > form > div.item_form.type_search > div > input'));
                    link.click();  
                    link.sendKeys(newLink, Key.ENTER);
                
                    console.log(">> search News Link : " , newLink);
                    sleep(3000);
                   
                    driver.wait(until.elementLocated(By.css('#mainContent > div.editor_board > div > div.area_contents > div.cont_tab > form > div.view_contents > ul')), 50000).then( async function(){

                            driver.wait(until.elementLocated(By.css('#mainContent > div.editor_board > div > div.area_contents > div.cont_tab > form > div.view_contents > ul > li > div.wrap_util > button')), 40000).then( async function() {
                                
                                let img = await driver.findElements(By.css('#mainContent > div.editor_board > div > div.area_contents > div.cont_tab > form > div.view_contents > ul > li > div.wrap_thumb > img'));

                                if(img == "")
                                {
                                    console.log(">> no img", img); //์ธ๋„ค์ผ ์—†์Œ
                                    selectView(1);
                                }
                                
                                let sel_button = await driver.findElement(By.css('#mainContent > div.editor_board > div > div.area_contents > div.cont_tab > form > div.view_contents > ul > li > div.wrap_util > button'));          
                                sel_button.click();                    
                                
                                let tab = await driver.findElement(By.css('#mainContent > div.editor_board > div > div.area_contents > div.tab_g.tab_type2 > ul > li:nth-child(3) > a'));
                                tab.sendKeys(Key.ENTER);

                                driver.wait(until.elementLocated(By.css('#mainContent > div.editor_board > div > div.area_contents > div.cont_tab > form > div > div > input')), 40000).then( async function(){
                                    
                                    let titleArr =  regExp(removeEmojis(title)).split(" ")
                                    console.log(">> Keyword News Search : ", titleArr[0] + '' + titleArr[1]);
                                    
                                    link = await driver.findElement(By.css('#mainContent > div.editor_board > div > div.area_contents > div.cont_tab > form > div > div > input'));
                                    link.click();  
                                    link.sendKeys(titleArr[0] + '' + titleArr[1], Key.ENTER);

                                    driver.wait(until.elementLocated(By.css('#mainContent > div.editor_board > div > div.area_contents > div.cont_tab > div.head_sort > div.tab_sort > a:nth-child(2)')), 40000).then( async function(){
                                        
                                        driver.findElement(By.css('#mainContent > div.editor_board > div > div.area_contents > div.cont_tab > div.head_sort > div.tab_sort > a:nth-child(2)')).click();
                                        driver.wait(until.elementLocated(By.css('#mainContent > div.editor_board > div > div.area_contents > div.cont_tab > div.view_contents')) ,40000).then( async function(){
                                            
                                            sleep(2000);

                                            let ele =  await driver.findElements(By.css('#mainContent > div.editor_board > div > div.area_contents > div.cont_tab > div.view_contents > ul > li'));
                                            
                                            for (var j=0; j<ele.length-1; j++){
                                                let num = j+2; 
                                                
                                                if (num == 2)
                                                {
                                                    let img2 = await driver.findElements(By.css(' #mainContent > div.editor_board > div > div.area_contents > div.cont_tab > div.view_contents > ul > li:nth-child(2) > a > div > img'));

                                                    if(img2 == "")
                                                    {
                                                        console.log(">> add content no img", img); //์ธ๋„ค์ผ ์—†์Œ
                                                        selectView(1);
                                                    }
                                                }
                                                sleep(2000);

                                                await driver.findElement(By.css('#mainContent > div.editor_board > div > div.area_contents > div.cont_tab > div.view_contents > ul > li:nth-child('+ num + ') > div.wrap_util > button')).click();
                                                sleep(2000);
                                                console.log(">>>> add link count : " , num );
                                                
                                                if(j > 6 || j > ele.length ) { break; }
                                            }

                                            await selectCategory(chflag, category1,category2 ,isReserve, uploadTime);

                                            resolve(true);

                                        });
                                    },async ( err ) => {
                                            selectView(3);
                                            await selectCategory(chflag, category1,category2 ,isReserve, uploadTime);
                                            resolve(true);
                                        }
                                    
                                    );
                                    

                                });
                                

                            });
                    }); 
                
                });    
            }); 

        },4000);
    });
}

2-4.  ์นดํ…Œ๊ณ ๋ฆฌ ์„ ํƒ ํ›„ ๋ฐœํ–‰ํ•˜๊ธฐ(์˜ˆ์•ฝ OR ์ฆ‰์‹œ)

๋ณด๋“œ๊ฐ€ ์ž‘์„ฑ์ด ์™„๋ฃŒ๋˜๊ณ  [๋ฐœํ–‰ํ•˜๊ธฐ] ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ์˜ˆ์•ฝ ๋ฐœํ–‰๊ณผ ์•„๋‹Œ ๊ฒฝ์šฐ๋ฅผ ๋‚˜๋ˆ ์„œ ํ–ˆ๋Š”๋ฐ ์ •๋ฆฌํ•˜๊ณ  ๋„ˆ๋ฌด ๊ธธ์–ด์„œ ์ •๋ฆฌํ•˜๊ณ  ์‹ถ์ง€๋งŒ, ์•„์ง๋„ ์ด์Šˆ๊ฐ€ ๋งŽ์•„์„œ ๊ทธ๋ƒฅ ๋‚ด๋ฒ„๋ ค ๋‘๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์›นํŽ˜์ด์ง€ ๋กœ๋”ฉ๋ผ์„œ ์ •์ƒ์ ์ธ ๋œ element๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ๊ฐ€ ๋„ˆ๋ฌด ๊ธธ๋‹ค๊ณ  ์ด๋ฒˆ์— ๋Š๊ผˆ์Šต๋‹ˆ๋‹ค. ์นดํ…Œ๊ณ ๋ฆฌ ์„ ํƒํ•˜๊ณ  ์‹ค์ œ ๋ณด๋“œ๋ฅผ ๋ฐœํ–‰ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

async function selectCategory(chflag, cate1, cate2, isReserve, reserveTime){
    return new Promise( async function(resolve) {       
            let btnOk = await driver.findElement(By.css('#mainContent > div.wrap_btn > div.align_r > button.btn_g.btn_primary.btn_icon'));
            btnOk.click();

            driver.wait(until.elementLocated(By.css('#layer > div > div > div.layer_body > div > div:nth-child(3) > dl > dd > div')), 40000).then( async function(){

                if(isReserve)
                {
                    await driver.findElement(By.css('#layer > div > div > div.layer_body > div > div:nth-child(2) > dl > dd > div > div:nth-child(2) > label > span.txt_choice')).click();
                    driver.wait(until.elementLocated(By.css('#layer > div > div > div.layer_body > div > div:nth-child(2) > dl > dd > div > div:nth-child(5) > div > a')), 40000).then( async function(){
                       reserveTime = await dateUpdate(reserveTime);

                        await driver.findElement(By.css('#layer > div > div > div.layer_body > div > div:nth-child(2) > dl > dd > div > div:nth-child(5) > div')).click();
                        driver.wait(until.elementLocated(By.css('#layer > div > div > div.layer_body > div > div:nth-child(2) > dl > dd > div > div:nth-child(5) > div > div > ul')), 40000).then( async function(){

                            let selectBox = await driver.findElement(By.xpath('//*[@id="layer"]/div/div/div[2]/div/div[2]/dl/dd/div/div[5]/div/a'));
                            driver.sleep(2000);

                            reserveTime = parseInt(reserveTime) + 1;
                            let selectli = await driver.findElement(By.css('#layer > div > div > div.layer_body > div > div:nth-child(2) > dl > dd > div > div:nth-child(5) > div > div > ul > li:nth-child('+reserveTime+ ') > a > span'));
                            selectli.click();

                            driver.sleep(2000);

                            console.log(">> category 1: ", cate1, "category 2: ", cate2 );

                            await driver.findElement(By.css("label[for='"+cate1+"']")).click();
                            await driver.findElement(By.css("label[for='"+cate2+"']")).click();

                            sleep(2000);

                            console.log(">> category all select");

                            let lastBtn = await driver.findElement(By.css('#layer > div > div > div.layer_body > div > div.wrap_btn.align_r > button.btn_g.btn_primary.btn_icon'));
                            lastBtn.click();

                            driver.wait(until.elementLocated(By.css('#layer > div > div > div.layer_foot > div > button')), 40000).then( async function(){
                        
                                await driver.findElement(By.css('#layer > div > div > div.layer_foot > div > button')).click();
                                sleep(2000);

                                driver.wait(until.elementLocated(By.css('#mainContent > div.wrap_tit > div > a')), 50000).then( async function(){
                                    
                                    await driver.findElement(By.css('#mainContent > div.wrap_tit > div > a')).click();
                                    sleep(2000);

                                    resolve(true);
                                });          
                            });
                            
                        });
                    });
                }
                else {

                    console.log(">> category 1: ", cate1, "category 2: ", cate2 );

                    await driver.findElement(By.css("label[for='"+cate1+"']")).click();
                    await driver.findElement(By.css("label[for='"+cate2+"']")).click();

                    sleep(2000);

                    console.log(">> category all select");

                    let lastBtn = await driver.findElement(By.css('#layer > div > div > div.layer_body > div > div.wrap_btn.align_r > button.btn_g.btn_primary.btn_icon'));
                    lastBtn.click();

                    driver.wait(until.elementLocated(By.css('#layer > div > div > div.layer_foot > div > button')), 50000).then( async function(){
                
                        await driver.findElement(By.css('#layer > div > div > div.layer_foot > div > button')).click();
                        sleep(2000);

                        driver.wait(until.elementLocated(By.css('#mainContent > div.wrap_tit > div > a')), 50000).then( async function(){
                            
                            console.log(">> new board btn click");

                            await driver.findElement(By.css('#mainContent > div.wrap_tit > div > a')).click();
                            sleep(2000);

                            resolve(true);
                        });          
                    });
                }                
            }); 
    });
}

์˜ˆ์•ฝ ๋ฐœํ–‰ ์‹œ ์‹œ๊ฐ„์ด ์ง€๋‚ฌ์œผ๋ฉด ํ˜„์žฌ ์‹œ๊ฐ„์œผ๋กœ ๋ณ€๊ฒฝํ–ˆ๋˜ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

async function dateUpdate(time)
{
    let newDate = new Date();
    let today = newDate.toFormat("YYYY-MM-DD HH24:MM");
    let temptime ;

    if(time.length < 2)
    {
        temptime = "0" + time;
    }

    let resevationTime = newDate.toFormat("YYYY-MM-DD") + " " + temptime + ":00"

    if(Date.compare(today,resevationTime) == 1 )
    {
        let txt = today.split(" ");
        resultTime = txt[1].split(":");

        console.log(">> Change resevationTime : ", resultTime[0]);
        return resultTime[0];
    }
    else{
        return time;
    }
    
}

์•ž์œผ๋กœ๋„ ๊ณ„์† ์ˆ˜์ •ํ•  ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ๊ธฐ์‚ฌ ์ œ๋ชฉ์„ ๊ฐ€์ง€๊ณ ์™€ ๋ณ€ํ˜•ํ•˜๋ฉด์„œ ๋ณด๋“œ ์ œ๋ชฉ์„ ๋งŒ๋“  ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. mecab ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ ์„ค์น˜ ๊ณผ์ •์ด ๊ฝค๋‚˜ ๋ณต์žกํ•ด์„œ ๋ณ„๋„๋กœ ๋‹ค๋ฃจ๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ํฌ์ŠคํŒ… ๊ธ€์—๋„ ๋งŽ์ด ์ฐพ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function getTitle(strTitle, tempChflag){

    var tempTitle = removeEmojis(strTitle);

    console.log(">> strTitle length :" , tempTitle.length);

    if(tempTitle.length > 35)
    {
        console.log(">> strTitle before :" , tempTitle);
        tempTitle = tempTitle.substring(0,36);
        let lastidx  = tempTitle.lastIndexOf(" ");
        tempTitle = tempTitle.substring(0,lastidx);

        console.log(">> strTitle after :" , tempTitle);
    }
    
    if(tempTitle.length == 24)
    {
        tempTitle = tempTitle + " ";
    }

    if(tempChflag == "youtube")
    {
        tempTitle = tempTitle.substring(0,30);
        tempTitle = "[playlist]" + tempTitle;

        return tempTitle;
    }

    sleep(1000);

    if(tempChflag == "naver" || tempChflag == "daum" )
    {
        return new Promise((res, rej) => {
            mecab.nouns(tempTitle, function(err,result){
                console.log("result", result.length);
                var title = "";
                for(var i=0; i<result.length/2; i++)
                {
                    title = title + result[i];
                    title = title + " ";
                } 
                var endWord =  "์ด์Šˆ !";

                if (result.length > 3)
                {
                    endWord = "!!!";
                }

                tempTitle = result[result.length-1] + " " + title + endWord; 
        
                console.log(">> strTitle return :" , tempTitle);
                res(tempTitle);
            });
        });
    }
    else{
        return tempTitle;
    }

}

2-5. ์‹ค์ œ ์‹คํ–‰ํ•˜๋Š” Main ํ•จ์ˆ˜

์นด์นด์˜ค ๋ทฐ๋ฅผ ๋„์›Œ ๋กœ๊ทธ์ธ ํ›„ ํ”Œ๋žซํผ๋ณ„ config ์„ค์ •์„ ๊ฐ€์ ธ์™€ ๋ณด๋“œ ์ž‘์„ฑ ํ˜ธ์ถœํ•˜๋Š” ๋ฉ”์ธ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

function main(){

        console.log(">> kakao channel open!");

        driver.get('https://creators.kakao.com/channel/'+ configJson.kakaoview.channelID + '/board/create').then( async function(){
            try{
                    await init();  
                    sleep(2000);
                    console.log(">> Google connect Success!")

                    await kakaoLogin();
                    sleep(2000);
                    
                    console.log(">> Kakao login ok!");
                    sleep(2000);

                    //ํ”Œ๋žซํผ ๋ณ„ ํ˜ธ์ถœ
                    await boardcreatebyPlatform(configJson.navernews.isUsed, configJson.navernews.type, configJson.navernews.cate1, configJson.navernews.cate2, configJson.google.navernews, configJson.navernews.isReserved, configJson.navernews.time);
                    await boardcreatebyPlatform(configJson.daumnews.isUsed, configJson.daumnews.type, configJson.daumnews.cate1, configJson.daumnews.cate2, configJson.google.daumnews, configJson.daumnews.isReserved, configJson.daumnews.time);
                    await boardcreatebyPlatform(configJson.tistory.isUsed, configJson.tistory.type, configJson.tistory.cate1, configJson.tistory.cate2, configJson.google.tistory, configJson.tistory.isReserved, configJson.tistory.time);
                    await boardcreatebyPlatform(configJson.naverblog.isUsed, configJson.naverblog.type, configJson.naverblog.cate1, configJson.naverblog.cate2, configJson.google.naverblog, configJson.naverblog.isReserved, configJson.naverblog.time);
                    await boardcreatebyPlatform(configJson.youtube.isUsed, configJson.youtube.type, configJson.youtube.cate1, configJson.youtube.cate2, configJson.google.youtube, configJson.youtube.isReserved, configJson.youtube.time);

                }
                finally{
                   console.log(">> close!!!!!!!!!!!!!!!!");
                   driver.close();
                }        
            });
    
}

๊ทธ ์™ธ. ๋ถ€์ˆ˜์ ์œผ๋กœ ํ•„์š”ํ–ˆ๋˜ ํ•จ์ˆ˜

nodejs์—์„œ drive์˜ sleep ์“ฐ๋Š” ๊ธฐ๋Šฅ์„ ๋ชฐ๋ผ ๋ณ„๋„๋กœ ๊ตฌํ˜„ํ•˜์—ฌ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค ๐Ÿ˜ญ  ์ด์™ธ์—๋„ ์ด๋ชจ์ง€ ์—†์• ๊ธฐ, ํŠน์ˆ˜๋ฌธ์ž ์—†์• ๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

function sleep(delay) {
    var start = (new Date()).getTime();
    while ((new Date()).getTime() - start < delay) {
        //     continue   ๏ผ›
        continue; 
    }
}

async function wait(delay){
    try {
        await driver.wait(() => { return false; }, delay);
    } catch (err) {
        console.log(err);
    } 
}


function removeEmojis(string) {
    var regex = /(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])/g;
    
    return string.replace(regex, '');
}

function regExp(str){  
    var reg = /[\{\}\[\]\/?.,;:|\)*~`!^\-_+<>@\#$%&\\\=\(\'\"]/gi
    //ํŠน์ˆ˜๋ฌธ์ž ๊ฒ€์ฆ
    if(reg.test(str)){
      return str.replace(reg, "");    
    } else {
      return str;
    }  
}  

function uploadSplit(tempTime)
{
    let nCount = tempTime.split(",").length;

    return nCount+1;
}

์—‰๋ง์ง•์ฐฝ ํ˜„์žฌ๋„ ์ข…์ข… ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€๋งŒ, ์ง€์†์ ์œผ๋กœ ์ˆ˜์ •ํ•˜๋ฉด์„œ ์‚ฌ์šฉํ•ด๋ณผ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” ์ž๋™ ๋ฐœํ–‰ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. 

์ž๋™๋ฐœํ–‰ ์ดํ›„๋กœ ๋ณด๋“œ๊ฐ€ ์ €ํ’ˆ์งˆ์ด ๋˜์–ด ๋…ธ์ถœ ์ˆ˜๊ฐ€ 1/1000์œผ๋กœ ๊ฐ์†Œํ–ˆ๋Š”๋ฐ์š”. ๋ณด๋“œ ์ œ๋ชฉ๊ณผ ๋‚ด์šฉ์„ ์ฃผ๊ธฐ์ ์œผ๋กœ ์ˆ˜์ •ํ•ด๋ณด๋ฉด์„œ ๋ฐœํ–‰ํ•˜์—ฌ ์ƒํ™ฉ์„ ์ง€์ผœ๋ณผ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

์ž๋™๋ฐœํ–‰ ์ „ / ์ž๋™๋ฐœํ–‰ ํ›„

์ถ”๊ฐ€์ ์œผ๋กœ ๋Šฆ๊ฒŒ ์‹œ์ž‘ํ•˜์—ฌ ๋ณด๋“œ ์ „์ฒด ์˜ˆ์•ฝ ๋ฐœํ–‰ํ•˜๋Š” ๋ถ„ ์ค‘ ์ง€๋‚œ๋‹ฌ 150๋งŒ ์› ์ˆ˜์ต ๋‚œ ๋ถ„์ด ์žˆ์–ด์„œ ์˜ˆ์•ฝ ๋ณด๋“œ ๋ฐœํ–‰์€ ์ €ํ’ˆ์งˆ์ด๋‚˜ ๋…ธ์ถœ์ด ์•ˆ ๋˜๋Š” ์‚ฌ์œ ๋Š” ์•„๋‹ˆ๋ผ๋Š” ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ์š” ๋ฐ”์˜๋”” ๋ฐ”์œ ํ˜„๋Œ€ ์‚ฌํšŒ์ธ๋ฐ ์˜ˆ์•ฝ๋งŒ์œผ๋กœ ์ €ํ’ˆ์งˆ์ด๋ฉด ๋„ˆ๋ฌด ์–ต์šธํ•  ๊ฒƒ ๊ฐ™์•„์š”.

์ €๋Š” ์ˆ˜๋™์œผ๋กœ ๋ฐœํ–‰ํ•˜๋Š” ์‹œ๊ฐ„์ด ๋„ˆ๋ฌด ์˜ค๋ž˜ ๊ฑธ๋ ค ๊ธธ๊ฒŒ ์นด์นด์˜ค ๋ทฐ๋ฅผ ํ•  ์ƒ๊ฐ์œผ๋กœ ์ž๋™๋ฐœํ–‰ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ๋…ธ๋ ฅํ•œ ์ง€๋‚˜๊ฐ€๋Š” ์œ ์ €์ž…๋‹ˆ๋‹ค. ์‹ค์ œ ์นด์นด์˜ค ๋ทฐ ๋…ธ์ถœ ๋ฐ ์ˆ˜์ต ๋…ธํ•˜์šฐ๋Š” ์•„๋ž˜ ์นดํŽ˜์—์„œ ๋งŽ์€ ์ •๋ณด๊ฐ€ ์žˆ์œผ๋‹ˆ ์ฐธ๊ณ  ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

 

๊ฒŒ์„๋Ÿฌ๋„ ๋ˆ๋ฒŒJob : ๋„ค์ด๋ฒ„ ์นดํŽ˜

๋””์ง€ํ„ธ๋…ธ๋งˆ๋“œ๋กœ ๊ฒฝ์ œ์  ์ž์œ ๋ฅผ ๋ˆ„๋ฆฌ๋ ค๋Š” ์นดํŽ˜ ๊ฒŒ์„๋Ÿฌ๋„ ๊พธ์ค€ํ•˜๊ฒŒ ๋ˆ๋ฒŒ ๊ธฐํšŒ๋ฅผ ์ฐพ์•„๋ณด๋Š” ์นดํŽ˜

cafe.naver.com

 

๋Œ“๊ธ€