hanamon.kr에서 이미지참조

 

 

ORM이란?
ORM(Object Relational Mapping)은 객체와 관계와의 설정을 의미한다.

더 자세히 말하자면, 말하는 객체(Object)는 OOP (Object_Oriented Programming)의 객체로 구현되는 클래스와 RDB (Realational DataBase)에서 쓰는 데이터인 테이블을 자동을 연결하는 것을 의미한다. 클래스와 테이블은 서로 호환가능성을 두고 만들어진 것이 아니기때문에 일치하지 않는데, 이를 ORM을 통해 객체 간의 관계를 바탕으로 SQL문을 자동으로 생성하여 불일치를 해결한다. 

 

 

ORM의 장점

 

1. 객체 제향적인 코드로 인해 더 직관적이고 비즈니스 로직에 더 집중할 수 있게 도와준다. 

  • ORM을 이용하면 SQL문이 아닌 직관적인 코드로 데이터를 조작하여, 객체 지향 프로그래밍에 집중할 수 있다. 
  • 선언문, 할당, 종료 같은 부수적인 코드를 줄일 수 있다. 
  • 각종 객체에 대한 코드를 별도로 작성하여 가독성을 높일 수 있다.
  • SQL의 절차적이고 순차적인 접근으로 객체지향적 접근만 고려되어 생산성이 증가할 수 있다. 

 

2. 재사용, 유지보수, 리팩토링이 편리하다. 

  • ORM은 기존 객체와 독립적으로 작성되어 있어, 해당 객체들은 재활용 할 수 있다.
  • 매핑정보가 명확하여 ERD를 보는 의존도를 낮출 수 있다.

 

3. DRMS (DataBase Management System)에 대한 종속성이 줄어든다. 

  • 대부분 ORM솔루션은 DB에 종속적이지 않다. (구현방법과 많은 솔루션, 자료형 타입까지 종속적이지 않다.)
  • 개발자는 객체(Object)에 집중함으로서 극단적으로 DBMS를 교체하는 큰 작업에도 리스크가 적고 소요시간도 줄어든다. 
  • 자바에서 가공할 경우 equals, hashCode의 오버라이드 같은 기능을 이용할 수 있고 빠르게 가공할 수 있다.

 

 

ORM의 단점

 

1. ORM으로만 서비스를 구현하기 어렵다. 

  • 사용하기는 편리하지만, 설계는 매우 신중하게 해야한다. 
  • 프로젝트 복잡성이 커질 경우 난이도 또한 올라가며, 부족한 설계로 속도 저하나 일관성을 무너뜨리는 문제점이 생길 수 있다.

 

2. 절차가 많은 시스템에는 ORM의 객체 지향적인 장점을 활용하기 어렵다.

  • 절차가 많은 시스템에서는 다시 객체로 바꿔야하며, 그 과정에서 생산성 저하 또는 리스크가 많이 발생할 수 있다. 

 

 

ORM과 Node.js 프레임워크

ORM은 Node.js 추상화계층의 고려해야할 가장 높은 수준의 추상화이다. ORM의 요점처럼 관계형 데이터 베이스의 데이터를 애플리케이션의 객체에 매핑하는 것이다. Node.js ORM, Sequelize는 Postgres, MySQL, MariaDB, SQLite 등을 지원하는 Promize에 기반한 비동기로 동작한다.

 

 

 

 

아래의 블로그를 참고하여 작성되었습니다. 

https://yceffort.kr/2021/07/dont-use-nodjs-orm

 

Home

yceffort

yceffort.kr

 

Node.js 프로젝트를 

활성화시키면서 자동적으로 만들어지는

"package.json"

에 대해서 알아보고자 한다.


npm 이란?

 

npm은 Node Package Manager의 약어로, 명칭 그대로 노드 패키지 매니저이다.

 

노드가 자바스크립트 프로그램을 컴퓨터에서도 실행할 수 있게 해준다. 

자바스크립트 프로그램은 패키지로 npm에 등록되어 있으며

특정 기능의 패키지가 필요하다면 npm 에서 찾아 설치하면 된다.

 

 

 

package.json

프로젝트에 필요한 패키지를 추가하다보면 패키지가 어마어마해진다.
사용하는 패키지는 저마다 고유한 버전이 있으며,
동일한 버전을 설치하지 않으면 문제가 생길수 있다. 

이때 설치한 패키지의 버전을 관리하는 파일을
package.json 이라고 한다.

 

 

 

package.json 설치하기

프로젝트를 시작하기 전에 폴더 내부에 무조건 package.json부터 만들고 시작해야 한다!

npm init -y

* -y : 모든 항목에 Yes를 한다는 의미이다.

프로젝트 이름, 설명 등을 작성하고 싶다면, 

'npm init'로 실행시키고 콘솔창에서 작성할 수 있다.

 

 

아래의 형식으로 package.json 미리보기가 나온다.

{
  "name": "프로젝트 이름",
  "version": "프로젝트 버전",
  "description": "프로젝트 설명",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "작성자 이름",
  "license": "ISC",
  }
}

 

 

 

package.json 작성시 알아두기

package name :

