프로그래머스의 코딩테스트 연습 > 연습문제 > 카드뭉치 문제에 대한 문제 풀이입니다.

https://school.programmers.co.kr/learn/courses/30/lessons/159994

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

먼저 문제는 아래와 같습니다. (문제의 전체 내용은 위 링크를 확인하시면 됩니다.)

 

문제설명

코니는 영어 단어가 적힌 카드 뭉치 두 개를 선물로 받았습니다. 코니는 다음과 같은 규칙으로 카드에 적힌 단어들을 사용해 원하는 순서의 단어 배열을 만들 수 있는지 알고 싶습니다.

  • 원하는 카드 뭉치에서 카드를 순서대로 한 장씩 사용합니다.
  • 한 번 사용한 카드는 다시 사용할 수 없습니다.
  • 카드를 사용하지 않고 다음 카드로 넘어갈 수 없습니다.
  • 기존에 주어진 카드 뭉치의 단어 순서는 바꿀 수 없습니다.

예를 들어 첫 번째 카드 뭉치에 순서대로 ["i", "drink", "water"], 두 번째 카드 뭉치에 순서대로 ["want", "to"]가 적혀있을 때 ["i", "want", "to", "drink", "water"] 순서의 단어 배열을 만들려고 한다면 첫 번째 카드 뭉치에서 "i"를 사용한 후 두 번째 카드 뭉치에서 "want"와 "to"를 사용하고 첫 번째 카드뭉치에 "drink"와 "water"를 차례대로 사용하면 원하는 순서의 단어 배열을 만들 수 있습니다.

문자열로 이루어진 배열 cards1cards2와 원하는 단어 배열 goal이 매개변수로 주어질 때, cards1과 cards2에 적힌 단어들로 goal를 만들 있다면 "Yes"를, 만들 수 없다면 "No"를 return하는 solution 함수를 완성해주세요.

 

입출력 예

cards1 cards2 goal result
["i", "drink", "water"] ["want", "to"] ["i", "want", "to", "drink", "water"] "Yes"
["i", "water", "drink"]
["want", "to"] ["i", "want", "to", "drink", "water"] "No"

 

풀이

만들고자 하는 카드의 배열은 goal 입니다. goal 을 만들기 위해 cards1 과 cards2 배열 중 가장 첫 번째 요소를 꺼내어 goal 을 만들 수 있으면 "Yes", 만들 수 없다면 "No" 를 응답하면 됩니다.

 

만들고자하는 결과인 goal 요소를 순회하면서 cards1 과 cards2 중 첫 번째 요소에 해당 단어가 있는지 살펴보고, 해당 단어가 있을 경우에 사용한 카드(요소)는 버리도록 shift() 메소드를 사용해서 배열의 첫 번째 요소를 삭제하겠습니다.

function solution(cards1, cards2, goal) {
    
    for (let ele of goal) {
        if (ele === cards1[0]) {
            cards1.shift();
        } else if (ele === cards2[0]) {
            cards2.shift();
        } else {
            return 'No';
        }
    }
    return 'Yes';
}

 

for ~ of 구문으로 배열을 순회하면서 해당 카드(요소)가 cards1 과 cards2 중 하나라도 첫 번째 요소에 있는지 확인하고 있을 경우에는 확인한 카드(요소)를 shift() 메소드로 뽑아서 버리고 다음 카드(요소)를 순회합니다. 그리고 없을 경우에는 해당 단어를 만들 수 없으므로 바로 "No"를 응답합니다.

 

 

 

300x250

프로그래머스의 코딩테스트 연습 > 코딩 기초 트레이닝 > 수 조작하기1 문제에 대한 문제 풀이입니다.

https://school.programmers.co.kr/learn/courses/30/lessons/181926

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

먼저 문제는 아래와 같습니다. (문제의 전체 내용은 위 링크를 확인하시면 됩니다.)

 

문제설명

정수 n과 문자열 control이 주어집니다. control은 "w", "a", "s", "d"의 4개의 문자로 이루어져 있으며, control의 앞에서부터 순서대로 문자에 따라 n의 값을 바꿉니다.

  • "w": n이 1 커집니다.
  • "s": n이 1 작아집니다.
  • "d": n이 10 커집니다.
  • "a": n이 10 작아집니다.

위 규칙에 따라 n을 바꿨을 때 가장 마지막에 나오는 n의 값을 return 하는 solution 함수를 완성해 주세요.

 

입출력 예

n control result
0 "wsdawsdassw" -1

 

풀이

수가 n부터 시작하므로 모든 control 요소의 값을 더한 후 n에 더해주면 되는 문제입니다. for 문과 if 문을 사용해서 작성해보면 아래처럼 작성할 수 있습니다.

function solution(n, control) {

    for (let inx=0; inx<control.length; inx++) {
        if (control[inx] === 'w') {
            n = n + 1;
        } else if (control[inx] === 's') {
            n = n - 1;
        } else if (control[inx] === 'd') {
            n = n + 10;
        } else {
            n = n - 10;
        }
    }
    return n;
}

 

위 내용은 누적값을 구하는 내용이므로 reduce 함수를 사용해서 아래와 같이 작성해 볼 수도 있습니다.  

