출처: https://bumcrush.tistory.com/182 [맑음때때로 여름]

 

 

파스칼 케이스로 해야 되는 간단한 문제..였다 ㅎ..

 

// 리액트 에서 컴포넌트들을 생성하는것은 파스칼 케이스에 해당되기 때문에 gdlButton 와 같이 생성하면 렌더링이 되지 않습니다.

 

-> GdlButon 과 같이 첫 문자가 대문자로 오는 파스칼 케이스여야 합니다.



출처: https://ipex.tistory.com/entry/React-시작-전-준비-단계-트러블-슈팅-Trouble-Shooting [깍돌이]


CRA (create-react-app)

- 리액트 개발 환경을 직접 구축하려면 많은 지식과 노력이 필요한데 자동으로 구축해준다.

(webpack, babel, jest, eslint, polyfill, hmr, css후처리)

- 페이스북에서 관리하는 공식 툴이라 믿고 사용할만 하다~

- 서버사이드 렌더링을 지원하지 않음. (할수있지만 깔끔한 방법이없음)

 => 서버사이드 렌더링이 필요하다면 Next.js를 사용하자

 

 

참고 : (왜냐면 서버사이드 렌더링이 뭔지모르니깐..ㅎ)

 

[주니어탈출기] 서버사이드렌더링(SSR) & 클라이언트사이드렌더링(CSR)

서버사이드렌더링 & 클라이언트사이드렌더링 왜 모바일의 시대에 등장한 클라이언트사이드렌더링 Single Page Application(SPA)! 고려해야할 점들이 있다. SPA는 최초 한 번 페이지 전체를 로딩한 후 데

velog.io

 

 

인강버전은 뭔가 자꾸 에러가나서 책에 나온 버전으로 cra설치함

npm install -g yarn // yarn설치

npm install -g create-react-app // cra설치

create-react-app cra-test // cra-test라는 app 만들어줌

yarn start // 시작

3000번 포트로 들어가서 리액트앱화면뜨면 성공

 

[리액트] 개발환경 설치하기

