[AWS] Amazon Linux AMI 버전 - APM 세팅 하기[AWS] Amazon Linux AMI 버전 - APM 세팅 하기

Posted at 2020. 3. 27. 16:03 | Posted in AWS



참고 : Amazon Linux AMI를 사용하여 LAMP 웹 서버 설치





■ Amazon Linux AMI 업데이트


 $ sudo yum -y update

 



 Apache 2.4 세팅



#01. Apache2.4 설치

 $ sudo yum install httpd24

 


 $ sudo service httpd start

 


 $ sudo chkconfig httpd on

 


 $ sudo chkconfig --list httpd

 



#02. Apache2.4 설정 변경

 $ sudo vim /etc/httpd/conf/httpd.conf 

 


 $ sudo service httpd restart

 




 PHP 7.2 세팅



① PHP 7.2 설치


 $ sudo yum install php72

 


 $ php -v

 


 $ sudo usermod- a -G apache ec2-user

 


 $ exit

 


 $ groups

 


 $ sudo chmod -R ec2-user:apache /var/www

 


 $ sudo chmod 2775 /var/www

 


 $ find /var/www -type d -exec sudo chmod 2775 {} \;

 


 $ find /var/www -type d -exec sudo chmod 0664 {} \;

 


 $ sudo yum install php72-fpm php72-pdo php72-common php72-opcache php72-mcrypt php72-cli php72-gd php72-curl php72-mysql php72-mysqlnd php72-xml php72-xmlrpc php72-soap php72-mbstring php72-json php72-process php72-imap php72-devel

 



② php.ini 설정 변경

 $ php -ini | grep php.ini

 


 $ sudo vim /etc/php.ini

 



③ php 설치 및 설정 변경 확인

$ echo "<?php phpinof(); ?>" > /var/www/html/phpinfo.php

 






 Data Base 설치



#01. MySQL 설치


 $ sudo yum install mysql157-server

 


 $ sudo service mysqld start

 


 $ sudo chkconfig mysql on

 


$ sudo chkconfig --list mysql

 






#02. MariaDB 설치


① MariaDB 설치 준비


 $ sudo vim /etc/yum.repos.d/MariaDB.repo 

[mariadb]

name = MariaDB

baseurl = http://yum.mariadb.org/10.4/centos6-amd64

gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB

gpgcheck=1


 $ sudo yum clean metadata

 



② MariaDB 설치


 $ sudo yum install MariaDB-server MariaDB-client

 


 $ sudo service mysql start

 


 $ sudo chkconfig mysql on

 


$ sudo chkconfig --list mysql

 




#03. root 계정 비밀번호 설정 및 접속가능여부 설정

 $ sudo mysql_secure_installation

① Enter current password for root (enter for none) : Enter

② Change root password? [Y/n] Y

③ New password : 사용자 지정 패스워드

④ Re-enter new password: 사용자 지정 패스워드

⑤ Remove anonymous users? [Y/n] Y

⑥ Disallow root login seremotely? [Y/n] Y

⑦ Remove test database and access to it? [Y/n] Y

⑧ Reload privilege tables now? [Y/n] Y



#04. root 계정 접속 및 DataBase 생성


$ sudo mysql -u root -p

 Enter password : placedb@031120##


MariaDB> CREATE DATABASE cmsdb;

MariaDB> use mysql;

