요약하면 UpdraftPlus를 이용해서 사이트 백업 후, 다음 파일을 wordpress 디렉토리 내부에 comments-fix.php로 저장한 후 이를 브라우저에서 로딩해서 실행한다. 내부의 DB_HOST, DB_USER, DB_PASSWORD, DB_NAME 등을 바꾼다. 나의 경우, “localhost”, “dasomoli”, “PASSWORD”, “wordpress” 로 바꿔주었다.
<?php
include("wp-config.php");
$myConnection = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD);
if (!mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD)) { die('Could not connect: ' . mysqli_error()); }
if (!mysqli_select_db($myConnection, DB_NAME)) { die('Could not connect: ' . mysqli_error()); }
$result = mysqli_query($myConnection, "SELECT term_taxonomy_id FROM ".$table_prefix."term_taxonomy");
while ($row = mysqli_fetch_array($result)) {
$term_taxonomy_id = $row['term_taxonomy_id'];
echo "term_taxonomy_id: ".$term_taxonomy_id." count = ";
$countresult = mysqli_query($myConnection, "SELECT count(*) FROM ".$table_prefix."term_relationships WHERE term_taxonomy_id = '$term_taxonomy_id'");
$countarray = mysqli_fetch_array($countresult);
$count = $countarray[0];
echo $count."<br />";
mysqli_query($myConnection, "UPDATE ".$table_prefix."term_taxonomy SET count = '$count' WHERE term_taxonomy_id = '$term_taxonomy_id'");
}
$result = mysqli_query($myConnection, "SELECT ID FROM ".$table_prefix."posts");
while ($row = mysqli_fetch_array($result)) {
$post_id = $row['ID'];
echo "post_id: ".$post_id." count = ";
$countresult = mysqli_query($myConnection, "SELECT count(*) FROM ".$table_prefix."comments WHERE comment_post_ID = '$post_id' AND comment_approved = 1");
$countarray = mysqli_fetch_array($countresult);
$count = $countarray[0];
echo $count."<br />";
mysqli_query($myConnection, "UPDATE ".$table_prefix."posts SET comment_count = '$count' WHERE ID = '$post_id'");
}
?>
웹페이지 내에 오디오를 넣고 싶을 때는 audio element로 넣을 수 있다. src attribute 혹은 source element로 하나의 오디오 소스를 가지거나 audio element의 children으로 source element 리스트를 넣어서 여러개의 오디오 소스를 가질 수 있다.
<audio controls src="media/dasomoli.mp3">여러분의 브라우저가 audio 태그를 지원하지 않는 것 같네요..</audio>
위처럼 <audio>와 </audio> 사이에 브라우저가 지원하지 않을 때 나타낼 메시지를 넣을 수 있다. controls attribute는 여러분이 오디오를 재생할 수 있도록 할 수 있다. 다음과 같은 contol이 나타난다.
다음과 같은 속성들이 있다.
autoplay (boolean)
preload (none / metadata / auto)
loop (boolean)
controls
autoplay는 전부 다운로드 받지 않더라도 재생이 가능할만큼만 되면 바로 재생한다. 사람들이 웹페이지에 들어왔을 때 오디오가 바로 재생되면 싫어하므로 사용에 주의하라.
preload는 미디어 소스의 로딩을 어떻게 할지를 정하고 싶을 때 사용한다. none은 preload하지 않고, metadata는 metadata만 로드한다. auto는 empty string(“”)과 동등한데, 전체 파일이 로드된다.
loop는 반복 재생하도록 한다.
controls는 브라우저의 기본 미디어 컨트롤을 추가한다. 사용자가 오디오의 재생을 제어할 수 있다. 브라우저마다 UI가 다른데, 공통적인 기능은 비슷하다. UI가 다르므로 controls attribute를 셋팅하지 않고 HTML, CSS, Javascript를 사용해서 customize한 control을 생성, 원하는 디자인을 할 수도 있다.
webm, mp3, ogg등 브라우저마다 지원하는 format이 다르다. 이에 대해서는 MDN의 다음 글을 참고하자.
여러개의 source를 넣고 싶을 때는 source element를 이용한다. src attribute를 사용하지 않고 여러개의 source를 사용했음에 주목하라. 이 중 지원하지 않는 format이 있으면 다음 것을 시도한다.
<audio controls>
<source src="media/dasomoli.webm" type="audio/webm">
<source src="media/dasomoli.mp3" type="audio/mp3">
<source src="media/dasomoli.ogg" type="audio/ogg">
여러분의 브라우저가 <code>audio</code>를 지원하지 않는 것 같아요!
</audio>
동영상 (Video)
video element와 audio element는 둘 모두 HTML media elements이다. 사실 video element로 audio를, audio element로 video를 재생하는 것도 가능하다. video element는 display 영역을 제공한다는 것이 차이이다.
video element의 attribute는 audio element 것을 모두 가진다. 추가로 다음 attribute를 제공한다:
height
width
poster
width와 height attribute는 video display area의 width와 height을 각각 조정한다. 둘 모두 pixel로 조정된다. %로 비율을 쓸 수 없다.
poster attribute는 video가 다운로드되는 동안 보여줄 이미지를 지정한다. 지정하지 않으면 video의 첫 frame의 다운로드 전에는 빈 네모가 보이고, 첫 frame을 다운로드 받으면 그 첫 frame이 보일 것이다.
Text track
track element는 media element와 연관된 시간 기준의 글을 지정한다. 이는 미디어 재생과 싱크가 맞는 시간에 어떤 글을 보여줄 수 있다는 뜻이다. 자막이나 해당 미디어에 대한 설명은 물론, 앞이 안보이거나 소리가 안들리는 사람들에게도 어떤 것인지 설명할 수 있도록 해준다.
video의 source element와 같이 하나의 media element 에 여러개의 track element를 넣어서 그 media에 대한 여러 track을, 예를 들면 다른 언어 자막 같은 식으로 제공할 수 있다.
track element의 attribute는 다음과 같다:
src: text track file의 위치
default: media element 당 하나의 track element가 default track으로 지정될 수 있다. 사용자 설정에 따라 override될 수 있다.
kind: text track이 무엇으로 사용되는지를 지정한다. subtitles, captions, descriptions, chapters, metadata같은 여러 옵션이 있다. default는 subtitles이다.
위에서 source element는 media attribute를 갖는다. 위 코드는 첫번째 것부터 media attribute가 참인지를 보고 맞다면, 위 코드에서는 viewport가 639 픽셀 이하인지를 보고 맞다면 해당 이미지를 보여준다. 아니라면 다음 것으로 넘어간다. 다 안맞으면 마지막의 img의 것을 보여주게 된다. 브라우저가 picture를 지원하지 않을 때도 picture의 가장 마지막 것을 보여주게 된다.
조건으로 media 외에도 type attribute나 mime type도 사용할 수 있다.
위의 .jpeg, .gif, .png, .webp 같은 foramt외에도 SVG (Scalable vector graphics)나 canvas element 처럼 프로그래밍한 그래픽을 생성할 수 있다. SVG는 vector graphics를 위한 XML 기반의 format이고, canvas element는 웹페이지 상에서 rasterized graphics를 생성하는데 사용되는 JavaScript drawing API로 접근 할 수 있는 element다.
svg element
svg는 vector graphics를 정의하는 XML 기반 format이다. Vector graphics는 깨지는 문제없이 비율에 따라 계산되기 때문에 반응형 웹에 매우 유용하다. 간단한 예로 play와 stop button을 만든다고 하자.
viewBox attribute로 x좌표 0, y좌표 0에서 100 dimension으로 설정했다. viewBox는 pixel로 표시하지 않는다. width와 height attribute로 비율을 정할 수 있다. 안에 들어가는 children들은 viewBox의 상대적 위치에 놓이게 된다.
circle element로 x좌표 50, y좌표 50의 위치에 반지름 50짜리 원을 그렸고, 안을 black으로 채웠다. hex value #rrggbb로도 당연히 설정 가능하다. 그 후 path로 3점을 정해서 삼각형을 하나 그리고 이를 white로 채웠다. 비슷하게 stop 버튼은 사각형을 하나 그리고 이를 white로 채웠다. 위 소스는 다음과 같이 렌더링된다.
svg는 canvas처럼 javaScript가 필요하지 않고 바로 접근 가능하지만, shape들이 많으면 성능 문제가 일어날 수 있다.
canvas Element
canvas element로는 rasterized graphics를 렌더링할 수 있다. 이를 위해서 JavaScript의 drawing API를 사용한다. 2D와 WebGL의 두가지 렌더링 모드가 있다. WebGL은 GPU acceleration과 같은 shader support를 제공한다.
browser가 canvas를 지원하는지를 확인한 후 이용하는 것이 좋다. 확인하는 코드는 다음과 같이 쓸 수 있다.
moveTo(x, y) 로 옮기고, lineTo(x, y) 로 경로를 정한 후, strokeStyle을 정한 후 stroke()로 외곽선을 그린다. lineTo로 이어서 그린 후 해당 경로를 fillStyle로 정한 후 fill()로 채울 수도 있다.
사각형(Rectangle) 그리기
속이 빈 사각형을 외곽선 만으로 그리고 싶으면, strokeStyle로 외곽선의 style을 정하고, lineWidth로 외곽선 굵기를 정한 후, strokeRect(x, y, width, height)로 그린다.
안이 채워진 사각형을 그리고 싶으면 fillStyle로 style을 정하고, fillRect(x, y, width, height)로 그린다. fillStyle은 CSS에서 사용하는 값이면 다 쓸 수 있다. color, backgroundColor같은 property나 black, red, white 같은 color값, hex value #rrggbb나, rgba(25, 35, 45, 0.7) 같은 rgba 값도 가능하다.
외곽선과 안이 채워진 것을 모두 적용하고 싶다면, strokeStyle과 fillStyle을 모두 설정하고, rect(x, y, width, height)로 사각형 경로를 설정하고, fill()로 채우고, stroke()로 외곽선을 그리면 된다.
viewport는 사용자의 웹페이지의 보여지는 영역이다. 디바이스에 따라 다르다. 일반적으로 모바일 폰은 컴퓨터 화면보다 작을 것이다.
Responsive Viewport
위처럼 width property로 device-width로 viewport를 셋팅하면 그 디바이스의 해상도에 맞게 보여줄 수 있다. initial-scale은 그 윂페이지의 초기 zoom을 제어한다. 이 값은 별 일 없는 한 1로 하는 것이 좋다. maximum-scale을 1로 셋팅하면 zoom하지 못하게 할 수 있지만 권하지 않는다.
미디어 쿼리 (Media Queries) 이해하기
미디어 쿼리는 CSS3의 핵심 기능이다. @media 로 어떤 조건이 참이 될 때만의 CSS properties를 담는 rule을 사용한다. 디바이스의 screen width와 orientation(portrait 또는 landscape)에 따라 또는 인쇄된 종이에 보여지는 것 조차 display를 바꿀 수 있다.
먼저 breakpoint부터 보자. breakpoint는 디바이스나 웹 브라우저의 width 또는 height에 반응하는 웹페이지의 한 point이다. breakpoint threshold에 다다르면, 다른 스타일을 CSS로 적용할 수 있다.
breakpoint의 추가는 min-width나 max-width 룰을 추가함으로써 할 수 있다. 예를 들어 640px보다 작을 때를 지정하고 싶다면, max-width: 640px 를 쓴다. 반대로 640px 보다 클 때를 지정하고 싶다면, min-width: 640px 를 쓴다.
미디어 쿼리는 @media 뒤에 breakpoint 조건을 쓴 뒤 { } 안에 적용하고 싶은 CSS code를 적으면 된다. 예를 들어, max-width 800px로 screen에 어떤 스타일을 적용하고 싶다면 @media only screen and (max-width: 800px) 그리고 뒤에 { } 를 붙여 그 안에 스타일을 적어주면 된다.
다음 코드는 디바이스 상의 웹페이지가 800 px까지는 p 태그의 글자색을 red로 바꿀 것이다.
@media only screen and (max-width: 800px) {
p {
color: red;
}
}
@media 코드를 각 디바이스에 따라 다르게 아래처럼 적용할 수도 있다. 그러나 브라우저는 로딩 시 width에 따라 css파일을 load하지 않고, width와 상관없이 모든 css파일을 읽어들인다.
<link rel="stylesheet" media="screen and (max-width: 480px)"
href="mobilephone.css" />
<link rel="stylesheet" media="screen and (min-width: 481px) and
(max-width: 768px)" href="tabletpc.css" />
Device Orientation에 따른 처리
디바이스의 orientation에 따른 처리를 하고 싶다면, 다음 미디어 쿼리를 사용하면 된다. 아래 코드는 landscape일 때의 rule을 적용할 것이다.
@media (orientation: landscape)
반대로 portrait일 때의 rule은 다음으로 한다.
@media (orientation: portrait)
다음과 같은 코드는 orientation이 landscape일 때만 p.warning을 보인다.
Landscape 혹은 portrait로의 전환을 확인해보고 싶다면 브라우저의 개발자도구에서테스트 가능하다.
여러 개의 미디어 쿼리 합치기
여러 개의 breakpoint로 어떤 스타일을 지정하고 싶다면 콤마(,)를 사용해서 합쳐서 사용할 수 있다. 콤마(,)는 미디어 쿼리를 OR해서 처리한다. 다음 코드는 width 480px 에서 640px 사이, 또는 1024px를 넘어가면 배경색을 green으로 바꾼다.
@media screen and (max-width: 640px) and (min-width: 480px),
(min-width: 1024px) {
body {
background: green;
}
}
인쇄 시의 스타일 (Print Stylesheets) 지정
CSS3 미디어 쿼리는 해당 페이지를 인쇄할 때의 스타일을 따로 지정할 수 있다. 두가지 방법이 있다.
기존에 쓰던 Raspberry pi 3의 OS 버전 업그레이드를 게을리 했더니 해당 버전이 php5까지만 지원해서 그런가 자꾸 누가 들어온다;; 근래 설치했던 php7을 지원하는 Raspberry pi 4 4GB 모델로 워드프레스 블로그를 이전한다.
워드프레스 컨텐츠 내보내기
wordpress 내보내기 도구로 모든 컨텐츠 내보내기
먼저, 기존 워드프레스에서 wordpress 내보내기 도구를 이용해 모든 컨텐츠를 다운로드 받는다: “대시보드” > “도구” > “내보내기” > “모든 컨텐츠” 선택 후 “내보내기 파일 다운로드”
내보낸 파일에서 site 경로 수정하기 (optional)
여기서 내가 예전에 했던 일로 나만 적용되는 게 있는데, 맨 처음에 티스토리에서 워드프레스로 이전할 때 블로그 도메인 이름을 wp.dasomoli.org로 썼던 적이 있다. 그래서 모든 그 때 이전했던 글들 안의 이미지 경로가 wp.dasomoli.org를 사용한채로 export되었다. 내려받은 xml 파일 안의 모든 “wp.dasomoli.org” 혹은 “wp-dasomoli-org” 를 “blog.dasomoli.org”와 “blog-dasomoli-org”로 바꿔주었다.
미디어 라이브러리 복사해두기
미디어 라이브러리도 옮기기 위해 wp-content 안의 uploads/ 디렉토리를 압축해서 이전할 서버로 복사한다.
/var/www/wordpress/wp-content# tar cvfz uploads.tgz uploads
/var/www/wordpress/wp-content# scp uploads.tgz dasomoli@192.168.0.x:/home/dasomoli/
옮긴 미디어 라이브러리의 이전될 서버에서의 DB 등록을 위해서 “Moving Media Library” 플러그인을 설치한 후, 내보내기 후 json파일을 저장한다.
미디어 라이브러리 json 파일 내의 site 경로 수정하기 (optional)
여기서도 역시 json 파일 내부의 모든 “wp.dasomoli.org”를 “blog.dasomoli.org”로 수정한다.
/etc# tar cvfz letsencrypt.tgz letsencrypt
/etc# scp letsencrypt.tgz dasomoli@192.168.0.x:/home/dasomoli/
테마 추가 CSS 백업해두기
사용 중인 테마의 추가 CSS가 있다면, 해당 CSS 코드를 어딘가에 복사해두도록 한다: “테마 디자인” > “테마” > “사용자 정의하기” > “추가 CSS”
위젯 백업해두기
사용 중인 위젯들이 있다면, 해당 텍스트나 링크, 코드 등을 어딘가에 복사해두도록 한다: “테마 디자인” > “위젯”의 “Sidebar”
apache2 설정
새로 옮길 서버의 워드 프레스 경로는 이전 서버와 동일하게 “/var/www/wordpress”로 한다. 다음과 같이 이전 서버에서와 동일한 apache2의 site 설정 파일을 작성한다. https를 위한 Rewrite로 시작하는 마지막쯤의 주석 3줄은 지워도 무방하다.
# vi /etc/apache2/sites-available/blog.dasomoli.org.conf
<VirtualHost *:80>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
ServerName blog.dasomoli.org
<Directory /var/www/wordpress>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ServerAdmin dasomoli@gmail.com
DocumentRoot /var/www/wordpress
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/blog_error.log
CustomLog ${APACHE_LOG_DIR}/blog.access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
#RewriteEngine on
#RewriteCond %{SERVER_NAME} =blog.dasomoli.org
#RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
wordpress 설치
wordpress 내려받아 압축 해제하기
https://wordpress.org/ 에서 최신 버전의 wordpress의 .tar.gz 파일을 내려받아 새로 설치할 사이트의 /var/www/ 아래에서 압축을 해제한다. 현재는 5.4.1이다.
/var/www# tar xvfz wordpress-5.4.1.tar.gz
ads.txt 복사하기
ads.txt를 복사해온다.
/var/www/wordpress# cp ~dasomoli/ads.txt .
wordpress 디렉토리 아래 파일 owner와 권한 설정하기
/var/www/wordpress 디렉토리와 파일의 owner는 apache2를 실행하는 www-data로, 권한은 디렉토리는 755로, 파일은 644로 설정한다.
아래처럼 Require ip 구문을 추가한다. “::1” 은 local interface, 즉 127.0.0.1과 같다. “192.168.0” 은 192.168.0.x 대역을 말한다.
<Directory /usr/share/phpmyadmin>
Options SymLinksIfOwnerMatch
DirectoryIndex index.php
Require ip 192.168.0
Require ip ::1
apache2를 reload한다.
# systemctl reload apache2
wordpress가 사용할 database와 user 추가 및 설정하기
phpmyadmin은 phpmyadmin에서 database를 추가하기 위해서 root 사용자로 로그인하려고 할 때 어려움을 겪는다면, [MySQL] phpmyadmin에서 root 사용자 사용 불가 시 사용자 추가 방법을 참고하자. “wordpress” database와 “wordpress” 사용자를 추가한다. “wordpress” 사용자는 “wordpress” database에 모든 권한을 갖도록 설정한다.
apache2에서 wordpress site enable
apache2의 아까 설정했던 site를 enable한다.
# a2ensite blog.dasomoli.org.conf
워드프레스 설치 페이지 접속해 설치하기
워드프레스 설치 URL wp-admin/install.php (예를 들면, http://blog.dasomoli.org/wp-admin/install.php) 에 접속한다. 설치가 끝나면 wp-config.php가 생성될 것이다. 파일 권한 문제가 있어 생성하지 못하는 경우, 브라우저에 나타난 wp-config.php를 복사해서 쉘에서 생성 후 붙여넣기 한다.
미디어 라이브러리 복구하기
아까 복사해뒀던 미디어 라이브러리 압축 파일(uploads.tgz)를 wp-content/ 아래에서 압축 해제한다.
/var/www/wordpress/wp-content# cp ~dasomoli/uploads.tgz .
/var/www/wordpress/wp-content# tar xvfz uploads.tgz
uploads 디렉토리 역시 owner를 www-data로, 디렉토리는 755, 파일은 644로 권한 설정을 해준다.
div#primary는 primary content가 담기는 곳이다. 이는 실제 post를 담는 article element를 포함하는 main#main element로 싸여 있다. article element는 많은 class를 갖고 있는데, 이들로써 그 post를 다양한 방법으로 지정할 수 있도록 한다.
article 안에는 article의 header, h2, 그리고 div.entry-meta 안에 metadata를 담고 있는 header element가 있다. datetime 속성을 가지는 time element와 작성자를 보이는 vcard 등이 있다.
div.entry-content에 article이 담긴다. h3 이하 제목과 p elements, link들 같은게 담긴다.
textboxes나 textareas는 일반적으로 그 크기를 바꾸고, border를 제거한다. 또 예시 입력값인 placeholder를 추가해서 어떤 값을 입력하면 되는지를 도와주도록 한다.
button을 styling하기 위해서 일반적으로 배경색과 크기를 바꾼다. button의 box 바깥이 흉하므로 좀 손본다.
Select boxes를 styling하기 위해서는 일반적으로 text box처럼 보이게 만들고, 오른쪽의 아래 화살표를 styling한다.
form validation을 위해서 HTML은 required attribute를 제공한다. 입력이 꼭 필요한 field는 required attribute를 사용한다. CSS에서 이를 select하기 위해서 :valid 와 :invalid pseudo selector를 사용할 수 있다.