[TIL] WEB의 개념 / LAMP와 CGI를 이용한 Python-WEB 연동 📔

dosilv·2021년 4월 2일
0
post-custom-banner

생활코딩 | WEB1 - HTML & Internet & 생활코딩 | WEB2 - Python 강의 듣고 정리하기 😗

📔 WEB이란?

인터넷상의 정보를 하이퍼텍스트 방식과 멀티미디어 환경에서 검색할 수 있게 해 주는 정보검색시스템! 이라는 위키피디아의 설명 😶 유럽입자물리연구소 소속 팀 버너스 리가 만든 최초의 웹이 바로 World Wide Web(WWW).

웹이 구동되는 주요 요소는 웹 브라우저(=클라이언트)웹 서버(=서버)로 나눌 수 있음! 웹 브라우저가 도메인 입력 등으로 파일을 요청하면 웹 서버가 해당 파일을 찾아서 응답하며 서로 통신하게 됨.

다른 사람이 내 컴퓨터에 있는 파일에 접속하도록 웹 서버를 만드는 방법에는 두 가지가 있다.

1. web hosting 업체 이용
2. 컴퓨터에 직접 web server 설치

어떻게 다를까?

1. 웹 호스팅 업체 이용하기

1주차 과제 때 이용했던 github가 바로 웹 호스팅 업체들 중 하나. 무료이고, 전세계의 수많은 오픈소스들이 여기서 만들어지고 있음!

웹을 통해 보여주고 싶은 파일들을 repository(소스코드를 저장하는 공간)에 업로드하고 pages 기능을 활성화하면 다른 사람들이 깃허브로 해당 서버에 접속할 수 있다. 상대적으로 간단한 방법~~~🙂


2. 직접 웹 서버 설치하기

서버가 될 컴퓨터가 필요하고, 항시 켜져 있어야 함! 서버를 설치하고 또 잘 작동하도록 여러 설정도 해 줘야 하기 때문에 깃허브를 이용하는 것보다 복잡하다.

서버에도 apache, microsoft, sun, nginx, google 등 여러 가지 제품이 있다. 그중 apache는 깃허브처럼 무료&오픈소스이며, 웹 서버 시장점유율에서 한 번도 1위를 빼앗긴 적 없다고 한다.



📔 LAMP와 CGI를 이용한 Python-WEB 연동

나는 생활코딩 WEB2 - Python 강의를 따라 아파치를 직접 설치하는 대신, bitnamiLAMP를 통해 웹 애플리케이션을 구동해 보기로 함! 파이썬은 매일 문법 공부만 하다 보니 실제로 어떻게 적용하는지 궁금했는데, LAMP와 CGI를 이용하면 파이썬으로 동적페이지를 구현할 수 있다고 한다. 근데 그전에... 그게 다 뭔데.....😢

📌 LAMP

Linux(운영체제) / Apache(웹 서버) / MySQL 또는 MariaDB(DB 서버) / PHP, Perl 또는 Python(프로그래밍 언어)의 약자로, 서버 운영에 자주 쓰이는 소프트웨어들의 앞글자를 딴 것! 윈도우 기반의 WAMP, 맥 기반의 MAMP도 있다. LAMP를 이용해서 아파치를 직접 설치하지 않고도 웹 앱을 구현해 볼 수 있음!

📌 CGI

Common Gateway Interface의 약어. 웹 서버외부 프로그램간에 정보를 주고받는 규약을 말한다. 동적 웹사이트를 만들기 위해서는 단순한 html 파일 시스템이 아닌, 프로그래밍 언어를 사용하게 된다. 그러나 대부분의 HTTP 서버는 C나 C++로 작성되어 파이썬과 같은 다른 언어로 작성된 코드를 실행할 수 없는데, CGI 덕분에 프로그램과 서버 사이에 정보교환이 가능해지는 것!


나는 새로 페이지를 만드는 대신, 1주차 과제로 만든 자기소개 페이지를 수정해 보기로 했다. 기존 페이지는 카테고리별로 index.html, likes.html, coding.html, contcat.html의 총 네 개의 html 파일과 한 개의 css파일로 구성되어 있었음!

컨텐츠가 들어있는 섹션을 제외하고 헤더, 배경, 그 외의 레이아웃은 각 html 파일마다 공통되는 부분으로 들어가있었다. 이걸 합칠 순 없나? 의문이었는데 이번 강의를 통해서 한 가지 방법을 배웠다 😉


1. 우선 LAMP 설치 후 에디터에서 프로젝트 폴더 불러오기

