반응형

서버 이용의 기본은 "form(양식)"이다. 폼에서 정보를 보내고 그것을 받아 처리하는 기본 중의 기본부터 설명한다.


양식(form) 송신

서버 측 프로그램을 작성한다는 것은 "클라이언트와 서버간에 교환하기" 위한 것이다라고 해도 좋을 것이다. 여기서 클라이언트란 서버에 액세스하는 프로그램이다. 즉, Web 브라우저을 말한다. 브라우저와 서버간에 다양한 정보를 주고 받으면서 프로그램이 동작하는 것을 만드는데, 서버 측 프로그램은 필요한 것이다. 브라우저 안에서만 동작하는 경우에는 JavaScript만으로 충분하다. 서버 사이드 프로그램은 불필요하다.

그런데, 클라이언트와 서버 사이에 교환할 경우, 가장 일반적으로 사용되는 것이 "양식(form)"이다. 모두에게 익숙한 HTML에서 입력 필드와 버튼 등을 표시하여 전송하는 것이다. 양식을 준비하고 이를 서버에 전송하고 전송된 값을 서버 프로그램에서 처리해서 다시 클라이언트로 결과를 반환한다. 이렇게 Web 응용 프로그램은 동작한다.

그럼 PHP를 사용하여 양식에서 보내온 데이터를 처리해 보자. 아래와 같이 간단한 예제를 작성해 보겠다.

<?php
    $str = $_POST['text1'];
    if ($str != null){
        $result = "당신은 '{$str}'이라고 썼습니다.";
    } else {
        $result = "아무것도 쓴 것이 없습니다.";
    }
?>
<!DOCTYPE html>
<html lang="ko">
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
        <title>sample page</title>
    </head>
    <body>
        <h1>Hello PHP!</h1>
        <div><?php echo $result; ?></div>
        <form method="post" action="./index.php">
            <input type="text" name="text1">
            <input type="submit">
        </form>
    </body>
</html>

이를 Web 브라우저에서 액세스 해보자.

여기에서는 다음과 같은 형태로 양식을 준비하고 있다.

<form> 태그

method는 "post", action은 "./index.php"이다. method라는 것은 전송의 방식을 보여준다. 이는 HTTP라는 프로토콜의 "GET" 또는 "POST"중 하나를 지정한다. GET이라는 것은 보통 페이지의 내용을 받기 위한 것이고, POST가 데이터를 쓰기 위한 것이다. 어떤 것으로도 보낼 수 있지만, 여기에서는 POST를 지정한다.

또한 action이라는 양식의 송신처를 지정한다. 여기에서는 이 index.php 파일 자체 전송한다. 즉, 양식을 송신하면 서버에서 다른 이 파일을 읽고, 거기서 보내온 양식을 처리한다는 것이다.

<input type="text"> 태그

텍스트 입력하는 태그이다. 여기에서 name="text1"로 지정하고 있다. 이는 중요하다. 양식을 서버로 전송했을 때, 전송된 데이터는 이 name으로 식별되기 때문이다.

<input type = "submit"> 태그

전송 버튼이다. 이는 특히 name과 id 등의 설정은 필요 없다. 전송 외에는 서버 측에 영향이 미치는 것이 없기 때문이다.

송신 양식과 $_GET, $_POST

그럼 전송된 폼의 내용은 어디서 어떻게 받고 있는가? 받은 부분은 파일이 시작하는 부분의 <?php ?> 태그 내에 있다. 여기에서 다음과 같은 처리를 하고 있다.

$str = $_POST['text1'];

이 $_POST라는 것은 보낸 양식의 내용을 저장하는 배열이다. 배열, 기억하고 있는가? 많은 값을 한꺼번에 관리할 수 있는 특별한 변수이다. 배열은 인덱스에 관리되고, 연관 배열은 key라는 값으로 관리된다. 결국은 $_POST는 "연관 배열"이라는 것이다.

이번에는 POST으로 보냈기 때문에 이 $_POST에 내용이 정리되었지만, 만약 GET으로 전송한 경우에는 $_GET 배열에 정리된다. 이 2가지 연관 배열이 양식의 내용을 관리하기 위한 것이다.

이 배열에는 폼의 내용이 name으로 지정된 이름으로 정리되고 있다. 여기에서 name="text1"이라는 속성의 태그가 준비되어 있기에 $_POST[ 'text1']와 같은 형태로 값이 저장되어 있는 것이다.

