위키백과에서 먼저 정의를 살펴보았습니다.

 

 

"라이브러리는 주로 소프트웨어를 개발할 때 컴퓨터 프로그램이 사용하는 비휘발성 자원의 모임이다.

여기에는 구성 데이터, 문서, 도움말 자료, 메시지 틀, 미리 작성된 코드, 서브루틴, 클래스, 값, 자료형 사양을 포함할 수 있다."

 

"컴퓨터 프로그래밍에서, 소프트웨어 프레임워크는 복잡한 문제를 해결하거나 서술하는 데 사용되는 기본 개념 구조이다.

간단히 뼈대, 골조, 프레임워크라고도 한다."

 

글만 간단히 보아도 두 개념이 많이 다른 것을 알 수 있습니다.

라이브러리는 프레임워크에 비해 작은 개념입니다.

 

 

프론트개발을 할때 쉽게 접하는 것을 예로 들어보자면 jQuery, React 같은 것들이 라이브러리입니다.

엥? 왜 React가 라이브러리이지? 프레임워크 아니었어? 하는 사람이 있을 수도 있습니다.

과거의 저도 헷갈렸었는데, 정확히 리액트의 생태계는 프레임워크이지만 리액트만은 라이브러리라고 합니다.

 

프레임워크로 분류되기 위해서는 필수로 충족해야하는 것들이 있습니다. 

다른 많은 프레임워크들이 기본적으로 내장하고 있는 기능들말이죠.. (예를 들어 라우터 기능이라던가)

 

리액트에서 이러한 기능들을 구현하기 위해서는 여러가지 추가적인 라이브러리를 같이 사용해야합니다.

(react-router, react-redux, react-saga 등....) 

그렇기 때문에 React는 프레임워크로 분류되지 않고 라이브러리로 분류됩니다.

 

react 공식사이트 메인 캡쳐

 

 

물론 공식사이트에도 라이브러리로 소개되고 있습니다.^^

 

 

 

 

저는 DB를 공부한 사람이 아닙니다.

포트폴리오 사이트 제작을 하면서 겪었던 것에 대한 기록 글입니다.^^

 

 

 

 

들어가기 전에 잡담.

Sequelize를 통해 db 작업을 한 상태였는데, db의 d자도 모르다보니 

매번 정적인 데이터를 손으로 삽입하고는 했습니다.

(명령어를 치거나, 워크벤치 들어가서 작업하거나, 하다하다 안되서 어드민을 만들어서 데이터를 입력해서 db로 저장했습니다.)

근데 이게 db를 지워야하는 경우가 생기고, 배포 후에 운영db에 또 똑같은 일을 작업해야하고...

끝이 없는 이 작업 속에서 미치겠네라고만 생각했는데, (검색해볼 정도는 아니었나 ㅋ;;;;;)

 

여튼 그러다가 우연히 (Sequelize를 통해 작업한) back 폴더 안에서 seeders라는 폴더를 발견했고,

내가 만든 적도 없는데? 이게 뭥ㅈㅣ? 하다가 검색을 통해 알게되었습니다. 

seeders 폴더

Sequelize를 통해 더미데이터를 넣을 수 있다는 것을!!!!!!!!

자 매뉴얼을 참고하거나 아래 블로그 글을 일거보세요(전 처음부터 적지 않기 때문에)

 

매뉴얼

sequelize.org/master/manual/migrations.html

 

참고

any-ting.tistory.com/53

 

[Node.js] Sequelize Seeders 사용법

- 개요 안녕하세요. 이번 시간에는 Sequelize에 Seeders라는 기술에 대해 알아보겠습니다. 우리는 어떤 기능 개발을 하다 보면 테스트 데이터가 필요할 때가 있습니다. 필요할 때마다 우리는 데이터

any-ting.tistory.com

 

 

 

Sequelize Seed

만약, 모르고 seeders 폴더를 삭제했다면 아래 명령어로 init 하세요.

npx sequelize init:seeders 

 

 

 

DB 생성

- model 작업 후 db 생성 후의 상태를 전제로 합니다.

- seed를 통해 create하면서 진행할 수도 있는 것 같은데, 이러한 경우라면 매뉴얼을 참고하세요.

(model 작업 후 npx sequelize db:create를 통해 db 생성까지 할 수 있습니다.)

 

 

 

Migrate 하기 

npx sequelize-cli db:migrate