패키지 이름으로 Package.json의 name 속성에 저장된다. 

 

version :

패키지 버전은 SemVer의 방식의 버전 넘버링을 따라 항상 세자리로 이루어져 있다. 

 

package.json에 가장 중요한 항목은 "name" 과 "version" 이다.

이 2가지 항목을 통해 패키지 고유성을 판별하게 된다.

필수 항목이며, 해당 내용이 없으면 패키지를 설치 할 수 없다.

 

 

description :

문자열로 기입해야하며, 

npm search로 검색된 리스트에 표시되어 만들어진 패키지를 찾고 이해하는 도움을 준다. 

 

entry point :

자바스크림트 실행파일 진입점. 보통 마지막으로 module.exports를 하는 파일을 지정한다. 

package.json의 main속성에 저장된다.

 

test commend

코드 테스트 시 입력하는 명령어를 의미한다.

package.json scripts 속성안의 test 속성에 저장된다.

 

git repository :

코드를 저장해둔 깃 저장소 주소를 의미한다.

소스에 문제가 생기면 사용자들이 이 저장소에 방문에 문제를 제기하거나

코드 수정본을 올릴 수 있다. package.json repository 속성에 저장된다.

 

keywords : 키워드를 문자열 배열로 설명되며,

npm search로 검색된 리스트에 표시되어 만들어진 패키지를 찾고 이해하는 도움을 준다.

 

bugs :

프로젝트의 이슈와 버그 트레킹을 볼수있는 url 또는 이슈를 알릴 email 주소를 입력한다. 

패키지 사용자가 문제가 있을 시 도움을 줄 수 있다.

 

 license

패키지 사용자들이 만들어진 패키지를 사용하기 위해 어떻게 권한을 얻고,

어떤 금기 사항이 있는지 이해하기 위해 라이센스를 명시해야 한다. 

 

dependencies :

패키지 설치시, 패키지 이름과 함께 설치된 버전이 저장된다.  

 

devDenpendencies :

패키지 모듈을 이용하는 사람이라면, 패키지 테스트 및 문서 작성에 사용되는

외부 프레임 워크는 다운로드를 원하지 않을 것이다. 

이러한 경우, devDependencies 객체에 디펜던시를 추가하는 것도 좋은 방법이다.  

 

 

 

 

더 자세한 사항은 아래의 링크를 참조할 수 있다.

https://docs.npmjs.com/cli/v8/configuring-npm/package-json

게시글 페이지

 

프로젝트: 게시글 페이지

설명: 게시글 목록 조회, 등록, 수정 삭제의 기능 구현을 연습을 위해 제작되었습니다. 

제작: 2022.03.18 ~2022.03.24

 

시연영상: https://youtu.be/hJivoIls7AQ

깃허브: https://github.com/moonhjang/node_1

 


 

사용 기술
  • Server: AWS EC2 (Ubuntu 18.04 LTS)
  • Framework: Express, Mongoose (Node.js)
  • Database: MongoDB
  • front-end: HTML5, CSS3, Javascript, Jquery, bootstrap

 


 

핵심 기능
  • 게시글 목록조회페이지
    • 제목, 작성자명, 작성날짜 조회
    • 작성 날짜 기준으로 내림차순 정렬
    • 특정 게시글 선택시 게시글 조회페이지로 이동
  • 게시글 작성페이지
    • 제목, 작성자명, 비밀번호, 작성내용 입력 후 저장
    • 입력란이 비어있을 시, "입력해주세요" 알람띄우기
  • 게시글 조회페이지
    • 제목, 작성자명, 작성날짜, 작성 내용 조회
  • 게시글 수정/삭제페이지
    • 입력란이 비어있을 시, "입력해주세요" 알람띄우기
    • 비밀번호가 일치할 시, 수정/삭제 가능
    • 비밀번호가 일치하지 않을 시, "비밀번호 불일치" 알람띄우기

 


 

Trouble Shooting 

 

Node.js의 시스템을 완전히 이해하지 못한채 프로젝트를 진행하게 되었다. 1~2일차은 Node.js에 대해서 배웠고, 3~4일차에는 웹사이트의 백엔드 역할에 집중하였다. 5~7일차에는 프론트와 백엔드에 연결에 집중하여 프로젝트를 진행하였다. Node.js의 짧은 이해와 짧은 시간동안 프로젝트를 진행하였기에 완성도는 떨어지지만, 목표하는 기능구현은 완성하였다. 

 

▶ DB저장시, 각 포스팅에 대해서 postsid를 지정했는데, 1개 이후로 postsid 중복관련 에러가 나오면서 저장되지 않았다.

postsid를 작성날짜에 연관해서 넘버링 해주니 문제없이 저장됨

 

▶ MongoDB를 이용했을때와 다르게 Mongoose는 아이디와 비밀번호가 없어도 Robo3T에서 DB내용을 확인할 수 있었다.  하지만, 도메인과 연결 후 Robo3T에 저장된 내용과 연결되지 않고 자체 DB를 만들어 실행되었다. 어디에 저장되고 있는지 아직도 의문이 든다. DB내용 조회나 관리하기가 불편할 것같아 프로젝트 마지막날 소유하고있는 MongoDB로 경로를 변경하려고 하였음.

