안녕하세요 마무입니다. 오늘은 웹 관련 작업을 하다 보게 되는 "SSI(Server Side Includes)란", "SHTML이란"에 대해서 자세히 알려드리려고 합니다.
이 포스트의 'SSI'는 웹 백엔드에 쓰이는 기술로, 최소한 및 기본적인 네트워크 개념과 백엔드 작동 구조는 알아야 이해가 될 것입니다.
만약 모를 시 네트워크 독학 페이지에 가셔서 기초 네트워크 개념을 모두 보고 오시길 바랍니다.
-----목차-----
1. SHTML(Server-parsed HTML)이란?
2. SSI(Server Side Includes)란?
3. SSI 단점
4. SSI 활성화
5. SSI 형식
---------------
여기서 못 찾은 정보는
네트워크 독학 페이지 : https://mamu2830.blogspot.com/p/blog-page_15.html
에서 찾아보세요!
1. SHTML이란?
웹 관련 공부를 하다 보면 이 '.SHTML'이란 것을 가끔 보게 됩니다.
HTML은 웹 공부를 한다면 모를 수가 없는 하이퍼 문서지만, 이 SHTML이란 건 뭔지 모르겠단 말이죠~
결론적으로 말하자면 SHTML이란 Server-parsed(서버에서 테스트하고 데이터를 변환하는) HTML이란 뜻대로, 서버에서 클라이언트로 HTML를 보내기 전 서버에서 특정 문구를 해석해 데이터로 변환한 다음 클라이언트에게 보내는 HTML이란 뜻입니다.
이런 특별한 과정이 추가로 필요하기에, 서버 프로그램이 인식할 수 있게 끝에 ".shtml"이란 확장자를 붙입니다.
그 외 SHTML 대신 같은 의미인 "SHTM", "STM"으로 표시하기도 합니다.
그러면 클라이언트에게 보내기 전 서버에서 해석해야 하는 문구란 도대체 뭐냐?
대표적으로 백엔드에서 쓰이는 SSI(Server Side Includes)가 있습니다!
2. SSI(Server Side Includes)란?
'SSI'이란 Server-Side(서버 측에서) Includes(포함 시키는 것)이란 뜻으로, 서버의 환경 변수나 데이터들을 서버에서 HTML에 포함 시키는 기술입니다.
기존 C언어에서 include "sth.h" 이렇게 헤더 파일을 통해 다른 소스 코드를 불러와 같이 컴파일 하는 느낌처럼 서버 측 데이터(Server-Side)를 가진 변수들을 HTML에 포함(Includes) 시키는 것이라 해서 "SSI"라 하는 것이죠.
그리고 이런 SSI를 쓸 경우 파일의 이름에 위에서 말한 ".shtml" 확장자를 붙여줘야 합니다.
자 그럼 우린 만능 CGI(백엔드에서 쓰이는 프로그래밍 언어)가 있는데 굳이 SSI를 왜 쓰냐?
질문부터 나오실 겁니다.
음.. 당연히 만능이란 말대로 CGI만 알아도 됩니다만, SSI를 쓰면 편한 부분이 꽤 있기 때문입니다.
이 SSI는
<pre>
<!-- #exec cmd="grep -c 192.168.100.5 /usr/local/apapche/logs/access_log" -->
</pre>
이런 형태로 HTML내에 직관적으로 넣을 수 있기 때문에, 간단한 동적 요소인 경우 쉽게
처리할 수 있습니다.
위 SSI는 서버의 리눅스 쉘 명령어 "grep -c 192.168.100.5 /usr/local/apapche/logs/access_log" 를 실행하란 뜻으로, 실행되면 /usr/local/apache/logs/access_log 파일 내에 있는 192.168.100.5 IP가 포함된 줄의 개수를 출력합니다.
즉 HTML에서 원하는 위치에
<pre>
<!-- #exec cmd="grep -c 192.168.100.5 /usr/local/apapche/logs/access_log" -->
<pre>
를 적어 놓으면, 클라이언트가 받은 HTML에선 192.168.100.5 IP를 가진 컴퓨터가 서버에 접근한 횟수가 나오는 것이죠.
정말 간단하죠? 또
현재 서버 시각은 : <!--#echo var="DATE_LOCAL" --> 입니다.
이런 형태로, 우리가 익히 아는 출력 명령어 'echo'를 이용해 컴퓨터의 시간이 적힌 환경 변수 "DATE_LOCAL"의 값을 HTML에 포함할 수 있습니다.
이런 것 외에도 같은 HTML Footer를 사용하는 여러 HTML들을 한번에 변경하고 싶으면
따로 Footer 섹션 전용 HTML을 적은 "footer.shtml" 파일을 만든 다음
각 HTML의 <body></body>태그 안에
<!--#include file="footer.shtml" -->
이렇게 적어서 클라이언트에게 html파일을 보내기 전 footer.shtml 파일 내용을 포함 시키는 것이죠.
또
접속한 사람의 수를 카운트하는 "/cgi-bin/couter.py'란 CGI를 만들어 놓고
<!--#include virtual="/cgi-bin/counter.py" -->
이렇게 써서 CGI의 결과만을 HTML에 포함할 수 있습니다.
이렇듯 SSI라는 것을 잘만 사용하면 작업 효율이 엄청 좋아지는 것이죠.
3. SSI 단점
음.. 당연히 장점만 있을 순 없는 법....이 SSI의 치명적인 단점이 몇 개 있습니다
i) 서버의 부담이 커진다
당연히 SSI는 서버에서 처리하는 기술이기 때문에, SHTML을 보낼 때마다 서버의 부하가 추가로 생깁니다.
그래서 보통 서버의 현재 시간과 같은 크기가 적은 정보들을 동적으로 표현할 때 사용합니다.
ii) SSI를 사용하면 보안적인 부분에서 리스크가 커집니다.
쉘 명령어를 사용하는 "#exec cmd"인 경우가 대표 SSI의 보안 취약점 입니다.
자 특정 웹 서버에 클라이언트가 서버에 글을 남길 수 있는 기능이 있고, 만약 HTML도 쓸 수 있으며, #exec cmd를 사용할 수 있게 해놓았다고 해봅시다.
여기서 악성 유저는 글에 HTML과 #exec cmd를 쓸 수 있으므로, 매우 간단하지만 가장 위험한
<--#exec cmd="/bin/rm -rf /home"-->
이렇게 쳤다고 해봅시다. 다들 리눅스 1을 다 잘 배웠으니 아실겁니다..
"rm -rf"이란 명령어를 통해 강제로 /home과 그 밑에 있는 모~든 유저 파일들을 제거해버리는 것이죠.
삭제 명령어가 아니라, 당연히 데이터를 빼오는 것도, 만드는 것도, 그 외에 쉘 명령어를 이용한 행위면 전부 가능할 겁니다.
이렇듯 SSI의 exec는 상당히 조심히 다뤄야하는 녀석이기 때문에, 기본적으로 대부분의 웹 프로그램(아파치)에선 <Directory "디렉토리"></Directory> 내부 지시어 Options의 IncludesNOEXEC와 같이 SSI는 쓰되, exec는 못 쓰게 하는 옵션을 지원하는 겁니다.
이렇듯 유저가 웹 페이지 내용을 수정 가능한 곳엔 절대 exec SSI를 못 쓰게 해야하며, 이러 SSI를 이용한 외부 명령어나 프로그램을 실행 시 <pre></pre> 태그로 감싸는 게 좋습니다.
그리고 SSI를 이용한 외부 프로그램 결과에 HTML이 포함돼 있으면, 그것 또한 브라우저가 해석하므로 유의해야 합니다.
4. SSI 활성화
아파치인 경우 SSI를 사용할 디렉토리는 내부에 SSI를 의미하는 "Options Includes"를 추가해주면 됩니다.
만약 exec는 제한하고 싶으면 "Options IncludesNOEXEC"를 쓰고요~
i) 그리고 당연히 아파치가 ".shtml"확장자를 인식해야하므로
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml
이렇게 httpd.conf에 AddType과 AddOutputFilter 지시어를 추가해주면 됩니다.
하지만 이 경우 당연히 SSI를 쓰는 경우 파일의 확장자가 ".shtml"이여야 해요.
또는
ii) 실행 권한(x)이 있는 파일은 모두 서버측에서(Server-Side) 해석되어야 하는 파일로 취급하라는 'XbitHack' 지시어를
XbitHack on
이렇게 on으로 적은 다음
SSI 지시어가 있는 html 파일에게 chmod +x로 실행 권한(x)을 주면 됩니다.
이 경우엔 실행 권한만 주면 되므로, 파일 확장자가 shtml이 아니여도 됩니다.
하지만 XibtHack 지시어는 윈도우에서 지원이 안된다고 하니, 윈도우 아파치 서버는 유의해야 할 것 같습니다.
5. SSI 형식
자 그럼 이러한 SSI 기능을 사용할 수 있는 SSI 형식은 어떻게 되는지, 종류를 한번 알아봅시다.
위에서 보시고 눈치를 채셨겠지만, 이 SSI의 형식은 html의 주석 표시를 이용한
<!-- #[function] 속성(태그)=값 속성(태그)=값 ... -->
형태입니다.
이 html의 주석을 이용하기 때문에 html 어디에나 쓸 수 있으며, 만약 SSI가 실행되는 시스템이 아니면 브라우저는 그냥 주석으로 해석합니다.
대표적으로 맨 앞에 function은 SSI 주 기능을 하는 녀석으로 '#'을 붙입니다.
저~~ 위에서 예시로 보여줬던
#exec , #include이 있었죠.
'속성'은 '#으로 시작하는 함수'에 들어있는 변수입니다.
사이트마다 속성(attribute)로 표현하기도 하고 tag로 표현하기도 하는데, 속성으로 표현한 곳이 더 많아 저도 속성으로 표현하겠습니다.
그리고 이 SSI 속성은 용도에 맞춰 이미 정해져 있습니다.
그럼 각 #function과 그에 속한 속성들을 정리해보겠습니다
참고로 '속성 값'은 항상 ""로 감싸주는게 좋습니다.
-----SSI의 function과 속성-----
#include : 문서의 글을 SSI로 해석되는 문서에 포함 시키는 명령어로, 이 때 포함되는 파일들은 일반적인 접근 제어를 따릅니다.
---> virtual="아파치 웹 기준 파일 경로" : 포함되는 파일이 웹 페이지와 같은 디렉토리에 없는 경우 사용하는 속성 값
ex) www.mamu.com(/usr/local/apache/htdocs/index.html)에 포함할 counter.py CGI가 www.mamu.com/cgi-bin/counter.py(/usr/local/apache/cgi-bin/counter.py)에 있을 경우
<!--#include virtual="/cgi-bin/counter.py" -->
---> file="파일명" : 포함되는 파일이 웹 페이지와 같은 디렉토리에 있는 경우 사용하는 속성 값
ex) www.mamu.com(/usr/local/apache/htdocs/index.html)에 포함할 footer.html가 같은 디렉토리에 있으면 그냥
<!--#include file="footer.html" -->
#flastmod(file last modification) : 특정 파일의 마지막 수정일을 나타내는 명령어
---> file="파일명" : #include와 마찬가지로 같은 디렉토리 내 파일 지정
---> virtual="아파치 웹 기준 파일 경로" : 다른 디렉토리 내 파일 지정
#fszie(file size) : 특정 파일 크기를 나타내는 명령어
---> file="파일명" : #include와 마찬가지로 같은 디렉토리 내 파일 지정
---> virtual="아파치 웹 기준 파일 경로" : 다른 디렉토리 내 파일 지정
#config : SSI 를 해석할 때의 설정을 변경 하는 명령어
---> errmsg="에러 메세지" : SSI 해석 중 에러가 발생 했을 때 표시할 에러 메세지 변경
---> timefmt="시간 형식자들..." : #flastmod와 같이 시간을 표현하는 형식을 지정한 형식으로 변경한다
(timfmt 형식자)
%a: 요일 이름 축약형
%A : 풀 요일 이름
%b : 월 이름의 축약형
%B : 풀 월 이름
%D : %m/ %d / %y 형태 날짜
%m(month) : 01~12 사이 월
%d(day) : 1~31일
%y(year) : 같은 세기의 00~99 사이 년도
%H(Hour) : 00~23 사이 시간
%M(Minutes) : 00~59 사이 분
%S(Seconds) : 00~59 초
%p : AM 또는 PM 문자
%Z : 타임 존 이름
---> sizefmt="크기 형식자들..." : 파일 크기를 표현하는 형식을 지정한 형식을 변경한다
(sizefmt 형식자)
bytes : 바이트 형태로 크기 표현
abbrev : 킬로바이트나 메가바이트로 표현
#set : 새로운 환경 변수를 만드는 명령어
---> var="변수" : 변수를 만드는 속성
---> value="변수에 저장할 값" : 앞서 언급한 var 변수에 저장할 값
ex) <!--set var="test" value="this is test" -->
#echo : SSI 환경 변수 값을 출력하는 명령어
---> var="변수" : echo할 변수를 지정하는 속성
(echo에 사용 가능한 SSI 환경 변수들)
LAST_MODIFIED : 마지막 파일 수정일
DOCUMENT_NAME : 파일 이름
DOCUMENT_URI : 파일 URL
DATE_GMT : 그리니치 평균시(영국 기준 시간) 날짜
DATE_LOCAL : 동부 표준시 날짜
HTTP_USER_AGENT : HTTP의 대리인(운영체제, 브라우저 등등)
HTTP_HOST : 호스트이름
SERVER_NAME : 서버 이름(도메인)
HTTP_ACCEPT : 받은 HTTP 정보
HTTP_ACCEPT_LANGUAGE : 받은 HTTP 정보의 언어
#exec(execute) : cgi나 쉘 스크립트를 실행하는 명령어
---> cmd="쉘 명령어 형식" : 서버의 쉘이 명령어를 실행하게 합니다. 그리고 이 때 '$[환경변수]' 형태로 SSI 환경 변수를 사용할 수도 있습니다.
ex) <!--#exec cmd="/usr/local/date" -->
---> cgi="CGI 파일 이름" : #include virtual로 가져온 cgi 파일을 실행합니다.
여기서 그럼 #exec cgi="CGI 파일위치"랑 #include virtual="CGI 파일위치" 뭐가 다른지 의문이 들텐데요~ 결론은 같습니다.
보통 #exec 명령어는 보안적인 이유로 막아놓기 때문에, 대신 #include virtual를 사용하는 느낌이라고 보시면 됩니다.
---------------------------------------------------
이 외에 SSI를 사용한 if, elif, else문도 있는데요.. 사실 대부분 상황에서 CGI를 사용하기에 굳이 쓸 필요가 없을 것 같아 생략했습니다.
만약 SSI의 if문이나 다른 명령어들이 궁금하면
에서 찾아보세요!
이 포스트를 쓰기 위해 하루 6시간 총 3일 걸렸네요 에고.. 제 엄청난 노력이 들어간 만큼 꼭 이 포스트를 읽는 분들에게 도움이 되길 바랍니다!
도움이 되셨다면 팔로우 클릭 및 따뜻한 댓글을 달아주시면 저에게 큰 힘이 돼 포스트 퀄리티 향상에 도움이 됩니다!
그럼 다음에 더 좋은 포스트로 찾아뵙겠습니다!
-정보 지식 참고 출처-
댓글 없음:
댓글 쓰기
#1 여러분들이 소중한 시간을 투자해 달아주시는 따뜻한 댓글들은 저에게 정말 큰 힘이 됩니다!
#2 저의 각 포스트들은 엄청난 노력과 시간 투자를 통해 만들어진 포스트들로, 무단 복제나 모방하는 것을 금지합니다.
#3 저의 포스트에도 틀린 정보가 있을 수도 있습니다. 그럴 경우 친절한 말투로 근거와 함께 댓글로 달아주시면 정말 감사하겠습니다!