// [D] 가장 최근 migration 돌리기(취소)
npx sequelize-cli db:migrate:undo

 

 

 

Seeder 파일 만들기

파일명에 본인이 생성할 파일 명을 적어주세요.

npx sequelize seed:generate --name 파일명

 

예시

catchmind 데이터를 관리할 것이어서 catchmind를 파일명으로 지정했습니다.

npx sequelize seed:generate --name catchmind

seeder 만들기 결과

명령어를 통해 파일이 생성되는데, 앞에 생성한 날짜?와 같은 숫자들이 적힌채로 생성됩니다.

 

 

 

seeders 파일 내용 작성

파일로 들어가보면 코드들이 작성되어있습니다.

up은 실행 시 seeder를 수행할때 실행되는 로직이고 down은 실행 취소 시 실행되는 로직입니다.

'use strict';

module.exports = {
  up: async (queryInterface, Sequelize) => {
    /**
     * Add seed commands here.
     *
     * Example:
     * await queryInterface.bulkInsert('People', [{
     *   name: 'John Doe',
     *   isBetaMember: false
     * }], {});
    */
  },

  down: async (queryInterface, Sequelize) => {
    /**
     * Add commands to revert seed here.
     *
     * Example:
     * await queryInterface.bulkDelete('People', null, {});
     */
  }
};

 

예시

컬럼이나, 데이터 타입 같은 것들을 안 맞추면 실패합니다.

string으로 넣어야하는데 실수로 json으로 넣었더니 fail이 되었습니다.

이때는 터미널에서 알려줍니다.

 

[데이터베이스]

db를 테이블 캡쳐를 보면, 저에게 필요한 것은 id, question, correct, incorrect 네가지인 것 같습니다.

id는 자동으로 증가해서 추가하지 않아도 되지만, 문제 번호로써 그냥 추가했습니다.

만약 id를 작업하지 않으면 자동으로 삽입이 됩니다만, undo후 seed를 반복하면 0로 reset되는 것이아니라 계속 증가하는 번호로 삽입됩니다. (저는 reset하는 것을 찾지 못했습니다 ㅜ)

catchmind db 캡쳐

 

[models/catchMind.js]

모델에서 데이터 타입을 다시한 번 확인해봤습니다.

const DataTypes = require('sequelize');
const { Model } = DataTypes;

module.exports = class CatchMind extends Model {
    static init(sequelize) {
        return super.init({
            question: {
                type: DataTypes.TEXT,
                allowNull: false, 
            },
            correct: {
                type: DataTypes.STRING(100),
                allowNull: false,
            },
            incorrect: {
                type: DataTypes.TEXT,
                allowNull: false, 
            },
        }, {
            modelName: "CatchMind", 
            tableName: "CatchMind", 
            timestamps: false,
            charset: 'utf8mb4', 
            collate: 'utf8mb4_general_ci',
            sequelize,
        });
    }

    static associate(db) {}
};

 

[seeders/XXXXXXXXXXXXXX-catchmind.js]

'use strict';

module.exports = {
    up: async (queryInterface, Sequelize) => {
        await queryInterface.bulkInsert('catchmind', [
            {
            	id: '1',
                question: 'https://okayoon-bucket.s3.ap-northeast-2.amazonaws.com/game/catchmind/quiz/img_quiz00.png',
                correct: '가로수',
                incorrect: '["공","장","소","궁","한","이","야","기","잼","난","사","건"]',
            },
            {
            	id: '2',
                question: 'https://okayoon-bucket.s3.ap-northeast-2.amazonaws.com/game/catchmind/quiz/img_quiz01.png',
                correct: '견인차',
                incorrect: '["강","초","숭","구","리","당","하","늘","개","퍼","풍","사"]',
            },
            {
            	id: '3',
                question: 'https://okayoon-bucket.s3.ap-northeast-2.amazonaws.com/game/catchmind/quiz/img_quiz02.png',
                correct: '도시',
                incorrect: '["강","초","숭","구","리","당","기","잼","난","사","수","김"]',
            },
        ], {});
    },

    down: async (queryInterface, Sequelize) => {
        await queryInterface.bulkDelete('catchmind', null, {});
    }
};

up