function solution(n, control) {
    const point = {'w': 1, 's': -1, 'd': 10, 'a': -10}
    return [...control].reduce((a, v) => a + point[v], n);
}

 

먼저 각 문자 당 수에 쉽게 접근하기 위해 문자와 수를 연결한 오브젝트를 하나 생성합니다.

 

전개 구문

아래와 같이 문자열에 전개 구문을 사용하면 해당 문자열을 배열로 변경할 수 있습니다.

const control = 'wsdawsdassw';
console.log([...control]);
//['w', 's', 'd', 'a', 'w', 's', 'd', 'a', 's', 's', 'w']

 

reduce 함수

reduce 함수는 배열을 순회하며 해당 배열 요소의 누적값을 구할 수 있습니다. 위와 같이 사용하면 초기값을 n으로 하여 point[v]의 값을 a에 누적한 후 return 하라는 의미입니다.

300x250

'프로그래머스 문제풀이 > Lv.0' 카테고리의 다른 글

"이어 붙인 수" 문제 풀이 (Lv.0)  (0) 2023.11.16

프로그래머스의 코딩테스트 연습 > 코딩 기초 트레이닝 > 이어 붙인 수 문제에 대한 문제 풀이입니다.

https://school.programmers.co.kr/learn/courses/30/lessons/181928

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

먼저 문제는 아래와 같습니다. (문제의 전체 내용은 위 링크를 확인하시면 됩니다.)

 

문제설명

정수가 담긴 리스트 num_list가 주어집니다. num_list의 홀수만 순서대로 이어 붙인 수와 짝수만 순서대로 이어 붙인 수의 합을 return하도록 solution 함수를 완성해주세요.

 

입출력 예

num_list result
[3, 4, 5, 2, 1] 393
[5, 7, 8, 3] 581

 

풀이

간단하게 주어진 배열을 반복하면서 홀수와 짝수를 구한 후 이어 붙여서 두 수의 합을 구하면 됩니다. 가장 간단하게 for 문을 사용해서 아래와 같이 풀어볼 수 있습니다.

function solution(num_list) {
    let odd = '';
    let even = '';
    
    for (let inx=0; inx<num_list.length; inx++) {
        if (num_list[inx] % 2 === 0) {
            even += num_list[inx];
        } else {
            odd += num_list[inx];
        }
    }
    return Number(odd) + Number(even);
}

 

홀수와 짝수는 값을 2로 나눈 나머지가 0이면 짝수, 아니면 홀수로 판단하면 됩니다. 해당 조건으로 판단하여 홀수와 짝수의 문자열을 만들고 그 합을 구해 return 하는 문제입니다.

 

위 문제를 filter 메소드를 사용해서 풀어보면 아래와 같습니다.

function solution(num_list) {
    const odd = num_list.filter(v => v % 2).join('');
    const even = num_list.filter(v => !(v % 2)).join('');
    return Number(odd) + Number(even);
}

 

개념은 같습니다. filter 메소드는 파라미터로 전달하는 콜백 함수의 결과가 참인 경우로 새 배열을 만들어서 return 해줍니다. 하여 홀수는 v로 나눈 나머지가 1(true)인 수들을 모아서 새 배열을 생성한 후 join으로 하나의 문자열로 변환합니다. 짝수도 마찬가지 방법으로 구할 수 있습니다.

 

 

300x250

'프로그래머스 문제풀이 > Lv.0' 카테고리의 다른 글

"수 조작하기1" 문제 풀이 (Lv.0)  (0) 2023.11.16

본 포스트는 HTTP Response Header 의 값 중 서버 시간을 구해서 사용하는 방법에 대한 설명입니다.

 

 

클라이언트에서 서버의 시간을 참조할 일이 있을 경우, 서버 API에서 응답값에 현재 시간을 보통 포함시켜서 전달합니다. 하지만 정말로 딱! 시간만 필요한 경우는 아래와 같이 빈 페이지나 빈 API의 Response Header의 Date를 참조하면 손쉽게 서버 시간을 구할 수 있습니다.

 

인터페이스를 하면 아래와 같이 Response Header가 응답에 포함되어 있습니다.

아래와 같은 식으로 간단하게 Response Header에 있는 Date 값을 구할 수 있습니다.

fetch(url, {
	method: 'GET'
}).then((resp) => {
	console.log(resp.headers.get('Date'));
});

프로젝트에서 jQuery를 사용한다면 아래 코드를 참고하시면 됩니다.

var options = {};
options.url = window.location.href.toString();
options.method = 'HEAD';
var xhr = $.ajax(options);
xhr.always(function() {
	console.log(xhr.getResponseHeader('date'));
});

 

300x250

본 포스트는 JavaScript의 getTimeZoneOffset() 메소드를 사용하여 UTC 시간을 구한 뒤 서버와 클라이언트의 시간을 동일하게 계산할 수 있는 방법에 대한 설명입니다.

 

요즘 개발하는 서비스들은 대부분 국내에서 뿐만 아니라 해외에서도 사용 가능한 형태로 개발합니다. 해외에서 서비스를 사용하는 경우 뿐 아니라 사용자가 각자 사용하는 Device의 국가, 시간 설정을 대한민국이 아닌 다른 곳으로 해두었을 경우 JavaScript의 new Date() 는 해당 국가 설정을 참조하여 시간을 return 합니다.

 