bitnami 홈페이지에서 LAMP 다운로드
나는 atom 에디터를 이용했고, lampstack-8.0.3-1/apache2 폴더 전체를 불러옴!


2. python 파일을 cgi 스크립트로 실행하록 만드는 작업

전적으로 강의에서 시키는 대로 따라한 부분...!^^

1) /apache2/conf에서 httpd.conf 파일을 찾아서 연다.
2) httpd.conf 내에서 #LoadModule cgid_module modules/mod_cgid.so를 찾아(mod_cgi로 검색) 맨앞의 #을 없애준다.
3) <Directory "/home/doeun/lampstack-8.0.3-1/apache2/htdocs">를 찾아서 쭉 내리다보면 </Directory>로 닫히는 부분이 있다. 그 안에 아래 내용을 추가해 준다.

    <Files *.py>
      Options ExecCGI
      AddHandler cgi-script .py
    </Files>

여기서 Options ExecCGI는 Options 지시어로 특정 디렉토리에서 CGI 실행을 허용하는 것이고, 다음 줄은 AddHandler 지시어로 확장자가 py인 파일을 CGI로 실행하라고 알리는 것! 바꾼 설정을 반영하기 위해서 bitnami로 아파치 서버를 restart 해줘야 함.


3. cgi프로그램 작성하기

파일명은 index.py (index 대신 아무거나 가능)
다음과 같은 내용이 들어가야 한다.

#!/usr/bin/python3
print("content-type:text/html; charset=utf-8")
print()
  • 첫 번째 줄은 #!+[파이썬 파일의 경로]를 적어준 것. 각 컴퓨터별로 상이할 수 있음!
  • 두 번째 줄은 MIME-type header라고 한다. 안 적게 되면 header 오류가 발생하기 때문에... 적어줘야 함...^^(단순)
  • 세 번째 줄은 헤더 다음에 한 칸 띄우기 위한 용도

이렇게 설정한 뒤 아래에 아무 파이썬 코드를 입력하고, localhost:8080으로 접속해서 코드가 제대로 출력되는지 확인했다. 만약 오류가 발생한다면 /apache2/logs/error_log 에서 오류 내용을 확인해 본 후 구글링~~

파일을 새로 만들고 접속하면 permission denied 오류가 뜨는데, 터미널을 열어서 해당 파일이 있는 폴더로 경로를 설정하고, chmod a+x 해당파일명.py을 입력해서 권한을 주면 해결됨!


4. html 파일 👉 python 파일로 바꾸기

위에서 작성한 파일 아래에 html을 추가한다. 이때! 그대로 복붙하면 안되고 프린트문으로 감싸야 한다. 근데 html에는 줄바꿈이 어마어마하게 많기 때문에... '''으로 또 감싸줌.

print('''
<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="./style.css">
    .
    .
    .
</html>
''')

그치만 html 파일은 여러 개인데 index.py는 하나다. 이걸 어떻게 처리하냐면! 공통된 부분만 남기고 페이지별로 달라지는 부분은 비워 놓는다. 대신 거기에 {contents}를 넣어 준다. 그리고 ''' 앞에 f를 붙여 f-string을 만들어 주었다.

다음으로, 메뉴별로 각각의 html 파일에 링크되어있던 a 태그의 href 부분을 다음과 같이 수정한다.

수정 전
<a href="index.html">MAIN</a>
<a href="likes.html">LIKES</a>
<a href="coding.html">CODING</a>
<a href="contact.html">CONTACT</a>

수정 후
<a href="index.py?id=main">MAIN</a>
<a href="index.py?id=likes">LIKES</a>
<a href="index.py?id=coding">CODING</a>
<a href="index.py?id=contact">CONTACT</a>

이걸 쿼리스트링이라고 하는데, 사용자가 웹 프로그램으로 입력 데이터를 전달하는 가장 단순하고 널리 이용되는 방식이라고 한다. 클라이언트가 어떤 리소스에 접근하고 싶어하는지를 알려주는 것! URL주소?변수=값의 형태로, 변수와 값이 여러 개일 경우 &을 통해 구분해 준다.

그렇게 되면 각 메뉴를 클릭할 때마다 다른 html 파일로 연결되는 대신, 같은 index.py 파일 내에서 각각 다른 id를 갖게 된다. 그리고 이 id에 따라 표시할 컨텐츠를 달리 할 수 있다 😀

{contents}를 조건에 따라 달리 표시하기 위해 cgi 모듈FieldStorage 클래스를 이용해야 한다.