MariaDB> INSERT INTO mysql.db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv, Drop_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Create_tmp_table_priv, Lock_tables_priv, Create_view_priv, Show_view_priv, Create_routine_priv, Alter_routine_priv, Execute_priv, Event_priv, Trigger_priv, Delete_history_priv) VALUE ('%', 'cmsdb', 'cmsdb', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y');

MariaDB> GRANT ALL ON *.* TO 'cmsdb'@'localhost' IDENTIFIED BY 'ppR346t4@fd' WITH GRANT OPTION;

MariaDB> GRANT ALL PRIVILEGES ON cmsdb.* TO 'cmsdb'@'%' IDENTIFIED BY 'ppR346t4@fd';

MariaDB> FLUSH PRIVILEGES;SHO

MariaDB> exit;







Name __

Password __

Link (Your Website)

Comment

SECRET | 비밀글로 남기기

[Flow.Txt] 낀대 - 웹드라마를 보며 구독 취소 했다.(2020.03.23)[Flow.Txt] 낀대 - 웹드라마를 보며 구독 취소 했다.(2020.03.23)

Posted at 2020. 3. 24. 00:01 | Posted in Flow.Txt




퇴근길 유튜브에 추천영상으로 오길래 보게된 영상이 있다.


낀대  ( 끼인 세대 )


참 재미있는 말이라는 생각이 든다.


요즘 내 상황에 참 적합한 말이라는 생각이 든다.









갑자기 영업 미팅이나 외부, 협력업체와 이야기를 하게 되면 난 항상 묻는게 있다.


어디가 갑이고 어디가 을입니까?


을로서의 행동도 중요하고, 갑질도 필요하다.



내가 가장 놀란건, 저렇게 갑인 광고주한테 박박 개기거나,


한참 선배한테( 과장 사원이면 못해도 정상적인 호봉제로 쳤을때 경력 7~8년 차이는 날테니... )



왜 자기들이 꼰대라고 지칭하는 사람들한테 한소리 들을 수 밖에 없을까?


그만큼 능력이 없으니까 자기 합리화 하는거지...




자기가 하고싶은 사이다 다 털어놓고, 뒤수습한 과장한테


죄송하다 사죄의 말 없이, 싫어하는 커피를 내미는 모습을 보았을때...


제는 일하기전에 사람부터 되야한다는 생각이 들었다.


커피 한잔 따르는 일 시키지 말라고, 커피 한잔도 제대로 못타는데 무슨일을 시킬까...







Name __

Password __

Link (Your Website)

Comment

SECRET | 비밀글로 남기기

[Ubuntu] Naver Whale Broswer 설치하기[Ubuntu] Naver Whale Broswer 설치하기

Posted at 2020. 3. 12. 04:09 | Posted in Linux/Ubuntu



참고 : https://forum.whale.naver.com/topic/10763/




■ 우분투에 네이버 웨일 브라우저 사용하기




우분투 터미널 창을 실행하고 해당 포스팅의 순서대로


명령어를 차례로 입력하면 설치가 가능하다.



 $ sudo sh -c 'echo "deb http://repo.whale.naver.com/linux/ stable/" >> /etc/apt/sources.list.d/naver-whale.list'



 $ wget -q -O - http://repo.whale.naver.com/linux/stable/public.key | sudo apt-key add -



 $ sudo apt-get update





 $ sudo apt-get install -y naver-whale-stable




이제 설치된 프로그램 리스트를 확인해 보면.


Naver Whale이 추가된 것을 확인 할 수 있다.






해당 아이콘을 선택하고 실행해 하면





이제 우분투 데스크 환경에서 웨일 브라우저가 정상적으로 실행되는 것을 확인 할 수 있다.







Name __

Password __

Link (Your Website)

Comment

SECRET | 비밀글로 남기기

[Ubuntu] 18.04 LTS 버전에서 Flash Player 실행[Ubuntu] 18.04 LTS 버전에서 Flash Player 실행

Posted at 2020. 3. 12. 04:08 | Posted in Linux/Ubuntu




URL : https://brown.ezphp.net/entry/우분투-1804에-flash-player-설치하는-방법





■ 우분투 18.04 LTS 버전에서 플래쉬 플레이어 사용하기




먼저 의존성 패키지를 설치한다. 


PPA( Personal Package Archive ) 개인용 소프트웨어 패키지 저장소가 준비되어 있지 않다면, 아래 명령부터


준비되어 있다면 2번째 명령문부터 실행 하면 된다.



 $ sudo apt-get install software-properties-common




 $ sudo add-apt-repository "deb http://archive.canonical.com/ $(lsb_release -sc) partner"




 $ sudo apt-get update




 $ sudo apt-get install -y adobe-flashplugin browser-plugin-freshplayer-pepperflash












Name __

Password __

Link (Your Website)

Comment

SECRET | 비밀글로 남기기

[Docker] Container 다루기[Docker] Container 다루기

Posted at 2020. 3. 11. 18:24 | Posted in Docker





■ 컨테이너( Container ) 다루기




run 명령어와 create 명령어는 컨테이너를 생성만 할뿐 컨테이너로 바로 들어가 지지 않는다.




#01. 컨테이너 생성 - Ubuntu



 $ sudo docker run -i -t --name ubuntu_docker -p 80:80 -p 3306:3306 ubuntu:18.04

 



#02. 컨테이너 생성 - CentOS



※ 레드햇( RedHat ) 계열의 리눅스를 사용하는경우


레드햇 계열의 리눅스를 사용할 경우 정상적으로 접속



 $ sudo docker create -i -t --privileged -d --name cent_docker -p 80:80 -p 3306:3306 centos:7 init

 $ sudo docker exec -i -t cent_docker bash

 




$ sudo docker start cent_docker


$ sudo docker attach cent_docker


'Docker' 카테고리의 다른 글

[Docker] Container 다루기  (0) 2020.03.11
[Docker] Ubuntu - 도커 설치하기  (0) 2020.03.11
[Docker] 도커(Docker)란?  (0) 2020.03.10

Name __

Password __

Link (Your Website)

Comment

SECRET | 비밀글로 남기기

[Docker] Ubuntu - 도커 설치하기[Docker] Ubuntu - 도커 설치하기

Posted at 2020. 3. 11. 02:06 | Posted in Docker




참조 : https://hiseon.me/linux/ubuntu/install-docker/

참조 : https://roseline124.github.io/kuberdocker/2019/07/17/docker-study02.html




#01. 도커 설치여부 확인


사전에 도커의 설치 여부를 확인한다.


 $ sudo apt-cache policy docker-ce



만약 도커가 설치되어 있었다면,


remove 명령을 사용하여 도커를 삭제한 클린한 환경을 만든 다음


설치를 진행하자.



 $ sudo apt-get remove docker docker-engine docker.io







#02. 저장소( repository ) 갱신하기



우분투를 포함해 리눅스 배포판들은 주요 리눅스 프로그램들을 저장소라는 곳에 한 데 모아 제공한다. 이러한 프로그램을 패키지라고 한다.


이 저장소에 올라간 패키지들은 최신 버전이 아닌 경우가 많고, 사용자 리눅스 환경설정과 맞지 않아 설치가 되지 않는 경우가 있다.


최신 패키지로 저장소에 있는 패키지들을 업데이트 하려면 아래 명령어를 입력한다.



 $ sudo apt-get update









① apt-transport-https

 -. 패키지 관리자가 https를 통해 데이터 및 패키지에 접근할 수 있도록 한다.

 $ sudo apt-get install apt-transport-https




② ca-certificates : ca-certificate는 certificate authority에서 발행되는 디지털 서명. SSL 인증서의 PEM 파일이 포함되어 있어

                        SSL 기반 앱이 SSL 연결이 되어있는지 확인할 수 있다.

 $ sudo apt-get install ca-certificates




③ curl : 특정 웹사이트에서 데이터를 다운로드 받을 때 사용

 $ sudo apt-get install -y curl



④ software-properties-common : 

 -. *PPA를 추가하거나 제거할 때 사용한다.

 $ sudo apt-get install -y software-properties-common 



※ PPA( Personal Package Archive )란?


· 개인 패키지 저장소. 

· 개발자가 소스코드를 업로드하면 자동으로 패키지화함. 

· 사용자가 다운로드 받아 설치할 수 있게 해주는 소프트웨어 저장소.






#04. 도커 다운받기


curl 명령을 사용하여 도커를 다운 받는다.


 $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add


※ apt-key 

 패키지를 인증할 때 사용하는 키 리스트를 관리한다. 

 이 키를 사용해 인증된 패키지는 신뢰할 수 있는 것으로 간주한다. 

 add 명령어는 키 리스트에 새로운 키를 추가하겠다는 의미이다.



#05. repository에 패키지 저장소 추가


PPA 저장소를 추가해준다.

apt 리스트에 패키지를 다운로드 받을 수 있는 경로구 추가된다.


 $ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"






#06. repository에 저장소의 패키지 갱신




 $ sudo apt-get update




저장소에 라리브러리가 제대로 추가 되었는지 확인해 본다.


 $ sudo apt-cache policy docker-ce



apt-cache : 우분투에서 소프트웨어나 라이브러리를 터미널에서 검색한다.

policy : 내가 어떤 저장소를 설치했는지를 보여준다. 저장소를 설치했는지 안했는지 기억이 안날때 유용하다.






#07. 도커 설치하기

 $ sudo apt-get install -y docker-ce



#07. 도커 설치 확인



 $ sudo systemctl status docker



systemctl : 리눅스에서 서비스를 등록, 삭제(mask, unmask) / 활성화, 비활성화(enable, disable) / 시작, 중지, 재시작(start, stop, restart) / 상태 확인(status) / 서비스 확인(list-units, list-unit-files)을 할 수 있는 명령어




 $ docker -v




※ 참고 


아래 명령어는 접속한 사용자 계정을 docker 그룹에 추가하는 내용이다.


 $ sudo usermod -aG docker $USER





'Docker' 카테고리의 다른 글

[Docker] Container 다루기  (0) 2020.03.11
[Docker] Ubuntu - 도커 설치하기  (0) 2020.03.11
[Docker] 도커(Docker)란?  (0) 2020.03.10

Name __

Password __

Link (Your Website)

Comment

SECRET | 비밀글로 남기기

[Docker] 도커(Docker)란?[Docker] 도커(Docker)란?

Posted at 2020. 3. 10. 01:17 | Posted in Docker




발췌 : 시작하세요! 도커





■ 도커( Docker ) 란?





· 도커( Docker )는 리눅스 컨테이너에 여러 기능을 추가함으로써 

  플리케이션을 컨테이너로서 좀더 쉽게 사용할 수 있게 만들어진 오픈소스 프로젝이다.


· 도커는 GO 언어로 작성돼 있으며, 2013년 3월에 첫 번째 릴리스가 발표된 이후 지금까지 꾸준히 개발되고 있다.


· 기존에 쓰이던 가상화 방법인 가상 머신과는 달리 도커 컨테이너는 성느으이 손실이 거의 없어서

  차세대 클라우드 인프라 솔루션으로서 많은 개발자들에게 주목 받고 있다.




도커와 관련된 프로젝트는 도커 컴포즈( Docker Compose ), 레지스트리( Private Registry ), 도커 머신( Docker Machine ), Kitematic 등


여러가지가 있지만 일반적으로 도커라고 하면 도커 엔진( Docker Engine ) 혹은 도커에 관련된 모든 프로젝트를 의미한다.


보통 도커 엔진이라는 의미로 더 많이 쓰이는데 도커 엔진은 컨테이너를 생성하고 관리하는 주체로서 이 자체로도 컨테이너를 제어할 수 있고


다양한 기능을 제공하는 도커의 주 프로젝트이기 때문이다.



도커의 생태계에 있는 여러 프로젝트들은 도커 엔진을 좀 더 효율적으로 사용하기 위한 것에 불과하기 때문에 핵심이 되는 것은 도커 엔진이다.


이 때문에 도커 엔진을 사용하는 방법을 익히는 것은 도커와 관련된 모든 프로젝트를 능숙하게 다루기 위한 첫걸음이라고 봐도 무방하다.









#01. 가상 머신과 도커 컨테이너




기존의 가상화 기술은 하이바이저를 이용해 여러 개의 운영체제를 하나의 호스트에서 생성해 사용하는 방식이었다.


이러한 여러개의 운영체제는 가상 머신이라는 단위로 구별되고,


각 가상머신에는 Ubuntu, CentOS 등의 운영체제가 설치되어 사용된다.


하이바이저에 의해 생성되고 관리되는 운영체제는 게스트 운영체제( Guest OS ) 라고 하며,


각 게스트 운영체제는 다른 게스트 운영체제와는 완전히 독립된 공간과 시스템 자원을 할당받아 사용한다.


이러한 가상화 방식을 사용할 수 있는 대표적인 가사황 툴로 VirtualBox, VMware 등이 있다.







그러나 각종 시스템 자원을 가상화하고 독립된 공간을 생성하는 작업은 하이퍼바이저를


반드시 거치기 때문에 일반 호스트에 비해 성능의 손실이 발생한다.


그뿐만 아니라 가상 머신은 게스트 운영체제를 사용하기 위한 라이브러리, 커널 등을 전부 포함하기 때문에 


상 머신을 배포하기 위한 이미지로 만들었을 때 이미지의 크기 또한 커진다.


즉, 가상머신은 완벽한 운영체제를 생성할 수 있다는 장점은 있지만 일반 호스트에 비해 성능 손실이 있으며,


수 기가바이트에 달하는 가상 머신 이미지를 애플리케이션으로 배포하기는 부담스럽다는 단점이 있다.




이에 비해 도커 컨테이너는 가상화된 공간을 생성하기 위해 리눅싕 자체 기능이 chroot, 네임스페이스( namespace ), cgroup을 사용함으로써


프로세스 단위의 격리 환경을 만들기 때문에 성능 손실이 거의 없다.


컨테이너에 필요한 커널은 호스트의 커널을 공유해 사용하고,


컨테이너 안에는 애플리케이션을 구동하는데 필요한 라이브러리 및 실행 파일만 존재하기 때문에


컨테이너를 이미지로 만들었을 때 이미지의 용량 또한 가상머신에 비해 대폭 줄어든다.


따라서 컨테이너를 이미지로 만들어 배포하기는 시간이 가상머신에 비해 빠르며,


가상화된 공간을 사용할 때의 성능 손실도 거의 없다는 장점이 있다.










#02. 도커 엔진



01) 도커 엔진이 구동 가능한 OS



