Recent Posts
-
[jQuery] Lazy 로 이미지 리소스 트래픽 절약하기
이미지가 리소스가 많은 웹페이지 로드시 과도한 트래픽이 발생하게 되는데, lazy 는 화면에 노출된 이미지 리소스를 그때그때 로드하여 출력해 주는 플러그인이다. Plugin include cdn 서비스나 본 글 하단에 첨부된 js파일을 다운로드 하여 lazy 적용을 원하는 웹페이지 상단에 인클루드 한다. <script type="text/javascript" src="jquery.lazy.min.js"></script> img 태그 수정 lazy가 적용될 <img> 요소를 아래와 같이 수정한 다음, plugin 을 적용한다. <HTML> 1. src 어트리뷰트를 data-src 로 변경 2. class="lazy" 추가 <img data-src="path/to/image.jpg" class="lazy" /> <jQuery> .lazy 가 부여된 이미지 리소스에 대해 lazy 적용 $(function() { $('.lazy').Lazy(); }); 상세 옵션 설정 lazy는 커스터마이징이나 디버깅 할 수 있는 몇가지의 옵션을 제공한다. ( 전체 옵션 확인 : http://jquery.eisbehr.de/lazy/#configuration ) $(function() { $('.lazy').Lazy({ 'thresold' : 100, // 이미지가 화면에 100px 만큼 보인 시점에 등장하도록 설정 'effect' : 'fadeIn', // fade 등장효과 적용 (기본값: show) 'effectTime' : 500, // fade 적용시 duration 시간 'onError' : function(element) { // img 로드 실패시 callback 함수 console.log('error loading ' + element.data('src')); } }); });
-
[CSS] backdrop-filter 로 겹침 효과 주기
한때 음악 어플의 앨범 커버이미지 ui에서 자주 볼 수 있었던 흐림 효과를 CSS로 구현할 수 있다. backdrop-filter 를 통해 구현할 수 있는데, IE가 지원 중단 되면서 부터 비교적 자유롭게 사용할 수 있게 되었다. 사용법은 아래와 같다. blur backdrop-filter 중에 내가 가장 자주 사용하는 속성은 blur. backdrop-filter: blur(10px); 위와 같이 적용해 주면 되는데, 다만, 부모 엘리먼트에 이미 backgrop-filter 가 적용되어 있다면, 자식 요소에서는 적용되지 않는다는 점을 주의하자. invert / sepia등 다양한 속성 제공되는 다양한 속성 중 inver와 sepia를 비롯해 다양한 속성을 제공한다. 예시는 아래와 같다. backdrop-filter: invert(80%); backdrop-filter: sepia(90%); 아래는 Mozilla 가이드 페이지에서 제공하는 속성 설명이다.
-
AWS S3 리소스에 대한 CORS(크로스도메인) 설정 방법
S3에 저장된 이미지 리소스를 외부 사이트 웹페이지 등에서 사용 할 때 웹페이지의 도메인과 S3 endpoint의 도메인이 달라 크로스도메인(CORS) 오류가 발생하여 리소스가 로드되지 않는 경우 S3 콘솔에서 CORS 를 설정하여 특정 도메인의 크로스도메인 접근을 허용할 수 있다. AWS S3 버킷 관리 콘솔 AWS - S3 - 버킷 선택 - 권한 - CORS(Cross-origin 리소스 공유) 로 이동하여 [편집] 버튼을 클릭하여 관리 팝업을 연 다음 아래와 같 이 입력한다. CORS 설정 (JSON) AWS S3 에서는 JSON으로 CORS 설정이 가능하여 아래 구문을 복사한 뒤 적절히 수정하여 적용한다. [ { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "GET", "PUT", "POST", "DELETE" ], "AllowedOrigins": [ "https://허용할도메인1.com", "http://허용할도메인2.com" ], "ExposeHeaders": [] } ] CORS 설정 (XML) 대부분의 Object Storage 서비스는 S3 CORS 설정 방법과 동일하나, XML 구문만 지원하는 서비스도 간혹 있는데, XML의 경우 아래와 같이 설정한다. <CORSConfiguration> <CORSRule> <AllowedOrigin>https://허용할도메인1.com</AllowedOrigin> <AllowedMethod>PUT</AllowedMethod> <AllowedMethod>POST</AllowedMethod> <AllowedMethod>DELETE</AllowedMethod> <AllowedHeader>*</AllowedHeader> </CORSRule> <CORSRule> <AllowedOrigin>http://허용할도메인2.com</AllowedOrigin> <AllowedMethod>PUT</AllowedMethod> <AllowedMethod>POST</AllowedMethod> <AllowedMethod>DELETE</AllowedMethod> <AllowedHeader>*</AllowedHeader> </CORSRule> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> </CORSRule> </CORSConfiguration>
-
[HTML] textarea placeholder 에서 줄바꿈하기 1
textarea 에서 placeholder 입력시 \n 혹은 \r\n 로 줄바꿈을 할 수 없는데, 아래와 같이 엔터티를 입력하여 줄바꿈 가능하다. <textarea placeholder="첫 번째 줄 두 번째 줄"></textarea> 줄바꿈 엔터티 : 아래는 줄바꿈 placeholder 가 적용된 textarea.
-
[CSS] CSS만으로 scrollbar 디자인하기
최근 익스플로러가 사용 중단 조치 되면서 스크롤바 디자인이 좀 더 자유로워졌다. 아래 CSS를 통해 간단히 웹킷 브라우저에서 스크롤바 디자인을 변경할 수 있다. CSS 아래 코드를 통해 스크롤바 디자인이 가능하다. .scroll::-webkit-scrollbar {width: 10px} .scroll::-webkit-scrollbar-thumb {background-color: #b4b4b4; border-radius: 10px; background-clip: padding-box} .scroll::-webkit-scrollbar-track {background-color: #f1f1f1; border-radius: 10px; } 위 코드에서 .scroll 은 스크롤이 적용되는 엘리먼트이며, ::-webkit-scrollbar 는 스크롤바 전체 영역, ::-webkit-scrollbar-thumb 는 스크롤 바, ::-webkit-scrollbar-track 는 트랙의 스타일을 지정하면 된다. 예시는 아래와 같다.
-
[jQuery] jQuery UI autocomplete 적용하기
jQuery UI에 기본 탑재된 자동완성 기능 (autocomplete) 샘플 코드. 배열을 미리 선언하여 사용하는 방법과 ajax 방식으로 배열을 가져와 구동하는 방법으로 사용할 수 있는데 아래 예시는 배열을 미리 선언한 뒤 사용하는 방식이다. 자동완성 배열 선언 searchSource = [ { 'label' : '서울', 'value' : 'seoul' }. { 'label' : '대전', 'value' : 'daejun' } ] 자동완성 적용 위에서 선언된 배열을 자동완성으로 적용하는 예제이며, 자동완성을 선택하는 경우 위 배열 중 'value'는 input의 value가 되며, 'label'은 자동완성에서 노출될 항목명이 된다. <HTML> <input type="text" name="address" autocomplete="off"> <jQuery> $('input[name="address"]').autocomplete({ 'source' : searchSource, // 위에서 선언한 배열 'minLength' : 0, // 최소 몇글자 입력시 자농완성 노출할 것인지 'autoFocus' : false, // 자동으로 첫번째 항목에 focus를 위치시킬 것인지 'position' : { my : 'right top', at : 'right bottom' }, // 자동완성 창의 노출 위치 'delay' : 0, // 노출 딜레이 시간 'z-index' : 999, // z-index 'classes' : {}, // 자동완성 기본 css class 를 custom class로 대입하는 옵션. 'select' : function(event, ui) {}, // 항목 선택시 수행할 작업 'focus' : function(event, ui) {}, // 항목 focus시 수행할 작업 'close' : function(event) {} // 닫는 경우 수행할 작업 }).on({ 'focus' : function() { $(this).autocomplete("search", ""); // input에 포커싱 되는 순간 자동완성이 열리게 하는 코드 } }); autocomplete가 적용된 ui는 아래 예시와 같다.
-
[PHP] 배경색(HEX 코드) 판별하여 적합한 글자색(흰색/검정색) 반환
Element에 배경색과 배경색 위에 얹혀질 글자 색을 지정하는 경우 배경색이 밝은지 어두운지 판별하여 횐색/검정 글자중 적합한 색을 반환해 주는 함수. 코드에 HEX코드를 넣어주면 결과 값으로 black 혹은 white를 반환해준다. 배경색에 따라 white / black 반환 아래와 같이 함수에 HEX값 (배경색)을 넣어주면 white / black을 반환해 준다. // 글자색 반환 함수 function get_text_color($hex) { $rgb = sscanf($hex, "#%2x%2x%2x"); $brightness = (($rgb[0] * 299) + ($rgb[1] * 587) + ($rgb[2] * 114)) / 1000; return ($brightness > 125) ? 'black' : 'white'; } // 글자색 반환 실행 get_text_color('#000000'); // 결과 값 : 'white' 반환 위 함수는 아래와 같이 활용할 수 있다.
-
[centOS] 버퍼메모리 초기화 방법
프로그램의 과부하 혹은 메모리 누수로 인해 버퍼메모리가 과도하게 발생한 경우 아래와 같이 강제로 메모리를 초기화 할 수 있다. 퍼버메모리 초기화 아래와 같이 버퍼 메모리를 초기화 할 수 있다. #echo 3 > /proc/sys/vm/drop_cache
-
[centOS] 현재 FTP/SSH 접속해있는 접속자 ip 확인하기
현재 FTP와 SSH에 접속해있는 접속 ip를 확인할 수 있다. 현재 FTP/SSH 접속 ip확인 아래와 같이 확인 #last | grep logged | awk '{print $1,$3}' | sort | uniq -c | sort -n | awk '{print $2,$3}'
-
[centOS] hosts.allow 와 hosts.deny 설정으로 서버 접근 ip 차단
iptable에서 아이피 접근을 차단할 수 있지만, hosts.allow 와 hosts.deny 파일 설정을 통해 트래픽 유형별로 세분화하여 아이피 차단/허용 처리 할 수 있다. hosts.allow 로 아이피 차단 아이피 접근 차단 방법을 안내한다. # vi /etc/hosts.deny 설정 파일을 vi로 연다. ... ALL: ALL 위와 같이 모든 아이피를 차단할 수 있으며, 이 경우 허용하고자 하는 특정 아이피만 hosts.allow 에서 열어줘야 한다. 입력 방법은 아래 참고. ... ALL: 111.222.333.444, 222.333.444.555 위와 같이 차단할 아이피를 지정할 수 있다. 여러 아이피인 경우 콤마(,)로 입력한다. ... sendmail: 111.222.333.444, 222.333.444.555 sendmail: ALL 위와 같이 sendmail 에 대한 접근 차단을 할 수도 있다. hosts.allow 로 아이피 허용 아이피 접근 허용 방법을 안내한다. # vi /etc/hosts.allow 설정 파일을 vi로 연다. ... ALL: 111.222.333.444, 222.333.444.555 위와 같이 허용할 아이피를 지정할 수 있다. 여러 아이피인 경우 콤마(,)로 입력한다. ... sendmail: 111.222.333.444, 222.333.444.555 위와 같이 sendmail 에 대한 접근 허용을 할 수도 있다.
-
[centOS] 포트별 접속자 수를 출력하는 sh 스크립트 파일 작성
현재 포트별 접속자 수를 출력하는 스크립트. 스크립트 파일 작성 vi로 스크립트 파일을 작성한다. # vi /var/log/port_stat.sh 파일 내용에 아래와 같이 입력한다. #!/bin/bash ports=("443" "80" "21000" "20000" "3306") for port in "${ports[@]}"; do count=$(netstat -an | grep ":${port}" | wc -l) echo "Port ${port} => ${count}" done 위 스크립트를 실행하면, 아래와 같이 포트별 접속자 수가 출력된다. # /var/log/port_stat.sh
-
[centOS] 아파치 access_log 에서 특정 기간동안 아이피별 접속 횟수 추출하기
아파치의 access_log 파일 내용을 활용하여 특정 기간동안 아이피별로 접속 횟수를 추출해주는 스크립트 파일. 오늘 아이피별 접속 횟수 출력 vi로 sh 파일을 생성한다. # vi /var/log/today_log.sh 파일 내용에 아래와 같이 입력한다. #!/bin/bash LOG_FILES=( "/var/log/httpd/access_log" "/home/username/access_log" ) DATE=$(date +"%d/%b/%Y") for LOG_FILE in "${LOG_FILES[@]}"; do output=$(grep "${DATE}" "${LOG_FILE}" | grep -Ev '(\.js|\.css|\.woff|\.jpg|\.jpeg|\.gif|\.png|\.bmp|\.txt)' | awk '{ip_count[$1]++} END {for (ip in ip_count) {print ip, ip_count[ip]}}' | sort -k2,2n) echo "[ Log File: ${LOG_FILE} ]" echo "$output" echo done 위 스크립트중 LOG_FILES 배열은 추출할 다수의 로그 파일 경로를 지정하며, grep -Ev '(\.js|\.css|\.woff|\.jpg|\.jpeg|\.gif|\.png|\.bmp|\.txt)' 는 js, css, jpg 등 리소스 파일은 제외하고 순수한 웹페이지 파일 접속 아이피만을 추출한다. 위 스크립트를 실행하면, 아래와 같이 아이피별 접속 횟수가 출력된다. # /var/log/today_log.sh
-
[centOS] CentOS 7 에서 기본적인 iptables 설정
centos7은 firewalld와 iptable이 함께 구동 되는데, 나의 경우 firewalld가 익숙하지 않기 때문에 firewalld를 비활성화 한 뒤 iptable 위주로 사용한다. 서버 앞단에 방화벽이 없는 경우 iptable 설정이 필수이기 때문에 기본적인 설정 방법을 정리해 본다. firewalld 사용을 원치 않는 경우 비활성화 하기 아래 명령어로 firewalld를 종료 및 비활성화 한다. # systemctl stop firewalld # systemctl mask firewalld iptables 정책 확인 아래와 같이 현재 설정되어 있는 iptable 정책 내용을 확인한다. # iptables -nL 모든 포트 접속을 차단한 뒤 특정 포트만 접속 허용 보안을 위해 서버에 들어오는 모든 포트를 기본적으로 차단하고 특정 필요한 포트만 개방시키는 정책을 설정한다. 먼저 설정되는 정책이 우선 순위를 갖게 되므로 허용할 포트를 먼저 설정한 뒤 모든 포트를 차단하는 정책을 마지막에 설정해야 한다. 차단 정책이 먼저 설정되는 경우 SSH 접속이 불가하니 주의해야 한다. 가장 먼저, 현재 등록되어 있는 정책을 모두 초기화 시킨다. # iptables -F output tcp/udp 포트는 모두 개방시킨다. # iptables -A OUTPUT -p tcp -j ACCEPT # iptables -A OUTPUT -p udp -j ACCEPT 한번 연결된 트래픽에 대한 응답을 지속 시키기 위해 아래와 같이 정책을 추가한다. 아래 정책이 없는 경우 pdo로 database를 연결하는 웹앱에서 문제가 발생할 수 있다. # iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 그 다음, 필요한 포트를 아래와 같이 개방 시킨다. # iptables -A INPUT -p tcp --dport 22 -j ACCEPT 아래와 같이 범위로 포트를 지정할 수도 있다. # iptables -A INPUT -p tcp --match multiport --dports 5000:5050 -j ACCEPT 필요 포트를 모두 개방 하였다면, 마지막으로 나머지 포트를 모두 차단한다. # iptables -A INPUT -j DROP 등록된 정책의 우선순위 변경 아래와 같이 나중에 등록한 정책의 우선순위를 높일 수 있다. 원하는 우선순위를 숫자로 입력하여 설정한다. # iptables -I INPUT 1 -p tcp --dport 8080 -j ACCEPT 등록된 정책 삭제 등록된 정책 중 원치않는 정책을 삭제할 수 있. 우선순위의 숫자로 지정 하거나, 포트 번호를 명시하여 지정할 수 있다. # iptables -D INPUT 1 # iptables -D INPUT -p tcp --dport 8080 -j ACCEPT 정책 저장 및 복구 iptable 사용시 주의해야 할 점은, 데몬을 restart하는 경우 정책이 모두 초기화 된다는 점이다. (이를 보완하기 위한 데몬이 존재하기는 하지만) 지금까지 설정한 정책을 시스템에 저장한 뒤 원할 때 마다 복구시킬 수 있는 방법이 있다. 먼저, iptable 정책 설정이 마무리 되었다면 아래와 같이 정책을 저장한다. # service iptables save or # iptables-save > /etc/sysconfig/iptables 데몬 재시작 후 정책이 초기화 되었다면 아래와 같이 저장된 정책을 다시 복구시킨다. # iptables-restore < /etc/sysconfig/iptables iptable을 통해 접속 ip 차단 시키기 iptable에서 특정 input ip를 접속 차단시킬 수 있는데, 정책 등록시 아이피 대역으로도 설정할 수 있다. 아래와 같이 ip를 지정하여 접속을 차단시킨다. # iptables -A INPUT -s 111.222.333.444 -j DROP [ ip대역으로 차단하는 경우 - 111.222.333.xxx ] # iptables -A INPUT -s 111.222.333.0/24 -j DROP [ ip대역으로 차단하는 경우 - 111.222.xxx.xxx ] # iptables -A INPUT -s 111.222.0.0/16 -j DROP [ ip대역으로 차단하는 경우 - 111.xxx.xxx.xxx ] # iptables -A INPUT -s 111.0.0.0/8 -j DROP
-
[PHP] sms 본문 내용 byte 계산 (멀티바이트로 계산하기 - 한글 2byte)
SMS의 내용을 byte로 계산할 때 일반적으로 한글, 특수문자는 2byte, 영어, 숫자 줄바꿈등은 1byte로 계산한다. 한글을 php나, javascript에서 UTF-8의 byte를 계산하는 경우 3byte로 계산하는데, sms 서비스의 경우 한글을 2byte로 계산해야 한다. mb_strwidth() 함수를 사용한 byte 계산 아래와 같이 멀티바이트 (string width)로 계산하면 한글을 2byte로 계산할 수 있다. function getByteLength($str) { $strlen = mb_strwidth(str_replace("\r\n", "\n", $str), 'UTF-8'); return $strlen; } 위 코드 중 str_replace("\r\n", "\n", $str) 코드는 리눅스의 경우 줄바꿈을 \r\n 으로 처리하기 때문에 2byte가 되는데, 이를 윈도우 기준인 \n으로 치환하여 1byte로 계산 하도록 한다.
-
[Javascript] SMS 본문 내용 byte 수 계산하는 함수
SMS문자 본문 내용의 byte를 계산하는 간단한 코드. ASCII 코드가 128이상인 경우(한글, 한문, 특수기호 등) 2byte로 계산하고 그 외의 문자 (영어, 숫자, 기본기호 등)는 1byte로 계산한다. Javascript // 내용 byte 체크 function getByteLength(str) { var byteLen = 0; for(var i = 0; i < str.length; i++) { var charCode = str.charCodeAt(i); if (charCode > 128) { byteLen += 2; } else { byteLen ++; } } return byteLen; }
-
[jQuery] 마우스 드래그 금지 & 우클릭 금지
마우스 드래그 및 우클릭 금지하는 jquery 코드. event로 간단하게 처리 가능하다. jQuery <script type="text/javascript"> $(document).ready(function(){ //우클릭 금지 $(document).bind('contextmenu', function(e){ return false; }); //드래그 금지 $('*').bind('selectstart', function(e){ return false; }); }); </script>
-
[PHP] microtime과 랜덤 문자를 조합하여 중복되지 않는 PK 문자 만들기
microtime() 과 랜덤 글자 조합하여 중복되지 않는 Primary Key 문자를 생성하는 함수. 함수의 인자 값으로 원하는 길이를 넘기면 랜덤 문자열과 microtime()을 조합 후, 다시 str_shuffle()로 무작위로 섞은 결과 문자열을 return 해준다. ($length는 최소 30자 이상 설정 가능) Primary Key 생성 함수 function make_random_char($length = 30) { $length = ($length < 30) ? 30 : $length; $length = $length - 19; $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $randomString = ''; $max = strlen($characters) - 1; for ($i = 0; $i < $length; $i++) { $randomString .= $characters[mt_rand(0, $max)]; } $microtime = str_replace(array(' ', '.'), array('', ''), microtime()); return str_shuffle($randomString.$microtime); // 문자열을 다시 무작위로 섞음 } 결과 예시 4q344nM250001GS69e2y2X61198mT1
-
[PHP] 연락처가 올바른 연락처인지 검증하는 함수
연락처가 올바른 연락처인지 검증하는 함수. 함수에 연락처를 인자로 전달할 때 하이픈(-)을 포함하여야 한다. - 000-000-0000 (휴대전화번호) - 000-0000-0000 (휴대전화번호) - 00-000-0000 (유선전화번호) - 00-0000-0000 (유선전화번호) - 000-000-0000 (유선전화번호) - 000-0000-0000 (유선전화번호) - 0000-0000 (대표전화번호) <?php function get_phone_check($number) { if (!preg_match('/^[0-9-]/', $number)) return false; if (!preg_match('/^0(2|[3-9]\d{1})-?\d{3,4}-?\d{4}$|^01([016789])-?\d{3,4}-?\d{4}|\d{4}-\d{4}$/', $number)) return false; return true; } ?>
-
[Javascript] 연락처가 올바른 연락처인지 검증하는 함수
연락처가 올바른 연락처인지 검증하는 함수. 지원되는 연락처 유형은 아래와 같다. - 휴대전화 번호 - 02 (서울) 번호 - 000 (지역) 번호 - 0000-0000 대표번호 Javascript check_phone = function(destPhone) { var regex = /^[0-9-]/; var regex2 = /^0(2|[3-9]\d{1})-?\d{3,4}-?\d{4}$|^01([016789])-?\d{3,4}-?\d{4}|\d{4}-\d{4}$/; if (regex.test(destPhone) && regex2.test(destPhone)) { return true; } else { return false; } };
-
[PHP] 연락처가 휴대전화 번호인지 유선전화번호인지 확인하는 함수
연락처가 휴대전화 번호인지 유선전화 번호인지 검증하는 함수. 휴대전화 번호라면, 'phone'을, 그 외 유선전화 번호라면 'tel'을 반환한다. 함수에 연락처를 인자로 전달할 때 하이픈(-)을 포함하여야 한다. <?php function get_phone_type($number) { $is_phone_number = preg_match('/^01([016789])-?\d{3,4}-?\d{4}$/', $number); $is_tel_number = preg_match('/^(0\d{1,2}[-\s]?)?\d{3,4}[-\s]?\d{4}$/', $number); if (!$is_phone_number && !$is_tel_number) return false; return ($is_phone_number) ? 'phone' : 'tel'; } ?>
-
[PHP] 숫자만 입력한 연락처에 자동으로 하이픈(-) 추가해주는 함수
하이픈(-) 없이 입력한 휴대전화번호, 유선전화번호에 자동으로 하이픈을 반환해주는 함수. 지원되는 연락처는 아래와 같다. - 000-000-0000 (휴대전화번호) - 000-0000-0000 (휴대전화번호) - 00-000-0000 (유선전화번호) - 00-0000-0000 (유선전화번호) - 000-000-0000 (유선전화번호) - 000-0000-0000 (유선전화번호) - 0000-0000 (대표전화번호) <?php function set_add_phone_hipen($value) { if (!$value) return ""; $value = preg_replace('/[^0-9]/', '', $value); $result = array(); $restNumber = ""; if (strpos($value, "02") === 0) { $result[] = substr($value, 0, 2); $restNumber = substr($value, 2); } elseif (strpos($value, "1") === 0) { $restNumber = $value; } else { $result[] = substr($value, 0, 3); $restNumber = substr($value, 3); } if (strlen($restNumber) === 7) { $result[] = substr($restNumber, 0, 3); $result[] = substr($restNumber, 3); } else { $result[] = substr($restNumber, 0, 4); $result[] = substr($restNumber, 4); } return implode("-", array_filter($result)); } ?>
-
[jQuery] 멀티 파일 업로드 플러그인 (MultiFile)
:file input을 멀티파일 업로더로 손쉽게 적용해주는 jQuery 플러그인. 첨부 가능 확장자, 용량 제한 등 다양한 옵션을 제공하는 간편한 플러그인이다. 직관적인 작동 방식으로 커스터마이징이 편하다. HTML <input type="file" name="attach" id="attach"> <div class="attaedbox"></div> jQuery <script type="text/javascript"> $(':file[name=attach]').MultiFile({ 'max' : 5, 'accept' : 'gif|jpg|jpeg|bmp|png|pdf', 'maxfile' : 10240, //각 파일 최대 업로드 크기 (kb) 'list' : $(':file[name=attachedbox]'), //파일목록을 출력할 요소 지정가능 'STRING' : { // error문구를 원하는대로 수정 'remove' : "<a href=\"#\" class=\"remove\">제거</a>", 'duplicate' : "$file 은 이미 선택된 파일입니다.", 'denied' : "$ext 는(은) 업로드 할수 없는 파일확장자입니다.", 'selected' :'$file 을 선택했습니다.', 'toomuch' : "업로드할 수 있는 최대크기를 초과하였습니다.($size)", 'toomany' : "업로드할 수 있는 최대 개수는 $max개 입니다.", 'toobig' : "$file 은 크기가 매우 큽니다. (max $size)" } }); </script>
-
[Javascript] text input에 연락처 입력시 자동 하이픈(-) 처리
text input에 연락처를 입력하는 경우 자동으로 하이픈(-) 처리하는 코드. 지원되는 연락처 유형은 아래와 같다. - 휴대전화 번호 - 02 (서울) 번호 - 000 (지역) 번호 - 0000-0000 대표번호 HTML <input type="text" callnumber /> Javascript $(document).on('keyup', 'input[callnumber]', function() { var value = $(this).val(); if (!value) return ""; value = value.replace(/[^0-9]/g, ""); let result = []; let restNumber = ""; // 지역번호와 나머지 번호로 나누기 if (value.startsWith("02")) { // 서울 02 지역번호 result.push(value.substr(0, 2)); restNumber = value.substring(2); } else if (value.startsWith("1")) { // 지역 번호가 없는 경우 // 1xxx-yyyy restNumber = value; } else { // 나머지 3자리 지역번호 // 0xx-yyyy-zzzz result.push(value.substr(0, 3)); restNumber = value.substring(3); } if (restNumber.length === 7) { // 7자리만 남았을 때는 xxx-yyyy result.push(restNumber.substring(0, 3)); result.push(restNumber.substring(3)); } else { result.push(restNumber.substring(0, 4)); result.push(restNumber.substring(4)); } $(this).val(result.filter((val) => val).join("-")); });
-
[PHP] pdo를 class의 __construct(생성자) 로 연결하는 경우 인스턴스 여러개 만들어도 한번만 연결 되도록 하기
내가 직접 개발한 CMS를 실무에 잘 사용해 오다, 최근 비교적 복잡한 기능을 개발하다 치명적인 문제점을 발견하게 됐다. mariadb를 pdo로 접속해서 php와 연동하여 사용하는데, php 코드에서 필요할 때 마다 pdo접속 Class를 인스턴스로 매번 생성하여 사용한다. (아래 예시) $db = new PdoClass(); $db2 = new PdoClass(); $db3 = new PdoClass(); ... PdoClass() 함수는 __construct() (생성자 함수) 로 pdo에 자동 접속되도록 구성되어 있다. (new PDO) 즉, 위 코드대로 라면 pdo 접속이 3번 연달아 발생하게 되는 것이다. 오랜 기간 동안 pdo 중복 접속으로 인해 DB 성능이 저하되고 있다는 것을 간과하고 있었다. (특정 웹페이지는 무려 20번 이상의 pdo 중복 연결이 이뤄지고 있었었으며, 페이지 로딩 시간은 500ms 에 달했다.) 특히나, 내가 운영중인 서비스의 경우 외부DB 서버를 이용하고 있어 체감되는 접속 지연은 배가 되었다. 지금이라도 발견 했으니 다행이라 생각한다. 기본 중의 기본을 실수해 버렸고, 기본 중의 기본인 방법으로 이를 해결했다. 최초 인스턴스 생성시 다수의 인스턴스가 생성 되어도 1개만 존재할 수 있는 static 변수에 pdo 객체를 저장한다. 이후 두번째 인스턴스 연결 부터는 static 변수에 저장된 객체가 있다면 중복 연결 하지 않고 기존의 pdo객체를 재활용 하게 된다.
-
Python Django 를 Mariadb와 연동 및 admin 활성화 방법
Python Django를 설치하면 기본으로 설치되는 urls.py 파일에 아래와 같은 코드를 확인할 수 있는데, django를 설치하게 되면 기본적으로 admin 기능이 함께 설치가 되는데, admin 페이지 접근을 위해 작성되어 있는 코드다. django 개발시 admin페이지를 손쉽게 구축할 수 있으며, 웹사이트의 관리 또한 한결 쉬워진다. 브라우저에서 https://domain.name/admin 과 같이 접근하면 장고 admin페이지로 접근된다. admin을 사용하기 위해선 서버 환경에 아래 몇가지 사전 작업이 필요하다. - django 와 mariadb 연동을 위한 settings.py 환경설정 - django project에 커넥터 모듈 (pymysql) 설치 - django manage.py 로 table 생성 및 static 파일 다운로드 django 와 mariadb 연동을 위한 settings.py 환경설정 django 설치시 admin은 로컬서버의 sqlite dmns를 기본으로 사용하도록 셋팅되어 있다. 하지만, 나의 경우 외부에 mariadb 서버가 따로 있으므로, sqlite 대신 원격 mariadb를 바라보도록 설정했다. mariadb 연동을 위해 settings.py 파일을 vi로 연다. 나의 경우 ( /home/py/public_html/testproject/testproject/settings.py ) 경로에 설정 파일이 있다. #vi /home/py/public_html/testproject/testproject/settings.py settings.py을 열어 보면 아래와 같이 기본 설정되어 있는 것을 확인할 수 있다. 위 설정을 아래와 같이 변경한다. 여기서 반드시 'ENGINE'을 'django.db.backends.mysql' 로 설정해야 한다. (mariadb는 mysql엔진에서 파생되어 나온 엔진이기 때문에 mysql로 설정하면 된다.) django project에 mysql 커넥터 모듈 설치 (pymysql) 설치 django에서 mariadb 연결을 위해 mysql 커넥터 모듈이 설치되어 있어야 한다. 나의 경우 django를 python 가상 환경에서 설치 하였기 때문에 가상환경 진입 후 모듈을 설치하였다. 먼저, 가상환경 디렉토리가 있는 경로로 이동한다. # cd /home/py/public_html/ ( 이 경로에 'pyenv'라는 명칭으로 만들어 놓은 가상환경 디렉토리가 있다. ) pyenv(가상환경 디렉토리)를 통해 가상 환경에 접근한다. # source pyenv/bin/activate 가상 환경에 진입 되었다면, pip를 통해 pymysql 모듈을 설치한다. 파이썬 공식 사이트에서는 mysqlclient 사용을 권장하고 있지만, mysqlclient는 centos 환경에 mysql-devel 이 설치되어 있어야 하기에, 나는 그냥 pymysql을 설치했다. (성능은 mysqlclient 가 더 좋다고 한다.) (pyenv) pip3 install pymysql 설치가 완료 되었다면, deactivate로 가상환경에서 빠져 나온다. (pyenv) deactivate * mysqlclient 를 설치했다면 manage.py 설정 변경은 필요 없지만, pymysql을 설치했기 때문에 manage.py 와 settings.py 에서 pymysql을 mysqldb로 인식 시켜줘야 한다. (기본이 mysqlclient 인가보다.) # vi /home/py/public_html/testproject/manage.py 로 열어 아래와 같이 pymysql관련 구문을 추가한다. import pymysql pymysql.install_as_MySQLdb() 마찬가지로, settings.py 에도 추가해 준다. # vi /home/py/public_html/testproject/testproject/settings.py 로 열어 아래와 같이 pymysl관련 구문을 추가한다. import pymysql pymysql.install_as_MySQLdb() manage.py 로 mariadb에 table 생성 앞서 만났던 manage.py를 통해 admin 구동에 필요한 기본 db table과 static 파일을 다운로드 받을 수 있다. manage.py가 있는 경로로 이동한다. # cd /home/py/public_html/testproject/ 아래와 같이 manage.py 명령어로 연동되어 있는 mariadb 데이터베이스에 admin 구동에 필요한 필수 table을 생성한다. # python3 manage.py migrate mariadb에 접속해서 table이 잘 생성 되었는지 확인해 본다. 생성된 여러개의 테이블이 확인 된다! 생성된 테이블에 manage.py를 통해 최고 권한의 superuser를 등록해주면 DB설정은 모두 끝. # python3 manage.py createsuperuser 화면에서 나오는 안내에 따라 관리자 id, email, pw를 차례로 설정한다. manage.py 로 static 파일 다운로드 DB 설정까지 모두 완료 됐다면, 브라우저로 /admin 을 접속 해보자! 위와 같이 css가 적용되지 않는채로 화면이 보이는데, 아직 admin 관련 static 파일을 다운로드 하지 않아서 그렇다. 좀 전과 마찬가지로 manage.py를 통해 자동 다운로드 한다. #python3 manage.py collectstatic 위와 같이 css, font, img, js 파일이 다운로드 됐다. 다시 한 번 admin으로 접속 해보자!
-
[centOS] CentOS 7 에서 여러 파일 동시에 개행처리 '\n' 으로 변경 (feat. vscode 개행 설정)
윈도우, mac, 리눅스는 vscode 나 에디트플러스 같은 IDE 등에서 코드를 작성하는 경우 개행(줄바꿈) 처리 방식이 다르다. 눈에 보이지 않지만, 라인의 끝(EOL)에는 각 os마다의 개행 코드가 들어간다. 윈도우 = \r\n mac = \r 리눅스 = \n 만약, 하나의 파일에 대해 윈도우와 mac을 왔다갔다 하며 코딩을 진행 했다면 두가지의 개행처리가 혼재되는 경우 vscode 등에서 줄바꿈이 두번 되거나, 컴파일이 안되는 등 문제가 발생할 수 있다. (문제가 되는 파일을 리눅스에서 vi로 열어보면 라인 끝에 ^M 이 비정상적으로 붙는 것을 확인할 수 있다.) 때문에, os를 혼용하며 코딩을 하더라도 개행처리가 한가지로 통일 되도록 해야 하는데, 호환성을 위해 리눅스 (\n) 기준으로 모두 통일시켜 작업하는 것이 좋다. 개행처리 오류가 발생한 파일들을 일괄적으로 '\n' 으로 변환하기 # find {폴더명} \( -name ".htaccess" -o -name "*.php" -o -name "*.html" -o -name "*.sql" -o -name "*.css" -o -name "*.js" -o -name "*.xml" -o -name "*.txt" -o -name "LEADME" -o -name "LICENSE" \) -type f -exec sed -i 's/\r//g' {} + 위 명령어를 리눅스에서 실행한다. 특정 폴더 내에서 .php / .html / .sql / .css / .js / .xml / .txt / LEADME / LICENSE 파일에 대해서 코드상의 개행을 '\n'으로 바꾼다. 쉽게 보면 윈도우 개행이 발견되면 '/r' 을 지워 리눅스 개행으로 바꾸는 것이다. vscode의 개행처리를 '\n'으로 변경 다시는 개행처리가 뒤섞이는 일이 없도록 vscode의 개행처리 설정을 변경한다. (\n 으로 통일.)
-
[HTML] 아이폰(iOS) Safari에서 전화번호, 주소, 이메일주소 자동링크 기능 끄기
HTML에 작성된 텍스트 중 전화번호(휴대전화번호), 주소, 이메일 주소로 예측되는 텍스트가 있는 경우 아이폰 Safari는 텍스트에 자동으로 링크를 활성화 해준다. Safari의 편의 기능이기는 하나, 퍼블리셔가 의도하지 않은 텍스트가 a태그의 스타일을 상속 받아 레이아웃이 깨지는 경우가 있다. 이럴 경우 자동으로 링크가 활성되지 않도록 meta태그로 기능을 끌 수 있다. <meta name="format-detection" content="telephone=no, address=no, email=no"> meta태그의 content 인자 값에 비활성화 되길 원하는 속성을 입력한다. telephone=no => 전화번호 자동링크 끄기 address=no => 주소 자동링크 끄기 email=no => 이메일 자동링크 끄기
-
Python Django 의 views.py 분리 및 urls.py 처리 방법
Python Django를 설치 후 프로젝트 디렉토리 내의 views.py 와 urls.py로 라우팅하여 웹페이지로 띄우게 되는데, 웹페이지의 수가 증가할 수록 코드가 길어져 식별이 어려워지게 된다. 이번 글에서는 views.py를 원하는 디렉토리에 여러개로 분산시키고 urls.py로 라우팅 하는 방법을 안내한다. 사전 작업 환경 views.py 와 urls.py 분리 작업에 앞서 현재 구성된 django 프로젝트의 환경을 요약해 본다. - 외부접속주소 : http://py.chanyeongpark.com - project경로 : /home/py/public_html/testproject/ - views.py / urls.py경로 : /home/py/public_html/testproject/testproject/ - app 경로 : /home/py/public_html/testproject/testapp/ 현재 /home/py/public_html/testproject/testproject/ 내에 위치한 views.py를 통해 template과 결합되고, urls.py를 통해 py.chanyeongpark.com 으로 외부 접속시 index 화면이 노출되고 있다. [현재 views.py] [현재 urls.py] project 메인 urls.py 설정 project 의 메인 urls.py 에서 app 디렉토리에 추가로 생성할 urls.py로 라우팅할 수 있도록 설정한다. 프로젝트 설정 폴더로 이동하여 urls.py를 vi로 연다. # cd /home/py/public_html/testproject/testproject # vi urls.py vi로 urls.py에 아래와 같이 app urls.py로 라우팅해주는 구문을 추가한다. from django.contrib import admin from django.urls import path, include from . import views urlpatterns = [ path('views/', include('testapp.urls')), path('admin/', admin.site.urls), path('', views.index, name='index'), ] urlpatters 에 path('views/', include('testapp.urls')), 가 추가 되었으며, 접속하는 url이 http://py.chanyeongpark.com/views/* 와 같은 경우 testapp 앱의 urls.py로 이관하게 된다. app 디렉토리에 views.py, urls.py 추가 생성 프로젝트 urls.py에서 이관 받아 매핑 처리할 views.py와 urls.py를 앱 디렉토리내에 추가 생성하도록 한다. 아래와 같이 앱 디렉토리로 경로 이동 후 views.py 파일들을 몰아 넣을 디렉토리를 하나 만든다. # cd /home/py/public_html/testproject/testapp/ # mkdir views vscode 등에서 작업할 수 있도록 호스팅 user(py) user에게 적절한 권한을 부여한다. # chown -R py.py views # chmod -R 705 views views 디렉토리로 들어가 새로운 views 파일 ( basic_views.py / test_views.py )을 생성한다. # cd views # vi basic_views.py basic_views.py는 아래 내용으로 작성한다. basic_views.py는 http://py.chanyeongpark.com/views/ 로 접속시 화면 출력을 담당한다. from django.shortcuts import render def index(request): return render(request, 'index.html') test_views.py를 하나 더 만든다. test_views.py는 http://py.chanyeongpark.com/views/test 로 접속시 화면 출력을 담당한다. # vi test_views.py from django.shortcuts import render def test(request): return render(request, 'views/test.html') views 파일을 생성 했다면, 그 다음 urls.py 추가 생성을 위해 앱 디렉토리로 이동한다. # cd ../ (또는) # cd /home/py/public_html/testproject/testapp vi 로 urls.py 를 작성한다. # vi urls.py urls.py 내용은 아래와 같다. from django.urls import path from .views import basic_views, test_views app_name = 'testapp' urlpatterns = [ path('', basic_views.index, name='index'), path('test', test_views.test, name='test'), ] from .views import basic_views, test_views 는 'app디렉토리 > views' 디렉토리 내의 basic_views.py 와 test_views.py 파일을 import 시키는 구문이다. app_name = 'testapp' 통해 app 이름을 명시한 뒤 urlpatters 를 추가한다. 이 때, http://py.chanyeongpark.com/views/test 로 URL을 매핑을 해야 하는데 '/views' 가 urlpatterns 에 명시되지 않은 이유는, 프로젝트 메인경로의 urls.py 에서 매핑하여 app디렉토리의 urls.py 로 라우팅 해줬기 때문이다. views 파일이 views 디렉토리에 새로 생성 되었으니, app 디렉토리의 기본 views.py는 필요가 없어졌으니 삭제 한다. # rm -rf /home/py/public_html/testproject/testapp/views.py app 에 template 생성 앞서 생성한 앱의 views 파일에서 결합된 template 파일 생성을 위해 app의 templates 경로로 이동한다. # cd /home/py/public_html/testproject/testapp/templates templates 경로에 http://py.chanyeongpark.com/views/ 와 결합될 index.html 템플릿을 생성한다. (경로는 앞서 작성한 basic_views.py 에서 명시한 경로와 일치해야 한다.) # vi index.html (내용은 'Hello World 1' 로 했다.) 그런 다음, 디렉토리를 하나 더 만들어 http://py.chanyeongpark.com/views/test 와 결합될 템플릿을 하나 더 만든다. (경로는 앞서 작성한 test_views.py 에서 명시한 경로와 일치해야 한다.) # mkdir views # vi views/test.html (내용은 'Hello World 2' 로 했다.) 현재까지 작성된 파일들의 구조는 아래 화면과 같다. 브라우저에서 테스트 해보기 urls.py가 제대로 매핑 되는지 웹브라우저에서 접속해 본다. [http://py.chanyeongpark.com/views/ & http://py.chanyeongpark.com 출력 결과] http://py.chanyeongpark.com 의 경우 프로젝트의 urls.py에서 앱의 urls.py에서 설정한 index와 같은 템플릿 파일로 설정되어 있기 때문에 http://py.chanyeongpark.com/views/ 와 같은 화면을 호출하고 있다. [http://py.chanyeongpark.com/views/test 출력 결과]
-
CentOS7 Apache 환경에 Python Django 설치하기
CentOS 7 환경에서 Python Django를 설치한 뒤 Apache의 Virtual Host에 연결하여 웹에서 띄우는 방법을 설명한다. 사전에 Python3와 Apache2가 설치되어 있어야 하며, Virtual Host 구동을 위해 'py' 라는 user와 호스팅 경로(/home/py/public_html)를 만들어둔 상태다. Python 가상환경 진입 및 프로젝트, 앱 생성 Django를 사전에 만들어 놓은 홈디렉토리(/home/py/public_html/)에 설치해도 구동에 문제는 없지만, 로컬 python환경의 의존적이지 않은 독립적인 구동 환경 구성을 위해 가상환경을 생성한 다음 가상환경내에서 django 설치와 프로젝트 생성, 앱 생성등의 작업을 수행한다. 우선, django 프로젝트를 생성할 미리 만들어 놓은 홈디렉토리로 이동한다. #cd /home/py/public_html/ pyenv 명칭의 새로운 가상환경을 생성한다. # python3 -m venv pyenv 위와 같이 가상환경을 생성하면 현재 경로에 pyenv 디렉토리가 새로 생긴 것을 확인할 수 있다. 새로 생성된 디렉토리 내에 가상환경 관련 실행파일이 위치해 있으며, 아래 명령어를 통해 가상환경에 진입한다. # source pyenv/bin/activate 위와 같이 진입하게 되면 프롬프트상에 '(penv)' 가 추가되며, 진입에 성공한다. 이제, django 패키지를 설치하면 된다. (pyenv) pip3 install django 설치가 완료 되었다면, 같은 경로에 testproject 명칭의 django 프로젝트를 생성한다. (pyenv) django-admin startproject testproject 프로젝트 생성이 완료되면 방금 전 생성한 pyenv와 나란히 testproject 디렉토리가 생성된다. 그런 다음, testproject 디렉토리로 들어간다. (pyenv) cd testproject testproject 내부에 새로운 앱을 생성하기 위해 아래와 같이 명령어를 실행한다. (pyenv) python3 manage.py startapp testapp 현재 경로에 testapp 디렉토리가 새로 생긴 것을 확인할 수 있다. 이제 모든 가상환경 셋팅이 마무리 되었으며, 아래 명령어로 가상환경에서 빠져 나온다. (pyenv) deactivate 현재까지 생성된 디렉토리의 구성은 아래와 같다. Django 에 필요한 teplates, static 디렉토리 생성 Django View역할을 할 html 파일들이 위치할 templates 디렉토리와 img, css, js 등의 정적 파일들이 위치할 static 디렉토리를 생성하기 위해 앞서 생성된 testapp 디렉토리로 이동한다 # cd testapp templates, static 디렉토리를 생성한다. # mkdir templates static vscode 등에서 파일을 작성하거나 수정할 수 있어야 하기에 적절히 권한을 부여한다. # chown -R py.py templates static # chmod -R 705 templates static Django wsgi.py, setting.py 환경 설정 기본적인 django 설정을 위해 프로젝트 환경설정 디렉토리로 이동한다. # cd ../testproject (혹은) # cd /home/py/public_html/testproject/testproject wsgi.py 파일을 vi 로 연다. # vi wsgi.py 아래와 같이sys 모듈과 django.core.handlers.wsgi 모듈을 import한 뒤 프로젝트 디렉토리와 가상환경 모듈 디렉토리를 시스템 경로로 설정한다. import os import sys import django.core.handlers.wsgi sys.path.append('/home/py/public_html/testproject') sys.path.append('/home/py/public_html/pyenv/lib/python3.6/site-packages') from django.core.wsgi import get_wsgi_application os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testproject.settings') application = get_wsgi_application() setting.py 파일을 vi 로 연다. # vi setting.py ALLOWED_HOSTS 에 접근 host 값을 추가한다. 모든 host가 접근 가능하도록 설정 하려면 '*'를 입력한다. INSTALLED_APPS 에 앞서 추가한 앱 이름을 추가한다. TEMPLATES 에서 DIRS 에 앞서 생성한 templates 디렉토리 경로를 입력한다. LANGUAGE_CODE 와 TIME_ZONE 을 설정한다. STATIC_ROOT 를 추가하고 앞서 생성한 경로를 입력 해준다. Apache Vritualhost에 Django 앱 연동 Apache Virtualhost에 django 앱을 연동하여 도메인 접속으로 웹에서 볼 수 있도록 연동한다. 연동에 앞서 먼저 apache 와 django를 연동해주는 아파치 모듈을 yum으로 설치한다. # yum install mod_wsgi virtualhost 설정파일을 열어 호스트를 추가한다. # vi /etc/httpd/conf.d/vhosts.conf 위 예시는 py.chanyeongpark.com 으로 접속시 django 프로젝트의 wsg.py를 참조하여 프로젝트와 static 디렉토리를 호스팅 하는 역할을 해준다. <VirtualHost *:80> ServerName py.chanyeongpark.com DocumentRoot /home/py/public_html ErrorLog /home/py/error_log CustomLog /home/py/access_log common WSGIScriptAlias / /home/py/public_html/testproject/testproject/wsgi.py <Directory /home/py/public_html/testproject> <Files wsgi.py> Require all granted </Files> </Directory> Alias /static /home/py/public_html/testproject/testapp/static <Directory /home/py/public_html/testproject/testapp/static> Require all granted </Directory> </VirtualHost> 아파치 재시작 후 웹브라우저에서 실행시 아래와 같이 화면이 나온다면 정상적으로 모든 설치가 완료된 것이다. urls.py 설정으로 index 화면 설정하기 아파치 설정 후 웹브라우저로 접속시 위와 같은 django 환영 페이지가 노출되는 이유는 urls.py 설정이 되지 않았기 때문이다. django는 urls.py 설정을 통해 간단하게 접속 url을 조작하여 controller 구성을 할 수 있다. urls.py가 route 역할을 한다고 보면 된다. 웹페이지가 구성되기 위해선 templates/index.html => 템플릿 파일 views.py => Controller 파일 urls.py => route 세 파일이 결합되어야 한다. 먼저, 템플릿 파일 생성을 위해 앱 디렉토리의 templates 로 이동한다. # cd /home/py/public_html/testproject/testapp/templates index.html 파일을 만든다. # vi index.html (예시에서 index.html 의 파일 내용은 'Hello World!!' 로 했다.) view.py 설정을 위해 프로젝트 설정 디렉토리로 이동한다. # /home/py/public_html/testproject/testproject 해당 경로 내에 view.py 파일이 없는 경우도 있는데, vi 로 파일을 새로 생성하면 된다. # vi views.py views.py 내용은 아래와 같이 작성한다. from django.shortcuts import render def index(request): return render(request, 'index.html') urls.py를 설정하기 위해 vi로 설정 파일을 연다. # vi urls.py urls.py 내용을 아래와 같이 추가한다. from django.contrib import admin from django.urls import path from . import views urlpatterns = [ path('admin/', admin.site.urls), path('', views.index, name='index'), ] from . import views (파일명) 로 방금 생성한 views.py를 import 했고, urlpatterns 에 path('', views.index, name='index') 를 추가하여 앞서 생성한 views.py 의 index 함수를 호출하도록 했다. views.index 함수 구문에 의해 index.html 이 render되어 브라우저에 출력 되는 것이다.
-
[Javascript] 텍스트 클릭시 클립보드(clipboard)에 복사
특정 텍스트 클릭시 클립보드(Clipboard)에 복사하는 Javascript 코드. 복사할 텍스트를 text input 에 value값으로 넣어 클릭시 텍스트를 전체 선택하고 클립보드에 복사하는 방법이다. javascript 구문을 input의 onclick으로 작성 하였기 때문에 간편한 사용이 가능하다. HTML & Javascript <input type="text" value="복사할 텍스트" onclick="this.select();document.execCommand('copy');alert('클립보드에 복사 되었습니다.');return false;" readonly />