리엑트 네이티브) XMLHttpRequest를 활용한 서버 통신

2018. 1. 4. 23:42프로그래밍(주력)/JAVASCRIPT

리엑트 네이티브 내의 app.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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import React, {
    Component
} from 'react';
 
import {
    StyleSheet,
    Text,
    View,
    Image,
    FlatList,
    Dimensions,
    ActivityIndicator
 
} from 'react-native';
 
const screen = {
    width: Dimensions.get('window').width,
    height: Dimensions.get('window').height
};
 
const today = new Date();
 
 
export default class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            isLoading: true,
            today_idol: []
        }
    }
 
    componentDidMount() {
        const xobj = new XMLHttpRequest();
        const that = this;
        xobj.open('POST''http://ngdb.iptime.org:765/api/posts/day'true);
        xobj.setRequestHeader("Content-type""application/x-www-form-urlencoded");
        xobj.onreadystatechange = function () {
            if (xobj.readyState !== 4) {
                return;
            }
            if (xobj.status === 200) {
                console.log('success')
                that.setState({
                    isLoading: false,
                    today_idol: xobj.responseText
                })
            } else {
                console.warn('error');
            }
        };
        xobj.send('month=' + (today.getMonth()+1+ '&day=' + today.getDate() + '&where=[-1]');
 
 
    }
 
    render() {
        console.log(this.state.today_idol)
        if (this.state.isLoading) {
            return (
                <View style={{flex: 1, paddingTop: 50}}>
                    <ActivityIndicator />
                </View>
            );
        }
        return (
            <View style={styles.container}>
                <Text style={styles.UpTitle}>오늘 생일인 아이돌</Text>
                <FlatList
                    horizontal={true}
                    data= {eval(this.state.today_idol)}
                    renderItem={({item}) =>
                        <View style={styles.idolitem}>
                            <Image style={styles.idolPic} source={{uri: 'http://ngdb.iptime.org:765/'+item.img}}/>
                            <Text style={styles.idolname}>{item.name}</Text>
                        </View>
                    }
                />
 
 
            </View>
        );
    }
}
 
const styles = StyleSheet.create({
    UpTitle : {
        fontSize: 35,
        marginBottom: 30
    },
    container: {
        marginTop: 50,
        flex: 1,
        backgroundColor: '#fff',
        alignItems: 'center',
        justifyContent: 'center',
    },
    idolPic: {
        width300,
        height400,
    },
    idolitem: {
        width: screen.width,
        height500,
        alignItems: 'center',
        justifyContent: 'center',
    },
    idolname: {
        flex:1,
    }
});
 
cs

주인장이 만든 아이돌 생일 웹을 앱으로 만드는 중간 과정이다.(아직은 많이 미완성)