1. 노드 버전 매니저로 노드JS설치하기 1-1. NVM 설치하기 github.com/coreybutler/nvm-windows/releases 1-2 nvm이 잘 설치 됐는지 cmd로 확인해보기 1-3 NVM으로 노드제이에스 설치하기 (주의 10.16.2 버전으..

javappo.tistory.com

 

 

cra버전이 올라가면 대부분 react-scripts를 수정해주면 된다고 한다.

browerslist의 0.2는 0.2퍼센트 이상의 점유율을 가진 브라우저를 대상으로 하겠다는 뜻

(자세한 문법은 브라우저 리스트에 대해서 검색해보면 자세히 알 수 있다)

 

CRA의 4가지 명령어

 

start

: 개발모드로 실행할떄 사용, 여러가지 최적화가 적용이 안된 상태로 실행 (배포할때 사용X)

: 기본적으로 http로 실행된다.

: https로실행하고싶다면? => set HTTPS=true&&npm start  (혹은 yarn start).. (ㅡㅡ맥북이랑 윈도우랑다름..)

create-react-app.dev/docs/using-https-in-development/

 

Using HTTPS in Development | Create React App

Note: this feature is available with react-scripts@0.4.0 and higher.

create-react-app.dev

 

build

: 배포할 때 사용

: npm run build  or yarn run build => 빌드를 하면 정적 파일 생성

: 별도로 서버에 애플리케이션을 실행하지않기때문에 서버사이드 렌더링으로 동작할 수 없다함..(아직뭔말인지ㅎ)

: 빌드 시 작은 이미지는 base64로 자바스크립트에 저장 => 빠르게 하려고

\\react developer tools

 

test

npm test => app.test.js

__test__ 폴더에 넣으면 다 테스트파일로 인식

 

eject

: react scripts를 사용하지 않고, 모든 설정 파일을 추출하는 명령어 

: cra를 기반으로 직접 개발환경을 구축하고 싶을때 사용

: 추출을 하지 않으면 cra 에 기능이 추가됐을때 react scripts 버전만 올리면 되지만, 추출하면 직접 수정해야함

 

caniuse.com

브라우저별로 지원여부나옴 => 특정기능 중 사용하고 싶은 것입력 (ex: padStart)

지원하지 않는 브라우저에서도 지원하고 싶다 ==> polyfill 추가해야함 => 보통 core-js라는 것을 많이 사용함

cra에는 기본적으로 core-js가 내장되어있으므로 (원래는 설치해야하지만)

core-js에서 padstart를 검색하고 import해서 사용 import 'core-js/~!##$#' (복사내용)

 

환경변수

개발, 테스트 환경별로 다른값을 쓸때 유용

process.env.{변수 이름}

process.env.NODE_ENV [기본]

npm start로 실행하면 development , npm test로실행하면 test 

 

출처 : yngmanie.space/posts/cache

브라우저에서 캐시란 무엇이여 왜 중요할까요?

javascript  HTTP

11 Apr 2019

해당 포스트는 What is a browser cache, and why is it important?를 번역하여 작성하였습니다. 잘못된 부분이 있다면 댓글 부탁드립니다.

캐시라는 단어를 들어봤더라도 그것이 웹에서 정확하게 어떤 의미인지는 잘 모를겁니다. 흔히 캐싱의 의미는 어떤 것을 나중에 유용하게 사용하기위해 저장한다는 뜻입니다. 브라우저나 웹에서의 캐시는 이와 동일한 뜻이고 추가로 프로그램과 웹사이트 자산을 저장합니다. 웹사이트를 방문했을 때, 당신의 브라우저는 몇 개의 페이지를 가지고 있고 그것을 컴퓨터 하드디스크에 저장합니다. 브라우저가 저장할 자산은 아래와 같습니다.

  • 이미지: 로고, 사진, 백그라운드 등
  • HTML
  • CSS
  • Javascript

간단히 말해서 브라우저는 정적인 자산(웹페이지에 방문할 때마다 변하지 않는 것들)을 캐시합니다.

무엇을 캐시하고 얼마나 저장할지는 웹사이트에 의해 결정됩니다. 어떤 자산을 며칠만에 제거되지만 어떤 것들은 1년 넘게 캐시되어 있을 수 있습니다.

많은 사람이 웹사이트가 당신의 컴퓨터에 허락도 없이 자산을 저장한다고 했을 때, 그들은 약간 신경쓰입니다. 그리고 우리는 웹 개발자가 파괴적이고 악의적인 것들을 우리의 다바이스에 저장시키지 않도록 희망하면서 신뢰하고 있다고 말할 수 있습니다.

브라우저 캐싱의 이점은 위험보다 훨씬 큽니다. 좋은 방화벽, 바이러스 스캐너는 당신의 기계가 안전하도록 유지합니다.

캐시의 이점

웹사이트에 처음 방문했을 때, 당신의 브라우저는 원격으로 호스트 사이트 서버와 커뮤니케이션을 합니다. 브라우저는 요청하고 서버는 응답을 하면서 웹사이트 자산을 전달해 줍니다. HTML이 처음 다운로드되고 이것이 어떤 사이트를 그려야 하는지에 대한 정보가 담겨있습니다. 브라우저가 HTML 코드를 읽을 때 서버에게 다른 페이지에 대한 정보를 추가로 요청하는데 대부분 위에서 언급한 정적 자산입니다.

이 프로세스는 bandwidth을 사용합니다. 일부 웹페이지는 자산이 많고 크기때문에 모든 페이지를 다운로드하고 기능을 수행하는데 오랜 시간이 걸립니다.

예를 들어, 텍스트가 이미지가 먼저 나타나는 것을 웹사이트 처음 방문했을 때 느꼈을 겁니다. 텍스트가 자산 크기가 작기때문에 다운로드하는데 적은 시간이 걸리는 겁니다. 반면에 고화질의 이미지가 로드되는데는 몇초가 걸릴 수 있습니다.

캐싱은 브라우실 속도를 향상시킵니다. 일단 자산을 다운로드하면 그것은 어러분의 기계에 일정 기간동안 존재합니다. 당신의 하드디스크에서 파일을 검색하는 것이 인터넷이 아무리 빠르더라도 원격으로 서번에 요청하는것보다 효율적입니다.

일반적인 이커머스 사이트로 생각했을 때, 로고와 같은 자산은 사이트 어느 페이지에 있던 간에 동일한 위치에 표시됩니다. 캐시 기능이 없다면 다른 페이지로 이동할 때 마다 로고를 다운로드해야합니다.

고 퀄리티 이미지와 같이 복잡한 사이트는 큰 자바스크립트 파일을 사용합니다. 구매하기 버튼이 제품 하단에 나타나는데 5~10초 정도 걸린다고 가정했을 때 유저의 전환률이 부정적인 영향을 준다고 상상을 해봅시다. 유저가 편안하고 전환율을 높일 수 있게 하기위해서는 웹페이지는 빠르고 유동적이어야 합니다. 더불어 다음번에 캐시가 된 웹페이지에 방문하면 당신 디바이스에 저장된 자산을 활용해 빠르게 로딩할 수 있습니다.

모바일 디바이스는 빈번하게 bandwidth에 의해 제한됩니다. 일부 모바일데이터는 bandwidth에 대한 캡과 비용을 부과합니다. 유저입장에서 웹사이트를 다운로드를 하지않아야 좋을 것입니다.

캐시의 문제점

웹사이트에서 캐싱된 자산을 사용할 수 있도록 허용했습니다. 다음 날 로고는 색을 변경했습니다. 로고 색이 변경되고 웹사이트에서 변경된 색으로 확인했습니다. 그러나 오래된 로고는 여전시 웹사이트에 있습니다.

이미지 교체를 완벽하게 교체해도 문제는 캐싱이 되고 있다는 뜻입니다.

당신의 기기는 하드디스크에 캐시된 로고 버전이 있습니다. 그것은 새로운 이미지를 다운받도록 요청하지 않습니다. 그러므로 캐시가 만료되지 않는 한 새로운 로고를 얻을 수 있습니다.

유저가 하드디스크에 최신버전파일이 캐시되어 있지 않으면 여러 문제가 발생할 수 있습니다. 포맷이 안맞고, 자바스크립트가 깨지고 올바르지 않는 이미지가 나타납니다.

대부분의 경우 서버가 어떤 자산이 업데이트되고 유저 기기에서 교체되어야하는지 알고있기 때문에 문제가 되지 않습니다. 만약 일부 유저가 홈페이지가 깨졌다고 문제제기를 하면 브라우저캐시를 삭제해보라고 권하면 됩니다.

대부분의 브라우저는 ‘캐시 제거’버튼이 있습니다. 버튼을 클릭하면 캐시된 모든 파일이 삭제됩니다. 캐시를 지우고 자주 방문하던 사이트에 들어가봤을 때 로드되는 얼마나 걸리는지 확인해보세요.

브라우저는 특정 웹사이트만의 캐시를 삭제할 수 있습니다. 특정 사이트만 캐싱 이슈가 있다면 문제가 되는 사이트의 캐시를 지우고 기존 캐싱이 되어있는 사이트를 빠르고 유동적으로 사용하세요.

 

웹팩은 오픈 소스 자바스크립트 모듈 번들러로써 여러개로 나누어져 있는 파일들을 하나의 자바스크립트 코드로 압축하고 최적화하는 라이브러리입니다.

 

웹팩의 기본 개념 이해하기

: 다양한 기능 제공

- 파일 내용을 기반으로 파일 이름에 해시값 추가 => 효율적으로 브라우저 캐싱 이용

- 사용되지 않은 코드 제거

- JS에서 CSS,JSON, 텍스트 파일 등을 일반 모듈처럼 불러오기

 (자바스크립트 안에서 여러가지를 처리할 수 있다)

- 환경변수 주입

 

* 웹펙을 사용하는 가장 큰 이유 => 모듈 시스템(ESM, commonJS)을 사용하고 싶어서

 

- 웹사이트가 점점 동적으로 변하면서 많은 js파일이 필요하게 됨

=> 선언된 자바스크립트 파일의 순서에 따라서 동작이 달라질 수 있다.

=> 외부라이브러리와 내부의 파일들이 서로 싱크가 맞아야 하는데 그 문제를 해결해준다.

  (변수 이름 충돌 같은 것은 빌드단계에서 잡아낼 수 있고 외부라이브러리는 npm으로 관리를 할 수가 있다고 함..)

- 요즘 브라우저는 ESM을 지원해서 웹팩을 사용하지 않고도 서비스 할수 있지만 오래된 브라우저도 서비스를 해야하고, 많은 오픈 소스가 commonJS로 작성되어있고, 요즘 브라우저는 commonJS를 처리를 못한다.

 

웹팩에 필요한 패키지 설치

npm install webpack wepack-cli react react-dom

 

npx 실행

 

 

 

나중에 읽어볼 링크

 

[JS][WEBPACK] 1. 웹팩이란 무엇인가

웹팩은 오픈 소스 자바스크립트 모듈 번들러로써 여러개로 나누어져 있는 파일들을 하나의 자바스크립트 코드로 압축하고 최적화하는 라이브러리입니다.

medium.com

 

바벨 (Babel)

 : ES6 문법을 ES5 문법으로 변환해주는 용도로 주로 사용

 : 리액트에서는 jsx 문법을 createElement 함수로 호출하는 코드로 변환하기 위해 사용한다.

 

최근) 코드에서 주석을 제거하거나, 코드를 압축하는 용도로 사용되기도 한다.

 

 

// 바벨설치하기 

 

package.json 파일생성

(npm은 node.js를 설치하면 알아서 설치됨.. 노드 패키지 매니저)

 

npm init -y를 하면 생성

npm install @babel/core @babel/cli @babel/preset-react 설치

(강의에선 npm install @~~ @~~ @~~ 해서 한방에 설치했으나 나는 안되서 한개씩..)

 

core : 바벨의 핵심 기능을 가지고 있는 패키지