도커는 다양한 운영체제에서 사용할 수 있다.


도커는 리눅스 컨테이너를 제어하는 API를 GO언어로 구현한 libcontainer를 사용하기 때문에


대부분의 리눅스 운영체제에서 사용할 수 있다.


도커를 사용할 때 쓰는 대표적인 리눅스 운영체제로는 Ubuntu, CentOS 등이 있다.


어느 운영체제를 선택하든 상관 없지만 가능하다면 지원이 중단되지 않은 최신 버전의 운영체제 배포판을 사용하는 것이 좋다.


마이크로소프트 윈도우, 맥 OS X에서도 도커를 사용할 수 있지만


Windows10, Mac OS X 10.10.3 Yosemite 이전 버전의 운영체제를 사용한다면 도커를 사용하기 위해


가상화 공간을 별도로 생성해야 한다.


그러나 도커가 어느 운영체제에 설치되든 사용법은 거의 같다.




02) 도커 엔진의 종류 및 버전



2017년 이전의 도커 엔진은 1.12과 같이 1.x 버전으로 표기되어 왔다.


그러나 도커 엔진은 1.13을 마지막으로, 2017년 3월부터 도커 엔진은 도커 EE( Docker Enterprise Edition )와


도커 CE( Community Edition )으로 구분되어 제공되고 있으며,