현재 제가 사용하는 Device는 대한민국 표준시를 사용하도록 설정되어 있습니다.

 이 상태에서 아래 코드의 결과는 다음과 같습니다.

new Date();
//Thu Jun 23 2022 07:36:14 GMT+0900 (한국 표준시)

이번에는 Device의 시간을 미국으로 변경해 보겠습니다.

 

 

그러면 동일한 코드는 아래와 같은 결과를 보여줍니다.

new Date();
//Wed Jun 22 2022 17:35:43 GMT-0500 (북미 중부 하계 표준시)

서비스의 성격에 따라 판단할 문제이지만 만약 서버에서 시간을 체크해야 하는데 화면의 Request에서 시간을 받아서 검증이나 사용을 하게될 경우 서버는 대한민국 표준시를 사용하지만, 화면은 북미 중부 표준시를 사용하게 되므로 대한민국 표준시를 사용하지 않는 사용자는 적절하지 않은 오류를 만나게 될 수도 있습니다.

 

경우에 따라 다르지만 클라이언트 JavaScript 코드에서도 대한민국 표준시로 통일하는 방법이 있습니다.

 

const now = new Date();
const utcDate = now.getTime() + (now.getTimezoneOffset() * 60 * 1000);
const korDate = new Date(utcDate + 9 * 60 * 60 * 1000);

우리나라는 그리니치 표준시 + 9H를 사용하므로, UTC 기준시각에 9시간을 더해주는 로직입니다.

 

위와 같이 코드를 작성하면 클라이언트에서 북미 중부 표준시를 사용하더라도 대한민국 표준시를 화면에서 사용할 수 있습니다. 물론 위와 같은 코드보다는 서버의 시간을 Response Header에서 참조하여 변환하는게 좀 더 일반적인 사용 방법입니다. 

 

300x250

몇 년 전에도 모 프로젝트에서 지원 요청이 와서 한 번 Code Review 하여 해결을 했었고, 얼마 전에도 운영 중인 시스템에서도 동일한 Case가 있었던 것을 보면 아주 기초적인 사항임에도 생각보다 잘 지켜지지 않는 부분일 수 있겠다는 생각이 듭니다.

 

jQuery 사용

대기업에서 SI 프로젝트에 몸 담고 있다보면, 혹은 대기업 SI 프로젝트에서 개발한 시스템을 인수하는 운영 담당자의 역할로 있다보면 서비스 기업들에서 많이들 사용하는 Vue, React 등의 Framework, Library는 구경하기 힘들고 2022년인 현재도 많은 프로젝트들이 jQuery 기반으로 진행되는 것을 알 수 있습니다.

 

대규모 SI 프로젝트의 경우 개발자가 수십~수백 명에 이르는데 Vue나 React를 사용하는 개발자들을 충분히 소싱하기 힘들고, 상용 UI 솔루션들과 연계해야 하는 상황에서 아직 jQuery 기반으로 제공되는 솔루션들이 많아 어쩔 수 없는 선택이 되곤 합니다.

(사실 Zepto 등의 경량 Library도 고려 대상일 수 있겠으나, 이미 검증된 수많은 Plug-in이 있다는 점은 SI 프로젝트에 너무 매력적인 요소로 작용하는 듯 합니다.)

 

jQuery 기반의 프로젝트에서 업무 화면이 복잡해져서 하나의 프로그램에서 수행하는 XHR과 calback이 많아지면 아래와 같은 문제들이 종종 발생하게 됩니다.

 

화면 특정 영역에 데이터가 나오다 말다 해요

A와 B 두 개의 function이 있습니다. A function은 DOM을 초기화하는 function이고, B function은 서버에서 데이터를 받아와 A function이 구성한 DOM에 Data를 Bind하는 역할을 하는 function 입니다.

function A() {
	// 특정 조건에 따라 UI에 특정 영역을 표시하거나 제거합니다.
}

function B() {
	// $.ajax 등의 함수로 서버와 통신하여 A 영역에서 생성한 DOM에 Data를 Bind 합니다.
}

생각보다 많은 개발자들이 아래와 같이 작성하고 (물론 위와 같이 너무 단순한 구조는 아닙니다만), 사실 또 대부분의 경우에 연산은 또 순식간에 일어나므로 올바르게 동작합니다.

A();
B();

하지만 복잡한 Front-end 프로그램을 개발하다 보면 아주 많은 경우의 수가 발생합니다. 사용자의 휴대폰이 구형이라 브라우저의 동작 자체가 느린 환경도 있고, 데이터 음영 구간도 있고, 접속 상태가 좋지 못한 Wi-Fi를 사용하여 Network가 느린 경우도 있어 반드시 작성한 순서대로 실행을 보장하지는 않습니다.

 

Callback function 사용

순서가 반드시 보장되어야 하는 코드들은 정확히 실행해야 하는 타이밍을 callback function을 사용하여 구현합니다. 

 

위와 같은 경우에도 A function에서 생성해야 할 DOM이 생성되지 않은 상태에서 B function의 Data bind가 수행이 되는 경우가 발생하면 해당 영역에는 올바르게 Data를 표시하지 못하는 경우가 발생합니다.

 