cli : cli에서 사용할 바이너리가 들어있음

preset-react : 리액트를 위한 플러그인 여러개를 모아놓은 것

 

바벨에는 프리셋과 플러그인이라는 개념이있고

플러그인 : 하나의 변환하는 기능을 의미

프리셋 : 그런 여러개의 플러그인을 모아놓은 것 (특정 목적을 위해)

npx babel --watch src --out-dir . --presets @babel/preset-react 

(watch모드로 동작을 시킴 / src폴더에 있는 것을 현재 폴더로 출력을 해줌

/ 프리셋으로 이전에 설치했던 preset-react를 쓰겠다는뜻..)

npx를 명령어를 사용하면 노드모듈안의 바벨 바이너리를 실행해준다.

(바벨을 설치하지 않았다면 npx가 알아서 바벨을 설치해주는 똑똑이짓을함)

simple1.js복사~

 

복사된 simple1.js는 원본이 바뀔때마다 컴파일해서 createElement코드로 변환된다.

 

 

 

<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title></title>
</head>

<body>
    <h2>안녕하세요</h2>    
    <div id="root"></div>

    <h3>root1</h3>
    <div id="root1"></div>
    <h3>root2</h3>
    <div id="root2"></div>
    <h3>root3</h3>
    <div id="root3"></div>

    
    <script src="react.develpment.js"></script>
    <script src="react-dom.development.js"></script>    
    <script src="simple1.js"></script>

</body>
</html>
function LikeButton(){
    // likebutton에 liked라는 상태값을 추가
    const [liked, setLiked] = React.useState(false);
    const text = liked ? '좋아요 취소' : '좋아요';

    return React.createElement(
        'button',
        { onClick: () => setLiked(!liked)},
        text,     
    )
}

// const domContainer = document.getElementById('root');
// ReactDOM.render(React.createElement(LikeButton), domContainer);

const domContainer = document.getElementById('root');
ReactDOM.render(
    React.createElement(
        'div',
        null,
        React.createElement(LikeButton),
        React.createElement(LikeButton),
        React.createElement(LikeButton),
    ),
    domContainer
);



const domContainer1 = document.getElementById('root1');
ReactDOM.render(React.createElement(LikeButton), domContainer1);
const domContainer2 = document.getElementById('root2');
ReactDOM.render(React.createElement(LikeButton), domContainer2);
const domContainer3 = document.getElementById('root3');
ReactDOM.render(React.createElement(LikeButton), domContainer3);


// React.createElement(
//     'div',
//     null,
//     React.createElement('p',null,'hello'),
//     React.createElement('p',null,'world'),
// );

 

ithub.tistory.com/264

 

React Error Target container is not a DOM element

안녕하세요. 오늘은 웹 작업을 할때 발생하는 Target container is not a DOM element 에러에 대해서 알아보겠습니다. 리액트를 사용할때, (리액트를 사용하지 않을때도 발생할 수 있습니다.) UInvariant

ithub.tistory.com

 

 

javascript 파일을 head에서 불러올 경우 하단에 있는 body 엘리먼트가 읽혀지지 않은 상태에서 javascript 파일이 호출되어 DOM element를 참조할 경우 에러가 발생하게 된다

 

해결 방법
1.  javascript 파일을 body 하단부에 등록해주는 방법
2. javascript의 실행을 DOM이 load 되고 난 이후에 발생하도록 하는 방법

 

 

나는 빨간 표시를 아랫부분으로 내려줌! (해결방법1)

 

 

 

왜그런가했네..

 

 

컴포넌트에 데이터를 전달하는 프로퍼티

- 프로퍼티 기초 알아보기

import React from 'react';
import PropTypes from 'prop-types';

class PropsComponent extends React.Component {
  render() {
    return <div className="message-container">{this.props.name}</div>;
  }
}

// 자료형을 선언하는 예제
PropsComponent.propTypes = {
  name: PropTypes.string,
};

export default PropsComponent;
import './App.css';
import { Component } from 'react';
import PropsComponent from './03/PropsComponent';

class App extends Component{
  render(){
    return(
      
      <PropsComponent name="두잇 리액트"/>
    )
  }
}

export default App;

 

- 다양한 프로퍼티 사용하기

import React, { Component } from 'react';
import PropTypes from 'prop-types';

class ChildComponent extends Component {
  render() {
    const { boolValue, numValue, arrayValue, objValue, nodeValue, funcValue } = this.props;

    return (
      <div>
        <span>불리언 값 : {boolValue}</span>
        <span>숫자값 : {numValue}</span>
        <span>배열값 : {arrayValue}</span>
        <span>객체값 : {String(objValue)}</span>
        <span>노드값 : {nodeValue}</span>
        <span>함수값 : {String(funcValue)}</span>
      </div>
    );
  }
}
ChildComponent.propTypes = {
  boolValue: PropTypes.bool,
  numValue: propTypes.number,
  arrayValue: PropTypes.arrayOf(PropTypes.number),
  objValue: PropTypes.object,
  nodeValue: PropTypes.node,
  funcValue: PropTypes.func,
};

export default ChildComponent;
import './App.css';
import { Component } from 'react';
import ChildComponent from './03/ChildComponent';

class App extends Component{
  render(){
    return(
      <ChildComponent
        boolValue={true}
        numValue={1}
        arrayValue={[1,2,3]}
        objValue={{ name : '제목', age : 30}}
        nodeValue={<h1>노드</h1>}
        funcValue={()=> { console.log('메시지'); }}
        />
    )
  }
}

export default App;

결과값은 같지만 개발자간의 실수를 줄이기 위해 변수에 객체를 담아 전달하는 아랫 방식을 선호한다.

import './App.css';
import { Component } from 'react';
import ChildComponent from './03/ChildComponent';

class App extends Component{
  render(){
    const array=[1,2,3];
    const obj = {name : '제목', age:30};
    const node = <h1>노드</h1>;
    const func = () => { console.log('메시지'); };
    return(
      <ChildComponent
        boolValue={true}
        numValue={1}
        arrayValue={array}
        objValue={obj}
        nodeValue={node}
        funcValue={func}
        />
    )
  }
}

export default App;

 

- 불리언 프로퍼티 사용하기

=> 실무에서 자주 사용하므로 알아두기

import React, { Component } from 'react';

class BooleanComponent extends Component {
  render() {
    const message = this.props.bored ? '놀러가자' : '하던 일 열심히 마무리하기';
    return <div className="message-container">{message}</div>;
  }
}

export default BooleanComponent;
import { Component } from 'react';
import BooleanComponent from './03/BooleanComponent';

class App extends Component {
  render() {
    return (
      <div>
        <div>
          <b>지루할 때 :</b>
          <BooleanComponent bored />
        </div>
        <div>
          <b>즐거울 때 :</b>
          <BooleanComponent />
        </div>
      </div>
    );
  }
}

export default App;

 

- 객체형 / 필수 프로퍼티 사용하기

 

import React from 'react';
import PropTypes from 'prop-types';