→ 도메인에 연결된 자체 DB는 껏다 켜도 같은 DB에 연결되어서 아직도 사용해도되는지 의문이 듦.

해당부분은 추후 스터디가 필요함.

 

▶ 비밀번호 저장시, 암호화처리가 어려웠다.

→ 게시글 작성시 암호화 처리된 비밀번호로 저장이 가능함. 하지만, 삭제 및 수정페이지에서 비밀번호 확인시 작성된 비밀번호를 암호화 시킨것과 저장된 비밀번호를 비교했을때 같은 값이 아님. 또한, 암호화 처리된 비밀번호가 '$'와 같은 기호가 있어 Schema에서 비밀번호는 'String' 지정된 상태와 달라서 오류를 냄. 또한, 비밀번호 암호화처리를 위한 충분한 시간이 없어서 추후 다시 도전할 예정임.

 

 

 

 

JavaScript에서 ES 란?

ECMASCRIPT의 약어를 뜻하며, 자바스크립트의 표준, 규격을 나타내는 용어이다.

 

모든 브라우저에서 동작할 수 있는 표준화된 자바스크립트가 필요해지면서

비영리 표준화 기구인 ECMA 인터네셔널에 자바스크립트의 표준화를 요청하였다.

 

ES5 는 2009년도에 HTML5와 함께 출연한 표준 사양이며,

ES6는 2015년에 버전업을하여 출시한 버전이다. 

ES6 이후로도 매년 업데이트가 되고 있고, 이후를 '모던 자바스크립트'라고 부른다.

 

아래에는 ES6에 포함된

let, const 키워드 /  화살표 함수 / 클래스 / 모듈 다루고 있다.

 

 


 

 

let, const 키워드

ES5

ES5의 변수 선언 방법은 var가 유일하다.

 

var :  선언과 초기화가 동시에 실행 

 

단점: 

함수 레벨 스코프 지원 → 지역변수를 전역변수로 사용남발

var키워드 생략 허용 → 암묵적 전역변수 양산

변수 중복 선언 허용 변수값의 의도치 않은 변경

변수 호이스팅  → 선언하기 이전에 참조

 

 

ES6

 var 키워드의 단점을 보완하기위해

let과 const 키워드가 도입되었다. 

 

const : 상수(변하지 않는 값, 재할당 x)

let : 재할당이 가능한 값

 

블록 레벨 스코프 지역변수{ } 에서 사용된 변수는 코드 블로내에서만 유효

변수 중복 선언 금지 →  중복 선언시, 문법에러가 발생

호이스팅 변수 선언 이전에는 참조할 수 없다. 

 

변수 선언에는 기본적으로 const를 사용하고, 

let은 재할당이 필요한 경웨 한정하여 사용하는 것이 좋다. 

 

전역 변수 (Global scope)
전역에서 선언된 변수이며, 어디에서든지 참조할 수 있다. 

지역 변수 (Local scope of Function-level scope)
지역(함수) 내에서 선언된 변수이며, 그 지역과 그지역의 하부지역에서만 참조할 수 있다.
함수 레벨 스코프 (Function-level scope) 
함수 내에서 선언된 변수는 함수 내에서만 유효, 함수 외부에서는 참조할 수 없다. 
즉, 함수 내부에서 선언변수는 지역변수 / 함수 외부에서 선언한 변수는 전역  변수

블록 레벨 스코프 (Block-level scope)
모든 코드 블록(함수 if문, for문, while문, try/catch 문 등)내에서 선언된 변수는 코드 불록 내에서만 유효, 
코드 블록 외부에서는 

 

 

 

화살표 함수(Arrow function)의 선언

 

화살표 함수는 function키워드 대신 (=>)를 사용하여 함수를 선언한다.

// 매개변수 지정 방법
    () => { ... } // 매개변수가 없을 경우
     x => { ... } // 매개변수가 한 개인 경우, 소괄호를 생략할 수 있다.
(x, y) => { ... } // 매개변수가 여러 개인 경우, 소괄호를 생략할 수 없다.

 

ES5보다  ES6의 화살표 함수는 좀더 간결하게 표현된다.

// ES5
var pow = function (x) { return x * x; };
console.log(pow(10)); // 100

// ES6
const pow = x => x * x;
console.log(pow(10)); // 100

기존의 함수와 this 바인딩이 다르며,

Lexical this를 지원하므로 콜백함수로 사용하기 편리하다.

(이 부분은 추가적으로 공부가 필요할 것같다.)

 

 

 

클래스(Class)

ES5

생성자 함수와 프로토타입, 클로저를 사용하여

객체 지향 프로그래밍을 구현하였다.

 

// ES5
var Person = (function () {
  // Constructor
  function Person(name) {
    this._name = name;
  }

  // public method
  Person.prototype.sayHi = function () {
    console.log('Hi! ' + this._name);
  };

  // return constructor
  return Person;
}());

var me = new Person('Lee');
me.sayHi(); // Hi! Lee.

console.log(me instanceof Person); // true

 

 