순서를 보장하기 위해서는 아래와 같이 작성합니다.

function A(callback) {
	//특정 조건에 따라 UI에 특정 영역을 표시하거나 제거합니다.
    if (callback && typeof callback === 'function') callback();
}

function B() {
	//$.ajax 등의 함수로 서버와 통신하여 A 영역에서 생성한 DOM에 Binding 합니다.
}

A(B);

위와 같은 형태로 작성하면 DOM을 구성하는 작업이 완료된 후 B function을 실행하므로 화면을 올바르게 표시할 수 있습니다. 

 

사실 수백~수천 라인에 달하는 프로그램에서 모든 순서가 정확하게 보장되기가 쉽지가 않습니다. 이 과정에서 callback 지옥 역시 발생합니다. ES6+에서는 async/await, Promise를 사용하여 이런 callback 지옥 구조를 많이 개선했지만 아직 많은 대고객 서비스에서는 I.E를 지원해야 하기 때문에 여전히 callback 지옥을 헤어 나오기는 힘듭니다.

300x250

백오피스나 내부 사용자를 위한 시스템은 Edge로 전환 후 I.E에 대한 고려를 이제 걷어내어도 되겠지만, 대고객 서비스를 하는 시스템들은 계속 I.E에 대해 고려할 필요가 있습니다.

 

JavaScript에서 일자 formatting이나 연산에 많이 사용하는 momentJs 사용 시 약간의 주의사항이 있습니다.

 

서버 API에서 일자 정보가 아래와 같이 내려온 경우 I.E에서는 정상적으로 처리가 되지 않습니다.

 

const curDate = '2022.06.22';
moment(curDate).format('YYYYMMDD');

위와 같은 코드를 실행할 경우 I.E에서는 "Invalid date"를 return 합니다.

 

I.E를 제외한 Chrome 등의 브라우저에서는 정상적으로 "20220622"를 return 합니다.

 

하여 서버 API에서 전달 받는 일자 데이터에 dot(.)이 포함되어 있을 경우 안전하게 데이터를 가공한 후 formatting 하면 됩니다.

 

const curDate = '2022.06.22';
moment(curDate.replace(/[.]/g, '')).format('YYYYMMDD');
300x250
MAC OSX에서의 PhoneGap 개발환경 구성에 대해 알아 보겠습니다. 요즘 특정 Hybrid Framework에서는 Windows 환경에서도 iOS Application을 Build하는 방법을 제공하지만, Open Source인 PhoneGap에서는 아직 제공하지 않으므로 MAC OSX 환경에서 개발환경을 구성하는 방법에 대해 알아 보겠습니다.
아래부터는 편의를 위해 경어는 생략하도록 하겠으니 양해 바랍니다.
1. XCode 설치
XCode는 Apple AppStore나 홈페이지에서 다운로드 할 수 있다. Apple AppStore에서 다운로드 할 경우 최신 버전만 다운로드 가능하므로 이전 버전의 XCode를 다운로드하고 싶을 경우 홈페이지에 접속하여 다운로드 받도록 한다. 홈페이지 아래의 경로로 접근하면 다운로드 가능하다.

https://developer.apple.com/downloads

XCode는 현재 OS 버전에 따라 설치할 수 있는 버전이 제한되며, 최신 버전의 iOS 지원을 위해서는 개발에 사용하는 MAC Book, iMac의 OS 버전도 최신으로 업데이트해야 한다.

2. Command Line Tools 설치
혹시나 Command Line Tools가 아직 설치되어 있지 않다면, 1번 과정과 동일한 방법으로 Command Line Tools를 설치한다.
3. Node.js 설치
PhoneGap 3.5 버전부터는 다운로드는 허용하지 않으며, CLI를 통한 설치만 허용한다. 해당 작업이 Node.js 기반으로 구성되었으므로 먼저 아래 URL로 접근하여 Node.js를 설치한다. -. http://nodejs.org

4. PhoneGap 설치
PhoneGap 3.5 부터는 CLI를 통한 다운로드만 허용하고 있으므로 npm install 명령으로 설치한다. Command Window를 실행한 후 아래 화면과 같이 명령어를 입력한다.

명령어를 입력하면 NodeJS 모듈이 PhoneGap을 다운로드하여 자동으로 설치한다. 설치가 종료되면 Command Window에서 cordova –v 라고 입력하여 설치한 PhoneGap version을 확인할 수 있다.

5. PhoneGap 프로젝트 생성
위 과정으로 PhoneGap 프로젝트 생성을 위한 준비가 끝났다. 실제 프로젝트를 생성하여 개발 툴인 XCode로 반입하는 방법은 아래와 같다.

1. 임시 workspace 생성

PhoneGap CLI로 생성한 프로젝트를 보관할 폴더를 하나 만든다. 각자 관리하기 편한 경로에 생성하면 된다. 일단 Sample로는 /Users/계정/Documents/phonegap/workspace/ 로 생성하였다.

2. PhoneGap 프로젝트 생성

