MAC Node version 변경하기


Server/Frontend 2019. 4. 2. 22:26



$ brew unlink node

 

바꾸고싶은 버전이 10.x라면,

$ brew install node@10 

 

$ brew link node@10 --force

 

 


WRITTEN BY
ShakeJ

트랙백  0 , 댓글  0개가 달렸습니다.
secret

Mac Postgres install and command


Server/Ruby on the Rails 2019. 3. 27. 23:45



brew install pg 

 

ps auxwww | grep postgres

pg_ctl -D /usr/local/var/postgres status

 

pg_ctl -D /usr/local/var/postgres start

pg_ctl -D /usr/local/var/postgres stop

 

OR 

 

brew services start postgresql

brew services stop postgresql

 

 

if "Library not loaded: /usr/local/opt/readline/lib/libreadline.7.dylib" error, 

ln -s  /usr/local/opt/readline/lib/libreadline.6.dylib  /usr/local/opt/readline/lib/libreadline.7.dylib


WRITTEN BY
ShakeJ

트랙백  0 , 댓글  0개가 달렸습니다.
secret

[React+Rails] 모델의 Index 페이지를 React로 만들어보자


Server/Frontend 2019. 3. 26. 18:58



기존에 Partial을 사용하여 Rails에서 모델의 Index의 list_item을 만들 때에는,

1
2
3
<% @articles.each do |article| %>
  <%= render 'sessions/contents/article_item', article: article %>
<% end %>
cs


이렇게 사용을 하던 부분을, React로 바꾸고자 합니다. 

여기서 고민이 생기는데, 해당 세줄을 통으로 

1
<%= react_component 'Articles', { data: @articles } %>
cs


이렇게 바꿀 것인가.. 

1
2
3
<% @articles.each do |article| %>
 <%= react_component 'Article', { data: article } %>
<% end %>
cs


이렇게 바꿀 것인가..


같은 Article 모델이지만 페이지가 뉴스, 주요뉴스, 해외뉴스 등 나뉘어져 있기 때문에, 재사용성을 고려하면 통으로 Article 리스트를 React component로 만드는 것보다, 리스트 아이템 한개씩 Component로 만드는 것이 나을 듯 합니다.


혹여나 해서 이리저리 구글링을 해보니, 컴포넌트 여러개를 사용하는 것에 대한 메모리 릭 이슈는 당연히 너무 많은 컴포넌트를 사용하고 각 컴포넌트마다 lifecycle에 어긋나게 사용 시 메모리 릭이 발생할 수 있음. 해외 블로거들의 경우 리스트를 react로 구현 시 리스트 Component 1개 / 리스트 아이템 Component 1개를 생성하여 리스트 Component에서 API 호출 후 아이템 여러개를 배치하는 경우로 주로 개발을 하는 것을 볼 수 있습니다.


* 여기서 문득 드는 생각은 Rails view를 완전히 배제하고 React componenet로만 모든 페이지를 구성하는 것이 좋은 방향인가? 라는 의문이... 얼핏 찾아봤을 땐 해당 문제에 대해서는 아직 별반 이야기를 못찾음. Rails view를 쓰되 각 요소별로 Componenet 위주로 React를 사용하는 것이 맞는지(뼈대는 erb를 사용하고 Rails 변수 사용 + React 요소 사용).. 잘 모르겠음. 추후 관련 내용을 찾으면 포스팅하겠습니다.


[추후 업데이트 할 예정입니다]




WRITTEN BY
ShakeJ

트랙백  0 , 댓글  0개가 달렸습니다.
secret

[React+Rails] 타이핑 효과나는 텍스트 제작하기


Server/Frontend 2019. 3. 26. 16:11




현재 프로젝트에 속보를 알려주는 타이핑 효과가 나는 텍스트를 리액트 컴포넌트로 바꿔보려 합니다. 


구글링을 해보니, 리액트 타이핑 효과를 내는 모듈이 많습니다. 그 중 react-typist 라는 패키지를 사용해보겠습니다. 