ES6

기존 방식보다 단순명료한 새로운 문법으로 Class함수가 추가 되었다.

 

// 클래스 선언문
class Person {
  // constructor(생성자)
  constructor(name) {
    this._name = name;
  }

  sayHi() {
    console.log(`Hi! ${this._name}`);
  }
}

// 인스턴스 생성
const me = new Person('Lee');
me.sayHi(); // Hi! Lee

console.log(me instanceof Person); // true

(디테일한 내용은 추가 공부가 필요할것같다.)

 

 

 

모듈 (Module)

모듈은 애플리케이션을 구성하는 개별적 요소로서 재사용이 가능한 코드 조각을 말한다. 

모듈은 세부 사항을 캡슐화하고 공개가 필요한 API만을 외부에 노출한다.

 

모듈은 파일단위로 분리되어 있으며 필요에 따라 모듈을 로드하여 재사용한다. 

 

script 태그에 type="module" 을 추가하면 모듈로서 동작한다. 

ES6 모듈의 파일 확장자는 모듈임을 명확하기 위해 mjs를 사용하도록 권장한다.

<script type="module" src="lib.mjs"></script>
<script type="module" src="app.mjs"></script>

 

모듈은 모듈 스코프를 가진다. 

모듈 내에서 var 키원드로 선언한 변수는 더이상 전역 변수가 아니며

window 객체 프로퍼디도 아니다.

// foo.mjs
var x = 'foo';

console.log(x); // foo
// 변수 x는 전역 변수가 아니며 window 객체의 프로퍼티도 아니다.
console.log(window.x); // undefined
// bar.mjs
// 변수 x는 foo.mjs에서 선언한 변수 x와 스코프가 다른 변수이다.
var x = 'bar';

console.log(x); // bar
// 변수 x는 전역 변수가 아니며 window 객체의 프로퍼티도 아니다.
console.log(window.x); // undefined
<!DOCTYPE html>
<html>
<body>
  <script type="module" src="foo.mjs"></script>
  <script type="module" src="bar.mjs"></script>
</body>
</html>

 

 

Export: 외부에 공개하여 다른 모듈들이 참조할 수 있게한다.

// lib.mjs
const pi = Math.PI;

function square(x) {
  return x * x;
}

class Person {
  constructor(name) {
    this.name = name;
  }
}

// 변수, 함수 클래스를 하나의 객체로 구성하여 공개
export { pi, square, Person };

 

 

Import: 모듈에서 공개한 (export)한 대상을 로드하려면 import 키워드를 사용한다.

아래의 import 3가지 방식을 참고할 수 있다.

// app.mjs
// 같은 폴더 내의 lib.mjs 모듈을 로드.
// lib.mjs 모듈이 export한 식별자로 import한다.
// ES6 모듈의 파일 확장자를 생략할 수 없다.
import { pi, square, Person } from './lib.mjs';                      // import 첫번째 방식
import * as lib from './lib.mjs';                                    // import 두번째 방식
import { pi as PI, square as sq, Person as P } from './lib.mjs';     // import 세번째 방식

console.log(pi);         // 3.141592653589793
console.log(square(10)); // 100
console.log(new Person('Lee')); // Person { name: 'Lee' }

 

 

<참고용>

lib.mjs / app.mjs / html 에서 import와 export 동작 사용방법 

// lib.mjs
export default x => x * x;
// app.mjs
// 브라우저 환경에서는 모듈의 파일 확장자를 생략할 수 없다.
// 모듈의 파일 확장자는 .mjs를 권장한다.
import square from './lib.mjs';

console.log(square(10)); // 100
<!DOCTYPE html>
<html>
<body>
  <script type="module" src="./lib.js"></script>
  <script type="module" src="./app.js"></script>
</body>
</html>

 

 

'오늘의 계절, 오늘의 노래' 라는 프로젝트를 진행하면서

JWT방식으로 로그인+회원가입을  프로그래밍을 해보았지만, 

JWT와 친해지지 않아 자세히 알아보기로 해보았다.

 


JWT 는 무엇일까?

JWT는 JSON Web Token의 약자로 전자 서명 된 URL-safe (URL로 이용할 수있는 문자 만 구성된)의 JSON입니다.

 

 

JWS (Jason Web Signature) : JSON을 암호화하여 URL-safe 문자열로 표현한 것

JWE (Jason Web Encryption) : JSON 데이터 구조를 사용하여 암호화 방법

*URL Safe : URL에 포함 할 수 없는 문자를 포함하지 않는 것

 

 

 

JWT 토큰 구성

JWT 토큰 구성은 헤어(header) + 페이로드(payload) + 서명(Signature)로 구성되며,

각 부분은  Base64로 인코딩 되어 표현된다. 

 

헤어(header) : 토큰의 유형 (JWT) +  HMAC, HS256(SHA256) 또는 RSA와 같은 해시 알고리즘을 나타낸다.

페이로드(payload) : 토큰에 담을 (name/value)를 한쌍으로 이룬 클레임(claim)정보를 나타낸다. 
                                   클레임 정보는 등록된 클레임, 공개 클레임, 비공개 클레임으로 나뉜다.

