회사에서 발생했던 mysql driver 의 크리티컬 이슈 


5.1.45 이상 버전으로 업그레이드가 피요하다.


https://bugs.mysql.com/bug.php?id=88242




Added the following entry to the Connector/J 5.1.45 changelog: "Normally, when the socketTimeout option has been set and a socket timeout occurs on the client side, the server may continue working and returning query results. At the next query executed after the timeout, Connector/J first clears the socket input stream and then sends a ping request to the server. However, an error occurred if the autoReconnect option was set to true and, after reconnection, a new query was executed by Connector/J, and the results from the previous queries arrived before Connector/J sent its ping request to the server, in which case the old packages might be mistaken as results for the new query. This fix corrects the issue by forcibly closing the network resources after a communication or IO exception. The next statement execution recreates the IO stream if autoReconnect=true; otherwise, the connection stays closed."


Posted by '김용환'
,

css의 id와 class의 차이

web 2018. 1. 8. 14:29



* ID's are unique

Each element can have only one ID

Each page can have only one element with that ID


* Classes are NOT unique

You can use the same class on multiple elements.

You can use multiple classes on the same element.


The “id=something” can be used to style one HTML element, whereas the “class=something” could be used to style multiple elements.


https://css-tricks.com/the-difference-between-id-and-class/


Posted by '김용환'
,



ubuntu에서 apt-get update가 행이 걸린다면 다음 로그를 보거나 strace로 확인한다. 


$ sudo vi /var/log/apt/term.log

$ sudo vi /var/log/dpkg.log

$ sudo vi /var/log/apt/history.log

$ strace apt-get update


잘못된 주소의 파일이 있거나, mirroring에 실패한 경우가 있을 수 있다. 



Posted by '김용환'
,



ES5에서는 require, ES6에서는 import를 사용한다.


import PropTypes from 'prop-types'; // ES6

var PropTypes = require('prop-types'); // ES5 with npm

Posted by '김용환'
,


개발자 역량/성장에 도움될만한 자료를 찾는 이에게 도움이 될만한 링크


https://artandlogic.com/what-makes-great-programmers-great/


http://sijinjoseph.com/programmer-competency-matrix/


https://news.ycombinator.com/item?id=4626695

Posted by '김용환'
,



react를 처음 해보는 개발자라면 인터넷에서 create-react-class를 봤을 것이다.


이게 15.5 이하에서 사용하던 부분인데. 15.6부터 바뀌었다. 



나는 react 16부터 개발하다 보니 소스 코드를 참조하려다가 react 15를 공부한 경우이다.




react 15.6부터는 create-react-class를 사용하면 deprecated warning 로그를 보게 될 것이다. 16.x부터는 삭제된다는 로그가 나온다. 


Warning: Accessing createClass via the main React package is deprecated, and will be removed in React v16.0. Use a plain JavaScript class instead. If you're not yet ready to migrate, create-react-class v15.* is available on npm as a temporary, drop-in replacement. For more info see https://fb.me/react-create-class




예전 코드라고 보고 정리하는 것이 좋다.


ES6의 React.Component로 사용하는 것이 최신 트렌드이다.



https://reactjs.org/docs/react-without-es6.html


https://reactjs.org/blog/2017/04/07/react-v15.5.0.html#migrating-from-react.createclass







예를 들어 아래와 creactReactClass가  React.Component를 상속한 형태로 변경된 것을 볼 수 있다. 



var
createReactClass = require('create-react-class'); var Greeting = createReactClass({ render: function() { return <h1>Hello, {this.props.name}</h1>; } });

=>

class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}








https://github.com/seatgeek/react-infinite/blob/7efd66437b5b01b28d21a35736fa2d8155605b9a/README.md#in-the-browser


아래와 같은 예제 코드는 다음 예제로 변경할 수 있다. 



var createReactClass = require('create-react-class');

var ListItem = createReactClass({
    render: function() {
        return <div className="infinite-list-item">
        List Item {this.props.num}
        </div>;
    }
});

