2018년 6월 21일 목요일

[JavaScript 예제] 065 배열/객체의 내용을 순서대로 처리하기




 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
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>배열/객체의 내용을 순서대로 처리하기</title>
</head>
<body>
  <ul id="list"></ul>
  <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
  <script>
  $(function() {
    var animal = [
      { name: '프렌치불독',
        type: '강아지'},
      { name: '요크셔테리어',
        type: '강아지'},
      { name: '닥스훈트',
        type: '강아지'},
      { name: '스코티시폴드',
        type: '고양이'},
      { name: '포메라니안',
        type: '강아지'},
    ];

    $.each(
      animal,
      function(index, value) {
        // '고양이'가 발견되면 출력을 중지
        if(value.type == '고양이') { return false; }
        $('<li></li>')
          .append(value.name)
          .appendTo('#list');
      }
    );
  });
  </script>
</body>
</html>




2018년 6월 20일 수요일

[JavaScript 예제] 064 해시/객체들 병합하기


객체/해시(연관 배열)를 결합하려면 jQuery의 $.extend 메소드를 이용한다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>해시/객체들 병합하기</title>
</head>
<body>
  <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
  <script>
  var data1 = { id:10, name:'Ava' }
  var data2 = { age:40, married:true }
  var data3 = { blood:'A', name:'David' }

  $.extend(data1, data2, data3);
  console.log(data1);
  // 결과: {id: 10, name: "David", age: 40, married: true, blood: "A"}
  </script>
</body>
</html>

같은 이름 멤버가 존재하는 경우 나중의 것으로 덮어쓴다.

  • 위의 경우에서 data1의 내용을 변경하지 않을려면 다음과 같이 한다.
    • var merged = $.extend({}, data1, data2, data3);




[JavaScript 예제] 062 배열 가지고 놀기


배열의 요소를 추가/삭제


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>배열 가지고 놀기</title>
</head>
<body>
  <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
  <script>
  var data = ['팬더', '토끼', '코알라'];
  data.push('땅콩');
  data.unshift('강아지');

  console.log(data.toString()); // 결과: 강아지,팬더,토끼,코알라,땅콩
  console.log(data.pop());      // 결과: 땅콩
  console.log(data.toString()); // 결과: 강아지,팬더,토끼,코알라
  console.log(data.shift());    // 결과: 강아지
  console.log(data.toString()); // 결과: 팬더,토끼,코알라
  </script>
</body>
</html>


  • push() / pop() 메소드
    • 배열의 끝 요소를 넣고 뺀다
  • unshift() / shift() 메소드
    • 배열의 첫 요소를 넣고 뺀다


배열에 배열을 연결하기 ( concat() 메소드 )


배열 결합 ( 배열.join([구분문자]) )



배열 일부 빼내기 ( 배열.slice(시작위치 [,종료위치]) )