(Typist로만 감싸주면 애니메이션 효과가 나타나는 것이 간단해보여서 선택해봅니다)


1
npm install react-typist --save
cs


npm을 통해 설치합니다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
       <div class="ticker">
          <ul>
             <% breakings = Article.order("created_at desc").limit(10) %>
             <% breakings.each do |article| %>
              <li>
                <a href="/API주소?파라미터=<%= article.id %>" target="_blank">
                  <strong>속보</strong>
                  <% title = article.title %>
                  <% if title.length > 100 %>
                    <% title = "#{title[0..100]}..." %>
                  <% end %>
                  <%= title %>
                </a>
              </li>
             <% end %>
         </ul>
        </div>
cs


Rails view에서 직접 쿼리를 날려 받아와 작성 된 코드입니다. (지저분..)


해당 코드 외에도 typed.js를 초기화하는 자바스크립트가 존재합니다. 


전부 삭제! 하고 

1
<%= react_component("BreakingNewsType") %>
cs


컴포넌트 호출 단을 HTML에 추가합니다. 


app/javascript/components/BreakingNewsType.js 파일을 생성합니다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React, {Component} from 'react';
import Typist from 'react-typist';
 
export default class BreakingNewsType extends Component {
 
  render() {
    return (
      <Typist>
        Animate this text.
      </Typist>
    );
  }
}
 
cs


오호 export default를 하단에 적어줄 수도 있지만, 클래스 앞쪽에 통합해서 적을 수 있네요. 


이렇게 예제를 적고 웹을 보니, 



정상적으로 타이핑 애니메이션이 동작합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import React, {Component} from 'react';
import Typist from 'react-typist';
 
const API = '';
 
export default class BreakingNewsType extends Component {
  constructor(props) {
    super(props);
    this.state = {
      title: []
    };
  }
 
  componentDidMount() {
    this.intervalId = setInterval(() => this.loadData(), 1000 * 5);
    this.loadData();
  }
 
  componentWillUnmount() {
    clearInterval(this.intervalId);
  }
 
  loadData() {
    console.log("load breaking news");
    fetch(API)
      .then(response => response.json())
      .then(data => this.setState({
        title: data.title
      }));
  }
 
  render() {
    return (
      <div className="ticker_container">
        <Typist>
          <b>최신</b> {this.state.title}
        </Typist>
      </div>
    );
  }
}
cs


API를 만들고, 받아온 최신 뉴스를 보여주도록 만들었습니다. 


어랏 근데 동작을 안합니다.


loadData() 이후 데이터를 받고 나면 타이핑을 시작해주어야 하는 듯 합니다. 


state가 바뀌는데 왜 다시 render를 하지 않을까? 혹시 restart라는 함수가 있거나, update?를 호출해주어야 하나 싶어 살펴봅니다. (아니야 이러면 react의 장점이 없잖아!)

분명 react는 state가 변경되면, 자동으로 뷰가 변경될텐데... 싶어 찾다보니, react-typist에 key라는 것을 발견합니다. 


key의 경우 여러가지 문장을 이어서 쓰려고 할 때, 설정을 하는 것이라고 합니다. 

key는 고유값이니, api를 통해 받아온 뉴스의 ID값(고유값)으로 추가해 봅니다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
export default class BreakingNewsType extends Component {
  constructor(props) {
    super(props);
    this.state = {
      title: [],
      textIndex: 0,
    };
  }
 
  componentDidMount() {
    this.intervalId = setInterval(() => this.loadData(), 1000 * 5);
    this.loadData();
  }
 
  componentWillUnmount() {
    clearInterval(this.intervalId);
  }
 
  loadData() {
    fetch(API)
      .then(response => response.json())
      .then(data => this.setState({
        title: data.title,
        textIndex: data.id,
      }));
    this.forceUpdate();
  }
 
  render() {
    return <div key={this.state.textIndex} className="ticker_container">
        <Typist>
          <b>최신</b> {this.state.title}
        </Typist>
      </div>
  }
}
 