PhoneGap 프로젝트는 CLI로 생성할 수 있으므로 Command Window를 열고 /Users/계정/Documents/phonegap/workspace/로 이동한다. 이동한 후 cordova create 명령으로 PhoneGap 프로젝트를 생성할 수 있다. 생성하는 과정은 아래 그림을 참고한다.

실행한 결과를 보면 com.edu.bbs 라는 아이디를 가진 MobileBBS라는 프로젝트를 생성하였는데, 그 경로가 /Users/계정/Documents/phonegap/workspace/mobileBBS 에 생성되었다는 결과가 표시되었다.

3. Platform 추가

프로젝트를 생성했으면 프로젝트에서 사용할 Platform을 추가해야 한다. 당연히 이번에는 iOS를 추가해보자. 먼저 방금 생성한 프로젝트 폴더로 이동하여 cordova platform add 명령을 실행한다. 과정은 아래 그림을 참고한다.

4. XCode 반입

이제 생성한 Project를 XCode로 반입해야 한다. MAC OSX에서 반입은 프로젝트 파일만 실행시키면 쉽게 XCode 프로젝트로 등록 가능하다. 방금 전 단계에서 iOS platform을 추가하였으므로 ./platform/ios/ 경로에 접근해보면 MobileBBS.xcodeproj 파일을 볼 수 있다. 해당 파일을 더블클릭하면 자동으로 XCode Project로 등록된다.




300x250

'모바일 > 개발환경구성' 카테고리의 다른 글

PhoneGap 개발환경구성 (Windows)  (3) 2015.01.05
언젠가부터 Enterprise Mobile Application을 개발하는데 Hybrid 개발 방법이 많이 쓰이고 있습니다. 물론 Native나 Mobile Web과는 일정 부분의 득과 실이 있겠지만, 기업 입장에서 전체적인 개발 비용을 다운시킬 수 있고 하나의 소스로 유지보수 할 수 있는 점은 무시할 수 없는 매력으로 작용했을 듯 합니다.
이런 Hybrid 개발은 사용자가 직접 Android, iOS 등에서 WebView를 생성하여 개발하기도 하지만 공통적인 부분들을 이미 개발해 놓은 Hybrid Framework를 사용해서 많이들 개발합니다. 각 기업들에서 내놓은 솔루션들도 많지만 가장 많이 사용하는 건 아무래도 Open Source인 PhoneGap이 아닐까 합니다. 하여 이미 많이들 사용하고 계시지만 PhoneGap 개발을 위한 개발환경 구성에 대해 알아보도록 하겠습니다.
아래부터는 편의를 위해 경어는 생략하도록 하겠으니 양해 바랍니다.
1. ADT(Android Developer Tools) 설치
프로젝트에서 IDE로 사용할 ADT를 다운로드 받아 압축을 해제한다. 개발자들에게 압축하여 배포할 형태를 고려하여 폴더를 생성한다. ADT는 아래 경로에서 다운로드 받아 압축만 해제하면 된다.

http://developer.android.com/sdk/index.html

프로젝트에서는 Packaging 뿐만 아니라 WEB Resources도 같은 IDE에서 개발할 것이므로 HTML, JavaScript, CSS 개발에 필요한 Eclipse Plug-in을 설치한다. Eclipse에서 [Help] – [Install New Software] 메뉴를 선택하면 아래와 같은 창이 표시된다. 해당 창의 Work with 란에 아래 주소를 입력하면 아래 그림과 같은 미설치 Plug-in 목록이 조회된다.

Eclipse에서 [Help] – [Install New Software] 메뉴를 선택하면 아래와 같은 창이 표시된다. 해당 창의 Work with 란에 아래 주소를 입력하면 아래 그림과 같은 Plug-in 목록이 조회된다. 입력할 주소 : http://download.eclipse.org/releases/kepler

조회된 Plug-in 목록 중 [Web, XML, Java EE and OSGi Enterprise Development] 좌측의 화살표를 클릭하면 해당 Category 하위의 Plug-in목록이 조회된다. 그 중 한 가지에 체크를 하여 설치한다.

-. Eclipse Java Web Developer Tools
2. Node.js 설치
PhoneGap 3.5 버전부터는 다운로드는 허용하지 않으며, CLI를 통한 설치만 허용한다. 해당 작업이 Node.js 기반으로 구성되었으므로 먼저 아래 URL로 접근하여 Node.js를 설치한다. -. http://nodejs.org/ 페이지의 중간에 있는 큼직한 INSTALL 버튼을 클릭하면 *.msi 파일을 다운로드 하며, 해당 파일을 클릭하면 Node.js가 설치된다.

3. Git 설치
PhoneGap 3.x 대 버전부터는 Project를 생성할 때 사용하고자 하는 js API를 Git에서 선택적으로 추가해서 사용하는 구조이므로 Git도 설치 및 PATH에 잡혀 있어야 한다. Git는 아래 URL에서 다운로드하여 설치한다. -. http://msysgit.github.io/

4. PhoneGap 설치
PhoneGap 3.5 부터는 CLI를 통한 다운로드만 허용하고 있으므로 npm install 명령으로 설치한다. Command Window를 실행한 후 아래 화면과 같이 명령어를 입력한다.