var InfiniteList = createReactClass({
    getInitialState: function() {
        return {
            elements: this.buildElements(0, 20),
            isInfiniteLoading: false
        }
    },

    buildElements: function(start, end) {
        var elements = [];
        for (var i = start; i < end; i++) {
            elements.push(<ListItem key={i} num={i}/>)
        }
        return elements;
    },

    handleInfiniteLoad: function() {
        var that = this;
        this.setState({
            isInfiniteLoading: true
        });
        setTimeout(function() {
            var elemLength = that.state.elements.length,
                newElements = that.buildElements(elemLength, elemLength + 1000);
            that.setState({
                isInfiniteLoading: false,
                elements: that.state.elements.concat(newElements)
            });
        }, 2500);
    },

    elementInfiniteLoad: function() {
        return <div className="infinite-list-item">
            Loading...
        </div>;
    },

    render: function() {
        return <Infinite elementHeight={40}
                         containerHeight={250}
                         infiniteLoadBeginEdgeOffset={200}
                         onInfiniteLoad={this.handleInfiniteLoad}
                         loadingSpinnerDelegate={this.elementInfiniteLoad()}
                         isInfiniteLoading={this.state.isInfiniteLoading}
                         >
            {this.state.elements}
        </Infinite>;
    }
});

ReactDOM.render(<InfiniteList/>, document.getElementById('container'));



->


class ListItem extends React.Component {
render() {
return <div className="infinite-list-item">
List Item {this.props.num}
</div>;
}
}

class InfiniteList extends React.Component {
constructor(props) {
super(props)
this.state = {
elements: this.buildElements(0, 20),
isInfiniteLoading: false
}
}

buildElements(start, end) {
var elements = [];
for (var i = start; i < end; i++) {
elements.push(<ListItem key={i} num={i}/>)
}
return elements;
}

handleInfiniteLoad() {
var that = this;
this.setState({
isInfiniteLoading: true
});
setTimeout(function() {
var elemLength = that.state.elements.length,
newElements = that.buildElements(elemLength, elemLength + 1000);
that.setState({
isInfiniteLoading: false,
elements: that.state.elements.concat(newElements)
});
}, 2500);
}

elementInfiniteLoad() {
return <div className="infinite-list-item">
Loading...
</div>;
}

render() {
return <Infinite elementHeight={40}
containerHeight={250}
infiniteLoadBeginEdgeOffset={200}
onInfiniteLoad={this.handleInfiniteLoad}
loadingSpinnerDelegate={this.elementInfiniteLoad()}
isInfiniteLoading={this.state.isInfiniteLoading}
>
{this.state.elements}
</Infinite>;
}
}

ReactDOM.render(
<InfiniteData />,
document.getElementById("container")
);






Posted by '김용환'
,


Spark 2.0의 데이터 셋(dataset)은 다음과 같이 정의되어 있다.



type DataFrame = Dataset[Row]



Dataset은 스키마를 갖고 있다. 


(spark 1.5) DataFrame에 encoder를 추가한 것이 Dataset이라 할 수 있다.  


(spark 2.0) DataFrame은 특별한 encoder 없이 Dataset[Row]의 앨리어스로 쓸 수 있게 되었다.





데이터 셋을 고도로 최적화한 바이너리(binary)로 표현하는 RDD의 효율적인 테이블로 생각할 수 있다.


바이너리 표현은 인코더(encoder)를 사용해 이루어 진다.


인코더는 RDD 표현보다 성능이 더 좋은 다양한 오브젝트를 바이너리 구조로 직렬화한다.


데이터 프레임은 내부적으로 RDD를 내부적으로 사용하고 데이터 프레임/데이터 셋은 RDD와 동일하게 배포되므로 분산 데이터 집합이기도 하다.


분명 데이터 셋은 불변임을 의미한다.

Posted by '김용환'
,


Play2와 webjar를 이용해 React를 개발하고 있다.


react-infinite.js를 사용하다가 다음과 같은 에러가 발생되었다. 



org.webjars.MultipleMatchesException: Multiple matches found for react-infinite.js. 