class ChildComponent2 extends React.Component {
  render() {
    const { objValue, requiredStringValue } = this.props;

    return (
      <div>
        <div>객체값: {String(Object.entries(objValue))}</div>
        <div>필수값: {requiredStringValue}</div>
      </div>
    );
  }
}

ChildComponent2.propTypes = {
  // 객체형 프로퍼티
  objValue: PropTypes.shape({
    name: PropTypes.string,
    age: PropTypes.number,
  }),
  // 필수 프로퍼티
  requiredStringValue: PropTypes.string.isRequired,
};

export default ChildComponent2;
import { Component } from 'react';
import BooleanComponent from './03/BooleanComponent';
import ChildComponent2 from './03/ChildComponent2';

class App extends Component {
  render() {
    return (
      <div>
        <ChildComponent2 objValue={{ age: '20살' }} />
      </div>
    );
  }
}

export default App;

age에 number가 아닌 String을 대입한 에러1과, 필수 프로퍼티로 지정한 RequiredStringVaule에 값이 전달되지 않아서 에러가 나게 됐다.

import { Component } from 'react';
import BooleanComponent from './03/BooleanComponent';
import ChildComponent2 from './03/ChildComponent2';

class App extends Component {
  render() {
    return (
      <div>
        <ChildComponent2 objValue={{ age: 20 }} requiredStringValue="문자" />
      </div>
    );
  }
}

export default App;

수정해주니까 에러 사라짐~

 

 

컴포넌트 상태 관리하기

 

1. state로 상태관리하기.

import React from "react";

class StateExample extends React.Component {
  constructor(props) {
    super(props);
    // 상태 정의
    this.state = {
      loading: true,
      formData: "no data",
    };
    // 이후 콜백 함수를 다룰때 bind를 선언하는 부분에 대해 다룹니다
    this.handleData = this.handleData.bind(this);
    // 생성 후 4초 후에 handleData를 호출합니다.
    setTimeout(this.handleData, 4000);
  }
  handleData() {
    const data = "new data";
    const { formData } = this.state;
    // 상태 변경
    this.setState({
      loading: false,
      formData: data + formData,
    });
    // this.state.loading 은 현재 true 입니다.
    // 이후 호출될 출력함수에서의 this.state.loading은 false입니다.
  }
  // 다음과 같이 setState함수를 사용할 수 있습니다.
  // handleData(data) {
  //   this.setState(function(prevState) {
  //     const newState = {
  //       loading : false,
  //       formData: data + prevState.formData,
  //     };
  //     return newState;
  //   });
  // }
  render() {
    return (
      <div>
        {/* 상태 데이터는 this.state로 접근 가능합니다. */}
        <span>로딩중: {String(this.state.loading)}</span>
        <span>결과: {this.state.formData}</span>
      </div>
    );
  }
}

export default StateExample;

왼쪽 => 4초뒤 => 오른쪽

 

state를 사용할 떄 주의점

: 생성자에서 반드시 초기화 해야 한다.

: state값을 변경할 떄는 setState()함수(상태관리함수)를 반드시 사용해야함

: setState()함수는 비동기로 처리되며, setState() 코드 이후로 연결된 함수들의 실행이 완료된 시점에

  화면 동기화 과정을 거친다.

 

 

2. 클래스 인스턴스 변수와 forceUpdate()함수로 State관리하기

import React from "react";

class ForceUpdateExample extends React.Component {
  constructor(props) {
    super(props);
    //state 정의
    this.loading = true;
    this.formData = "no data";

    //이후 콜백 함수를 다룰 때 bind를 선언하는 부분에 대해 다룹니다
    this.handleData = this.handleData.bind(this);
    // 4초후 호출
    setTimeout(this.handleData, 4000);
  }
  handleData() {
    const data = "new data, ";
    //state 변경
    this.loading = false;
    this.formData = data + this.formData;
    // 컴포넌트 내장 함수 forceUpdate()를 호출하여 강제로 화면을 새로고침 한다.
    this.forceUpdate;
  }
  render() {
    return (
      <div>
        {/* 상태 데이터는 this.state로 접근 가능합니다. */}
        <span>로딩중: {String(this.state.loading)}</span>
        <span>결과: {this.state.formData}</span>
      </div>
    );
  }
}

export default ForceUpdateExample;
C;

  

 

위에 것과 결과는 같지만 리액트 성능에 제약이 있으므로, 매번 새롭게 화면을 출력해야 되는 경우가 아니라면

가급적 사용하지 않기를 권한다고 한다

'front-end > react' 카테고리의 다른 글

[리액트] create-react-app  (0) 2021.03.15
[리액트] 웹팩 webpack  (0) 2021.03.15
[리액트] 바벨 babel  (0) 2021.03.14
[리액트] 기본 렌더링  (0) 2021.03.14
[리액트] Target container is not a DOM element. 에러  (0) 2021.03.14
[리액트] 개발환경 설치하기  (0) 2021.03.12
[리액트] 기본  (0) 2021.03.12

1. 노드 버전 매니저로 노드JS설치하기

1-1. NVM 설치하기

github.com/coreybutler/nvm-windows/releases

1-2 nvm이 잘 설치 됐는지 cmd로 확인해보기

1-3 NVM으로 노드제이에스 설치하기

(주의 10.16.2 버전으로 설치하자)

책에서처럼 8.버전으로 설치했더니 10이하에서는 create-react-app이안됐다. 

1-4 nvm이 설치한 노드제이에스 사용 설정하기

nvm ls를 사용하면 설치된 node버전들을 볼 수있다.

(역시 사용도 use 10.16.2로하자...)

 

 

2. yarn과 create-react-app 설치하기

2-1 yarn 설치하기

2-2 create-react-app 설치하기 및 생성

(10 버전 이상을 써야 설치가능.. 책에선 8도됐지만^^....) 참고 참고!

그리고 global add하니까 안댐 ㅎ.. 휴 옛날책이네..

npm install -g create-react-app 했다..

(아래링크 참고!)

ssungkang.tistory.com/entry/React-React-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-create-react-app

 

2-3 리액트 앱 구동하기

이 화면이 뜨면 성공 !

나같은 경우 바로안뜨고 좀 걸렸다..

 

 

루트 폴더에 package.json을 필요에 맞게 수정하고

루트폴더에서 cmd 실행시키고 yarn을 입력하면 라이브러리들을 설치한다.

warning메세지는 버전의 호환성에 대해 제작 당시 명시된 버전과 다르다는 것을 알려주는 내용이라함

리액트 : 페이스북에서 개발하고 관리하는 라이브러리

앵글러와 달리 UI기능만 제공

=> 전역상태 관리, 라우팅, 빌드시스템을 직접 구축해야함

=> 자유도는 높지만 개발환경을 직접 구축해야하는 번거로움이 있다

=> create-react-app을 이용해서 이 단점을 보완함

 

프론트엔드 라이브러리나 프레임워크를 사용하는 이유

: UI를 자동으로 업데이트 해준다

: 브라우저의 돔을 직접 수정 하지 않아도 되어서 좋다.

 

 

- 자동으로 업데이트 되는 UI

- UI = render(state)