버전 이름 또한 17.03-EE 또는 17.03.CE와 같이 ( 출시 년도 ) - ( 출시 월 ) - ( 도커 엔진 종류 )의 형태로 변경되어 왔다.



도커 EE는 유료로 제공되는 기업용 솔루션이며, 각종 기술 지원 및 실제 서비스 단계에서


필요한 각종 부가 기능들을 도커 엔진과 함께 제공한다.


도커 CE는 무료로 제공되는 도커 엔진으로서, 별도의 기술 지원 및 서비스를 제공하지는 않지만


도커 엔진 자체의 핵심적인 기능을 무료로 사용할 수 있다는 장점이 있다.


또한 도커 EE는 3개월마다 안정화된 버전으로서 릴리즈 되는 반면 도커 CE는 stable과 edge 버전으로 구분해


각각 3개월, 1개월 단위로 릴리즈 된다는 차이점도 있다.



도커 EE와 도커 CE는 기술 지원 및 서비스 운용을 위한 부가적인 서비스 지원 수준에서 차이가 있지만,


핵심적인 컨테이너 기술은 도커 CE에서도 동일하게 사용할 수 있다.



도커 CE의 edge 버전은 새로운 기능을 먼저 사용해 볼 수 있다는 장점이 있지만


각종 버그가 발생할 수 있기 때문에 가능하면 도커 CE의 stable 버전을 설치하는 것을 권장한다.