Please provide a more specific path, for example by including a version number.




디버깅 버전으로 테스트해보니..(https://github.com/knight76/webjars-locator-core)


build와 dist 디렉토리에 동일한 파일이 있음을 확인했다. 



react-infinite.js/build/0.11.0/react-infinite/webjars/resources/META-INF/=META-INF/resources/webjars/react-infinite/0.11.0/build/react-infinite.js, 

react-infinite.js/dist/0.11.0/react-infinite/webjars/resources/META-INF/=META-INF/resources/webjars/react-infinite/0.11.0/dist/react-infinite.js, 



다음과 같이 build.sbt를 수정하면 된다. 

excludeDependencies ++= Seq(
"org.webjars.npm" % "react-infinite"
)



unmanagedJars in Compile += file("lib/react-infinite-without-conflict-0.11.0.jar")



ivy2에서 캐싱된 내용때문에 그냥 실행하면 기존 파일이 남아 있을 수 있다. 

그리고 새롭게 변경된 lib을 사용할 때마다 다음 커맨드를 실행한다. 


# sbt clean

# sbt clean-files






Posted by '김용환'
,


아파치 NIFI를 처음 써보려면 약간 당혹스러울 수 있다.


보통 NIFI에 KAFKA나 HADOOP을 연동할 터인데요. 초반에 애를 먹는다.



아래 블로그를 참조하면 어떻게 KAFKA, HDFS, CASSANDRA를 사용하는 예를 참고하면 좋을 것 같다.


https://blog.autsoft.hu/beginners-guide-to-apache-nifi-flows/









Posted by '김용환'
,



HadoopRDD는 하둡 1.x 라이브러리의 맵리듀스 API를 사용해 HDFS에 저장된 데이터를 읽는 핵심 기능을 제공한다. 

그러나 일반 파일 시스템에서 읽을 때도 HadoopRDD가 사용된다. 


HadoopRDD는 기본적으로 사용되며 모든 파일 시스템의 데이터를 RDD로 로드할 때 HadoopRDD를 살펴볼 수 있다.




scala> val statesPopulationRDD = sc.textFile("test.csv")

statesPopulationRDD: org.apache.spark.rdd.RDD[String] = test.csv MapPartitionsRDD[27] at textFile at <console>:24


scala>  statesPopulationRDD.toDebugString

res22: String =

(2) test.csv MapPartitionsRDD[27] at textFile at <console>:24 []

 |  test.csv HadoopRDD[26] at textFile at <console>:24 []







NewHadoopRDD는 Hadoop 2.x 라이브러리의 새로운 맵리듀스 API를 사용해 HDFS, HBase 테이블, 아마존 S3에 저장된 데이터를 읽는 핵심 기능을 제공한다. NewHadoopRDD는 다양한 포맷으로 읽을 수 있기 때문에 여러 외부 시스템과 상호 작용하기 위해 사용된다.


스파크 컨텍스트의 wholeTextFiles 함수를 사용하여 WholeTextFileRDD를 생성하는 것이다. 실제로 WholeTextFileRDD는 다음 코드처럼 NewHadoopRDD를 상속한다.

scala> val rdd_whole = sc.wholeTextFiles("test.txt")

rdd_whole: org.apache.spark.rdd.RDD[(String, String)] = wiki1.txt MapPartitionsRDD[29] at wholeTextFiles at <console>:24


scala> rdd_whole.toDebugString

res23: String =

(1) test.txt MapPartitionsRDD[29] at wholeTextFiles at <console>:24 []

 |  WholeTextFileRDD[28] at wholeTextFiles at <console>:24 []




직접적으로 스파크 컨텍스트의 newAPIHadoopFile을 사용할 수 있다. 




import org.apache.hadoop.mapreduce.lib.input.KeyValueTextInputFormat


import org.apache.hadoop.io.Text


val newHadoopRDD = sc.newAPIHadoopFile("test.txt", classOf[KeyValueTextInputFormat], classOf[Text],classOf[Text])






Posted by '김용환'
,