서명(Signature) : secret key를 포함하여 암호화 되어있다.

 

 

JWT Process 

- 클라이언트의 로그인 정보를 서버에 저장하지 않아, 토큰기반 인증 메커니즘을 제공한다.

- 로그아웃 시, 로컬 스토리지 저장된 JWT 데이터를 제거한다.

 

 

 JWT의 적용

  • 회원인증 : JWT의 가장 흔한 방법 
  • 정보교류 : 두 개체 사이에서 안정성있게 정보를 교환하기에 좋은 방법이다.  
                    정보가 서명되어있기 때문에, 보낸이가 바뀌진 않았는지 도중에 조작되지 않았는지 확인할 수 있다.

 

 

JWT 장점  

  • 사용자 인증에 필요한 모든 정보는 토큰 자체에 포함되어 별도 인증 저장소가 필요없다.
  • 디버깅 및 관리가 용이하다.
  • 트래픽 부담이 낮다.    
  • 독립적인 JWT

 

JWT 단점 

  • 더 많은 정보를 입력할수록 토큰이 커져 네트워크 부하를 줄 수 있다. 
  • JWT는 상태를 저장하지 않아 제어가 어렵다. 
  • 임의로 토큰을 삭제할 수 없어 '토큰 만료 시간'을 꼭 넣어주어야 한다.
  • Payload 는 암호화 한 것이 아니기 때문에
  • JWE를 암호화 하거나 Payload에 중요한 데잉터를 넣지 말아야한다.

 

 

 

 

opennaru blog, 'JWT(JSON Web Token) 이해와 활용' 참고하였습니다.

http://www.opennaru.com/opennaru-blog/jwt-json-web-token/

 

프로젝트: 오늘의 계절 오늘의 노래

설명: 계절감을 보다 감각적으로 느낄 수 있도록 봄, 여름, 가을 겨울을 만끽할 수 있는, 혹은 지나간 계절들을 떠오르게 하는 노래 추천 커뮤니티 사이트입니다. 

제작: 2022. 03. 07 ~ 2022. 03. 11

 

http://sparta-jhh.shop

시연 영상:  https://youtu.be/czaQvEnr6Ts

깃허브:  https://github.com/tayyoon/week1

 


초안

로그인페이지 (로그인을 해야 메인페이지로 넘어간다)

 

메인페이지


사용 기술
  • Server: AWS EC2 (Ubuntu 18.04 LTS)
  • Framework: Flask (Python)
  • Database: MongoDB
  • front-end: HTML5, CSS3, Javascript, Jquery, bootstrap

핵심 기능
  • 로그인/회원가입
    • 아이디 중복확인 기능
    • 회원가입시 아이디 유효성 검사
  • 메인페이지
    • 카드출력: URL, 계절, 코멘트 입력시 카드출력
    • 코멘트수정: 카드 선택시 모달화면에서 타이틀, 코멘트 입력시 해당카드 수정
    • 회원만 이용가능:  로그인한 아이디로 연결된 닉네임으로 확인가능
    • 로그아웃: 상단의 'logout' 선택시 로그아웃

Trouble Shooting

▶ 파이썬과 도메인 구동환경이 달라 도메인이용시 로그인시 메인화면으로 넘어가지 않았음

→  파이썬 이용시, "decode(utf-8)' 주석처리 / 도메인이용시,  "decode(utf-8)' 주석처리 해제로 해결

 

▶ 로그인시, 쿠키를 받아오지 못했음.

→  login.html 에 <head>와<body> 사이의 <scirpt>를 넣음으로서 해결

 

▶ 메인페이지, 반복문으로 DB의 내용을 가져오다 보니 코멘트/하트 수정시 첫 카드만 연결이 되어 수정이 불가

→ 추후에 보완이 필요한 문제

'COPA'의 메인화면


토이프로젝트:  코파 (코로나 아파!)

제작 기간: 2주
웹개발 종합반에 배운 내용과 추가적으로 공부한 내용들로
코로나 현황과 코로나 증상체크리스트, 주변선별진료소, 백신후기를 만들었다.

 

웹사이트 내의 완벽한 구현은 어려우나

2주간의 웹개발 종합반 강의를 듣고 만든 것치고는 만족스럽다.2주의 짧은 시간동안 모든 팀원이 정말 많은 삽질로 고생이 많았다. 

 

http://januaryholder.shop/
시연영상: https://www.youtube.com/watch?v=tJEO2UBt_H4
깃허브주소: https://github.com/yoodeve/toy

 

 

 

COPA의 Dashboard

팀원 모두 디자인의 큰 관심이 없었기에 기능구현에 초점을 맞추어서 프로젝트를 진행하게 되었다. 

부트스트랩을 참고하여 웹사이트 템플릿을 정하게 되었는데, 직접 만드는게 나은 것같다. 

개발하기 전, 부트스트랩을 이해하고 필요없는 것들 지우는데 1~2일을 소비했다는 것이 참 아쉽다.

하지만, 배우지 않았던 자바스크립트를 보고 이해할 수 있던 시간들이 있어 나쁘지 않은 소득이였다.

 

 