- render 함수는 순수 함수로 작성

 > 랜덤 함수 사용(X)

 > 외부 상태 변경(X)

- state는 불변 변수로 관리 => 복잡도가 낮아지고, 버그 발생확률로 낮아짐 / 렌더링 성능 향상

- 가상돔(Virtual DOM)

=> 변경된 부분만 실제 DOM에 반영 해줌

=> 그렇다고 무조건 자바스크립트나 다른 것보다 무조건 빠른 것은 아니다.

 

 

 

나중에 정리할 것

 

 

설치한 것들

 

 

자바런타임에서 버전이랑 설정 가능

 

 

 

컨트롤 쉬프트 P 누르고 스프링 버전이랑 등등 선택해준다.

스프링 버전선택 그다음에 java

그다음에 이름 설정해줌 (ex: com.회사이름.프로젝트이름)

 

 

 

오케이오케이~

 

 

필요한 폴더들 생성해준다

main, webapp, 등등

 

어플리케이션 프로퍼티스에서 각종 설정 가능 (yml과 같음..)

spring에서의 설정파일이라고 생각하면 된다.

 

mapper에는 위에..

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao주소">
</mapper>

pip install flask_cors

--------------------------------------------------------

import flask_cors CORS, cross_origin

CORS(app) # 모든 요청

--------------------------------------------------------

CORS(app, resources={r'*': {'origins': '*'}}) #모든 곳에서 호출하는 것을 허용

CORS(app, resources={r'*': {'origins': 'http://www.test.com'}}) # http://www.test.com 에서의 호출만 허용

CORS(app, resources={r'/_api/*': {'origins': 'http://www.test.com:5000'}}) # http://www.test.com:5000 에서의 호출만 허용

ecsimsw.tistory.com/entry/Spring-MVC-multipartResolver-Http-multipart-request?category=915995

 

참고 :

khanrc.tistory.com/entry/REST-API-%EC%84%9C%EB%B2%84-%EC%A0%9C%EC%9E%91%EA%B8%B0-2-Flask-%EC%84%9C%EB%B2%84-%EC%98%AC%EB%A6%AC%EA%B8%B0

 

yum install python3

> pip3가 자동으로 깔린다

 

pip3 install ~~

로  사용해야함 

1. 무료 도메인 발급

.

(my.freenom.com/)

사용하고 싶은 도메인 이름을 Check 해봅니다. ‘Free’라는 태그가 붙은 도메인은 무료이므로 사용하고 싶은 것을 고르면 됩니다. [Get it now!]를 클릭합니다. 버튼이 [Selected]로 바뀌면 발급이 완료된 것입니다.

Period 에서 무료로 사용할 수 있는 기간을 선택할 수 있습니다. 12개월을 선택 후 [Continue]를 클릭합니다.

구글 로그인으로 무료 체크아웃하기

생성된 도메인은 상단의 [Services] -> [My Domains]를 클릭하면 위와 같이 구매한 도메인을 확인할 수 있습니다.

2. Route 53 에 도메인 등록

이제 AWS 콘솔로 넘어가겠습니다. Route 53 콘솔로 들어가 [Hosted zones] -> [Create Hosted Zone]을 클릭합니다.

Domain Name에 이전에 발급받은 도메인을 기입합니다. [Create]를 클릭합니다.

생성 완료!

NS 타입과 SOA 타입의 레코드 셋이 생성되어 있는 것을 확인할 수 있습니다. NS는 네임 서버 레코드, SOA는 권한 시작 레코드입니다.

 

레코드 생성 버튼을 클릭해 빠른 레코드를 생성합니다.

Name 에는 하위 도메인을 설정할 수 있습니다. 여기서는 일반적으로 쓰이는 www를 사용하겠습니다. Type은 A 레코드를 선택하고 값에 인스턴스 퍼블릭 IP 주소를 입력합니다. 설정을 마쳤으면 [Create]를 클릭합니다.

레코드 생성 완료!

Record Set에 방금 생성한 A 레코드의 도메인을 확인할 수 있습니다. 하지만 여기서 끝난 것이 아닙니다. 네임서버를 이전에 발급받은 무료 도메인에 적용해 주어야 합니다.

3. 도메인 AWS Route53의 NameServer로 변경

freenom 사이트의 My Domains에서 구매한 도메인의 [Manage Domain]을 클릭합니다.

[Management Tools] -> [Nameservers] 를 클릭한 다음, Use custom nameservers (enter below)를 체크하고 Route 53 NS 레코드의 Value 값을 넣어줍니다. 전부 입력하고 [Change Nameservers]를 클릭합니다.

네트워크 전파 속도 때문에 네임서버를 변경하면 바로 적용이 안 되기 때문에 몇 분 내지는 몇 시간의 시간이 필요합니다.

www.maymaymay.ml:8080/ 테스트 성공 !

등록한 도메인을 브라우저 주소창에 입력하면 톰캣 화면이 출력되는 것을 확인할 수 있습니다.

 

 

4. CloudFlare를 이용해 https 주소 우회하기

※ 도메인에 HTTPS를 적용하기 위해 Cloud Flare 사용하기 ※

▶ Cloud Flare 가입: https://dash.cloudflare.com/sign-up

클라우드 플레어에 가입한 이후에 HTTPS를 적용할 수 있습니다.

 

 주소 입력

 

 

4. add cloudflare's nameservers  (나중에 복사해서 프리넘에 등록)

 

 

ipv4 address는 ec2에 있는 아이피이다.

 

Freenom 네임서버로 이동합니다.

기존에 입력했던 Route 53 네임서버를 삭제하고, Cloudflare 네임서버 2개를 추가합니다.

이제 시간이 조금 지나면 SSL에 인증서가 발급되어 있을 겁니다. Active 상태가 되면 페이지 규칙을 추가할 수 있습니다.

 

Page Rules 에 들어가 아래와 동일하게 ****페이지 규칙을 추가합니다.

http://domainname.tk/*

http://www.domainname.tk/*

Always Use HTTPS

5. AWS 컴퓨트 서비스에서 웹서버 설정하기

먼저 AWS EC2 > 인스턴스 > 보안 그룹 에 https 80 포트를 추가합니다.

현재는 http://www.lecturesearch.shop:8080 처럼 도메인에 8080포트번호를 명시하여야 웹사이트로 접근이 됩니다.

이는 톰캣은 기본적으로 8080포트를 사용하는데, 브라우저가 기본적으로 80포트로 접근하기 때문입니다.

이러한 번거로움이 없도록 80포트를 8080포트로 리다이렉트 해주도록 합니다.

iptables 명령을 사용하여 추가해주도록 합니다.

# yum install -y httpd # service httpd start # iptables -t nat -I PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080 # service iptables save # service httpd status # service httpd restart

https://maymayweather.ml/main/ 테스트 성공!


하지만 이렇게 https로 주소를 우회할 시 새로운 문제가 생길 수 있다.

https 프로토콜만 지원하는 특정 웹페이지에서 AJAX 통신을 시도한다고 가정했을 때

url : ‘/aaa/bbb/file.ext’

