일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Android
- scrollview
- button
- Javscript
- fragment
- 랜덤넘버
- Hook
- 스프링부트
- JS
- RecyclerView
- 코틀린
- 랜덤번호
- npm
- 구글맵스
- SpringBoot
- stylesheet
- 안드로이드
- Linux
- TextView
- array
- 오버라이딩
- nodejs
- GoogleMaps
- 리액트
- JavaScript
- TypeScript
- Java
- 자바스크립트
- React
- Kotlin
- Today
- Total
타닥타닥 개발자의 일상
react / Axios 이용해서 스프링부트로 만든 웹페이지 안드로이드 화면과 연결시키기 (회원가입/게시판/글작성) 본문
react / Axios 이용해서 스프링부트로 만든 웹페이지 안드로이드 화면과 연결시키기 (회원가입/게시판/글작성)
NomadHaven 2022. 3. 13. 23:30https://developerson.tistory.com/117
스프링 부트로 SpringBoot 회원가입, 페이징, 글작성-수정-삭제-답변, 댓글 작성 되는 게시판 페이지
기본적 세팅은 아래글 https://developerson.tistory.com/114 페이징은 아래글을 참고해서 만든 게시판이다. https://developerson.tistory.com/116 별도의 설명 없이 우선 코드만 백업할 예정. 이제 이걸 이해하..
developerson.tistory.com
react와 연결시킬 스프링 프로젝트는 해당 링크에 있는 프로젝트다.
react와 스프링 부트를 잘 연결시키기 위해서는 sts를 통해서 해당 프로젝트의 서버를 미리 켜준다.
또한 스프링 부트 프로젝트의 BbsDto 부분에 @JsonProperty("userid")라는 어노테이션을 추가해준다.
react에서 이름이 그냥 id된 데이터를 잘 못받아서 그런다는데.. 잘 모르겠다.
![](https://t1.daumcdn.net/keditor/emoticon/niniz/large/044.gif)
그럼 리액트 프로젝트도 생성해보자
생성문
npx react-native init Samples --template react-native-template-typescript
여러 기능을 써야하므로 미리 입력해줄 설치문도 많다
설치문
npm install @react-navigation/native
npm install @react-navigation/native-stack
npm install react-native-safe-area-context
npm install react-native-gesture-handler
npm install react-native-screens
npm install watcher
npm i axios
npm i @react-native-async-storage/async-storage
npm i react-native-paper
watcher 때문에 설치가 불안정할수 있는데 그럴때는 package.json에서 dependencies에 있는 watcher 버전을 1.1.0 으로 바꿔준다.
그럼 이제 본격적으로 react 프로젝트를 만들어보자
![](https://t1.daumcdn.net/keditor/emoticon/niniz/large/022.gif)
파일 구성 및 폴더 구성
이용할 이미지는 assets 폴더를 생성해서 저장한다.
screens 폴더를 생성하고 그 안에 bbs/member 폴더를 생성한다.
회원가입/로그인 화면을 위해 member 폴더 안에 Account.tsx / Login.tsx 파일을 생성
게시판 목록/ 글쓰기 / 글읽기 기능을 위해 bbs 폴더 안에 Bbs.tsx/Bbsdetail.tsx/Bbslist.tsx/Bbswrite.tsx 파일을 생성
각 파일별 코드는 아래와 같다.
bbs 폴더 안에 있는 파일들
Bbs.tsx
import React, { useState } from "react";
import { Button, StyleSheet, Text, View } from "react-native";
import Bbsdetail from "./Bbsdetail";
import Bbslist from "./Bbslist";
import Bbswrite from "./Bbswrite";
function Bbs(){
const[bbslist,setBbslist]=useState("bbslist")
const[bbs,setBbs]=useState({})
let child:any
if(bbslist=="bbslist"){
// child = (<Text>Bbslist view</Text>)
child=(<Bbslist setBbslist={setBbslist} setBbs={setBbs}/> )
}else if(bbslist=="bbswrite"){
// child = (<Text>BbsWrite view</Text>)
child =(<Bbswrite setBbslist={setBbslist}/>)
}else if(bbslist=="bbsdetail"){
// child = (<Text>BbsDetail view {JSON.stringify(bbs)} </Text>)
child=(<Bbsdetail bbs={bbs}/>)
}
return(
<View>
<View style={styles.menu}>
<View style={styles.button}>
<Button title="글목록" onPress={bbslist=>setBbslist("bbslist")}/>
</View>
<View style={styles.button}>
<Button title="글추가" onPress={bbslist=>setBbslist("bbswrite")}/>
</View>
</View>
<View>{child}</View>
</View>
)
}
const styles = StyleSheet.create({
menu:{
flexDirection:"row",
flexWrap:"wrap",
},
button:{
flex:1,
height:50,
margin:1,
},
childView:{
height:760,
}
})
export default Bbs;
Bbsdetail.tsx
import React from "react";
import { StyleSheet, ScrollView, Text } from "react-native";
import { Avatar, Card, Headline, Paragraph } from "react-native-paper";
import { SafeAreaView } from "react-native-safe-area-context";
function Bbsdetail(props:any){
return(
<SafeAreaView>
<ScrollView contentContainerStyle={styles.contentContainer}>
<Headline>글 내용</Headline>
<Card style={styles.card}>
<Card.Title
title={props.bbs.title}
subtitle={"작성자 :" + props.bbs.userid}
left={props=><Avatar.Text {...props} label="AAA"/>}/>
<Card.Content>
<Paragraph style={styles.content}>
{props.bbs.content}
</Paragraph>
<Text style={{textAlign:"right"}}>
조회수:{props.bbs.readcount}
</Text>
<Text style={{textAlign:"right"}}>
작성일:{props.bbs.wdate}
</Text>
</Card.Content>
</Card>
</ScrollView>
</SafeAreaView>
)
}
const styles = StyleSheet.create({
contentContainer:{
padding:16
},
card:{
marginTop:20
},
content:{
fontSize:20
}
})
export default Bbsdetail
Bbslist.tsx
import axios from "axios";
import React, { useEffect, useState } from "react";
import { StyleSheet, View, TouchableOpacity, Image, Text, FlatList } from "react-native";
//연습용 데이터
// const data=[
// {
// "userid":"aaa",
// "title":"첫번째 제목",
// "readcount": 3
// },
// {
// "userid":"bbb",
// "title":"두번째 제목",
// "readcount": 2
// },
// {
// "userid":"ccc",
// "title":"세번째 제목",
// "readcount": 1
// }
// ]
function Item({id,title,readcount,seq, props}:any){
function itemClick(seq:number){
console.log('itemClick')
console.log(seq)
axios.get("http://192.168.35.3:3000/bbsdetail", { params:{seq:seq}})
.then(function(resp){
console.log(resp.data)
//짐싸기
props.setBbs(resp.data)
})
.catch(function(err){
console.log(err)
})
//bbsdetail로 이동
props.setBbslist("bbsdetail")
}
return(
<View style={styles.item}>
<TouchableOpacity onPress={()=>itemClick(seq)}>
<View style={styles.idRow}>
<Image style={styles.image} source={require("../../assets/dog.png")}/>
<Text style={styles.title}>{title}</Text>
</View>
<View style={styles.idRow}>
<Text style={styles.id}>{id}</Text>
<Text style={styles.readcount}>{readcount}</Text>
</View>
</TouchableOpacity>
</View>
)
}
function Bbslist(props:any){
const[data,setData]=useState([])
function renderItem({item}:any){
function strLength(str:String){
if(str.length > 20){
return str.substring(0,17)+"..."
}else{
return str
}
}
return(
<Item id={"작성자:"+item.userid} title={strLength(item.title)}
readcount={"조회수:" +item.readcount} seq={item.seq} props={props}/>
)
}
let mounted= true
useEffect(()=>{
axios.get("http://192.168.35.3:3000/getBbsList",{} )
.then(function(resp){
console.log(resp.data)
setData(resp.data)
}).catch(function(err){
console.log(err)
})
},[])
return(
<View style={styles.scrView}>
<FlatList data={data} renderItem={renderItem} />
</View>
)
}
const styles = StyleSheet.create({
item:{
backgroundColor:'#d7d9f4',
padding:10,
marginVertical:2,
marginHorizontal:8,
borderColor:"#ff0000",
borderRadius:15,
borderStyle:'solid',
borderWidth:2
},
image:{
width:50,
height:50,
marginTop:15
},
title: {
fontFamily: "roboto-regular",
paddingLeft: 20,
color: "#400040",
height: 60,
width: 500,
fontSize: 24,
},
id: {
fontFamily: "roboto-regular",
//backgroundColor: "#ffff00",
color: "#121212",
height: 30,
width: 166,
fontSize: 20,
marginLeft: 80,
marginTop: 8
},
readcount: {
fontFamily: "roboto-regular",
//backgroundColor: "#00ff00",
color: "#121212",
height: 30,
width: 211,
fontSize: 20,
marginLeft: 51,
marginTop: 8,
textAlign: "center",
},
idRow:{
height:40,
flexDirection:"row",
marginLeft:5,
},
scrView:{
height:760
}
})
export default Bbslist;
Bbswrtie.tsx
import AsyncStorage from "@react-native-async-storage/async-storage";
import axios from "axios";
import React, { useState } from "react";
import { Alert, StyleSheet, Text, View } from "react-native";
import { Button, TextInput } from "react-native-paper";
function Bbswrite(props:any){
const [id,setId] = useState('')
const [title,setTitle]= useState('')
const [content, setContent] =useState('')
const loginData = async () =>{
try{
let user = await AsyncStorage.getItem('login')
if(user !=null){
setId((JSON.parse(user)).id )
}
}catch(err){}
}
loginData()
function bbsWriteBtn(){
console.log(id)
console.log(title)
console.log(content)
if(title.trim()==""){
}
axios.get("http://192.168.35.3:3000/bbswrite",
{
params:{
id:id,
title:title,
content:content
}
}).then(function(resp){
console.log(resp.data)
if(resp.data=="YES"){
props.setBbslist("bbslist")
}
}).catch(function(){
Alert.alert("추가되지 않았습니다.")
})
}
return(
<View>
<Text style={styles.text}>글추가</Text>
<View style={{alignItems:'center'}}>
<TextInput
style={styles.texInput}
mode="outlined"
label="작성자"
value={id}
editable={false}/>
<TextInput
style={styles.textArea}
mode="outlined"
label="제목"
value={title}
onChangeText={title=>setTitle(title)}/>
<TextInput
style={styles.textArea}
placeholder="내용"
multiline={true}
numberOfLines={20}
value={content}
onChangeText={content=>setContent(content)}/>
<Button
mode="outlined"
style={styles.button}
onPress={bbsWriteBtn}>작성완료</Button>
</View>
</View>
)
}
const styles = StyleSheet.create({
text:{
marginTop:10,
fontSize:30,
textAlign:"center"
},
texInput:{
marginTop:20,
fontSize:16,
width:500,
height:40,
backgroundColor:"#e3e3e3"
},
textArea:{
fontSize:16,
borderWidth:1,
marginTop:20,
backgroundColor:"#e3e3e3",
textAlignVertical:"top",
width:500
},
button:{
marginTop:20,
marginVertical:8
}
})
export default Bbswrite
member 폴더 안에 있는 파일들
Account.tsx
import axios from "axios";
import React, { useState } from "react";
import { Image, StyleSheet, View,TouchableHighlight, Text, TextInput, Alert} from "react-native";
export default function Account( {navigation}:any){
const[id,setId]= useState('')
const[msg,setMsg]=useState("msg")
const[pwd,setPwd]=useState("")
const[name,setName]=useState("")
const[email,setEmail]=useState("")
function idCheck(){
console.log('idCheck')
console.log(`${id}`)
if(id.trim()===""){
Alert.alert("아이디","아이디를 입력해 주십시오.")
setId("")
}else{
axios.post("http://192.168.35.3:3000/getId",null,{params:{id:id}})
.then(function(resp){
console.log(resp.data)
if(resp.data=="OK"){
setMsg("사용 가능합니다.")
}else{
setMsg("사용중입니다.")
setId("")
}
})
.catch(function(err){
console.log(err)
})
}
}
function regi(){
if(id.trim()===""){
Alert.alert("아이디","아이디를 입력해주십시오.")
}
else if(pwd.trim()===""){
Alert.alert("패스워드","패스워드를 입력해주십시오.")
}
else{
axios.post("http://192.168.35.3:3000/addmember",null,
{
params:{
id:id,
pwd: pwd,
name:name,
email:email
}
}
).then(function(resp){
console.log(resp.data)
if(resp.data=="YES"){
Alert.alert('regi',
'회원가입 되었습니다.',
[{
text:'확인',
onPress:()=>navigation.navigate('login')
}])
}
else{
Alert.alert("regi","가입되지 않았습니다.")
}
}).catch(function(err){
console.log(err)
})
}
}
return(
<View style={styles.container}>
<Image style={styles.logo} source={require("../../assets/welcome.jpg")}/>
<View style={styles.inputView}>
<TextInput
style={styles.textInput}
placeholder="아이디"
value={id}
underlineColorAndroid="transparent"
onChangeText={(id)=>setId(id)}/>
</View>
<View style={styles.idTextContainer}>
<Text style={styles.idText}>{msg}</Text>
<TouchableHighlight style={[styles.buttonContainer, styles.sendButton]}
onPress={()=>idCheck()}>
<Text style={styles.buttonText}>id확인</Text>
</TouchableHighlight>
</View>
<View style={styles.inputView}>
<TextInput
style={styles.textInput}
placeholder="패스워드"
underlineColorAndroid="transparent"
onChangeText={(pwd)=>setPwd(pwd)}/>
</View>
<View style={styles.inputView}>
<TextInput
style={styles.textInput}
placeholder="이름"
underlineColorAndroid="transparent"
onChangeText={(name)=>setName(name)}/>
</View>
<View style={styles.inputView}>
<TextInput
style={styles.textInput}
placeholder="이메일"
underlineColorAndroid="transparent"
onChangeText={(email)=>setName(email)}/>
</View>
<TouchableHighlight style={[styles.buttonContainer, styles.sendButton]} onPress={()=>regi()} >
<Text style={styles.buttonText}>회원가입</Text>
</TouchableHighlight>
</View>
)
}
const styles = StyleSheet.create({
container:{
flex:1,
justifyContent:"center",
alignItems:"center",
backgroundColor:"#fff"
},
logo: {
justifyContent:"center",
marginBottom:60
},
inputView:{
borderBottomColor:"#f5fcff",
backgroundColor:"#dcdcdc",
borderRadius:30,
borderBottomWidth:1,
width:300,
height:45,
marginBottom:20,
flexDirection:'row',
alignItems:"center"
},
textInput:{
height:45,
marginLeft:16,
borderBottomColor:"#fff",
flex:1
},
buttonContainer:{
height:45,
flexDirection:'row',
justifyContent:"center",
alignItems:"center",
marginBottom:20,
width:100,
borderRadius:30
},
sendButton:{
backgroundColor:"#ff4500"
},
idTextContainer:{
height:45,
flexDirection:"row",
justifyContent:"center",
alignItems:"center",
width:100,
borderRadius:30
},
idText:{
marginLeft:20,
marginBottom:20,
width:180
},
buttonText:{
color:'white'
}
})
Login.tsx
import AsyncStorage from "@react-native-async-storage/async-storage";
import axios from "axios";
import React, { useState } from "react";
import {
Image,
StyleSheet,
View,
TextInput,
Text,
TouchableOpacity,
Button,
Alert
} from "react-native";
export default function Login( { navigation }:any ) {
const [id, setId] = useState("")
const [password, setPassword] = useState("")
function login(){
if(id.trim() == ""){
Alert.alert("id", "아이디를 입력해 주십시오")
}
else if(password.trim() == ""){
Alert.alert("password", "password를 입력해 주십시오")
}
else{
axios.post("http://192.168.35.3:3000/login", null,
{
params: {
id: id,
pwd: password
}
}).then(function(resp){
if(resp.data != null && resp.data != ""){
console.log("로그인 되었습니다")
console.log(resp.data)
AsyncStorage.setItem('login',JSON.stringify(resp.data))
//loginData()
navigation.navigate('bbs')
}
else{
Alert.alert("login", "아이디나 패스워드를 확인하세요")
}
}).catch(function(err){
Alert.alert("err", err)
})
}
}
const loginData = async () =>{
try{
let user = await AsyncStorage.getItem('login')
console.log("login 정보:"+user)
}catch(err){}
}
return (
<View style={styles.container}>
<Image style={styles.image} source={ require("../../assets/logo2.png") } />
<View style={styles.inputView}>
<TextInput
style={styles.textInput}
placeholder="id를 입력해 주세요"
placeholderTextColor="#003f5c"
onChangeText={(id)=>setId(id)} />
</View>
<View style={styles.inputView}>
<TextInput
style={styles.textInput}
placeholder="password를 입력해 주세요"
placeholderTextColor="#003f5c"
secureTextEntry={true}
onChangeText={(password)=>setPassword(password)} />
</View>
<TouchableOpacity onPress={()=> navigation.navigate("account")}>
<Text style={styles.forgot_button}>회원가입</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.loginBtn} onPress={()=>login()}>
<Text>로그인</Text>
</TouchableOpacity>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center"
},
image: {
marginBottom: 40
},
inputView: {
backgroundColor: "#ffc0cb",
borderRadius: 30,
width: "70%",
height: 45,
marginBottom: 20,
alignItems: "center"
},
textInput:{
height: 50,
flex: 1,
padding: 10,
marginLeft: 20
},
forgot_button: {
height: 30,
marginBottom: 30
},
loginBtn: {
width: "50%",
borderRadius: 25,
height: 50,
alignItems: "center",
justifyContent: "center",
marginTop: 40,
backgroundColor: "#ff1493"
}
})
실행화면
'코딩 기록 > react' 카테고리의 다른 글
react / 리액트로 화면에 카메라 구현하고 촬영한 사진 저장하기 (0) | 2022.03.20 |
---|---|
react / builderX 로 레이아웃 간편하게 만들고 화면에 적용하기 (0) | 2022.03.13 |
react / Navigator로 화면간 이동 가능하게 만들기 (0) | 2022.03.09 |
react 메인 화면 구성하고 Navigator로 화면 이동하게 만들기 (0) | 2022.03.09 |
react / TextProvider, useContext 통해서 다른 파일에 있는 값 화면에 구현하기 (0) | 2022.03.09 |