명령어를 입력하는 NodeJS 모듈이 PhoneGap을 다운로드하여 자동으로 설치한다. 설치가 종료되면 Command Window에서 cordova –v 라고 입력하여 설치한 PhoneGap version을 확인할 수 있다.

5. Ant 설치
PhoneGap 3.x 에서는 Project 생성 시 CLI를 지원하며, Android Project 추가 시 내부적으로 Ant를 사용하여 Build 한다. 따라서 Android Project를 추가하기 위해서는 Ant 역시 설치되어 있어야 한다. Ant는 아래 URL에서 다운로드 할 수 있으며, 원하는 경로에 압축을 해제하면 된다. -. http://ant.apache.org/

Ant 는 설치 후 %ANT_HOME%을 등록하고 \bin 경로를 Path에 등록해 두어야 PhoneGap이 필요한 경로에서 Build 할 수 있다. 압축을 해제한 경로를 Path에 등록하자.

1. 시스템 변수 등록

[내 컴퓨터] – [속성]의 [고급 시스템 설정] 메뉴에서 [고급] 탭으로 이동한 후 [환경 변수] 버튼을 클릭하면 아래와 같은 창이 표시된다.

시스템 변수에 [새로 만들기] 버튼을 클릭하여 변수 이름에 ANT_HOME, 변수 값에 ANT 압축을 해제한 경로를 설정하도록 하자. 예를 들어 C:\Ant에 압축을 해제하였다고 하면 위와 같이 ANT_HOME 이라는 변수에 C:\Ant라는 값이 저장된다.

2. Path 추가

시스템 변수를 추가했으면 사용자 변수 중 Path 부분을 Edit 하여 해당 경로를 Path에 포함시켜야 한다. 사용자 변수 중 Path를 선택하고 [편집] 버튼을 누른 후 변수 값 가장 마지막 부분에 %ANT_HOME%\bin; 을 추가한다.
6. PhoneGap 프로젝트 생성
위 과정으로 PhoneGap 프로젝트 생성을 위한 준비가 끝났다. 실제 프로젝트를 생성하여 개발 툴인 ADT로 반입하는 방법은 아래와 같다.

1. 임시 workspace 생성

PhoneGap CLI로 생성한 프로젝트를 보관할 폴더를 하나 만든다. 각자 편한 이름으로 생성하면 된다. 일단 Sample로는 d:\phonegap_workspace 로 하나 생성했다.

2. PhoneGap 프로젝트 생성

PhoneGap 프로젝트는 CLI로 생성할 수 있으므로 Command Window를 열고 d:\phonegap_workspace로 이동한다. 이동한 후 cordova create 명령으로 PhoneGap 프로젝트를 생성할 수 있다. 생성하는 과정은 아래 그림을 참고한다.

실행한 결과를 보면 com.edu.bbs 라는 아이디를 가진 MobileBBS라는 프로젝트를 생성하였는데, 그 경로가 d:\phonegap_workspace\mobileBBS 에 생성되었다는 결과가 표시되었다.

3. Platform 추가

프로젝트를 생성했으면 프로젝트에서 사용할 Platform을 추가해야 한다. 일단은 Android 이번 범위에서는 Android 만 진행할 예정이므로 Android 만 추가해보자. 먼저 방금 생성한 프로젝트 폴더로 이동하여 cordova platform add 명령을 실행한다. 과정은 아래 그림을 참고한다.

4. ADT 반입

생성한 Project를 ADT로 반입해야 한다. Application 개발 시 ADT를 사용할 것이므로 CLI에서 생성한 Project를 ADT로 반입하여야 개발환경 설정이 완료된다. Package Explorer 의 바로가기 메뉴에서 [New] – [Other..]를 선택한다.

[Android] – [Android Project from Existing Code]를 선택하고 [Next] 버튼을 클릭한다.

Root Directory에 방금 전 생성한 PhoneGap Project 경로를 선택하고 아래 쪽에 있는 [Copy projects into workspace] 옵션에 체크한 후 [Finish] 버튼을 클릭한다. 여기까지 하면 PhoneGap Project 를 ADT 환경으로 반입할 수 있다. 현재 Bug 비슷하게 발생하는 문제가 있어서 Project 반입 시 오류가 발생하면 지우고 재 반입하면 정상적으로 반입할 수 있다. 반입한 후 Package Explorer 는 아래 그림과 같다.

Native 개발은 [프로젝트 명-CordovaLib] 프로젝트에서 진행하며, 화면 등의 주 개발 영역인 Web 개발은 위 프로젝트에서 진행한다. Web Resources는 /assets/www/ 폴더 경로에 위치한다.


300x250

'모바일 > 개발환경구성' 카테고리의 다른 글

PhoneGap 개발환경구성 (iOS)  (0) 2015.01.10

제목: 글쓰기 페이지 구성 (Client)

최초작성일: 2015-01-05

최종수정일: 2015-01-05