주의할 점은 이 $_GET$_POST와 같이 PHP의 시스템에서 제공하는 배열은 "값을 꺼낼 수 밖에 없다"는 점이다. 예를 들어, 이 값을 다시 작성해서 양식에 표시되는 값을 설정하려고 어떻게 생각을 하더라도 그건 무리이다. 이것은 단지 "전송된 데이터를 전달할 뿐"인 거라고 생각해야 한다.

텍스트를 써넣는 것에 대해(Variable interpolation)

여기에서는 사실 또 하나의 태크닉을 사용하고 있다. 시작 부분의 스크립트에서 $result에 텍스트를 설정하는 부분을 보도록 하자.

$result = "당신은 '{$str}'이라고 썼습니다.";

이런 식으로 적혀 있다. 이 {$str}라는 것은 변수 $str 값을 텍스트에 넣고 있는 것이다. 즉, 이 부분에 $str 내용이 덧붙여지지 텍스트가 만들어 진다.

큰 따옴표(")로 묶인 텍스트는 이처럼 변수를 넣을 수 있다. 즉, 이렇게 하면 다양한 변수 등을 사용하여 텍스트를 생성할 있다는 것이다.

그럼 반대로 $str이라는 텍스트를 출력시키고 싶은 경우에는 작은 따옴표(')를 사용하여 텍스트를 만든다. 작은 따옴표의 텍스트에는 써 넣을 수 없다. 모두 쓴대로 텍스트를 얻을 수 있다.

echo 'Variables do not $str';

예를 들면, 위와 같이 하면 화면에 "Variables do not $str"이 그대로 화면에 표시된다.

이 텍스트의 2가지의 작성법에 대한 차이는 확실히 기억해 두자.


보안 대책의 첫 걸음(XSS 방어)

식을 송신해서 서버에 처리한다는 것은 "서버 측 프로그래밍"의 첫발을 내딛은 당신이 다음에 꼭 해야 하는 것이다. 무엇일까? 그것은 "지금 만든 프로그램의 '구멍' 막는 것"이다.

서버에 프로그램을 제공하는 것은 불특정 다수의 사람이 해당 서버에 액세스하고 그 프로그램이 실행된다는 것이다. 즉, 서버에 액세스하는 모든 사람에게 "그 프로그램이 안전하게 움직인다"라는 것을 보장할 의무가 발생한다는 것이다. 만약에 그 프로그램에 의해 이용자에게 어떠한 피해가 발생하면 그 책임은 만든 개발자에게 있는 것이다.

물론 처음부터 "모든 보안 대책을 세우라"라는 말은 아니다. 하지만 적어도 최소한의 "기본적인 안전 대책"에 대해서는, 프로그램을 만들게되면 가장 먼저 배워야 한다.

그런데 지금 만든 예제 프로그램에는 커다란 '구멍'이 뚫려 있다. 그럼 그 구멍을 확인해 보자. 브라우저에서 이전의 페이지로 접근하여 다음과 같이 써보내 보자.

<script>alert("이 구멍이다!");</script>

전송하면 화면에 알림 창이 나타난다(최근의 브라우저에서는 이를 자동으로 막아주고 경고 메세지가 표시한다). 입력 필드에 쓴 JavaScript 스크립트가 페이지를 로드할 때 실행되는데 이런 현상이 일어나고있는 것이다. 왜 이것이 "구멍"인가? 그것은 "어디의 누군지는 모르는 사람이 여기에 JavaScript 스크립트를 작성하여 페이지를 표시했을 때 그것을 실행시켜 버릴 수 있기" 때문이다.

예를 들어, 이런 식으로 게시판 프로그램을 만들었다고 하자. 그러면 거기에 접근한 사람이 지금과 같이 하여 JavaScript 스크립트를 몰래 게시한다. 다음에 이 게시판에 접근한 모든 사람에게 표시가 될 때에 스크립트가 실행된다. 예를 들어 스크립트에서 "브라우저에 저장되어 있는 쿠키 정보를 얻어서 다른 사이트에 보낸다" 것과 같은 처리가 적혀 있었다고 한다면? 액세스한 사람의 쿠키 정보가 모든 낯선 사람에 도난하실 수 있다.

이른바 '스푸핑(Spoofing)'라는 범죄는 이렇게 발생한다. 이 스크립트를 이용한 방법은 "크로스 사이트 스크립팅(XSS)"라고 사이트 공격의 기본 중의 기본으로 널리 알려져 있다.

그럼 이 뚫린 '구멍'을 막아 보자. 먼저해야할 보안 대책은 사실 의외로 간단하다. 텍스트를 화면에 표시하는 echo 문 스크립트를 다음과 같이 다시 작성할 뿐이다.

<?php
    echo htmlspecialchars($result);
?>

이 "htmlspecialchars"라는 함수는 ()에 쓰여진 값(인수라고 한다)를 체크하고 HTML 태그를 모두 이스케이프 문자로 변환한 것을 돌려준다. 즉, 이렇게 하여 값을 기록한 것으로, <script> 태그 등을 모두 무효화하고 동작하지 않도록 할 수 있다.

양식을 사용하는 경우에는 보안 대책에 관한 철칙이 있다. 그것은 "사용자로부터 보내져 온 데이터는 절대로 그대로 화면에 출력하지 않는다"는 것이다. 거기에는 어떤 내용이 기술되어 있는지 모르기 때문에, 반드시 "표시해도 괜찮은" 형태로 처리해서 출력하는 것이 양식 사용의 기본이다.

<?php
    $str = $_POST['text1'];
    if ($str != null){
        $result = "당신은 '{$str}'이라고 썼습니다.";
    } else {
        $result = "아무것도 쓴 것이 없습니다.";
    }
?>
<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
        <title>sample page</title>
    </head>
    <body>
        <h1>Hello PHP!</h1>
        <div><?php
            echo  htmlspecialchars($result);
        ?></div>
        <form method="post" action="./index.php">
            <input type="text" name="text1">
            <input type="submit">
        </form>
    </body>
</html>



기타 양식용 요소(element)을 사용

이제 양식 사용의 기본이 알았으니 다른 요소(element)에 대해서도 사용법을 살펴 보자.

양식은 입력 필드 외에도 "체크박스", "라디오 버튼". "리스트", "텍스트 영역", ''암호 필드"라는 것이 있다. 텍스트 영역 또는 암호 필드는 이전 입력 필드와 마찬가지로 "텍스트를 써 보내는" 것이므로 사용법은 알 수 있다 (단, 보내져 온 문자를 받을 뿐이기 때문에).

그럼 체크 박스나 라디오 버튼 등은 일체 어떻게 값을 전달하는 것인가에 대해 실제로 시험해 보도록 하자.

아래 체크 박스, 두개의 라디오 버튼, 3개의 항목이 있는 리스트를 표시한 양식 예제를 보도록 하자.

<?php
    if ($_POST != null){
        $ck1 =$_POST['check1'];
        $rd1 = $_POST['radio1'];
        $sl1 = $_POST['list1'];
        $result = "CHECKBOX: {$ck1}\nRADIOBUTTON: {$rd1}\nSELECT: {$sl1}";
    } else {
        $result = "입력하십시오.";
    }
?>
<!DOCTYPE html>
<html lang="ko">
    <head> 
        <meta http-equiv="Content-Type"
            content="text/html; charset=UTF-8" /> 
        <title>sample page</title>
    </head>
    <body>
        <h1>Hello PHP!</h1>
        <pre><?php
            echo  htmlspecialchars($result);
        ?></pre>
        <form method="post" action="./index.php">
            <input type="checkbox" name="check1">체크 박스<br>
            <input type="radio" name="radio1" value="1번 선택">라디오 박스1<br>
            <input type="radio" name="radio1" value="2번 선택">라디오 박스2<br>
            <select name="list1">
                <option value="Windows">Windows</option>
                <option value="Mac OS">Mac OS</option>
                <option value="Linux">Linux</option>
            </select>
            <input type="submit">
        </form>
    </body>
</html>

이것을 실제로 움직여 각각의 값이 어떻게 전달되는지를 알아 보자.

체크 박스

이것은 체크가 ON이라면 "on"이라는 값을 보내온다. 그럼 체크가 OFF라면? 이는 아무것도 보내지 않는다. 즉, 빈값이다.

라디오 버튼

이는 선택된 라디오 버튼의 value가 보내진다. value가 설정되어 있지 않으면 체크 박스와 마찬가지로, 단지 "on"이라는 값이 들어오는 뿐이다. 이것에는 "어떤 라디오 버튼이 선택되어 있는지"를 모르기 때문에 반드시 value를 작성해 하도록 한다.

또한, 어떤 라디오 버튼이 선택되지 않은 경우 체크 박스처럼 아무것도 보내지 않는다.

리스트

<select>는 콤보 박스처럼 표시하거나 일람 리스트와 같이 표시를 할 수 있지만, 송진되는 오는 값은 모두 동일한다. 선택된 <option>의 value가 보내지게 된다. 만약 value가 설정되어 있지 않으면, <option>~</option> 사이에 기술된 텍스트가 전송된다.

또한, 아무것도 선택되어 있지 않으면 역시 아무것도 보내지 않는다.


리스트<select>의 여러 항목 선택

이제 양식의 항목 요소의 기본적인 사용 방법은 알았다. 하지만 아직 설명하지 않은 것이 하나 있다. 그것은 "<select> 여러 항목 선택"이다.

<select> 에 의한 리스트는 multiple이라는 속성을 설정하면, 여러 항목을 선택할 수 있게 된다. 이런 경우에 어떻게 선택된 항목을 체크하면 되는가? 보통의 방법으로는 잘되지 않는다. 약간의 태크닉를 사용해야 한다.

아래에 간단한 예제를 보도록 하자.

<?php
    if ($_POST != null){
        $arr = $_POST['list1'];
        $result = "";
        foreach($arr as $item){
            $result .= $item . "\n";
        }
    } else {
        $result = "입력하십시오.";
    }
?>
<!DOCTYPE html>
<html lang="ko">
    <head> 
        <meta http-equiv="Content-Type"
            content="text/html; charset=UTF-8" /> 
        <title>sample page</title>
    </head>
    <body>
        <h1>Hello PHP!</h1>
        <pre><?php
            echo htmlspecialchars($result);
        ?></pre>
        <form method="post" action="./index.php">
            <select name="list1[]" size="5" multiple>
                <option value="Windows">Windows</option>
                <option value="Mac OS">Mac OS</option>
                <option value="Linux">Linux</option>
                <option value="Android">Android</option>
                <option value="iOS">iOS</option>
            </select>
            <input type="submit">
        </form>
    </body>
</html>

양식의 항목을 적당히 여러개를 선택하여 보내 보자. 선택된 항목이 그 위에 출력된다.

여기에서는 $arr = $_POST[ 'list1'];와 같이 하여 선택한 목록의 값을 얻어 오고 있다. 그리고, foreach ($ arr as $ item) { $ result = $ item. "\ n"; }

이와 같이 foreach를 사용하여 $arr의 값을 순서대로 꺼내 처리를 하고 있다. 즉, $arr는 배열이다. 선택된 항목이 모두 배열로 전달되는 것이다.

이 배열로 데이터를 받기 위해서는 양식 측에도 설정을 해두지 않으면 안된다. <select> 태그 부분을 잘 보도록 하자.

<select name="list1[]" size="5" multiple>

여러 항목이 선택할 수 있도록 "multiple"라는 속성이 추가되어 있다. 이 포인트가 아니다. 이름이 name="list1[]"로 지정되어 있다. "list1"대신 "list1[]"이다. 이와 같이 작성하는 것으로, 이 list1 값은 일반 텍스트가 아닌 텍스트의 배열로 전달하게 되는 것이다.

이 "리스트의 여러 항목 선택"이라는 것은 중요하기 때문에 여기서 잘 이해하도록 하자.

텍스트 대입 연산자

그런데 여기에 또 다른 낯선 기호가 나오고 있다. ".="이다. 이것은 우변의 텍스트를 왼쪽 변수의 끝에 붙이는 연산 기호이다. 즉, "A .= B"라는 것은 "A = A . B"와 같은 의미이다. 이를 더 간단하게 쓸 수있게 한 것이다.



반응형

'php' 카테고리의 다른 글

[php] 텍스트 및 날짜 조작  (0) 2017.12.09
[php] 텍스트 파일 이용  (0) 2017.12.09
[php] form 전송 기본  (0) 2017.12.09
[php] 제어 구문  (0) 2017.12.09
[php] 산술 연산자  (0) 2017.12.09
[php] 값, 변수, 배열 및 문법  (0) 2017.12.09

+ Recent posts