cs


오.. key가 변경될때마다 (state 내에 title이 변경될때마다) 타이핑을 시작합니다!




WRITTEN BY
ShakeJ

트랙백  0 , 댓글  0개가 달렸습니다.
secret

[React+Rails] 주기적으로 업데이트 되는 위젯을 만들어보자


Server/Frontend 2019. 3. 26. 14:34



지난 번 Rails React 개발 환경을 마친 뒤, Jquery, Rails View, Html로 구성되어 있던 기존 프로젝트의 부분 부분을 변경해보고자 합니다. 


가장 먼저 만만하게 잡힌 곳은, 바로 요 부분입니다. 



기존에는 Rails view에서 Rails Model에 Query를 요청해서 표시를 했습니다. 

React로 변경하면, 얻는 이점은 

- Rails는 철저하게 백엔드의 역활만 수행하도록 분리한다. (유지보수 측면)

- 일정 시간이 지난 뒤 시세를 변경할 때 최소한의 리소스로 빠르고 간견할 코드로 업데이트가 가능하다.(Virtual Dom - 자세한 내용은 여기)

입니다. 


일단 React에 대한 별다른 기본 지식이 없기 때문에 기능 구현을 하며 이해하고 정리해봅니다. 



기존 코드의 경우 모델에 직접 요청을 하는 Rails 코드가 view안에 포함되어 있고, Rails 코드로 값을 가져오고 있습니다. (크흡 코드가 더럽습니다)

일단 기존 HTML 단에서 react_comopenet를 요청할 수 있도록 변경합니다.


1
2
3
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-6">
 <%= react_component("CoinPrice", { coin_name: "BCH" }) %>
</div>
cs


React component 중 CoinPrice라는 컴포넌트를 호출하도록 했습니다. 


app/javascript/ 폴더에 CoinPrice.js 파일을 생성합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import React from "react"
import PropTypes from "prop-types"
 
const API = '';
 
class CoinPrice extends React.Component {
  constructor(props) {
    super(props);
 
    this.state = {
      price_krw: [],
      percent_change_1h: []
    };
  }
 
  componentDidMount() {
    try {
      setInterval(async () => {
        const res = await fetch(API + "?coin_name=" + this.props.coin_name);
        const blocks = await res.json();
        this.setState({
          price_krw: parseInt(blocks.coin.price_krw, 10),
          percent_change_1h: blocks.coin.percent_change_1h
        })
      }, 30000 * 6);
    } catch(e) {
      console.log(e);
    }
 
    fetch(API + "?coin_name=" + this.props.coin_name)
      .then(response => response.json())
      .then(data => this.setState({
        price_krw: parseInt(data.coin.price_krw, 10),
        percent_change_1h: data.coin.percent_change_1h
    }));
  }
 
  render() {
    let html = "";
    html = <div className="display_inline">
              <div className="float_left"><b>{this.props.coin_name}</b></div>
              <div className="top_header_right_border"></div>
              <div className="float_right" style={{color: this.state.percent_change_1h > 0 ? "red" : "blue"}}>{this.state.price_krw}원 ({this.state.percent_change_1h}%)</div>
            </div>
 
 
    return html;
 
  }
}
export default CoinPrice
 
cs


state에 변수를 저장하고, 파라미터 (props)로 받은 코인 이름에 따라 API를 요청하고 받은 json을 render()합니다. 


fetch를 받는 부분이 2군데에 중복되어 있어 리팩토링을 합니다. 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import React from "react"
import PropTypes from "prop-types"
 
const API = '';
 