2015년 새해가 밝았습니다. 다들 2015년에는 하시는 일 원하시는대로 이루어지길 빌겠습니다. 물론 저도, 우리 꼬맹이도 건강하고 많이 이루어나가는 한 해가 되었으면 좋겠네요. 정말 한 해가 지나고 새해가 밝으면 문자 그대로 많은 일들을 후회하고, 새해에 대한 다짐과 기대에 차오르는 것 같습니다. 2015년에는 많은 핑계들로 다짐을 지워가는 한 해는 되지 않도록 열심히 살아봐야겠네요. 지난 시간에 목록 페이지에 이어 상세 페이지까지 개발해 보았습니다. 이제 신규로 글을 등록하는 기능을 구현해보도록 하겠습니다. 글 등록 역시 일단은 서버가 없으니 UI만 만들어보도록 하겠습니다. Local Storage에 저장할 수도 있고, WEB Database에 저장할 수도 있겠지만, 일단 저장은 하지 않고 UI 개발만 하고 멈추도록 하겠습니다. 입력에 사용할 항목은 아래와 같이 정의합니다.

-. 입력자 성명
-. 게시물 제목
-. 게시물 내용
-. 비밀번호
그럼 UI를 구성해보겠습니다.
1. 기본 HTML 구조 작성
글쓰기 페이지 역시 [헤더] - [본문] - [푸터]로 영역을 분할하여 구성하겠습니다. 아래 소스 코드를 참고하셔서 ./bbs_write.html 파일로 저장합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta http-equiv="content-type" content="text/html;charset=UTF-8">
        <meta name="viewport" content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, width=device-width">
        <title>Mobile BBS</title>
        <link rel="stylesheet" type="text/css" href="./css/common.css" />
    </head>
    <body>
        <header>
            <h1>Mobile BBS</h1>
        </header>
         
        <div class="wrap">
            <div class="content_line">
                <span class="header">작성자</span>
                <span><input type="text" class="input" id="inputUserName"><span>
                    </span></span></div>
            <div class="content_line">
                <span class="header">비밀번호</span>
                <span><input type="text" class="input" id="password"></span>
            </div>
            <div class="content_line">
                <span class="header">글제목</span>
                <span><input type="text" class="input" id="subject"></span>
            </div>
            <div class="content_line">
                <span class="header">글내용</span>
                <span><textarea id="content" class="text"></textarea></span>
            </div>
        </div>
         
        <footer>
            <button id="btnWrite">글쓰기</button>
        </footer>
    </body>
    <script type="text/javascript" charset="utf-8" src="./scripts/jquery-1.10.2.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="./scripts/common.js"></script>
</html>
HTML 페이지는 구조만 선언하므로 큰 내용이 없습니다. 글쓰기 페이지에서 표시할 정보에 대한 구조를 선언했습니다. 사용자가 입력해야 하는 값인 작성자, 비밀번호, 글제목, 글내용 컬럼을 입력할 수 있는 inputbox가 화면의 전부입니다. 글내용은 긴 내용도 입력할 수 있어야 하기 때문에 textarea로 구성합니다.
그럼 이제 글쓰기 페이지의 모양을 위해 간단하게 StyleSheet를 추가해보겠습니다.
2. StyleSheet 작성

StyleSheet는 모든 페이지에서 common.css를 사용하도록 하겠습니다. common.css에 글쓰기 페이지와 관련된 부분을 추가해보겠습니다.