'Docker' 카테고리의 다른 글

[Docker] Container 다루기  (0) 2020.03.11
[Docker] Ubuntu - 도커 설치하기  (0) 2020.03.11
[Docker] 도커(Docker)란?  (0) 2020.03.10

Name __

Password __

Link (Your Website)

Comment

SECRET | 비밀글로 남기기

[JavaScript] Canvas로 생성 이미지, 서버 전송 - Sample[JavaScript] Canvas로 생성 이미지, 서버 전송 - Sample

Posted at 2020. 3. 6. 17:38 | Posted in JavaScript & jQuery/JavaScript




참고 : https://bugsdb.com/_ko/debug/14292f07a628fd12f3b6afc4a751f956






■ 캔버스로 생성한 이미지 파일 서버에 업로드 하기




# 소스코드 - 클라이언트 페이지 ( 이미지 전송 )

 canvas_upload.php

<html>

<head>

<meta charset="UTF-8">

<title>:: JavaScript 캔버스 이미지 업로드 ::</title>

<meta name="viewport" content="width=device-width">

<link type="text/css" rel="stylesheet" href="./css/modern.css"/>

<style type="text/css">

    .imgArea { text-align:center; }

    canvas, #uploadFile, #submitBtn { display:none; }

</style>

<script type="text/javascript">


    // @breif AJAX 통신 함수

    function getXMLHTTPRequest() {

        let request = false;

        try { request = new XMLHttpRequest(); }

        catch(err01) {

            try { request = new ActiveXObject("Msxml2.XMLHTTP"); }

            catch(err02) {

                try { request = new ActiveXObject("Microsoft.XMLHTTP"); }

                catch(err03) { request = false; }

            }

        }

        return request;

    }


    const ajax = getXMLHTTPRequest();


    // @breif 이미지 업로드 함수

    function uploadImgFilePrinted() {


        // @details 업로드 파일 정보를 받아온다.

        let fileInfo = document.getElementById("uploadFile").files[0];

        let reader = new FileReader();


        reader.onload = function() {


            // @details 업로드 버튼 이미지의 넓이와 높이에 맞게 썸네일을 생성을 위해 그 값을 받아온다.

            const btnWidth = document.getElementById("uploadImg").width;

            const btnHeight = document.getElementById("uploadImg").height;


            // @details 업로드 이미지 출력

            document.getElementById("uploadImg").src = reader.result;

            document.getElementById("uploadImg").width = btnWidth;

            document.getElementById("uploadImg").height = btnHeight;


            // @details 등록버튼 노출

            document.querySelector("#submitBtn").style.display = "inline";

        };


        if(fileInfo) {

            // @details readAsDataURL을 통해 업로드한 파일의 URL을 읽어 들인다.

            reader.readAsDataURL(fileInfo);

        }

    }


    function registryUploadImg() {

        if(confirm("업로드한 이미지를 업로드 하시겠습니까?") == true) {


            let upImage = new Image();

            upImage.src = document.getElementById("uploadImg").src;


            upImage.onload = function() {


                // @breif 캔버스 위에 이미지 그리기

                let canvas = document.querySelector("canvas");

                let canvasContext = canvas.getContext("2d");


                // @details 리사이즈할 이미지의 크기는, 현재 클라이언트에게 노출되어 있는 이미지 크기로 지정

                const btnWidth = document.getElementById("uploadImg").width;

                const btnHeight = document.getElementById("uploadImg").height;


                // @details 캔버스 생성 및 이미지 그리기

                canvas.width = btnWidth;

                canvas.height = btnHeight;

                canvasContext.drawImage(this, 0, 0, btnWidth, btnHeight);


                // @details AJAX 전송 데이터 설정

                const arrData =  {

                      "mode" : "imgFileUpload"

                    , "imgBase64" : canvas.toDataURL("image/jpeg")

                    , "imgFileName" : document.getElementById("uploadFile").files[0]['name']

                };


                ajax.open("POST", "./upload_image.php", true); // @details 비동기 방식 사용

                ajax.setRequestHeader("Content-Type", "application/json;charset=UTF-8;");

                ajax.send(JSON.stringify(arrData));


                ajax.onreadystatechange = function() {

                    if(ajax.readyState == 4) {

                        if(ajax.status == 200) {

                            const json = JSON.parse(ajax.responseText);

                            if(json.ret == "success") {

                                alert(json.message);

        } else {

                                alert(json.message);

                            }

                        } else {

                            alert(json.message);

                        }

                    }

                };

            };


        } else {

            return false;

        }

    }

</script>

<link rel="import" href="/edit_img.html">

</head>

<body>

<div class="windowFilm"></div>

<form id="uploadFrom" method="post">

    <input type="file" id="uploadFile" onChange="uploadImgFilePrinted();" accept="image/*"/>

    <div class="contents">

        <h1>캔버스&nbsp;업로드<span>샘플</span></h1>

        <div class="imgArea">

            <a href="javascript:;" onClick="document.getElementById('uploadFile').click();">

                <img id="uploadImg" src="./user-anonymous.png"/>

            </a>

            <br/><br/>

            <input id="submitBtn" type="button" onClick="registryUploadImg();" value="등록">

        </div>

        <canvas></canvas>

        <div class="copyright" style="bottom:0;">

            <p>Producer &copy; 사악미소</p>

        </div>

    </div>