class CoinPrice extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      price_krw: [],
      percent_change_1h: []
    };
  }
 
  componentDidMount() {
    this.intervalId = setInterval(() => this.loadData(), 3000 * 10);
    this.loadData();
  }
 
  componentWillUnmount() {
    clearInterval(this.intervalId);
  }
 
  loadData() {
    fetch(API + "?coin_name=" + this.props.coin_name)
      .then(response => response.json())
      .then(data => this.setState({
        price_krw: parseInt(data.coin.price_krw, 10),
        percent_change_1h: data.coin.percent_change_1h
      }));
  }
 
  render() {
    let html = "";
    html = <div className="display_inline">
              <div className="float_left"><b>{this.props.coin_name}</b></div>
              <div className="top_header_right_border"></div>
              <div className="float_right" style={{color: this.state.percent_change_1h > 0 ? "red" : "blue"}}>{this.state.price_krw}원 ({this.state.percent_change_1h}%)</div>
            </div>
    return html;
  }
}
export default CoinPrice
 
cs


훨씬 깔끔해졌습니다. 

데이터를 요청할때에는 loadData를 사용하고, coponentWillUnmount() 시 setInterval을 그만 호출하도록 초기화했습니다. 


componentWillUnmount() is invoked immediately before a component is unmounted and destroyed. Perform any necessary cleanup in this method, such as invalidating timers, canceling network requests, or cleaning up any subscriptions that were created in componentDidMount().

You should not call setState() in componentWillUnmount() because the component will never be re-rendered. Once a component instance is unmounted, it will never be mounted again.


테스트를 해보니, 정상적으로 주기적으로 데이터를 요청하고 받아와서 해당 Element만 새롭게 Render 됩니다. 


render 내에 기존 HTML에서 사용하는 class 대신 className을 사용합니다. 


표기되는 가격 부분에 원화 표기를 위한 컴마를 붙여야 합니다. 


{this.state.price_krw} 로 표기되는 곳에 javascript의 정규식을 넣어봅니다.


{this.state.price_krw.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}원



{} 안에서는 javascript가 정상적으로 동작을 하는군요. (오.. 매우 편리합니다)



WRITTEN BY
ShakeJ

트랙백  0 , 댓글  0개가 달렸습니다.
secret

Rails + React + WebPack 환경 세팅 및 React 사용해보기


Server/Frontend 2019. 3. 25. 16:31



yarn add react react-dom react-prop-types react-router-dom semantic-ui-react react_ujs

yarn add babel-core babel-loader babel-preset-env babel-preset-react babel-preset-stage-1 css-loader style-loader html-webpack-plugin webpack webpack-dev-server webpack-cli -D
htt
gem 'webpacker'
gem 'react-rails'
$ bundle install
$ rails webpacker:install       # OR (on rails version < 5.0) rake webpacker:install

[webpacker.yml]

check_yarn_integrity = false 

변경 후 

$ rails webpacker:install:react # OR (on rails version < 5.0) rake webpacker:install:react $ rails generate react:install


해당 설정이 모두 완료되면, Rails 에서 React가 사용 가능하다! 

(배포의 경우, 따로 capistrano에서 추가할 gem은 없다.)

다만, NodeJS의 버전은 v6 이상이여야하고, yarn이 설치되어 있어야 한다. 


[application.html]

turbolink tag 아래에 삽입


<%= javascript_pack_tag 'application' %>


해당 코드를 추가한다.  


$ rails g react:component HelloWorld greeting:string

로 React component를 만들면, app/javascript/components 내에 hello_world.js.jsx 파일이 생성 된다. 


기존에 있는 프로젝트에 webpack build 시 에러가 나는 케이스는 자동으로 generate된 javascript 폴더를 확인한다. 

webpacker.yml에 source_path가 app/javascript로 지정되어 있는데 rails 내부에서는 app/assets/javascripts 에 생성된다. 

일단 기존에 쓰던 javascripts와 분리하여 설치할 경우, 

app/javascript 폴더 내에 packs와 componenets (React용 javascript 파일이 들어갈) 위치하도록 수정한다. 


app/javascript/components에 HelloWorld.js 파일을 만든 뒤, 

import React from "react"

import PropTypes from "prop-types"

class HelloWorld extends React.Component {

  render () {

    return (

      <React.Fragment>

        Greeting: {this.props.greeting}

      </React.Fragment>

    );

  }

}