여기서 어느 부분이 서버와 통신을 하냐면

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
componentDidMount() {
        const xobj = new XMLHttpRequest();
        const that = this;
        xobj.open('POST''http://ngdb.iptime.org:765/api/posts/day'true);
        xobj.setRequestHeader("Content-type""application/x-www-form-urlencoded");
        xobj.onreadystatechange = function () {
            if (xobj.readyState !== 4) {
                return;
            }
            if (xobj.status === 200) {
                console.log('success')
                that.setState({
                    isLoading: false,
                    today_idol: xobj.responseText
                })
            } else {
                console.warn('error');
            }
        };
        xobj.send('month=' + (today.getMonth()+1+ '&day=' + today.getDate() + '&where=[-1]');
 
cs

이부분이 서버와 통신한다.

개인적으로 fetch의 구조가 상당히 마음에 들지 않아 자바스크립트 내장 함수인 XMLHttp를 쓴다.


우선은

const xobj = new XMLHttpRequest();

로 XMLHttpRequest 객체를 선언해 준다.


다음으로

xobj.open('POST''http://ngdb.iptime.org:765/api/posts/day'true);

을 실행한다. 첫번째 인자로 어떤 방식으로 보낼건지. 두번째 인자로 주소를 보낸다. 세번째 인자는 참이면 비동기로 실행된다.


xobj.onreadystatechange

를 초기화해준다. 서버에서 반환값이 오고, callback함수가 실행되는데 그걸 정해주는 것이다.

xobj.onreadystatechange = function () {
            if (xobj.readyState !== 4) {
                return;
            }
            if (xobj.status === 200) {
                console.log('success')
                that.setState({
                    isLoading: false,
                    today_idol: xobj.responseText
                })
            } else {
                console.warn('error');
            }
        };

서버 통신규약(?)을 아는 사람이면 readyState와 status를 판단하는 숫자를 알 것이다.

표를 그려보겟다.


readyState 설명

 0 

 Uninitialized

  객체 초기화 안된 상태

 1

 Loading 

 서버로 보내는 과정을 안한 상태  

 2

 Loaded 

 아직 서버까지 도착하지 않은 상태 

 3

 Interactive 

 반환값을 받는 중 

 4

 Completed 

 반환이 완료되어 데이터로 사용 가능 


status설명

 200 

 Ok

 요청 성공

 403

 Forbidden 

 접근 거부(권한 문제) 

 404

 Not Found 

 페이지나 파일 없음 

 500

 Internal Server Error 

 서버 오류 발생(인터넷 연결이 안됬다던지)


어째튼 위 설명을 보면

readyState 4가 객체가 잘 선언 되어 보낸 것이고,

status 200이 잘 반환 되었을 경우이다.

이 두개가 모두 참인 경우에, 서버 통신이 완료되었다고 볼 수 있다.

그렇게 

if (xobj.status === 200) {
                console.log('success')
                that.setState({
                    isLoading: false,
                    today_idol: xobj.responseText
                })
            }

조건문으로 콘솔 'success'를 찍어주고

app.js의  App객체에 setState(리엑트의 변수 관리라고 생각하면 편함)로 저장을 해준다


여기서 주인장이 조금 헤맸는데, 평소 하듯이 this.setState를 해버리니 this가 

 xobj.onreadystatechange = function () {
            if (xobj.readyState !== 4) {
                return;
            }
            if (xobj.status === 200) {
                console.log('success')
                that.setState({
                    isLoading: false,
                    today_idol: xobj.responseText
                })
            } else {
                console.warn('error');
            }
        };

이걸 받아버려서 setState가 안됬다. 그래서 that이라는 변수에 App객체를 넣어버렸다. 어떻게?

const that = this;

이렇게~


넣고 호출에서 쓰니까 아주 편한하게 잘 됬다.

이제 마지막으로 비동기를 실행하기 위한 send를 선언하자

xobj.send('month=' + (today.getMonth()+1+ '&day=' + today.getDate() + '&where=[-1]');

보내는 형식은 위와 같다.

예를 들어 보낼 json이 


{

num = 1,

arr = [12,24]

}


라면

send('num=1&arr=[12,24]')

이렇게 보내면 된다.


&이 ,역할을 하고 :이 =이 된다고 보면 된다. 물론 json의 상징인 중괄호도 없애고


이러면 통신이 잘 되서 주인장같은 경우는



    render() {
        console.log(this.state.today_idol)
        if (this.state.isLoading) {
            return (
                <View style={{flex: 1, paddingTop: 50}}>
                    <ActivityIndicator />
                </View>
            );
        }
        return (
            <View style={styles.container}>
                <Text style={styles.UpTitle}>오늘 생일인 아이돌</Text>
                <FlatList
                    horizontal={true}
                    data= {eval(this.state.today_idol)}
                    renderItem={({item}) =>
                        <View style={styles.idolitem}>
                            <Image style={styles.idolPic} source={{uri: 'http://ngdb.iptime.org:765/'+item.img}}/>
                            <Text style={styles.idolname}>{item.name}</Text>
                        </View>
                    }
                />
 
 
            </View>
        );
    }


render함수에서 state변경에 따라 리프레시되는 리엑트의 특징에 맞게

요로코롬 처리하였다.