📌 FieldStorage란?

form data를 담는 클래스라고 할 수 있다. form data는 cgi로 상호작용하기 위해 클라이언트가 제출한 인풋인데, 앞서 언급한 쿼리스트링을 통해 서버에 전달될 수도 있고, HTML의 form tag로 전달되기도 한다. 폼 태그... 딱히 쓸 일이 없었어서 쩜 소홀히 했는데 그 부분도 나중에 한 번 정리해야겠당 😬

아무튼 이 FieldStorage에 form data가 딕셔너리 형태로 담긴다. 따라서 x = form["id"].value라는 변수를 설정하면 <a href="index.py?id=main">MAIN</a>에서는 x = "main"이 되고, <a href="index.py?id=likes">LIKES</a>에서는 x = "likes"가 되는 것.

그 다음엔 {contents} 부분을 위해 각 id 값을 파일명으로 하는 파일들을 index.py와 같은 디렉터리에 생성해 준다. 확장자명은 따로 붙이지 않음! 예를 들어 likes라는 이름의 파일을 만들고, likes.html의 {contents} 자리에 들어갈 html요소를 그대로 붙여넣는다. 그리고 이 파일들을 열고 읽어내기 위해서 파이썬 내장함수인 open과 read를 사용해 contents를 정의한다.

쿼리스트링이 붙지 않은 초기의 index.py에는 id값이 없는데, 에러를 방지하고 이때도 main(index.html)에 있던 컨텐츠를 보여주기 위해서 조건문으로 필요한 코드를 작성하면 다음과 같다.

import cgi
form = cgi.FieldStorage()
if 'id' in form:
    pageId = form["id"].value
    with open(pageId, 'r') as con:
        contents = con.read()
else:
    pageId = "main"
    with open('main', 'r') as con:
    	contents = con.read()

5. 그 외 고민

1)
기존 html과 css로 만든 페이지는 각 카테고리를 클릭하면 해당 메뉴의 텍스트 컬러가 바뀌도록 되어 있었다. 카테고리별로 html 파일이 달랐기 때문에, 메뉴 부분에서 해당 카테고리에만 id="selected"를 주고 css에서 #selected를 선택해 색을 줬었음!

[HTML(index.html)]
<nav class="container">
  <div class="item" id="selected"><a href="index.html">MAIN</a></div>
  <div class="item"><a href="likes.html">LIKES</a></div>
  <div class="item"><a href="coding.html">CODING</a></div>
  <div class="item"><a href="contact.html">CONTACT</a></div>
</nav>
 [CSS]
 #selected {
  color: #FEE074;
}

근데 index.py에서는 저 nav부분까지 공통이었기 때문에... 어떻게 하지? 생각하다가 if문을 활용해서 시도했다. html을 프린트하기 전에 다음 코드를 작성하고,

menu = {"main":'', "likes":'', "coding":'', "contact":''}
if pageId in menu:
    menu[pageId] = 'id="selected"'

nav 자식 요소들에 {menu[(각 pageID)]}를 추가해 줬다.

<nav class="container">
  <div class="item" {menu["main"]}><a href="index.py?id=main">MAIN</a></div>
  <div class="item" {menu["likes"]}><a href="index.py?id=likes">LIKES</a></div>
  <div class="item" {menu["coding"]}><a href="index.py?id=coding">CODING</a></div>
  <div class="item" {menu["contact"]}><a href="index.py?id=contact">CONTACT</a></div>
</nav>

너무 얼렁뚱땅 생각해낸 거라서 될까...? 하면서 눌러 봤는데 됐다! 신기하고 뿌듯 😆

2)
수정한 페이지를 깃허브에 올릴 수는 없나...? 했는데! 그대로 푸시했더니 에러가 떴다. 알고보니 깃허브는 기본적으로 정적 사이트의 웹호스팅만 지원한다고 한다. 파이썬으로 동적 사이트를 구현하려면 펠리칸을 추천한다고 하는데... 머리가 터질 것 같아서 그건 다음에~~~!;;


🙇‍♀️참고한 자료!

HOWTO Use Python in the web
아파치 투토리얼: CGI를 사용한 동적 페이지 생성
cgi — Common Gateway Interface support

profile
DevelOpErUN 성장일기🌈
post-custom-banner

1개의 댓글

comment-user-thumbnail
2021년 4월 4일

도은님 정리해주신 거 잘 읽고갑니다! 덕분에 저도 저 강의에 대해 정리하면서 도움이 되었어요

답글 달기