</form>

</body>

</html> 




# 소스코드 - 서버 ( 이미지 파일 저장 )

 upload_image.php

<?php

$RetVal = array("ret"=>"fail", "error"=>"", "error_msg"=>"", "message"=>"");

$backUrl = $_SERVER['HTTP_REFERER'];


// @breif php://input은 내용의 유형에 관계없이 요청 HTTP 헤더 뒤에 모든 원시 데이터를 반환한다.

$data = json_decode(file_get_contents("php://input"), true);


switch($data['mode']) {


    // @breif ajax 이미지 업로드

    case "imgFileUpload" :


        // @breif base64로 암호화된 이미지 파일명 디코드

        $uploadCanvas = base64_decode(preg_replace("#^data:image/\w+;base64,#i", "", $data['imgBase64']));


        // @breif 파일명과 확장자를 분리 하여 담는다.

        $fileName = array_shift(explode(".", $data['imgFileName'])); // @details 이미지 파일 이름


        // @breif 이미지 파일명 변경

        $uploadImgName = $fileName."_".time().".jpg";


        // @breif 업로드할 이미지 경로 설정

        $uploadSrc = "./upload/".$uploadImgName;


        // @breif 이미지 파일 저장

        file_put_contents($uploadSrc, $uploadCanvas);


        // @breif 성공 여부 확인

        if(file_exists($uploadSrc) == TRUE) {

            $RetVal['ret'] = "success";

            $RetVal['message'] = "파일을 업로드 하는데 성공하였습니다.\n축하합니다.";

        } else {

            $RetVal['message'] = "파일을 업로드 하는데 실패하였습니다.\n다시 시도하여 주시기 바랍니다.";

        }


// @return 업로드 성공 / 실패 유무를 json 방식으로 웹 페이지에 전달한다.

        print json_encode($RetVal);

        return;


    break;


    default :


    $RetVal['message'] = "서버와의 연결 실패";

    print json_encode($RetVal);

        return;


    break;

}


header("location:".$backUrl);

?>





# 출력결과








Name __

Password __

Link (Your Website)

Comment

SECRET | 비밀글로 남기기

[JavaScript] Canvas를 통한 이미지 회전[JavaScript] Canvas를 통한 이미지 회전

Posted at 2020. 3. 4. 11:06 | Posted in JavaScript & jQuery/JavaScript




■ 휴대폰 사진 업로드시 이미지가 가로, 세로가 변경되는 이유





휴대폰, 스마트폰의 카메라로 찍은 사진을 웹 브라우저를 통해 업로드 할경우,


이미지의 가로, 세로가 변경되어 등록되는 경우가 존재한다.


이러한 이유는 EXIF( Exchangeable Image File Format ) 의


회전값 변경이 반영되지 않기에 생기는 이유인데.



아래 이미지는 초기 스마트 폰에서 자주 볼 수 있었던 문제이다.

( 자이로 센서( Gyro Sensor ) 등의 기술 발전으로 이런 문제는 많이 해결 되었지만, 이미지의 편집등 다른 작업 과정으로 현재에도 이런 문제를 맏닥드릴 수 있다. )









가로로 찍은 이미지의 경우 스마트폰 상에서는 분명 정상적으로 보여주지만.


실제 이미지의 EXIF 값을 보면 회전정보( Orientation )가 90° CW 가 적용되어 있는것을 알 수 있다.