HelloWorld.propTypes = {

  greeting: PropTypes.string

};

export default HelloWorld


index.html.erb 에서 해당 모듈을 로딩해본다. 


<%= react_component("HelloWorld", { greeting: "Hello from react-rails." }) %>

정상적으로 로딩되는 지 확인해본다. 



추가적으로 크롬에서 React를 디버깅하는 툴을 다운받아 설치한다. 

기본적인 React의 개발환경은 모두 갖추어졌다!


다음 번엔 이어서 Rails 모델의 index 페이지를 React로 구현해보는 포스팅을 올릴 예정입니다.


WRITTEN BY
ShakeJ

트랙백  0 , 댓글  0개가 달렸습니다.
secret

구글플레이 귀하의 앱은 Android 광고 ID 사용 및 개발자 배포 계약의 4.8 조항을 위반하였습니다 해결방법


Android/안드로이드 프로그래밍 2019. 3. 19. 09:49




해당 이슈는, 구글 플레이 내 개인정보취급방침을 제출하지 않았을 때 앱이 삭제되는 부분이다. 

https://app-privacy-policy-generator.firebaseapp.com/

해당 Generator를 이용하여 개인정보 취급방침을 생성한 후 웹페이지를 하나 제출하면 해결! 


추가적으로, Youtube 채널, 혹은 동영상을 링크로 넣었을 경우 아래와 같이 유튜브 정책 위반으로 앱이 삭제된다. 

* 서버에 youtube link를 저장해서 가져올 경우엔 문제가 없는데 구글 플레이 APK 내부에 소스를 검사하면서 youtube링크가 발견되면 자동으로 삭제되는듯.




WRITTEN BY
ShakeJ

트랙백  0 , 댓글  0개가 달렸습니다.
secret

편의점 할인정보를 한눈에! 검색까지 "편의점 끝판왕"


Android/내어플이야기 2019. 2. 21. 17:08



몇년 전쯤엔가 만들었던 안드로이드 앱 '편의점 할인정보'를 간만에 제대로 업데이트 했습니다!


웹버전으로 편의점 끝판왕을 만나보실 수 있습니다 :) 

http://storeboss.co.kr/


편의점 끝판왕의 첫번째 화면으로 접속하면, 인기 상품과 편의점 관련 커뮤니티 글, 그리고 상품 댓글등을 볼 수 있습니다. 





편의점 끝판왕은, 세븐일레븐, GS25, 미니스톱, CU 4가지 편의점의 할인 상품들을 제공합니다. 

1+1, 2+1, 증정, 할인 네가지 종류를 제공합니다.


"마실걸 사러 집주변 GS25를 가야지!"라는 생각을 했을 때 좀 더 쉽게 찾기 위해, 

상품의 타입도 제공합니다.

전체, 생필용품, 음료, 음식, 과자, 아이스크림, 애견, 기타로 나누어 좀 더 쉽게 상품들을 찾을 수 있습니다.




반응형으로 만들어져 모바일이나 태블릿에서도 최적의 해상도로 보실 수 있어요 :) 



스크롤만 하시면 자동으로 다음 상품들이 로딩되어 보실 수 있습니다 :) 

상품을 클릭하면 상품의 상세화면과 댓글을보실 수 있습니다.




만약 찜을 해놓고 나중에 사먹으려고 하신다면, "찜" 버튼을 살포시 클릭하시면, 나의 페이지에서 보실 수 있습니다. 



로그인은 카카오톡으로 클릭한번이면 바로 로그인이 가능합니다! 


편의점 할인 정보 외에도 주변 편의점 찾기 기능 등 다양한 기능이 앞으로 추가 될 예정입니다 :) 


안드로이드 앱으로도 사용이 가능합니다 :) 



https://play.google.com/store/apps/details?id=com.shakej.convenience.store



WRITTEN BY
ShakeJ

트랙백  0 , 댓글  0개가 달렸습니다.
secret