COPA의 코로나 현상황 (본인 담당부분)

 

코로나 현상황

크롤링한 데이터를 ajax로 표를 만들었다. 

매일 업데이트된 상황을 다시 반영하도록 하였다. 

'서울'을 눌렀을 때, 서울에 맞는 데이터 나오게 만들었다. (첫 화면은 무조건 '서울')

 

아쉬운점

도시를 눌렀을때 DB에 임시로 저장해서 해당 도시의 데이터가 나오게 만들었다.

새로 선택하면 이전데이터는 삭제하고 새 데이터가 나오는 방식으로 만들었다. 

혼자 이용하는데에는 문제가 없었지만, 배포 후 여러명이 사용하면 DB에 남는 데이터가 겹쳐서 부산을 누르면 인천이 나오는 기괴한 현상이 일어났다. 또한 반응속도 느려 배포후, 두번 클릭해서야 데이터가 나왔다. 

 

 

코로나증상 체크리스트 / 내 주변 선별진료소 / 백신후기  

코로나증상 체크리스트

코로나 주요 증상들로 자신이 코로나에 걸렸는 지 확인할 수 있는 체크리스트이다. 

각 증상마다 점수가 다르게 들어가 있고, 총점 점수마다 알림내용이 다르다. 

 

 

내 주변 선별진료소

계획했던 바는 지도에서 자신의 위치를 확인하고, 주변의 선별진료소를 보여주는 것이 목표였다. 

하지만, 지도에 위치하기 위해서는 모든 선별진료소의 위도와 경도를 알아야하는 점과 자바스크립트를 처음 접하는 사람으로서 각 내용을 이해하고 결합하는데 2주의 시간은 굉장히 짧아 목표했던 바를 바꾸게 되었다.

모든 선별진료소가 목록으로 나오게 만들었다. 

 

비전공자라 '할수 있는 것'과 '할 수 없는 것'의 판단을 하기가 참 어려웠다. 그렇기에 무작정 된다고 생각하고 정말 많은 기능들을 도전해볼 수 있었다. 보여주는 것은 목록뿐이지만 팀원 모두 지도 관련해서 찾아보고 알아볼 수 있어서 좋은 기회가 되었다. 

 

백신후기

백신관련하여 네이버 블로그의 자료를 크롤링해 모아 볼수 있게 만들었다.

가져오는 내용이 많으니 페이지를 나누어서 크롤링하게 만들었다.

추가적으로 백신후기를 작성하여 공유할 수 있다. 

 

첫 토이프로젝트를 끝난 소감

2주의 공부 이후, 배운것들로만 만들어지지 않고 자신이 배운것도 더 공부하여 만들었다. 

'개발'을 처음 접했기에 있을 수 있던 열정이 아닌가 싶다. 프로젝트하는데에 정말 너무 수고했기에 성장이 많았던 것같다. 정말 아쉬운 점은 테스트기간이 없어 배포하고 수정하는데 충분한 시간을 갖지 못한것이 참 아쉽다.

본수업이 시작하기도 전인데, 진짜 많은 성장이 있던 프로젝트였다. 

 

 

 

- AWS 서버연결

- Gitbash 사용

- 가비아 도메인연결

 

1.
AWS 서버 구매하기

 

서울에 있는 '컴퓨터 1개 사는 것'과 같다.

▼ 더보기 클릭 ▼ 

더보기

1) AWS웹사이트 접속

https://ap-northeast-2.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-2

 

 

 

2) AWS 인스턴트 시작

① 지역: 서울

②'인스턴스' 선택 → '인스턴스 시작' 선택

 

 

 

3) AMI 선택

'Ubuntu Server 20.04 LTS'로 선택

(프리 티어 사용: 1년에 1대 무료사용 가능하다는 의미)

 

 

4) 인스턴스 유형 선택

프티티어사용 가능 체크 → '검토 및 시작' 선택

 

 

5) 인스턴스 시작 검토

'시작하기' 선택

 

 

6) 새 키 페어 생성

 

 

①새 키 페어 생성

② '키 페어 이름'은 마음대로 지정가능

③ '키 페어 다운로드' 선택 → 바탕화면에 저장

④ '인스턴트 시작' 선택

 

 

 

7) 인스턴스 업데이트

'대기중' 에서 '실행중'으로 변경됨

(1~2분소요)

 

 


 

 

추가) 인스턴스 중지와 종료할때

인스턴스 중지: AWS의 컴퓨터를 끈다. 

인스턴스 종료: AWS의 컴퓨터를 반납한다. 

#새로 만들때는 '인스턴스 종료'로 컴퓨터를 반납후, 새로 만든다. 

 

 


 

2.
Git Bash _ AWS 서버 확인하기

GitBash는 명령어로만 작동하기때문에 천천히 따라하기

▼ 더보기 클릭 ▼

더보기

1) Git Bash를 켠다.

 

MAC의 경우 초기작업이 필요하다.

sudo chmod 400 '위에서 저장한 키페어를 끌어 넣는다.' → 엔터 → 맥비밀번호 입력 

 