위의 url 로 파라미터를 던지고 결과를 받아야 하는데 아래와 같은 오류가 발생할 것이다.

Mixed Content: The page at ‘https://page.com‘ was loaded over HTTPS, but requested an insecure XMLHttpRequest endpointThis request has been blocked; the content must be served over HTTPS.

이럴 경우 2가지의 해결 방법이 있다.

  1. 싱글페이지를 포기하고 https 주소가 꼭 필요한 부분에서만 https 주소를 사용하는 페이지로 이동을 한다.

  2. 전부 https 로 통일한다.

 

 

 

 

 

 

 

 

 

---

 

참고

tech.cloud.nongshim.co.kr/2018/10/16/%EC%B4%88%EB%B3%B4%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-aws-%EC%9B%B9%EA%B5%AC%EC%B6%95-8-%EB%AC%B4%EB%A3%8C-%EB%8F%84%EB%A9%94%EC%9D%B8%EC%9C%BC%EB%A1%9C-route-53-%EB%93%B1%EB%A1%9D-%EB%B0%8F-elb/

프로젝트를 하면서 EC2를 사용했는데

사소한 에러 수정을 하더라도.. war를 업로드할때마다 게시판에 업로드 해둔 파일들이 사라짐...

그냥 다시 올리면 대지머.. 하고 그러려니 했는데 너무 귀찮아서 S3를 사용하기로 방금 마음 먹었다 ^^

 

 

가장 먼저 당연히 pom.xml에 라이브러리를 등록해준다 

		<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk -->
		<dependency>
			<groupId>com.amazonaws</groupId>
			<artifactId>aws-java-sdk</artifactId>
			<version>1.9.2</version>
		</dependency>

 

-

 

 

 

offbyone.tistory.com/114

참고블로그

 

Java로 썸네일(Thumbnail) 이미지 만들기

갤러리와 같은 웹애플리케이션을 만들게 되면 이미지의 썸네일을 만들게 됩니다. 가끔 보면 썸네일 없이 원본이미지를 줄여서 보여주고 있는곳이 있는데, 모바일 환경이라면 시간과 데이터 사

offbyone.tistory.com

 

scalr 라이브러리 pom.xml에 등록

		<!--scalr 라이브러리 -->
		<dependency>
			<groupId>org.imgscalr</groupId>
			<artifactId>imgscalr-lib</artifactId>
			<version>4.2</version>
		</dependency>

 

내가 사용한 코드 / ootdphoto는 MultipartFile이다.

package com.mw.ootd.Service;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;

import org.imgscalr.Scalr;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mw.ootd.Domain.ootdBoard;
import com.mw.ootd.dao.ootdInterfaceDao;

@Service
public class ootdRegService {
	// 글등록과 관련된 기능이 모여있는 서비스

	private ootdInterfaceDao dao;

	@Autowired
	private SqlSessionTemplate template;
	
	

	File newFile = null;
	String ootdphotoname = null;
	String saveDirPath = null;
	
	