1
2
3
.wrap .content_line .header{display:inline-block;width:100px;text-align:center;vertical-align:top;padding-top:5px;}
.wrap .content_line .input{width:250px;border:1px solid #ccc;background-color:#f4f4f4;border-radius:3px;height:22px;line-height:22px;}
.wrap .content_line .text{width:250px;border:1px solid #ccc;background-color:#f4f4f4;border-radius:3px;height:200px;line-height:200px;}
일단 inputbox 및 textarea의 크기는 고정으로 사용합니다. 입력할 내용이나 프로젝트의 UI 표준에 맞게 화면의 크기에 반응하여 늘어나게 해도 되고, 현재처럼 고정으로 사용하기도 합니다. CSS 까지 적용하시면 아래 그림과 같은 화면이 완성됩니다.


3. JavaScript 작성
글쓰기 페이지는 아직 서버와 인터페이스하지 않는 부분까지만 개발할 예정이므로, 개발할 수 있는 부분이 많지 않습니다.
-. Validation
-. 서버 인터페이스
-. 목록 화면으로 Re-Direction
작업 중 이번 과정에서는 Validation 부분과 인터페이스를 할 수 있는 모듈까지만 작성해보도록 하겠습니다. 그럼 먼저 Validation 부분을 살펴보도록 하겠습니다. 일반적으로는 4개의 컬럼이 필수라면 아래의 코드와 같이 작성합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
if ($('#inputUserName').val() == '') {
    alert('작성자는 필수 입력입니다.');
    return;
}
 
if ($('#password').val() == '') {
    alert('비밀번호는 필수 입력입니다.');
    return;
}
 
if ($('#subject').val() == '') {
    alert('글제목은 필수 입력입니다.');
    return;
}
 
if ($('#content').val() == '') {
    alert('글내용은 필수 입력입니다.');
    return;
}
jQuery Selector로 필수로 입력해야 하는 값들을 체크하여 값이 없을 경우 alert을 return하는 내용입니다. 하지만 필수 입력값이 많다면 저런 방식의 코드는 비효율적일 수 있으니 간단하게 현재 사용하는 inputbox와 textarea 만을 고려하여 Validation 후 미입력된 필수값을 alert으로 알려주는 코드를 구현해 보겠습니다. 먼저 HTML 파일을 아래와 같이 수정합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div class="wrap">
    <div class="content_line">
        <span class="header">작성자</span>
        <span><input type="text" class="input mandatory" id="inputUserName" data="작성자"><span>
    </span></span></div>
    <div class="content_line">
        <span class="header">비밀번호</span>
        <span><input type="password" class="input mandatory" id="password" data="비밀번호"></span>
    </div>
    <div class="content_line">
        <span class="header">글제목</span>
        <span><input type="text" class="input mandatory" id="subject" data="글제목"></span>
    </div>
    <div class="content_line">
        <span class="header">글내용</span>
        <span><textarea id="content" class="text mandatory" data="글내용"></textarea></span>
    </div>
</div>
사용자가 필수로 입력해야 하는 값들에 mandatory 라는 class를 하나 추가했습니다. 그리고 data 속성을 추가하여 해당 입력값이 무엇을 의미하는지 표시하였습니다. 그럼 이어서 ./scripts/common.js 파일에 function을 하나 추가하도록 하겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
COMM.validate = function() {
    var items = $('.mandatory');
    var messages = '', isValid = true;
    for (var inx=0; inx<items.length; inx++) {
        if ($(items[inx]).val() == '') {
            isValid = false;
            messages += $(items[inx]).attr('data') + '은(는) 필수 입력값입니다.\n';
            break;
        }
    }
     
    return {valid: isValid, messages: messages};
};
위 코드의 의미는 간단합니다. mandatory라는 class를 가진 element들을 Loop 돌면서 값이 입력되지 않았으면 해당 element에 값을 출력하라는 메시지를 return하는 함수입니다. 간단하게 구성해봤지만 이런 식으로 매번 반복적으로 사용했던 코드들을 공통화하는 방법을 생각하는 것은 매우 중요합니다. 그럼 위 코드를 호출하여 유효성 검사를 하는 부분을 구현해 보겠습니다. ./scripts/bbs_write.js 파일을 하나 생성하여 아래와 같이 작성합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var WRITER = {};
 
var WRITER.write = function() {
    var validator = COMM.validate();
    if (!validator.valid) {
        alert(validator.messages);
        return;
    }
};
 
$(document).ready(function() {
    $('#btnWrite').on('click', function() {
        WRITER.write();
    });
});
이제 아무것도 입력하지 않은 상태에서 [저장하기] 버튼을 터치해보면 "작성자은(는) 필수 입력값입니다." 라는 경고 메시지가 출력됩니다. 물론 입력값을 모두 입력한 후에 [저장하기] 버튼을 터치해도 값이 입력되었을 경우에 대한 로직은 구현하지 않았으므로 아무 반응도 없습니다. 그럼 이제 서버와의 인터페이스를 위한 함수를 구현해 보겠습니다. 서버와의 인터페이스는 Form Submit 방식을 사용하지 않고 AJAX 방식으로 인터페이스하며, jQuery에서 제공하는 $.ajax 함수를 사용하여 인터페이스 하겠습니다. 일단 ./scripts/common.js 파일에 아래 코드와 같이 function을 추가합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
COMM.doPost = function(url, input, success, fail) {
    var option = {};
    option.url = url + '?__jsonParams=' + JSON.stringify(input);
    option.type = 'POST';
    option.headers = {'Content-Type': 'application/json'};
    option.success = function(data) {
        try {
            if (typeof data == 'string') data = JSON.parse(data);
            success(data);
        } catch (e) {
            if (fail && typeof fail == 'function') {
                fail(e);
            } else {
                alert(e.stack);
            }
        }
    };
    option.error = function(jqXHR, status, error) {
        if (fail && typeof fail == 'function') {
            fail(error);
        } else {
            alert(error);
        }
    };
    $.ajax(option);
};
$.ajax를 간단하게 한 번 wrapping 한 형태입니다. 공통 성공, 실패 및 설정 부분에 대한 부분만 코딩되어 있습니다. 실제 프로젝트에서는 해당 프로젝트에서 사용하는 인터페이스 전문 및 파일 전송 여부 등에 따라 좀 더 꾸며져 있는 형태로 코딩하셔서 사용하시면 됩니다. 데이터를 전달하는 방법은 각자 프로젝트 성격에 맞게 Payload로 전달하셔도 되고, 아니면 샘플에서처럼 쿼리스트링 파라미터로 전달하셔도 됩니다. Payload에 전달하고 싶을 경우 아래 코드와 같이 써주시면 됩니다.
1
option.data = input;
자, 이번 시간은 네트워크 공통 모듈을 만드는 여기까지만 진행하겠습니다. 나머지는 Local 환경에 서버를 구성한 후 실제 인터페이스를 해보며 진행하겠습니다.
아직 이래저래 바쁘다보니 올해 달력은 자세히 못봤습니다. 하지만 달력이 꽤 좋다는 얘기는 좀 들리네요. 다들 일 때문에 늘 바쁘시겠지만 쉴 때는 좀 쉬어가며 Working & Life Balance를 잘 유지하는 한 해 되시기 바랍니다. 오늘도 수고하셨어요!


300x250

+ Recent posts