이를 회전정보 값을 브라우저에서는 인식하지 않고 보여지는 문제이다.







   # EXIF( Exchangeable Image File Format ) 란?



   디지털 카메라 등에서 사용되는 이미지 파일 메타데이터 포맷으로,


   카메라가 촬영한 사진, 녹음파일에 시간 등의 각종 정보를 담기 위해 개발되었다. 즉, 


   JPEG, TIFF 6.0과 RIFF, WAV 포맷에 이미지나 소리에 대한 정보를 추가로 기록할 수 있다.


   디지털카메라의 보급으로 널리 활성화되었고 이미지 메타데이터의 사실상 표준 지위에 있다.


   EXIF 데이터는 이미지 파일의 일부로 저장되며,


   EXIF 데이터를 지원하는 소프트웨어 사용 시 이미지를 변경해도 데이터를 보존한다.



   출처 : 나무위키( https://namu.wiki/w/EXIF )






간단하게 이미지 파일 하나를 선택하여 마우스 오른쪽 버튼을 클릭하고


오른쪽으로 회전( T ) 을 선택해 보자.





회전 정보 : 90° CW 로 반영된 것을 확인할 수 있다.


이 렇게 회전된 파일을 <img src="스토브리그.jpg">로 올려서 브라우저로 확인을 해 본다면.



# 소스코드

<html>

<head>

<title>:: 스토브리그 ::</title>

<style type="text/css">

/* image-orientation:from-image; */

</style>

</head>

<body>

<img src="stoveleague.jpg"/>

</body>

</html> 



# 출력결과




회전 정보 : 90° CW가 반영이 <img> 태그를 사용한 경우


브라우저에서 다시 정방향으로 돌려서 출력하는 모습을 확인 할 수 있다.




현재 파이어 폭스 브라우저의경우 CSS에 image-orientation:from-image; 를 넣어주는 것만으로도


회전정보 값을 읽어들여 반영하여 이미지가 돌아가는 것을 막아주어서 해결할 수 있지만.


아직까지 크롬등의 다른 브라우저에서는 CSS4의 실험적 기능이기에 적용되어 있지 않다고 한다.


결국 자동으로 이러한 상황을 해결 할 수는 없는 상황이기에


사용자의 폰, 찍은 각도에 따라 업로드시 문제가 발생할 수 있다.











■ 캔버스를 통한 업로드 이미지 각도 조정




그래서 필자는 이에대한 해결책으로


자동으로 이미지를 보정하는 것이 아닌,


사용자가 직접 수동으로 이미지를 수정하는 방향으로 가닥을 잡고,


다 완성된 정보만을 서버로 전달하는 형태로 취하는 방식을 택하게 되었다.




# 소스코드

<html>

<head>

<title>:: JavaScript 캔버스 - 회전 ::</title>

<script type="text/javascript">


    function uploadImgPreview() {


     // @breif 업로드 파일 읽기

     let fileInfo = document.getElementById("upImgFile").files[0];

     let reader = new FileReader();


     reader.addEventListener("load", function() {


          console.log("INDEX #02");


          // @details 업로드한 파일의 URL을 가져온다.

          document.getElementById("thumbnail").src = reader.result;


     }, false);


     if(fileInfo) {


          console.log("INDEX #01");


          // @details readAsDataURL을 통해 업로드한 파일의 URL을 읽어 들인다.

          reader.readAsDataURL(fileInfo);

        }

    }


    function rotateCanvasImg( angle ) {


     // @breif 썸네일 이미지 생성

    let tempImage = new Image();                         // @details drawImage 메서드에 넣기 위해 이미지 객체화

        tempImage.src = document.getElementById("thumbnail").src; // @details 업로드 완료된 이미지를 객체에 주입


     tempImage.onload = function() {


          // @breif 캔버스 위에 이미지 그리기

          let canvas = document.getElementById("canvas");

          let canvasContext = canvas.getContext("2d");


          // @breif 왼쪽( 270° ) 회전의 경우

          if( angle == '270' ) {


               // @details 270° 회전의 경우 이미지의 높이와 넓이를 서로 바꿔준다.

               canvas.width = tempImage.height;

canvas.height = tempImage.width;


               canvasContext.rotate((270) * Math.PI / 180);


               // @details 이미지가 270° 회전 했을 경우 x축의 값을 업로드 이미지의 넓이를 음수로 변경한다.

               canvasContext.drawImage(this, (tempImage.width * -1), 0);


          }


// @breif 오른쪽( 90° ) 회전의 경우

          else if( angle == '90' ) {


               // @details 90° 회전의 경우 이미지의 높이와 넓이를 서로 바꿔준다.

               canvas.width = tempImage.height;

canvas.height = tempImage.width;


               // canvasContext.rotate((90) * Math.PI / 180);

               canvasContext.rotate(Math.PI / 2);


               // @details 이미지가 90° 회전 했을 경우 y축의 값을 업로드 이미지의 높이 음수로 변경한다.

canvasContext.drawImage(this, 0, (tempImage.height * -1));


          }


          // @breif 거꾸로( 180° ) 회전의 경우

          else if( angle == '180' ) {


               canvas.width = tempImage.width;

               canvas.height = tempImage.height;


               // canvasContext.rotate((180) * Math.PI / 180);

               canvasContext.rotate(Math.PI);


               // @details 이미지가 180° 회전 했을 경우 x, y축의 값을 업로드 이미지의 넓이와 높이 음수로 변경한다.

               canvasContext.drawImage(this, (tempImage.width * -1), (tempImage.height * -1));


          }


          // @breif 정방향

          else {


               canvas.width = tempImage.width;

               canvas.height = tempImage.height;

               canvasContext.drawImage(this, 0, 0);

          }


          // @breif 캔버스의 이미지

          let dataURI = canvas.toDataURL("image/jpeg");

          document.querySelector("#thumbnail").src = dataURI;


     };

    }

</script>

</head>

<body>

    <!-- @breif accept 태그는 파일 업로드시 그것을 이미지 파일로 제한한다. -->

    <input type="file" id="upImgFile" onChange="uploadImgPreview();" accept="image/*">

    &nbsp;|&nbsp;

    <input type="button" onClick="rotateCanvasImg('270');" value="왼쪽(270°)"/>

    &nbsp;|&nbsp;

    <input type="button" onClick="rotateCanvasImg('90');" value="오른쪽(90°)"/>

    &nbsp;|&nbsp;

    <input type="button" onClick="rotateCanvasImg('180');" value="거꾸로(180°)"/>

    &nbsp;|&nbsp;

    <input type="button" onClick="uploadImgPreview();" value="되돌리기"/>

    <hr/>

    <img id="thumbnail" src="">

    <!-- @breif 캔버스는 화면에 노출시키지 않는다. -->

    <canvas id="canvas" style="display:none;"></canvas>

</body>

</html>




# 출력결과




이렇게 이미지 조작이 완료되었다면.


해당 미지를 마우스 우클릭으로 다운받아 보자.








다운받은 이미지는 index.jpg 라는 이름으로 생성되며


회전 정보가 표기되지 않는 0° CW 임을 알 수 있다.


그렇기에 해당 이미지를 <img> TAG를 사용해도 원하는 각도 조절이 가능하기에




사용자의 업로드한 사진의 이미지 축 보정 작업이 끝나고 사진 등록( 파일 업로드 )을 실행하면


편집된 캔버스의 작업내용을 서버에 전송하는 형태로 진행을 하면 된다.




관련글 : [JavaScript] Canvas로 생성 이미지, 서버 전송







  1. 비밀댓글입니다

Name __

Password __

Link (Your Website)

Comment

SECRET | 비밀글로 남기기

[JavaScript] 업로드한 파일 Resizer 하여 화면에 출력시키기[JavaScript] 업로드한 파일 Resizer 하여 화면에 출력시키기

Posted at 2020. 3. 4. 07:34 | Posted in JavaScript & jQuery/JavaScript




업로드한 파일 리사이즈 하여 화면에 출력시키기




<html>

<head>

<title>:: JavaScript 캔버스 - 뷰 ::</title>

<style type="text/css">

table {

            border:1px solid #444444;

            border-collapse:collapse;

  }

table th {

            border:1px solid #444444;

            padding:5px 10px 5px 10px;

            text-align:center;

            font-weight:bold;

}

table td {

            border:1px solid #444444;

            padding:10px;

            text-align:center;

  }

</style>

<script type="text/javascript">


    function uploadImgPreview() {


        // @breif 업로드 파일 읽기

        let fileInfo = document.getElementById("upImgFile").files[0];

        let reader = new FileReader();


        // @details INDEX #01 실행 이후, 파일의 업로드( onload )가 확인되고 나서 실행된다.

        reader.onload = function() {


            console.log( "INDEX #02" );


            // @details 업로드한 파일의 URL을 가져온다.

            document.getElementById("preview").src = reader.result;


            // @breif 썸네일 이미지 생성

            let tempImage = new Image();    // @details drawImage 메서드에 넣기 위해 이미지 객체화

            tempImage.src = reader.result;    // @details data-uri를 이미지 객체에 주입


            tempImage.addEventListener("load", function() {


                // @breif 캔버스 위에 이미지 그리기

                let canvas = document.getElementById( "canvas" );

                let canvasContext = canvas.getContext( "2d" );

                // @breif 캔버스 크기 셋팅

                canvas.width = 240;

                canvas.height = 300;

                // @breif 캔버스 위에 이미지 그리기

                canvasContext.drawImage(

                  this // @details 업로드한 이미지 파일의 정보

                , -10 // @details X좌표

                , -10 // @details Y좌표

                , 270 // @details 넣을 이미지의 가로 사이즈( 해당 예제는 변화를 보기위해 살짝 크게 다. )

                , 330 // @details 넣을 이미지의 세로 사이즈( 해당 예제는 변화를 보기위해 살짝 크게 했다. )

                );

                

                // @breif 캔버스 위에 이미지 그리기

                canvasContext.stroke();

                

                // @breif 캔버스의 이미지 URL 정보를 받아 썸네일 출력

                let dataURI = canvas.toDataURL("image/jpeg");

                document.querySelector("#thumbnail").src = dataURI;

            });

        };


        if( fileInfo) {


            console.log( "INDEX #01" );


            // @details readAsDataURL을 통해 업로드한 파일의 URL을 읽어 들인다.

            reader.readAsDataURL(fileInfo);

        }

    }


</script>

</head>

<body>

     <!-- @breif accept 태그는 파일 업로드시 그것을 이미지 파일로 제한한다. -->

    <input type="file" id="upImgFile" onChange="uploadImgPreview();" accept="image/*">

    <hr/>

    <table>

<tr>

<th>업로드 이미지 출력</th>

<th>이미지 캔버스 출력</th>

</tr>

<tr>

<td rowspan="3"><img id="preview" src=""></td>

<td><canvas id="canvas"></canvas></td>

</tr>

<tr>

<th>캔버스 이미지 변환</th>

</tr>

<tr>

<td><img id="thumbnail" src=""></td>

</tr>

    </table>

</body>

</html> 







① 이미지 파일을 업로드 한다.


② 업로드한 이미지를 화면에 출력한다.


③ 지정한 캔버스 영역에 해당 이미지를 그대로 리사이징 하여 따라 그리는 작업을 수행한다.

    ( 이때 기본적으로 이미지는 *.png 파일로 생성된다. )


④ 마지막으로 캔버스의 이미지 파일을 그대로 다시 이미지로 출력시키는 작업을 수행한다.







사실 필자가 해당 글을 작성하게 된 경위는


[JavaScript] Canvas를 통한 이미지 회전 포스팅의 사전 준비 과정이었다.


캔버스를 통해 프론트 개발의 좀더 넓은 시각을 바라보고.


HTML5의 가능성에 대해서 좀더 알아봐야 겠다는 생각을 하고 있다.











Name __

Password __

Link (Your Website)

Comment

SECRET | 비밀글로 남기기