	public int ootdWrite(ootdBoard ootd, HttpServletRequest request) throws Exception {
		int result = 5;
		// 성공은1 만약에 사진이없다면 0, 글 내용이 없다면 2를 반환하고 알려줄 것.

		if (ootd.getOotdtext().trim().isEmpty()) {
			result = 2;
			return result;
		}

		// 사진이 정상적인 파일인지 확인하기
		if (ootd.getOotdphoto() != null && !ootd.getOotdphoto().isEmpty()) {

			String uploadPath = "/fileupload/ootdimage";
			saveDirPath = request.getSession().getServletContext().getRealPath(uploadPath);
			// 새로운 파일이름 만들어주기
			ootdphotoname = String.valueOf(System.nanoTime());
			newFile = new File(saveDirPath, ootdphotoname);

		} else {
			// 정상적인 사진이 없을 경우
			result = 0;
			return result;

		}

		// 파일저장하기 > s3 변경
		try {
			ootd.getOotdphoto().transferTo(newFile);

		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		// 파일 이름 저장하기
		if (ootdphotoname != null) {
			ootd.setOotdphotoname(ootdphotoname);
		}

		// 썸네일 만들기
		makeThumbnail(saveDirPath, ootdphotoname, "png");

		// 데이터베이스에 저장하기
		try {
			dao = template.getMapper(ootdInterfaceDao.class);
			result = dao.ootdDocInsert(ootd);
			// 글번호값 리턴
			// int ootdidx = dao.ootdidxReturn(ootdphotoname);
			// System.out.println(ootdidx);
			// ootdidx에 맞는 좋아요 칼럼 생성
			// dao.makeLikeCol(ootdidx);

		} catch (Exception e) {
			e.printStackTrace();
			if (newFile != null && newFile.exists()) {
				newFile.delete();
			}
		}

		return result;

	}

	private void makeThumbnail(String filePath, String fileName, String fileExt) throws Exception {
		// 저장된 원본파일로부터 BufferedImage 객체를 생성합니다.
		BufferedImage srcImg = ImageIO.read(newFile);
		// 썸네일의 너비와 높이 입니다.
		int dw = 250, dh = 250;
		// 원본 이미지의 너비와 높이 입니다.
		int ow = srcImg.getWidth();
		int oh = srcImg.getHeight();

		// 원본 너비를 기준으로 하여 썸네일의 비율로 높이를 계산합니다.
		int nw = ow;
		int nh = (ow * dh) / dw;

		// 계산된 높이가 원본보다 높다면 crop이 안되므로
		// 원본 높이를 기준으로 썸네일의 비율로 너비를 계산합니다.
		if (nh > oh) {
			nw = (oh * dw) / dh;
			nh = oh;
		}
		// 계산된 크기로 원본이미지를 가운데에서 crop 합니다.
		BufferedImage cropImg = Scalr.crop(srcImg, (ow - nw) / 2, (oh - nh) / 2, nw, nh);

		// crop된 이미지로 썸네일을 생성합니다.
		BufferedImage destImg = Scalr.resize(cropImg, dw, dh);

		// 썸네일을 저장합니다. 이미지 이름 앞에 "THUMB_" 를 붙여 표시했습니다.
		String thumbName = filePath + "/THUMB_" + fileName;
		File thumbFile = new File(thumbName);
		//ImageIO.write(destImg, "PNG", thumbFile);
		//저장>s3
		ImageIO.write(destImg, fileExt.toUpperCase(), thumbFile);
	}
}

www.postman.com/downloads/다운로드 하거나 크롬 앱에 설치해서 사용

 

 

body-parser 설치해준다

 

: 이전에 생성한 테이블 참고

javappo.tistory.com/263

 

[mongodb] model & Schema 생성

const mongoose = require('mongoose') const userSchema = mongoose.Schema({ name :{ type : String, maxlength : 50 }, email : { type : String, trim : true, unique : 1 }, passworld : { type : String, mi..

javappo.tistory.com

 

 

const express = require('express')
const app = express()
const port = 3000

const {user, User} = require("./models/User");

const bodyParser = require('body-parser');
//application/x-www/-fom-urlencoded
app.use(bodyParser.urlencoded({extended:true}));
//application/json
app.use(bodyParser.json());

const mongoose = require('mongoose')
mongoose.connect('mongodb+srv://HYOSEON:비~~밀~~번~~호@hyseonbolierplate.9vvek.mongodb.net/myFirstDatabase?retryWrites=true&w=majority',{
    useNewUrlParser: true, useUnifiedTopology:true, useCreateIndex:true, useFindAndModify :false
}).then(() => console.log('mongoDB Connected..'))
 .catch(err => console.log(err))

app.get('/', (req, res) => {  res.send('Hello World!')})


app.post('/register', (req, res) => {
 
    // 회원가입할 때 필요한 정보들을 클라이언트에서 가져오면
    // 그것들을 db에 넣어준다


    const user = new User(req.body)

    user.save((err, userInfo) =>{
        if(err) return res.json({
            success :false, err
        })
        return res.status(200).json({
            success : true
        })
    })
})

app.listen(port, () => {  console.log(`Example app listening at http://localhost:${port}`)})

npm run start로 실행시켜주고 POSTMAN에 입력

 

git-scm.com/download/win

 

Git - Downloading Package

Downloading Git Now What? Now that you have downloaded Git, it's time to start using it.

git-scm.com

 

git init (깃 생성)

Microsoft Windows [Version 10.0.19041.804]
(c) 2020 Microsoft Corporation. All rights reserved.

C:\Users\bit\Documents\boiler-plate>git init
Initialized empty Git repository in C:/Users/bit/Documents/boiler-plate/.git/

C:\Users\bit\Documents\boiler-plate>git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        index.js
        models/
        node_modules/
        package-lock.json
        package.json

nothing added to commit but untracked files present (use "git add" to track)

C:\Users\bit\Documents\boiler-plate>

 

git add를 하면 소ㅑㄹ라소ㅑㄹ라~~ 라이브러리까지 다 올라감.. (staging area에)

 

C:\Users\bit\Documents\boiler-plate>git add .
warning: LF will be replaced by CRLF in node_modules/.bin/mime.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in node_modules/.bin/mime.ps1.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in node_modules/.bin/semver.
The file will have its original line endings in your working directory
C:\Users\bit\Documents\boiler-plate>git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   index.js
        new file:   models/User.js
        new file:   node_modules/.bin/mime
        new file:   node_modules/.bin/mime.cmd
        new file:   node_modules/.bin/mime.ps1
        new file:   node_modules/.bin/semver
        new file:   node_modules/.bin/semver.cmd

 

 

staging area에 올라간 ㅎㅎ.. node_modules (라이브러리)는 지워준다..

C:\Users\bit\Documents\boiler-plate>git rm --cached node_modules -r
rm 'node_modules/.bin/mime'
rm 'node_modules/.bin/mime.cmd'
rm 'node_modules/.bin/mime.ps1'
rm 'node_modules/.bin/semver'
rm 'node_modules/.bin/semver.cmd'
rm 'node_modules/.bin/semver.ps1'
rm 'node_modules/@types/bson/LICENSE

 

그리고 .gitignore 만들어줌..

 

 

commit -m "메모"

(깃허브에서 메모하는거랑 같은 것..)


C:\Users\bit\Documents\boiler-plate>git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   index.js
        new file:   models/User.js
        new file:   package-lock.json
        new file:   package.json

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .gitignore


C:\Users\bit\Documents\boiler-plate>git commit -m "처음 저장소 올림"
[master (root-commit) 1540315] 처음 저장소 올림
 4 files changed, 668 insertions(+)
 create mode 100644 index.js
 create mode 100644 models/User.js
 create mode 100644 package-lock.json
 create mode 100644 package.json

C:\Users\bit\Documents\boiler-plate>git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .gitignore


C:\Users\bit\Documents\boiler-plate>git commit -m "깃이그노어 추가"
[master 684ec62] 깃이그노어 추가
 1 file changed, 1 insertion(+)
 create mode 100644 .gitignore

C:\Users\bit\Documents\boiler-plate>git status
On branch master
nothing to commit, working tree clean

C:\Users\bit\Documents\boiler-plate>

'DB > ETC' 카테고리의 다른 글

[mongodb] model & Schema 생성  (0) 2021.02.24
[mongodb] 유저생성 및 nodejs 몽고 DB연결  (0) 2021.02.24
[mongodb] 몽고DB 클러스터 생성하기  (0) 2021.02.24
const mongoose = require('mongoose')

const userSchema = mongoose.Schema({

    name :{
        type : String,
        maxlength : 50
    },
    email : {
        type : String,
        trim : true,
        unique : 1
    },
    passworld : {
        type : String,
        minlegth : 5
    },
    lastname :{
        type : String,
        maxlength : 50
    },
    role : {
        type : Number,
        default : 0
    },
    image : String,
    token : {
        type : String
    },
    tokenExp : {
        type : Number
    }

})

const User = mongoose.model('User', userSchema)
module.exports = {User}

'DB > ETC' 카테고리의 다른 글

[GIT] git 설치  (0) 2021.02.24
[mongodb] 유저생성 및 nodejs 몽고 DB연결  (0) 2021.02.24
[mongodb] 몽고DB 클러스터 생성하기  (0) 2021.02.24

connect 누르고 username과 password 입력후 생성

 

체크 ~ 체크~

 

 

저 부분 복사해놓는다.

혹시몰라서 일단 가렸는데 별로 그럴 필요없었네;

 

 

몽구스 설치하기

 

VSCODE 터미널 혹은 cmd에서 npm install mongoose --save

 

 

package.json에 보면 mongoose가 생긴 것을 볼 수 있다.

 

 

몽고 DB 연결하기

 

const express = require('express')
const app = express()
const port = 3000


const mongoose = require('mongoose')
mongoose.connect('mongodb+srv://HYOSEON:비번@hyseonbolierplate.9vvek.mongodb.net/myFirstDatabase?retryWrites=true&w=majority',{
    useNewUrlParser: true, useUnifiedTopology:true, useCreateIndex:true, useFindAndModify :false
}).then(() => console.log('mongoDB Connected..'))
 .catch(err => console.log(err))

app.get('/', (req, res) => {  res.send('Hello World!')})

app.listen(port, () => {  console.log(`Example app listening at http://localhost:${port}`)})

 

비번이라고 된 부분엔 비번 쳐준다

복사할땐 <password>라고 되있지만 <>도 다 지워야함.

 

 

 

 

 

 

-- 인강이 너무 미리 설치된게 많아서 알아보고 다 다시해야했던 부분도 기록

npm 설치해야 터미널에서 npm run start 이런거 다 쓸 수 있음.

그리고 비밀번호에 @가 있을때도 에러가 난다고 한다.. 난 그냥 영문+숫자 조합으로 했다.

cloud.mongodb.com/v2/6035f632c682c16cee78ea88#security/database/users

비번 수정 등등은 여기서 가능..

 

 

cloud.mongodb.com/v2/6035f632c682c16cee78ea88#security/network/accessList

첫부분에 IP 추가해주던가 네트워크엑세스(링크) 들어가서 IP추가해줘야됌..

인강에서는 미리 다 추가가 되있어서 에러가 나지 않았던 것이었다.

 

연결 완료~

 

'DB > ETC' 카테고리의 다른 글

[GIT] git 설치  (0) 2021.02.24
[mongodb] model & Schema 생성  (0) 2021.02.24
[mongodb] 몽고DB 클러스터 생성하기  (0) 2021.02.24

인강을 듣는데 몽고 DB에서 클러스터 생성하는 페이지가 바뀌어서 헤매다가 찾아서 기록으로 남긴다.

 

인강에서는 맨처음에 들어가면 클러스터 생성이 뜨는데 바뀌어서 

일단 create an organizations를 눌러준다(초록버튼)

뭐라뭐라 뜨는데 그냥 이름 아무거나 입력해줌..

 

그럼 이제는 new Project를 생성하라고 한다.

역시 생성해줌..

 

프로젝트까지 생성하고 나면 클러스터를 생성할 수 있다.

 

 

당연히 프리선택 ^^^^

 

세개 중에 맘에 드는거 선택..

무료중에서는 한국이랑 제일 가까운 싱가폴 선택 추천

 

선택하고 클러스터네임은 자기맘대로 아무거나..

 

 

클러스터 생성되는데 몇분 걸린다. 끝!

'DB > ETC' 카테고리의 다른 글

[GIT] git 설치  (0) 2021.02.24
[mongodb] model & Schema 생성  (0) 2021.02.24
[mongodb] 유저생성 및 nodejs 몽고 DB연결  (0) 2021.02.24
C:\Users\bit>node -v
v14.16.0

C:\Users\bit>cd documents

C:\Users\bit\Documents>mkdir boiler-plate

C:\Users\bit\Documents>cd boiler-plate

C:\Users\bit\Documents\boiler-plate>npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help init` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (boiler-plate)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to C:\Users\bit\Documents\boiler-plate\package.json:

{
  "name": "boiler-plate",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this OK? (yes)

expressjs.com/en/starter/hello-world.html

 

 

 

Express "Hello World" example

Hello world example Embedded below is essentially the simplest Express app you can create. It is a single file app — not what you’d get if you use the Express generator, which creates the scaffolding for a full app with numerous JavaScript files, Jade

expressjs.com

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {  res.send('Hello World!')})

app.listen(port, () => {  console.log(`Example app listening at http://localhost:${port}`)})

 

 

 

 

 

자바에서 콘솔에는 한글이 안깨지는데 받아오면 깨지는 경우 @GetMapping

	@GetMapping(produces="text/plain;charset=UTF-8")

 

 

pip install --upgrade pip

 

 

from urllib import request
from bs4 import BeautifulSoup as bs
import re

url = 'https://search.musinsa.com/ranking/brand'

target = request.urlopen(url)
soup = bs(target, 'html.parser')

brand = soup.select('.brandLogo img')
brandname = []

print('----------------------------------------------------')

for alt in brand[:5] :
    #print(alt.get('alt'))
    brandname.append(alt.get('alt'))


print(brandname)
print('----------------------------------------------------')

import json
jsonString = json.dumps(brandname, ensure_ascii=False)

print(jsonString)


from flask import Flask

# 웹서버 생성
app = Flask(__name__)
print(app)
print(__name__)

#url
@app.route('/brand')
def brandName():
    return jsonString
    
if __name__ == '__main__':
     app.run(debug=True, port=8000)

 

 

 

 

from urllib import request
from bs4 import BeautifulSoup as bs
import re

url = 'https://search.musinsa.com/ranking/brand'

target = request.urlopen(url)
soup = bs(target, 'html.parser')

brand = soup.select('.brandLogo img')
rankup = soup.select('.rank')
result_list = soup.find_all('span', class_="rank")

brandname = []
brandrank = []
brandrank_data = []
rank_data = []

for span in result_list[:10] :
    brandrank_data.append(span.text)

print(brandrank_data)

print('----------------------------시작------------------------')

for alt in brand[:10] :
    #print(alt.get('alt'))
    brandname.append(alt.get('alt'))


print(brandname)
print(brandname[0])
print('----------------------------------------------------')


for cla in rankup[:10] :
    brandrank.append(cla.get('class'))

print(brandrank)
print('----------------------------------------------------')


for i in range(10) :
    rank_data.append(
        {
            'name':brandname[i],
            'rank':brandrank_data[i]
        }
        
        )

print(rank_data)
print('----------------------------------------------------')





import json
jsonString = json.dumps(rank_data, ensure_ascii=False)

print(jsonString)


from flask import Flask

# 웹서버 생성
app = Flask(__name__)
#print(app)
#print(__name__)


from flask_cors import CORS
CORS(app)

#url
@app.route('/brand')
def brandName():
    return jsonString
    
if __name__ == '__main__':
     app.run(debug=True, port=8000)

'memo' 카테고리의 다른 글

[JAVA] 이미지 파일 크롭하여 저장하기 (썸네일 생성)  (0) 2021.03.02
[자바] REST API 요청 시 한글깨짐  (0) 2021.02.17
[파이썬] pip 업그레이드  (0) 2021.02.17
자바스크립트 파일 절대경로 / decode  (0) 2021.02.08
최근 에러 참고  (0) 2021.02.03
[스프링] ajax 참고  (0) 2021.01.29
RESTCLIENT  (0) 2021.01.28

 

 

없으면 cmd에서 pip install pymysql 해준다.

포트는 기본 3306

import pymysql
project_db = pymysql.connect(host='127.0.0.1', db='open', user='aia', password='aia')

cursor1=project_db.cursor()

sql_select = 'select * from member'
cursor1.execute(sql_select)

while True :

    row = cursor1.fetchone()

    if row==None :
        break;
    print(row)

project_db.close()

 

 

import sys
import io
 
sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding = 'utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.detach(), encoding = 'utf-8')
#한글깨짐 방지

를 위에 넣어주거나

 

 

 

 

 

환경변수에 인코딩 추가하는 방법

 

사용하는 윈도우 환경 변수에 "PYTHONIOENCODING=utf-8" 추가합니다.

환경변수를 추가하려면 "제어판 -> 시스템 -> 고급시스템설정 -> 고급탭 -> 환경변수"로 이동 하셔서

 

 

 

 

 

환경변수 창 아래쪽에 있는 시스템 변수 항목에서 "새로만들기" 버튼 을 클릭 하고 새 시스템 변수에서 아래의 그림과 같이 변수 이름과 변수 값을 적어 넣으시고 확인 버튼을 누르시면 

 

 

 

 

 

 

 

위의 그림과 같이 시스템 변수에 인코딩이 추가된 모습을 볼 수 있습니다. 여기서 "확인" 버튼을 누르면 끝!!!

 



출처: https://mrcoding.tistory.com/entry/아톰에서-파이썬-스크립트-실행시-한글-깨짐현상-잡는-꿀팁 [Mr. Coding]

=

+ Recent posts