2) 윈도우/맥에서 작성 (구매한 AWS서버에 원격접속)

ssh -i '위에서 저장한 키페어를 끌어 넣는다.' ubuntu@'퍼블릭IPv4주소(IP주소)'   → 엔터 → yes → 엔터

퍼블릭IPv4 주소를 표시된 부분을 눌러서 복사 → 마우스왼쪽 '붙여넣기' 

*Git Bash에서 복사가 안됨.

*Gitbash를 다시 킬 경우, 화살표↑ 를 눌러서 작동가능.

 

 

 

 

+ Git Bash명령어:

폴더만들기  |   내위치확인하기  |  폴더 들어가기  |  폴더에서 나오기

▼ 더보기 클릭 ▼

더보기

1) 폴더만들기

mkdir newfolder     (폴더이름이 'newfolder'일때)

 

2) 내 위치에서 폴더확인하기

ls

 

3) A-folder에 들어가기 (현재 위치에서 'A-folder'가 있다면)

cd Afolder

#해당 폴더로 들어가면 '~/Afolder$'가 작성하는 곳에 생김

 

4) 폴더에서 나가기

cd ..

 

5) 아래의 5가지 패키지 설치하기 

 

# python3 -> python
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 10

# pip3 -> pip
sudo apt-get update
sudo apt-get install -y python3-pip
sudo update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1

# port forwarding
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 5000

 

 

 


 

 

3.
Filezila _ AWS서버 세팅하기

▼ 더보기 클릭 ▼

더보기

1) Filezila 접속

 위의 표시된 부분을 눌러 사이트관리자를 열어준다.

 

 

2) 사이트 관리자 설정

 

① New site 선택 → 'myec2' 로 저장  #폴더 이름은 마음대로

② 호스트는 IP주소 복사해서 붙여넣기

③ 포트(P) : 22

④ 로그온 유형 (L) : 키파일

사용자(U) : ubuntu

키파일(K) :  저장한 키페어 파일(PEM파일) 불러오기

( AWS 서버구매하기 키페어 저장 참고)

'연결' 선택 → 알수없는 호스트키 창에서 '확인' 선택

 

 

 

 

 

4.
AWS 보안 설정하기

▼ 더보기 클릭 ▼

더보기

1) 인스턴트 ID 선택

'인스턴트 ID' 선택

 

2) 보안선택

 '보안' 선택 → '보안그룹' 선택

 

 

3) 인바운드 규칙 설정

 '인바운드 규칙 편집' 선택 ('edit inbound rules')

 

 

4) 인바운드 규칙 설정 및 저장

 

① 기존의 포트범위 22는 있음 

② 규칙추가 → 포트범위: 5000  → 소스: Anywhere-IPv4 

③ 규칙추가 → 포트범위: 80  → 소스: Anywhere-IPv4 

④ 규칙 저장

 

 

 


+ Filezila에 파일을 올리고 실행시켜보기

▼ 더보기 클릭 ▼

더보기

1) 파일 옮기기

파일 옮길때는 static / templates / app.py 만 이동시킨다. 

(파일질라의 왼쪽은 내컴퓨터,  오른쪽은 구매한 컴퓨터)

 

 

 

2) Git Bash_구매한 컴퓨터 확인하기

 

위의 화면에서 시작

화살표 ↑ → 엔터

 (이전 작성한 키페어 생성)

ls → 엔터   

(현재위치 확인, '보라색 파일이름' 이 현재 위치)

cd sparta → 엔터

(화면 ~/sparta$ 이 생성됬다면 해당파일에 들어감)

ls (현재위치 확인) → 엔터   

(위의 옮긴 파일을 확인 가능)

python app.py → 엔터

    # No moudule named 'flask'가 나왔다면, pip install flask 

 

 

 

3) IP주소로 인터넷 배포 완료

 

IP주소:5000 또는 IP주소 로 접속 가능

( 13.000.000.000:5000  /  13.000.000.000 )

 

 

 

 4) gitBash_(원격)을 종료 + 종료해도 웹사이트 

  원격종료 없이 서버돌아가기 : nohup python app.py &

  강제종료하기 :  ps -ef | grep 'python app.py' | awk '{print $2}' | xargs kill

 

 

 


 

 

5.
가비아 _ 도메인 연결하기

 

 

1) 가비아 회원가입 후 도메인 구매하기

▼ 더보기 클릭 ▼

더보기

1) 가비아 회원가입 (특이사항이 없어 패쓰-!)

https://www.gabia.com/

 

2) 가비아 도메인 만들기

 

① 웹사이트 좌측 상단 'gabia' 선택 

② 자신이 원하는 도메인 작성 → 검색

 

 

 

3) 가비아 도메인 구매하기

 

.shop 의 도메인 선택 → 신청하기

(.shop은 1년동안만 500원으로 이용가능)

 

 

3) 가비아 도메인 결제하기

 

'1년' 으로 수정 

(보통 3년으로 선택되어있음)

안전 잠금 신청 선택 X

( 이 외 특이사항 없음)

무통장 입금으로 결제진행

(1천원 이하는 카트결제 불가)

 

 