배열의 내용 치환하기 ( 배열.splice(시작위치, 요소수 [, 치환후의요소, ...] )


배열의 요소 정렬하기


  •   배열.sort(function(m, n) {
        ...정렬규칙...
      })










2018년 6월 12일 화요일

[JavaScript 예제] 055 정규 표현 사용



분류 패턴 매칭하는 문자열
기본 xyz 'xyz'라는 문자열
[xyz] x, y, z 중 1개의 문자
[^xyz] x, y, z 이외의 1개의 문자
[a-z] a~z 사이의 1개의 문자
x|y|z x, y, z 중 하나
양 지정 x* 0문자 이상의 x("to*"는 "t", "to", "too" 등에 일치)
x? 0또는 1문자의 x("to?"는 "t", "to"에 일치)
x+ 1문자 이상의 x("to+"는 "to", "too" 등에 일치)
x{n} x와 n회 일치("[0-9]{4}"는 4자리 숫자)
x{n,} x와 n회 이상 일치("[0-9]{4,}"는 4자리 이상의 숫자)
x{m,n} x와 m~n회의 일치("[0-9]{2,4}"는 2~4자리 숫자)
위치 지정 ^ 앞부분이 일치
$ 끝부분이 일치
문자 세트 . 임의의 1문자에 일치
\w 대문자/소문자의 영문자, 숫자, 언더스코어(_)에 일치
("[A-Za-z0-9_]"와 동일)
\W 문자 이외에 일치("[^\w]"와 동일)
\d 숫자에 일치("[0-9]"와 동일)
\D 숫자 이외에 일치("[^0-9]"와 동일
\n 개행(라인 피드)에 일치
\r 복귀(캐리지 리턴)에 일치
\f 폼피드에 일치
\t 탭 문자에 일치
\v 수직 탭에 일치
\s 공백 문자에 일치("[\n\r\t\v\f]"와 동일)
\S 공배 이외의 문자에 일치("[^\s]"와 동일)
\~ '~'에서 나타내는 문자


JavaScript에서 이들의 정규 표현식 패턴을 해석하고 검색 등 기능을 제공하는 것은 RegExp 객체의 역할이다.


  • RegExp 생성자
    • var 변수 = new RegExp(정규표현, 옵션)
  • 정규 표현 리터럴
    • var 변수 = /정규 표현/옵션



  • 정규 표현식 옵션
    • g
      • 문자열 전체에 매치하는가
    • i
      • 대문자/소문자의 구분을 무시하는가
    • m
      • 개행 코드를 행 첫머리/행의 끝으로 인식하는가(여러행일 경우)



 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
40
41
42
43
44
45
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>정규 표현</title>
</head>
<body>
  <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
  <script>
  // test 메소드
  var ex = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/gi;
  var str1 = '샘플 파일은 http://www.Infopub.co.kr/에서 다운로드 할 수 있음';
  var str2 = '질문은 "게시판"으로 부탁드림';
  console.log(ex.test(str1)); // 결과 : true
  console.log(ex.test(str2)); // 결과 : false

  // search 메소드
  console.log(str1.search(ex)); // 결과 : 7
  console.log(str2.search(ex)); // 결과 : -1

  // match
  var str = str1;
  str += '질문은 HTTP://www.infopub.co.kr/로 부탁함';

  var result = str.match(ex);
  for(var i=0, len = result.length; i<len; i++) {
    console.log(result[i]);
  }
  // 결과
  // http://www.Infopub.co.kr/
  // HTTP://www.infopub.co.kr/

  // 정규 표현으로 문자열 치환
  var ex1 = /(http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?)/gi;
  console.log(str1.replace(ex1, '<a href="$1">$1</a>'));
  // 결과 : 샘플 파일은 <a href="http://www.Infopub.co.kr/">http://www.Infopub.co.kr/</a>에서 다운로드 할 수 있음

  // 정규 표현으로 문자열 문할
  var ex2 = /[\s\n\t]/gi;
  console.log('JavaScript Project'.split(ex2));     // 결과 : (2) ["JavaScript", "Project"]
  console.log('JS\n커뮤니티'.split(ex2));           // 결과 : (2) ["JS", "커뮤니티"]
  console.log('JS      Power프로젝트'.split(ex2));  // 결과 : (7) ["JS", "", "", "", "", "", "Power프로젝트"]
  </script>
</body>
</html>





2018년 6월 11일 월요일

[JavaScript 예제] 045 반올림 & n진수 구하기




 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
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>반올림</title>
</head>
<body>
  <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
  <script>
  // 소수점 이하 수치 반올림하기
  console.log(Math.ceil(4.56));   // 결과 : 5
  console.log(Math.ceil(-4.56));  // 결과 : -4
  console.log(Math.floor(4.56));  // 결과 : 4
  console.log(Math.floor(-4.56)); // 결과 : -5
  console.log(Math.round(4.56));  // 결과 : 5
  console.log(Math.round(-4.56)); // 결과 : -5

  // 임의의 자릿수에서 소수점을 반올림하기
  var num = 123.456;
  console.log(num.toFixed(2));    // 결과 : 123.46
  console.log(num.toFixed(5));    // 결과 : 123.45600
  console.log(num.toPrecision(5));  // 결과 : 123.46
  console.log(num.toPrecision(8));  // 결과 : 123.45600

  // n진수 구하기
  num = 255;
  console.log(num.toString(2));   // 결과 : 11111111
  console.log(num.toString(16));  // 결과 : ff
  console.log(num.toString(36));  // 결과 : 73
  </script>
</body>
</html>


  • 난수 구하기
    • console.log(Math.floor((Math.random() * 100) + 1));




2018년 5월 29일 화요일

[JavaScript 예제] 044 계층을 가진 네임스페이스 정의하기




 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
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>계층을 가진 네임스페이스 정의하기</title>
</head>
<body>
  <script>
  var namespace = function(ns) {
    // 네임스페이스를 '.'로 분할
    var elems = ns.split('.');
    var parent = window;

    // 이후 네임스페이스를 차례로 계층화하면서 등록
    for(var i=0, len=elems.length; i<len; i++) {
      parent[elems[i]] = parent[elems[i]] || {};
      parent = parent[elems[i]];
    }

    return parent;
  };

  // Myapp.Recipe.Samples 네임스페이스를 등록
  var ns = namespace('Myapp.Recipe.Samples');
  // 네임스페이스 예하에 클래스를 정의
  ns.MyClass = function() {};
  var c = new ns.MyClass();
  console.log(c instanceof Myapp.Recipe.Samples.MyClass); // true
  </script>
</body>
</html>



[JavaScript 예제] 043 클래스 이름 충돌 피하기




 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>클래스 이름 충돌 피하기</title>
</head>
<body>
  <script>
  var Info = Info || {};  // Info가 비어 있는 경우에만 새로운 이름 공간을 작성

  Info.Person = function(name, birth) {
    this.name = name;
    this.birth = birth;
  };

  Info.Person.prototype.toString = function() {
    return this.name + ' _ _ ' + this.birth;
  }

  var p = new Info.Person('이정우', new Date(1981, 5, 16));
  console.log(p.toString());
  </script>
</body>
</html>


[JavaScript 예제] 042 객체형 판정하기




 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>객체형 판정하기</title>
</head>
<body>
  <script>
  var Person = function() {};               // 함수 선언
  var BusinessPerson = function() {};       // 함수 선언
  BusinessPerson.prototype = new Person();  // Person을 상속
  var bp = new BusinessPerson();            // BusinessPerson 객체 생성

  console.log(bp instanceof BusinessPerson);  // 결과 true
  console.log(bp instanceof Person);          // 결과 true
  console.log(bp instanceof Object);          // 결과 true
  </script>
</body>
</html>



2018년 5월 28일 월요일

[JavaScript 예제] 040 클래스 상속하기




 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
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>클래스 상속하기</title>
</head>
<body>
  <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
  <script>
  // 부모 클래스 Person
  var Person = function() {};
  Person.prototype = {
    eat : function() {console.log('우물우물');}
  };

  // Person 클래스를 상속한 BusinessPerson 클래스
  var BusinessPerson = function() {};
  BusinessPerson.prototype = new Person();

  BusinessPerson.prototype.work = function() { console.log('먹보');}

  var bp = new BusinessPerson();
  bp.eat();
  bp.work();
  </script>
</body>
</html>




[JavaScript 예제] 037 클래스 정의하기

JavaScript에서 클래스르르 정의하려면 함수를 이용한다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>클래스 정의하기</title>
</head>
<body>
  <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
  <script>
  var Animal = function(name) {
    this.name = name;
    this.toString = function() {
      return 'Animal:' + this.name;
    };
  };

  var ani = new Animal('바루');
  console.log(ani.name);
  console.log(ani.toString());  
  </script>
</body>
</html>


프로토타입 기반 객체 지향

  • JavaScript는 객체 지향 언어이지만 그 구문은 프로토타입이라는 개념을 바탕으로 하고, 그 특수성을 말할 때 대표적인 특징으로 예를 든다.
    • 일반적인 클래스 기반 객체 지향에 대하여 프로토타입 기반의 객체 지향이라고 한다
  • 무엇보다 프로토타입 자체는 조금도 특수한 것이 아니라 '제약이 느슨한 클래스' 같은 것으로 인식하면 된다.


주의

  • 이름은 대문자로 시작한다.
  • 프로퍼티는 'this.프로퍼티 이름' 으로 정의한다.
  • 메소드는 함수형 프로퍼티이다.
  • 반환값은 필요 없다.
    • 생성자에서 자동으로 this가 가리키는 객체를 돌려주기 때문에 반환값은 필요 없다.
    • 명시적으로 반환값을 돌려준 경우 그 값이 new 연산자의 값이 된다.
      • 이 경우 this에 대한 프로퍼티 설정 등은 무시되므로 주의


new 연산 없이 호출 경우

1
2
3
4
5
6
var Animal = function(name) {
  if(!(this instanceof Animal)) {
    return new Animal(name);
  }
  // 코드 구성
}


클래스에 메소드 추가하기

생성자함수.prototype.메소드명 = function(...) {...}

정적 멤버 추가하기

생성자함수.프로퍼티명 = 값
생성자함수.메소드명 = function(...) {...}




[JavaScript 예제] 033 함수를 인수로서 전달하기




 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
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>함수를 인수로서 전달하기</title>
</head>
<body>
  <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
  <script>
  function benchmark(proc) {
    var start = new Date();
    proc();
    var end = new Date();
    return end.getTime() - start.getTime();
  }

  console.log(
    benchmark(function() {
      var x = 15;
      for(var i=0; i<10000000; i++) {
        x *= i;
      }
    })
  );
  </script>
</body>
</html>



[JavaScript 예제] 028 함수 정의하기


함수 정의하기

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// function 명령
function getSquareArea(width, height) {
  return width * height;
}

// Function 생성자
var getSquareArea = new Function(
  'width', 'height', 'return width * height;');

// 함수 리터럴
var getSquareArea = 
  function(width, height) { return width * height; };

console.log(getSquareArea(2, 3));
Function 생성자는 사용을 하지 않기를....


인수의 기본값 설정하기

1
2
3
4
5
6
7
8
9
function getSquareArea(o_width, o_height) {
  if( o_width === undefined ) { o_width = 1; }
  if( o_height=== undefined ) { o_height= 1; }
  return o_width * o_height;
}

colsole.log(getSquareArea(10, 5));
colsole.log(getSquareArea(10));
colsole.log(getSquareArea());



필수 인수 확인하기

1
2
3
if(width === undefined) {
  throw { name: 'ArgsMissing', message: '폭이 지정되지 않았습니다.' };
}



값만 전달하는 인수와 명명된 인수

1
showPanel('content.html', 200, 300, true, true, false);

1
2
3
4
5
6
7
8
showPanel({
  Path: 'content.html',  // 패널로 표시하는 내용
  height: 200,           // 높이
  width: 300,            // 폭
  resizable: true,       // 리사이즈 가능여부
  draggable: true,       // 드래그 가능여부
  modeless: false        // 모달리스 패널여부
});


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
function showPanel(args) {
  if(args.path === undefined) {
    throw { name: 'ArgsMissing', message: 'path는 필수임.' };
  }
  if(args.height === undefined) { args.height = 200; }
  if(args.width === undefined) { args.width = 300; }
  if(args.resizable === undefined) { args.resizable = true; }
  if(args.draggable === undefined) { args.draggable = true; }
  if(args.modeless === undefined) { args.modeless = false; }
  // ..... 구현부분
}


가변 길이 인수를 갖는 함수정의
- 기본예
1
2
3
4
5
6
7
8
9
function max(v_args) {
  var result = Number.NEGATIVE_INFINITY;
  for(var i=0, len=arguments.length; i<len; i++) {
    if(result < arguments[i]) {
      result = arguments[i];
    }
  }
  return result;
}

- 고정인수와 가변 인수가 함께 있는 예

1
2
3
4
5
6
7
8
9
function sprintf(format) {
  for(var i=1, len=arguments.length; i<len; i++) {
    var pattern = new RegExp('\\{' + (i-1) + '\\}', 'g');
    format = format.replace(pattern, arguments[i]);
  }
  return format;
}

console.log(sprintf('{0}를 키우는데 이름은 {1}입니다.', '햄스터', '롤리'));


2018년 5월 22일 화요일

[JavaScript 예제] 012 JavaScript 문법

배열
은 리터럴 표현으로 선언
var data2 = [ 'JavaScript', 'CoffeeScript', 'TypeScript' ];
data2[1]과 같이 사용


연관 배열
은 해시라고도 함, {}를 사용하여 생성
var obj1 = { a:100, b:500, c:800 };
obj1['a']와 같이 사용


데이터형 변환
parseInt()
parseFloat()
Number()


문자열형, 논리형으로 변환
typeof String(123); // String Type으로 변환 후 typeof에 의하여 string 결과
typeof Boolean(-1); // Boolean Type으로 변환 후 typeof에 의하여 Boolean 결과

console.log(typeof String(123)); // -> 결과 string
console.log(typeof new String(123)); // -> 결과 object

보다 쉽게 데이터형 변환
15 + ''; // -> string 형으로 변환
'15' - 0; // number 형으로 변환
!!value; // boolean형으로 변환

변수의 데이터형 판정
jQuery의 $.isXxxxx 메소드를 이용
메소드 개요 예와 결과
isArray  배열 여부 $.isArray(['one', 'two']) <- true
isEmptyObject  비어 있음 여부 $.isEmptyObject({a: 'hi'}) <- false
isFunction  함수 여부 $.isFunction(123) <- false
isNumeric  수치 여부 $.isNumeric(123) <- true
isPlainObject  Object 객체 여부 $.isPlainObject({a: 'hi'}) <- true
isWindow  Window 객체 여부 $.isWindow(window) <- true
isXMLDoc  XML 문서 여부 $.isXMLDoc($.parseXML('<name>infopub</name>'))
<- true

지정된 변수의 형을 문자열로 봔환하는 $.type 메소드도 있다.





[JavaScript 예제] 008 문자열 표시하기




 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
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>문자열 표시하기</title>
</head>
<body>
  <div id="result"></div>
  <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
  <script>
  var str1 = '안녕, 문자열1';
  var str2 = "안녕, 문자열2";

  // 대화상자를 표시
  window.alert(str1);

  // 콘솔에 표시
  console.log(str2);

  // 페이지(id="result")에 있는 요소에 직접 표시
  $('#result').text(str2);

  // 페이지 상에 출력
  document.write(str1);
  </script>
</body>
</html>


주요 이스케이프 시퀀스
이스케이프 시퀀스 설명
\b  백스페이스
\t  탭
\n  개행
\f  페이지 열기
\r  복귀
\'  작은 따옴표
\"  큰 따옴표
\\  \문자
\xXX  XX(2자리 16진수)로 나타내는 Latin-1 문자
\uXXXX  XXXX(4자리 16진수)로 나타내는 Unicode 문자



[JavaScript 예제] 006 JavaScript 코드 압축하기

온라인에서 이용할 수 있는 압축 도구
http://javascriptcompressor.com/



오프라인에서 이용할 수 있는 압축도구
https://archive.codeplex.com/?p=aspnet

[JavaScript 예제] 005 JavaScript의 위험한 구문 제거하기

Strict 모드를 이용한다.

Strict 모드는 '구문으로 존재하지만, 안전성/효율성의 관점에서 이용해서는 안 되는 것'을 검출하여 에러를 발생시키는 모드이다.

Strict 모드의 주요 제한
분류 제한 내용
변수 var 명령은 생략할 수 없다.
매개변수/속성 이름의 중복 금지
undefined, NaN으로 대입 금지
명령 with 명령은 이용할 수 없다
arguments, callee 속성에 접근할 수 없다
eval 명령으로 선언된 변수를 주위의 범위에 확산하지 않는다
기타 함수 아래 this는 Global 객체를 나타내지 않는다(undefined이 된다)
'0~'(8진수 표기)는 불가

함수에서 strict 모드 사용 방법

1
2
3
4
function sample() {
  'use strict';
  // 함수의 본체
}

Strict 모드의 대응 브라우저
브라우저 대응 버전
Internet Explorer 10~
Chrome 13~
Firefox 4~
Safari 6~
Opera 11.6~





[JavaScript 예제] 001 HTML 페이지에 JavaScript 코드 사용하기



  • <script> 요소를 이용하기
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>HTML 페이지에 JavaScript 코드 사용하기</title>
</head>
<body>
<script type="text/javascript">
console.log('Wooguy javascript 입니다.');  // 로그 출력 확인은 F12키
</script>
</body>
</html>



  • 외부 스크립트를 임포트하기


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>HTML 페이지에 JavaScript 코드 사용하기</title>
</head>
<body>
<p>Smart Link 프로젝트에서는 현재<span id="mem">멤버 모집 중</span>입니다.</p>
<!--외부 스크립트-->
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<!--인라인 스크립트-->
<script type="text/javascript">
$(function() {
  $('#mem').css('background-color', '#ff6');
});
</script>
</body>
</html>


  • 문자 코드는 UTF-8을 권장



[PHP예제] 237 JSON 형식의 데이터를 반환하는 Web API 만들기




 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
if( !isset($_SERVER['HTTP_X_REQUESTED_WITH']) ||
    $_SERVER['HTTP_X_REQUESTED_WITH'] !== 'XMLHttpRequest' )
{
  die(json_encode(array('status' => "잘못된 호출입니다.")));
}

// 데이터를 준비
$value = array(
  1 => array('item' => '라면', 'price' => 580, 'orders' => 113),
  2 => array('item' => '라면(아메리칸)', 'price' => 580, 'orders' => 72),
  3 => array('item' => '볶음밥', 'price' => 630, 'orders' => 87),
);

header("Content-Type: application/json; charset=UTF-8");
// IE가 Content-Type 헤더를 무시하지 않게 함
header('X-Content-Type-Optoins: nosniff');

echo json_encode(
  $value,
  JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
);



[PHP예제] 235 다른 페이지로 건너뜀




1
2
3
4
<?php
header('HTTP/1.1 303 See Other');
header('Location: http://www.woorits.com/');
exit();

http://www.woorits.com 사이트로 강제 이동

[PHP예제] 231 강제로 파일 다운로드



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
$fileName = 'test.jpg';
$fileSize = filesize($fileName);
$mime = 'image/jpeg';
//$mime = 'application/octet-stream'; // MIME 타입이 불분명한 경우

header('Content-Type: ' . $mime);
// IE가 Content-Type 헤더를 무시하지 않게 함
header('X-Content-Type-Optoins: nosniff');
header('Content-Disposition: attachment; filename="' . $fileName . '"');
header('Content-Transfer-Encoding: binary');
header('Cache-Control: no-store, no-cache, must-revalidate');

if( isset($_SERVER['HTTP_USER_AGENT']) &&
    strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE') )
{
  header('Cache-Control: post-check=0, pre-check=0', false);
  header('pragma: public');
}
header('Content-Length: ' . $fileSize);

readfile($fileName);

test.jpg 파일이 다운로드 됨

[PHP예제] 230 여러장의 이미지 업로드하기




  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
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>여러장의 이미지 업로드하기</title>
</head>
<body>
<div>
<?php
require_once './h.php';

$dir = './upload';
const MAX_SIZE = 102400;

// 'php.ini'의 post_max_size를 넘은 데이터가 전송되었는지 확인함
if( !checkPostMaxSize() )
{
  echo "파일 크기는 100KB 이하로 하시오.<br><br>";
}

// 파일이 업로드 되었는지 확인
if( isset($_FILES['uploadfile']) )
{
  // 반복 처리
  for( $i = 0; $i < count($_FILES['uploadfile']['name']); $i++ )
  {
    // 업로드 파일을 확인함
    list($result, $ext, $error_msg) = checkFile($i);
    if( $result )
    {
      $name = $_FILES['uploadfile']['name'][$i];
      $tmp_name = $_FILES['uploadfile']['tmp_name'][$i];

      // 여기에서는 저장할 디렉터리의 아래쪽에 '"upfile_" + 현재의 타임스탬프
      // + 일련번호 + "_"
      // + 마이크로초와 전체 파일명, 연결 전 IP 주소에 근거하는 MD5
      // + 확장자'로 배치함
      $move_to = $dir . '/upfile_' . time() . $i . '_'
                  . md5(microtime() . $name . $_SERVER['REMOTE_ADDR'])
                  . '.' . $ext;

      // 업로드한 임시 파일을 지정한 장소로 이동함
      if( move_uploaded_file($tmp_name, $move_to) )
      {
        // 이미지 파일을 표시함
        echo h($move_to) . '<br>';
        echo '<img src="' . h($move_to) . '" alt="업로드된 이미지"><br>';
      }
      else
      {
        $error_msg[] = '이미지의 업로드 실패';
      }
    }

    // 오류 메시지가 있으면 표시
    if( count($error_msg) > 0 )
    {
      foreach( $error_msg as $msg )
      {
        echo h($msg) . "<br>";
      }
    }
  }
}

function checkFile($i)  // 업로드 파일을 확인하는 함수
{
  $error_msg = array();
  $ext = '';

  $size = $_FILES['uploadfile']['size'][$i];
  $error = $_FILES['uploadfile']['error'][$i];
  $img_type = $_FILES['uploadfile']['type'][$i];
  $tmp_name = $_FILES['uploadfile']['tmp_name'][$i];

  if( $error != UPLOAD_ERR_OK ) // 업로드 오류의 경우
  {
    if( $error == UPLOAD_ERR_NO_FILE )
    {
      // 업로드되지 않은 경우는 오류 처리를 하지 않음
    }
    elseif( $error == UPLOAD_ERR_INI_SIZE
          || $error == UPLOAD_ERR_FORM_SIZE )
    {
      // 파일 크기 오류
      $error_msg[] = '파일 크기는 100KB 이하로 하시오.';
    }
    else
    {
      $error_msg[] = '업로드 오류임';
    }

    return array(false, $ext, $error_msg);
  }
  else
  {
    // 전송된 MIME 타입으로부터 확장자를 결정함
    if( $img_type == 'image/gif' )
    {
      $ext = 'gif';
    }
    elseif( $img_type == 'image/jpeg' || $img_type == 'image/pjpeg' )
    {
      $ext = 'jpg';
    }
    elseif( $img_type == 'image/png' || $img_type == 'image/x-png' )
    {
      $ext = 'png';
    }

    // 이미지 파일의 MIME 타입을 판별
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $finfoType = $finfo->file($tmp_name);

    // 이미지 파일의 크기의 하한을 확인함
    if( $size == 0 )
    {
      $error_msg[] = '파일이 존재하지 않거나 빈 파일임';
    }
    elseif( $size > MAX_SIZE )
    {
      $error_msg[] = '파일 크기는 100KB 이하로 하시오.';
    }
    elseif( $img_type != $finfoType )
    {
      $error_msg[] = 'MIME 타입이 일치하지 않음';
    }
    elseif( $ext != 'gif' && $ext != 'jpg' && $ext != 'png' )
    {
      $error_msg[] = '업로드 가능 파일은 gif, jpg, png 임';
    }
    else
    {
      return array(true, $ext, $error_msg);
    }
  }

  return array(false, $ext, $error_msg);
}

// 'php.ini'의 post_max_size를 넘은 데이터가 전송되었는지를 확인하는 함수
function checkPostMaxSize()
{
  $max_size = ini_get('post_max_size');

  // post_max_size가 8MB와 같이 설정된 경우에 정수로 함
  $multiple = 1;
  $unit = substr($max_size, -1);
  if( $unit == 'M' )
  {
    $multiple = 1024 * 1024;
  }
  elseif( $unit == 'K' )
  {
    $multiple = 1024;
  }
  elseif( $unit == 'G' )
  {
    $multiple = 1024 * 1024 * 1024;
  }
  $max_size = substr($max_size, 0, strlen($max_size) - 1) * $multiple;

  // post_max_size를 넘어선 데이터가 게시되었는지 확인
  if( $_SERVER['REQUEST_METHOD'] == 'POST' &&
      $_SERVER['CONTENT_LENGTH'] > $max_size )
  {
    return false;
  }
  else
  {
    return true;
  }
}
?>
  <hr>
  <p>업로드하고 싶은 이미지 파일(gif, jpg, png)을 지정하시오</p>
  <form method="post" action="230.php" enctype="multipart/form-data">
    <input type="hidden" name="MAX_FILE_SIZE" value="<?php echo h(MAX_SIZE); ?>">
    <input type="file" name="uploadfile[]"><br>
    <input type="file" name="uploadfile[]"><br>
    <input type="file" name="uploadfile[]"><br>
    <input type="submit" value="전송"><br>
    이미지 사이즈는 1개의 이미지에 대해 100KB 이하
  </form>
</div>
</body>
</html>




[PHP예제] 223 세션 사용하기


PHP에서 세션은 세션ID와 세션 변수의 조합으로 실현됨

  • 세션을 사용하기
    • session_start()
    • 세션 데이터를 초기화해 세션을 시작
    • 이미 세션이 시작된 경우에는 기존의 세션을 다시 시작
    • 클라이언트쪽에서는 웹브라우저의 쿠키에 세션ID가 저장됨
    • 서버쪽에는 'php.ini'의 session.save_path에서 지정한 디렉터리에 세션 변수를 저장할 파일이 생성됨
  • 브라우저에 출력하기 전에 session_start() 함수를 기술해야 함

  • 세션명을 구하고 설정하기
    • session_name()
    • 영어와 숫자만으로 구성되어야 함
    • 세션명을 'INFOPUB'에 설정함
      • $oldSessionName = session_name('INFOPUB');
  • session_name() 함수에 의한 세션명을 변경하려면 session_start() 함수보다 앞에 기술해야 함


  • 세션 ID를 구하기
    • session_id()
    • 인수를 지정하지 않으면 현재의 세션 ID를 되돌려줌
    • 기본 설정에서 세션 데이터는 'sess_'+'세션ID'라는 이름의 파일에 저장됨
    • 현재 세션이 없으면 공백문자('')를 되돌림
    • 같은 세션 ID를 계속 사용하는 것은 보안상 바람직하지 않으므로
      • session_regenerate_id() 함수로 세션 ID를 변경


  • 세션 변수를 사용하기
    • $_SESSION['세션변수명']
    • 세션 변수를 사용하려면 먼저 session_start() 함수로 세션을 시작해야 함



  • 세션 변수를 파기하기
    • unset()
      • unset($_SESSION['세션변수명']);
    • 모든 세션 변수를 파기(초기화)하려면 다음과 같이 해야 함
      • $_SESSION = array();


  • 세션 쿠키의 파라미터를 설정하기
    • session_set_cookie_params()


  • 세션을 파기하기
    • session_destroy()






[PHP예제] 222 쿠키 사용하기


222_w.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<?php
// 쿠키에 대입할 데이터를 설정
$cookie_data = 'data1=PHP 프로그래밍&data2=인기 발매 중';
// 쿠키에 쿠키명 'php_sample'로 저장
setcookie('php_sample', $cookie_data);
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>Cookie에 데이터 쓰기</title>
</head>
<body>
<div>
<p>Cookie를 저장함</p>
</div>
</body>
</html>




222_r.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>Cookie에서 데이터 읽기</title>
</head>
<body>
<div>
<?php
require_once './h.php';

echo "<p>Cookie의 내용: ";
echo h($_COOKIE['php_sample']);
echo "<p>parse_str() 함수로 분리한 쿠키의 내용:";
parse_str($_COOKIE['php_sample'], $output);
echo "data1: " . h($output['data1']) . "<br>";
echo "data2: " . h($output['data2']) . "<br>";
?>
</div>
</body>
</html>



[PHP예제] 156 spl_autoload_register() 함수에 의한 오토로드


FileInfo.php

 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
40
<?php
class FileInfo
{
  private $retCode;  // 줄 바꿈 코드 보존용

  // 파일을 읽고 조사하는 메소드
  public function readFile($file)
  {
    $this->retCode['CRLF'] = 0;  // 줄 바꿈 코드가 CRLF인 행 수
    $this->retCode['LF']   = 0;  // 줄 바꿈 코드가 LF인 행 수

    $fp = fopen($file, 'r');
    if (! is_resource($fp)) {
      die('파일을 열지 않음');
    }

    while (($line = fgets($fp)) !== false) {
      if (preg_match('/\r\n\z/', $line)) {
        $this->retCode['CRLF']++;
      } else {
        $this->retCode['LF']++;
      }
    }
    fclose($fp);
  }

  // 줄 바꿈 코드를 되돌려주는 메소드
  public function getRetCode()
  {
    if ($this->retCode['CRLF'] == 0 && $this->retCode['LF'] == 0) {
      return '';           // 줄 바꿈이 없는 경우
    } elseif ($this->retCode['CRLF'] == 0) {
      return 'LF';         // 모두 LF의 경우
    } elseif ($this->retCode['LF'] == 0) {
      return 'CRLF';       // 모두 CRLF의 경우
    } else {
      return 'CRLF & LF';  // CRLF와 LF가 함께 있는 경우
    }
  }
}


Counter.class.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?php
// Counter 클래스를 정의합니다.
class Counter
{
// 정적 프로퍼티 $count를 선언합니다.
  public static $count = 0;

// 정적 메서드 increment()를 선언합니다.
  public static function increment()
  {
    static::$count++;
  }
  
// 정적 메서드 current()를 선언합니다.
  public static function current()
  {
    return static::$count;
  }
}
/* ?>종료 태그 생략 [레시피 001]*/


autoload.php

 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
<?php
// 익명 함수를 사용하여 오토로드 함수를 등록함
spl_autoload_register(
  function ($classname)
  {
    // __DIR__은 이 소스 파일이 있는 디렉터리가 정의되는 매직 상수
    // 인수로서 전달된 클래스명을 바탕으로 '클래스명.class.php'를 찾음
    $filepath = __DIR__ . '/' . $classname . '.class.php';

    // 파일의 존재 확인을 진행
    if( is_readable($filepath) )
    {
      // 인수로 전달된 클래스명을 바탕으로 대응하는 파일을 읽음
      require $filepath;
    }
  }
);

spl_autoload_register(
  function ($classname)
  {
    // __DIR__은 이 소스 파일이 있는 디렉터리가 정의되는 매직 상수
    // 인수로서 전달된 클래스명을 바탕으로 '클래스명.class.php'를 찾음
    $filepath = __DIR__ . '/' . $classname . '.php';

    // 파일의 존재 확인을 진행
    if( is_readable($filepath) )
    {
      // 인수로 전달된 클래스명을 바탕으로 대응하는 파일을 읽음
      require $filepath;
    }
  }
);

156.php

 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
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>spl_autoload_register() 함수에 의한 오토로드</title>
    <link href="style.css" rel="stylesheet">
</head>
<body>
<div>
<?php
// 오토로드의 설정을 읽음
require './autoload.php';

echo "FileInfo 클래스를 인스턴스화 함: ";
$obj = new FileInfo();
$obj->readFile(__FILE__);
echo "<br>getRetCode() 메소드를 호출함: ";
echo $obj->getRetCode();
echo "<br>";
echo "Counter::current()를 호출함";
echo Counter::current();
?>
</div>
</body>
</html>