- await queryInterface.bulkInsert('테이블명', [{}] 을 통해 테이블 명을 적어줍니다.

- models에서 지정한 type에 맞춰 데이터를 넣어줍니다.

 

down

- await queryInterface.bulkDelete('테이블명', [{}] 을 통해 테이블 명을 적어줍니다.

- 저렇게 쓰면 전체 초기화 됩니다.

 

 

 

Seed 실행

위에 작업을 모두 마쳤다면 실행해보겠습니다.

seed 명령어를 입력하면 데이터가 여러번 중복해서 들어갈 수 있습니다.

 

 

전체 파일 seed 실행

npx sequelize-cli db:seed:all

 

 

단일 파일 seed 실행

파일명에 날짜까지 다 입력해줘야합니다.

npx sequelize db:seed --seed 파일명

// [D] 예시
// npx sequelize db:seed --seed 20210406123050-catchmind.js

 

결과

seed 실행 후 결과 창

 

 

그 외 명령어 입니다.

 

 

 

저는 외래키도 없고 단순한 테이블에 하는 작업이어서 어려움이 없었지만, 복잡할 수록 작업이 복잡해지니,

꼭 매뉴얼을 확인하시길 바랍니다.

 

 

https 적용을 진행하던 중에 오류가 나서 해결을 못하고 있었습니다.ㅠ

강의대로 진행했는데, 왜???

이러던 중에 질답게시판에 제로초님이 블로그글을 참고하여 진행하라고 댓글을 달아두신걸 봤고....

 

제가 나중에 헷갈릴가봐.. 나름대로 추가 정보를 정리하여 글을 작성합니다.

약간의 난관들도 있었지만, 다행이 성공했습니다.!

 

제로초님 블로그를 거의 대부분 참고했습니다.

www.zerocho.com/category/NodeJS/post/5ef450a5701d8a001f84baeb

 

(NodeJS) nginx와 let's encrypt로 SSL 적용하기(+자동 갱신)

리눅스에서 letsencrypt를 직접 설치합시다. 2020년 9월부로는 기존 방식보다 snap을 통해서 설치하는 게 더 쉬운 것 같습니다(https://snapcraft.io/certbot) 기존 방식 wget https://dl.eff.org/certbot-auto

www.zerocho.com

 

각 서버 모두 진행해야합니다. (프론트, 백 둘다)

다만 포트가 같으면 오류가 납니다.

 

 

설치

Certbot를 통해 Let's Encrypt SSL 인증서를 발급받습니다.

무료로 제공해주고 있습니다. 

이 인증서가 있어야 https를 사용할 수 있습니다.

인증서는 무료이지만, 3개월마다 갱신해줘야합니다.

sudo snap install certbot --classic
sudo apt-get install nginx

(apt-get은 우분투에서 사용하는 패키지 관련 명령어 도구입니다.)

 

 

nginx.conf 수정

그 후에 설정 하나를 수정해줘야합니다.

vim 에디터를 통해 수정해줄 것입니다.

vim /etc/nginx/nginx.conf

만약 이렇게 쳤는데.

권한을 요구한다면 sudo 를 통해 권한을 높여줍니다.

명령어 앞에 sudo를 붙이고 vim ~~를 입력하면 됩니다.

 

까만창이 뜨는데, 방향키로 움직일 수 있고 수정하기 위해서 

a를 누르면 INSERT 모드로 변경됩니다.

include 로 작성된 하단에 작업합니다.

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

// ===============작성해야하는 것
	server {
		server_name naver.com;
        listen 80;
        location / {
			proxy_set_header Host $host;
            proxy_pass http://127.0.0.1:3060;
            proxy_redirect off;
        }
    }
// ===============작성해야하는 것

server_name에 naver.com을 넣어놨는데, 본인의 사이트를 넣습니다.

 

저장할땐 ESC를 눌러서 커서를 제거한 후 :wq!를 입력합니다.

 

 

포트 확인

그 후에 80포트로 등록했으니 80포트가 사용되고 있는지 확인합니다.

사용되고 있다면 진행이 안되기 때문입니다.

sudo lsof -i tcp:80

80포트 확인

사용 중이라면 kill 해줍니다.

만약 내가 kill을 어떻게 하는 지 모르겠다면 아래와 같이 입력하세요.

위에서 PID는 (프로세스아이디) 19888이므로 아래와 같이 명령어를 입력합니다.

kill -9 19888

 

 

인증서 발급

그 후 인증서를 받기위해 명령어를 입력!

sudo certbot --nginx

 

이메일입력

 

이메일을 입력해줍니다.

그 후 약관동의를 다 해줍니다.

 

약관동의 1
약관동의2
설정 마지막

1번 입력 후 엔터를 쳐줍니다.

 

 

nginx.conf 설정

그 다음 다시 vim 에디터를 통해 작업을 합니다.

sudo vim /etc/nginx/nginx.conf

들어가보면 내가 작성하지 않은 코드들이 추가로 작성되어있습니다.

인증서를 발급 받으면서 작성된 코드들인데, 주석으로 #managed by Certbot과 같이 뒤에 적혀있습니다.

(제가 줄 정렬을 새로한 거라 그런데, 원본은 정렬이 안되어있습니다.)

nginx.conf 

 

 

default 수정

nginx.conf 2

 

nginx.conf 파일에서 include /etc/nginx/sites-enabled/*;가 작성되어있습니다.

때문에.. include가 되는 파일 중에 vim에디터를 통해 default 파일을 수정해줘야합니다.

vim /etc/nginx/sites-enabled/default

안에 server로 설정된 부분을 # <- 을 통해 주석처리합니다.

:wq!를 통해 저장하고 vim 에디터를 나옵니다.

 

 

nginx start

sudo service nginx start

 

 

참고

에러가 난다면 해 볼 수 있는 행동들입니다.

 

0. 무조건 상태먼저 확인

nginx 에러 도움말

systemctl status nginx.service

 

아래와 같이 status를 확인할 수 있습니다.

저 같은 경우에는 오타였습니다.

status 확인

 

 

1. 포트확인 후 kill

과정 중에 설명이 되어있습니다.  설명대로 다시 진행합니다.

sudo lsof -i tcp:80 // or 443
kill -9 프로세스아이디

 

 

2. 문법체크

sudo nginx -t

 

문법 체크 결과

ok, successful 이 아니라면 해당 파일을 확인해봐야합니다. (오타나 설정을 잘못 입력했는지)

 

 

3. 서버가 켜있던 상태에서 vim에디터를 통해 설정을 바꾼거라면 reload

sudo service nginx reload

 

 

nginx 명령어

// 시작
sudo service nginx start

// 재시작
sudo service nginx restart

// 중지
sudo service nginx stop

// 상태
sudo service nginx status

// 설정 
sudo service nginx reload

// 설정 파일 문법 체크
sudo nginx -t

 

 

 

 

개발일때에는 development, 배포일때에는 productionprocess.env.NODE_ENV를 구분해서 webpack의 설정을 진행해야하는 경우들이 있다.

예를 들면... 보안에 안좋아서 옵션을 달리해야한다던가..?

 

맥에서는 명령어만 삽입해도 진행이 되는데, windows에서는 라이브러리를 사용해줘야한다.

 

cross-env는 이때 운영체제나 플랫폼에 종속되지 않고 동일한 방법으로 env 변수를 주입해주는 패키지이다.

이것을 사용하면 동적으로 process.env(환경 변수)를 변경할 수 있다.

 

 

설치

npm i cross-env

 

사용할 커맨드 앞에 cross-env 를 붙여주기만 하면 된다.

 

 

 

package.json

사용 전 

"scripts": {
    "dev": "next -p 3060",
    "build": "ANALYZE=true NODE_ENV=production next build",
 },

 

 

사용 후

"scripts": {
    "dev": "next -p 3060",
    "build": "cross-env ANALYZE=true NODE_ENV=production next build",
 },

 

 

이렇게 간단하게 해결해주는 패키지이기 때문에 많은 사람들이 사용하고,

그렇기 때문에 비슷한 이름으로 해서 사용자를 헷갈리게 하여 설치하는 순간 정보를 빼가는 해커들도 있었다.

 

 

보안뉴스 캡쳐

 

보안뉴스

https://www.boannews.com/media/view.asp?idx=56184&skind=O

 

개발자는 속이기 쉽다? 자바스크립트 저장소 npm 감염되다

해커들에게 공격 툴이 있는 것처럼 개발자들에게도 소프트웨어 개발 툴이 있다. 그리고 그런 개발 툴들을 단위 단위로 묶어서 관리하는 체계도 있다. 자바스크립트라는 프로그래밍 언어의 패키

www.boannews.com

 

 

해커가 crossenv 라는 패키지를 배포하였고, 개발자가 install시 실수로 '-'를 빼고 설치하게되면 .env 파일을 가져가는 사건도 있었다.

.env에는 보안적인 정보들이 담겨있으니...

 

 

npm 블로그

https://blog.npmjs.org/post/163723642530/crossenv-malware-on-the-npm-registry.html

 

npm Blog Archive: `crossenv` malware on the npm registry

npm Blog (Archive); updates from the npm team are now published on the GitHub Blog and the GitHub Changelog

blog.npmjs.org

 

 

오늘도 이렇게 좋은 패키지를 알아간다ㅎㅎ

 

사이트에 Form을 만들고 이것을 통해 '사이트 주인에게 메일 발송'하는 기능을 작업해보도록하겠습니다.

 

 

EmailJS

- http://www.emailjs.com/

 

Send email from Javascript - no server code required | EmailJS

Send email directly from your client-side Javascript code – no server side code required. Add static or dynamic attachments, dynamic parameters, captcha code and more. Start with our free tier!

www.emailjs.com

- 무료는 텍스트만 가능, 파일전송 X

 

 

 

1. 가입

EmailJS 메인

 

 

 

2. Email Services 페이지

Add New service를 클릭해줍니다.

메일을 발송하고, 받을 수 있는 플랫폼을 선택하고 연동하는 작업입니다.

Email services 페이지

 

 

저는 Gmail를 선택했습니다.

Service ID는 옆에 키 모양 아이콘을 누르면 변경 가능합니다.

(이 key가 공개되면 제 메일을 이용할 수 있을 것이므로, 저는 캡쳐에 나온 키 안썼습니다.)

service 선택 팝업

 

 

Connect Account 눌러서 계정 연동해줍니다.

이때, 팝업이 뜨는데 허용 버튼을 눌러줍니다.

EmailJS 권한 팝업

 

 

안내 문구를 읽어보면 발신자가 본인이 된다는 의미입니다.

허용을 모두 마쳤다면, Create Service 버튼을 클릭합니다.

 

대시보드의 Email Services에 내가 방금 생성한 것이 확인됩니다.

Email Services 대시보드 생성예시

 

 

그리고 연동한 메일에도 관련 Test 메일이 와있습니다.

EmailJS 테스트 메일

 

 

허용 누를때 안내나왔던대로 내가 발신자가 됩니다.

이후, 대시보드에서 보낸 히스토리나 이벤트 같은 것들을 확인할 수 있습니다.

Events에서 방금 테스트메일에 대한 Events를 확인할 수 있습니다.

Events 페이지

 

 

 

3. Email Templates 페이지

Create New Template를 클릭해서 템플릿을 만들어줍니다.

Email Templates 페이지 create 버튼

 

일단, 뭐가 뭔지 모르니 그냥 오른쪽 위에 있는 Save버튼을 눌러줍니다...

 

 

 

4. Integration 페이지

본격적으로 작업을 해보겠습니다.

NPM, Browser, API 버튼을 누르면 각 설명이 적혀있습니다.

 

저는 npm을 통해 작업하겠습니다.

integration 페이지

 

자세한 내용은document을 한번 읽어보세요.

https://www.emailjs.com/docs/sdk/installation/

 

SDK Installation | EmailJS

Guide goes through the various methods used to install EmailJS SDK

www.emailjs.com

 

 

 

5. npm install 및 예제 코드 확인

npm install emailjs-com --save

 

document에 적혀있는 예제

import React from 'react';import emailjs from 'emailjs-com';
import './ContactUs.css';

export default function ContactUs() {
  function sendEmail(e) {
    e.preventDefault();

    emailjs.sendForm('YOUR_SERVICE_ID', 'YOUR_TEMPLATE_ID', e.target, 'YOUR_USER_ID')
      .then((result) => {
          console.log(result.text);
      }, (error) => {
          console.log(error.text);
      });
  }

  return (
    <form className="contact-form" onSubmit={sendEmail}>
      <input type="hidden" name="contact_number" />
      <label>Name</label>
      <input type="text" name="user_name" />
      <label>Email</label>
      <input type="email" name="user_email" />
      <label>Message</label>
      <textarea name="message" />
      <input type="submit" value="Send" />
    </form>
  );
  }

 

이 부분이 주의깊게 봐야하는 부분입니다.

 emailjs.sendForm('YOUR_SERVICE_ID', 'YOUR_TEMPLATE_ID', e.target, 'YOUR_USER_ID')
   .then((result) => {
   	console.log(result.text);
    
   }, (error) => {
   	console.log(error.text);
    
   });
 }

sendForm 메서드에는 3개의 id와 함께 form을 넘겨줘야합니다.

(form data가 아니라 form 엘리먼트입니다.)

 

 

3개의 ID를 발급 받을 수 위치입니다.

  • YOUR_SERVICE_ID : Email Services 페이지에서 발급
  • YOUR_TEMPLATE_ID : Email Templates 페이지에서 발급
  • YOUR_USER_ID : Integration 페이지에서 API Keys에 User ID 확인

 

 

 

6. 코드

Email.JS

import React, { useCallback } from 'react';
import useInput from '../hooks/useInput';
import emailjs from 'emailjs-com';
import styled from 'styled-components';

const Form = styled.form`   
    margin: 0 auto;
    padding: 20px;  
    width: 400px;
    background: #ccc;
    text-align: center;

    input {
        padding: 5px 10px;
        width: 100%;
        border: 1px solid #666;

        & + input,
        & + textarea {
            margin-top: 20px;
        }
    }

    textarea {
        padding: 5px 10px;
        width: 100%;
        min-height: 100px;
        outline: none;
        resize: none;
        IME-MODE: auto;
    }

    button {
        margin-top: 20px;
        padding: 5px 15px;
        background: #fff;
        border: 1px solid #666;
        outline: none;
        cursor: pointer;
    }
`;

const Email = () => {
    const [name, onChangeName] = useInput('');
    const [email, onChangeEmail] = useInput('');
    const [text, onChangeText] = useInput('');

    const onSubmit = useCallback((e) => {
        e.preventDefault();

        const inputNum = e.target.childElementCount - 1; // [D] 버튼한개 제외
        const data = new FormData(e.target);
        const entries = data.entries();
        let failNum = 0;

        for (let i = 0; i < inputNum; i++) {
            const next = entries.next();
            const key = next.value[0];
            const value = next.value[1];

            if (!value) {
                failNum++;
                alert(`${key} 비어있습니다.`);
                break;
            }
        }

        if (!failNum) {
            emailjs.sendForm(
            	'YOUR_SERVICE_ID', 
                'YOUR_TEMPLATE_ID', 
                e.target, 
                'YOUR_USER_ID'
                
            ).then((result) => {
                console.log('result.text', result.text);

            }, (error) => {
                console.log(error.text);
            });
        }
    }, []);

    return (
        <Form onSubmit={onSubmit}>
            <input
                type="text"
                name="name"
                placeholder="이름"
                value={name}
                onChange={onChangeName}
            />

            <input
                type="text"
                name="email"
                placeholder="이메일"
                value={email}
                onChange={onChangeEmail}
            />

            <textarea
                name="text"
                placeholder="메세지"
                value={text}
                onChange={onChangeText}
            />

            <button type="submit">
                발송
            </button>
        </Form>
    );
};

export default Email;

 

 

 

useInput

커스텀 훅입니다.

import { useState, useCallback } from 'react';

export default (initialValue = null) => {
    const [value, setValue] = useState(initialValue);
    const handler = useCallback(({target}) => {
        setValue(target.value);
    }, []);

    return [value, handler, setValue];
};

 

 

 

7. 템플릿 수정 (EmailJS 대시보드 Email Templates 페이지)

코드 작업이 끝났으니 초반에 만들었던 Email Templates를 수정해줍니다.

input의 name값과 맞춰서 key 값을 삽입해주면 됩니다.

 

 

수정 아이콘을 눌러서 수정페이지로 이동합니다.

Email Tempalte 수정 방법

 

 

제목, 컨텐츠 모두 수정해주었습니다.

수정을 완료하였다면 Save를 눌러주세요.

Template 수정 페이지

 

 

 

8. 메일 발송 확인

이제 폼을 작성하여 발송을 눌러봅니다.

예시 폼

 

그 후 내가 서비스로 선택한 플랫폼의 메일함을 보면 메일이 도착합니다.

 

emailJS 템플릿 테스트 메일

 

 

내용도 수정된 것이 확인됩니다.

정상적으로 동작ㅎㅎ!

emailJS 템플릿 테스트 메일 컨텐츠

 

 

파비콘(favicon.ico) 만들기

 

파비콘이란?

' 파비콘 또는 패비콘이란 인터넷 웹 브라우저의 주소창에 표시되는 웹사이트나 웹페이지를 대표하는 아이콘이다. '

-위키백과

 

 

파비콘에 사용할 아이콘 선정

저는 iconflat 사이트에서 무료라이센스 아이콘을 사용하고는 합니다. (라이선스 확인 및 출처 필수)

www.flaticon.com/

 

Flaticon, the largest database of free vector icons

Download all icons in SVG, PSD, PNG, EPS format or as webfonts

www.flaticon.com

 

검색어에 검색을하고 Filters에서 라이센스 Free를 선택해줍니다.

iconflat Filters창

 

원하는 아이콘을 검색하고 아이콘에 마우스를 올리면 다운로드 할 수 있는 버튼이 뜹니다.

iconflat 검색 결과창

 

다운로드 버튼을 클릭하여 아이콘 이미지를 다운로드 받습니다.

iconflat 아이콘

 

 

 

 

ICO 파일로 변환

convert 사이트를 이용해 해당 이미지를 ico 확장자로 변환하게씁니다.

변환사이트는 본인이 구글을 검색해도 되고 아래 사이트를 이용해도됩니다.

https://icoconvert.com

 

ICO Convert - Create Icons From PNG & JPG Images Online

ICO Convert is a free online icon maker and favicon generator, with it you can make icons from png or jpg images, just upload a photo of yourself, resize and crop it, convert to a shape you like, add borders and shadows, and save it as a PNG image or Windo

icoconvert.com

 

 

Step 1. 이미지업로드

이미지 업로드 Step1

파일 추가버튼 클릭 후 파일을 선택해주고, Upload 버튼을 클릭합니다.

Upload 버튼을 누른 후 아래 Step2로 스크롤해 내려갑니다.

 

 

 

Step 2. 이미지 자르기

이미지 자르기 Step 2

내가 올린 파일 이미지가 뜨고 이미지에 마우스 드래그 시 자를 수 있는 도구가 나옵니다.

전 그대로 사용하기 위해 Step 4로 넘어갔습니다.

 

 

 

Step3는 액자나 기울기 등을 적용하는 부분입니다.

파비콘은 심플한게 좋기때문에 건너뛰었습니다.

 

 

 

Step 4. 사이즈 및 포맷설정

Step 5. 다운로드

사이즈 설정 및 다운로드 Step4, 5

 

Step4에서 크기를 설정해줍니다.

디바이스나 브라우저마다 다른 사이즈의 파비콘을 사용할 수 있습니다.

물론 최적화 시켜서 다 맞추면 좋겠지만 일반적으로는 16x16이나 32x32가 많이 사용됩니다.

저는 32x32로 선택했습니다. 

파비콘은 사이트 탭에서 사이트 이름의 옆, 즐겨찾기 시 사이트 이름 옆, 바탕화면에 바로가기 등록 시에도 사용됩니다.

 

 

Step5에서 확장자를 선택 후 Convert ICO를 클릭하면 하단에 파란색 글씨로 Download your icon(s)가 나옵니다.

Download your icon(s) 글씨를 클릭하여 파일을 다운로드합니다.

 

 

+ 만약 다운로드가 안된다면 +

Download your icon(s)위에 마우스를 올린 후 우클릭을 하여 '검사'를 눌러줍니다.

마우스 우클릭 > 검사

 

 

그렇게 하면 옆에 막 코드가 적혀있는 창(개발자도구)이 뜨는데 <a href="링크" 부분의 링크를 클릭해 줍니다.

그러면 다운로드가 됩니다.

저는 16x16 / 32x32 / 64x64 / 256x256을 선택함으로 인해 multi-size 파일이되었는데,

하나만 선택해도 됩니다.

 

 

 

multi-size 옵션

만약 여러 사이즈가 필요하다면 Step4에서 한번에 여러 사이즈르 선택하여 다운로드 받으면 됩니다.

ico파일은 하나의 파일이지만 그 안에 다양한 크기의 이미지를 포함시킬 수 있는 기능을 지원합니다.

아래 참고 이미지처럼 사이즈를 여러개 선택한 후 다운로드 받아보시면 하나의 파일입니다.

multiple sizes 방법

 

 

 

설정 완료

파비콘 설정하면 내 사이트 탭 옆에 뜨는 것을 확인 할 수 있습니다.

사이트 바로가기 설정 시에도 아이콘 확인이 가능합니다.

브라우저 탭, 파비콘 확인
사이트 바로가기, 파비콘 확인

 

 

+ Recent posts