2) IP주소와 가비아 도메인 연결하기

▼ 더보기 클릭 ▼

더보기

1) 가비아 접속

https://dns.gabia.com/

 

 

 

2) 내 도메인 선택

도메인 '체크박스' 선택 'DNS 설정' 선택

 

 

 

3) 도메인 설정

 

호스트:  @ 

② 값/위치: IP주소

(숫자만 입력. 00.000.000.000)

③ 확인 → 저장

 

 

 

4) 도메인 확인

 자신의 도메인으로 접속해보기

 

 

 

 

 

 

 

서버연결 (파이썬)
import pymongo
import certifi

client = pymongo.MongoClient(
    "mongodb+srv://test:sparta@cluster0.hd7sx.mongodb.net/Cluster0?retryWrites=true&w=majority",
    tlsCAFile=certifi.where())
db = client.dbsparta

 

flask로 mongoDB연결 + HTML 연결 (파이썬)
from flask import Flask, render_template, request, jsonify

app = Flask(__name__)

@app.route('/')
def home():
    return render_template('index.html')

@app.route("/homework", methods=["POST"])
def homework_post():
    sample_receive = request.form['sample_give']
    print(sample_receive)
    return jsonify({'msg': 'POST 연결 완료!'})

@app.route("/homework", methods=["GET"])
def homework_get():
    return jsonify({'msg': 'GET 연결 완료!'})

if __name__ == '__main__':
    app.run('0.0.0.0', port=5000, debug=True)

 

크롤링(파이썬) 
import requests                       #pip install requests
from bs4 import BeautifulSoup         #pip install bs4

@app.route("/movie", methods=["POST"])
def movie_post():
    url_receive = request.form['url_give']
    star_receive = request.form['star_give']
    comment_receive = request.form['comment_give']

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
    data = requests.get(url_receive, headers=headers)

    soup = BeautifulSoup(data.text, 'html.parser')

    title = soup.select_one('meta[property="og:title"]')['content']
    image = soup.select_one('meta[property="og:image"]')['content']
    desc = soup.select_one('meta[property="og:description"]')['content']

    doc = {
        'title': title,
        'image': image,
        'desc': desc,
        'star': star_receive,
        'comment': comment_receive
    }
    db.movies.insert_one(doc)

    return jsonify({'msg':'저장 완료'})

 

html (POST) 웹내용 DB에 저장하기
function save_comment() {
    let name = $('#name').val()
    let comment = $('#comment').val()

    $.ajax({
        type: 'POST',
        url: '/homework',
        data: {name_give: name, comment_give: comment},
        success: function (response) {
            alert(response['msg'])
            window.location.reload()
        }
    })
}

 

html (GET) DB내용 웹에 보여주기
function show_comment() {

    $.ajax({
        type: "GET",
        url: "/homework",
        data: {},
        success: function (response) {
            let rows = response['fans']

            for (let i = 0; i < rows.length; i++) {
                let name = rows[i]['name']
                let comment = rows[i]['comment']

                let temp_html = `<div class="card">
                                <div class="card-body">
                                    <blockquote class="blockquote mb-0">
                                        <p>${comment}</p>
                                        <footer class="blockquote-footer">${name}</footer>
                                    </blockquote>
                                </div>
                            </div>`

                $('#comment-list').append(temp_html)
            }
        }
    })
}
mongoDB 연결 중 오류 (certificate verify fail)

맥 사용하시는 분들 중에서 mongoDB 연결 중 'certificate verify fail' 했다는 오류가 많았다. 

나는 윈도우인데...?

 

해결

1. certifi를 설치한다. 

Alt+F12를 누르면 아래에 터미널이 나온다. 

'pip install certifi' 작성하여 설치한다. 

 

*설치시 문제가 있다면, 파일 - 설정 - 프로젝트 - python 인터프리티에서 설치가능

 

2. 코드 수정 및 추가한다.

import pymongo
import certifi

client = pymongo.MongoClient("mongodb+srv://test:sparta@cluster0.hd7sx.mongodb.net/Cluster0?retryWrites=true&w=majority",tlsCAFile=certifi.where())
db = client.dbsparta


doc = {
    'name':'bob',
    'age':27,
}

db.users.insert_one(doc)

 


 

추가. 파이썬 업그레이드하기

1) 'certifi' 설치 시, 노랑글씨로 업그레이드방법이 나와있다면,

window + R 누르고. 

'C:  ...  --upgrade pip' 콤마 안에 있는 글을 복사 붙이면 업그레이드 끝.

 


mongoDB 파이썬으로 작동하기

mongoDB에 저장하기
doc = {'name':'bobby','age':21}
db.users.insert_one(doc)

 

mongoDB에서 한개 찾기
user = db.users.find_one({'name':'bobby'})

 

mongoDB에서 여러개 찾기 ( _id 값은 제외하고 출력)
all_users = list(db.users.find({},{'_id':False}))

 

mongoDB의 내용 바꾸기
db.users.update_one({'name':'bobby'},{'$set':{'age':19}})

 

mongoDB의 내용 지우기
db.users.delete_one({'name':'bobby'})

+ Recent posts