개발일기/Project

8. Spring boot + React Native + MongoDB - 회원 가입 구현

길동이이이잉 2024. 5. 31. 23:04
728x90
반응형

우선 기능만 구현했기 때문에 매우 못생김 주의

Frontend 

우선 Join.js 파일을 만들어주고 App.js 파일에서 관련 부분을 추가해 준다.

//App.js

import Join from "./src/Join";

function App(){

    .....
    <Stack.Screen name="Join" component={Join}/>
    .....

}

 

Join.js

import React, {useEffect} from "react";
import {Button, StyleSheet, Text, TextInput, View} from "react-native";
import axios from "axios";
import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs";
import {LocalizationProvider} from "@mui/x-date-pickers";
import {DatePicker} from "@mui/x-date-pickers";
import dayjs, {Dayjs} from "dayjs";

export default function Join({navigation, route}) {
    useEffect(() => {
        navigation.setOptions({
            title: "회원 가입",
            headerStyle: {
                backgroundColor: '#1F266A',
                shadowColor: '#1F266A',
            },
            headerTintColor: "#fff",
        })
    }, []);
    
    const baseUrl = "http://localhost:8080/";

    let [userId, onChangeUserId] = React.useState('');
    const [name, onChangeName] = React.useState('');
    const [pw, onChangePw] = React.useState('');
    const [birth, onChangeBirth] = React.useState(null);
    const [existText, setExistText] = React.useState('');
    
    //아이디 중복 확인
    const onCheckExist = () => {
        axios.get(baseUrl + "exist", {params: {userId: userId}})
            .then((res) => {
                if (res.data.userId === userId) {
                    setExistText('exist Id') // userId TextInput칸 아래 'exist Id' 노출
                    userId = '' //userId TextInput칸을 비워줌
                    onChangeUserId('')
                    console.log(userId)
                } else {
                    setExistText('') // userId TextInput칸 아래 'exist Id' 삭제
                }
            })
            .catch((err) => console.log(err))
    }
    
    //회원가입 버튼 클릭시 실행
    const onPressJoin = () => {
        let request;
        request = {
            userId: userId,
            name: name,
            pw: pw,
            birth: birth
        }
        
        //빈칸이 있을 경우 회원 가입 실행 불가
        if (request.userId === '' || request.name === '' || request.pw === '' || request.birth === null) {
            alert("정보를 모두 입력해주세요")
        } else {
            console.log(request.birth)
            axios.post(baseUrl + "join", request)
                .then((res) => {
                    console.log("data : ", res.data)
                    if (res.data === 'success') {
                        navigation.navigate('Login')
                        alert("가입 성공")
                    } else {
                        alert("가입 실패, 다시 시도해주세요")
                    }
                })
                .catch((err) => console.log(err))
        }
    }

    return (
        <View style={styles.container}>
            <h2> 회원가입</h2>
            <TextInput
                placeholder='Id'
                style={styles.input}
                onChangeText={onChangeUserId}
                value={userId}
                onBlur={onCheckExist} //포커스 아웃하면 아이디 중복 확인
            ></TextInput>
            <Text> {existText} </Text>
            <TextInput
                placeholder='Password'
                style={styles.input}
                onChangeText={onChangePw}
                secureTextEntry={true} //입력문자 * 표시
                keyboardType="numeric" //숫자만 입력
            />
            <TextInput
                placeholder='name'
                style={styles.input}
                onChangeText={onChangeName}
                value={name}
            ></TextInput>
            <LocalizationProvider dateAdapter={AdapterDayjs}>
                <DatePicker
                    label="생일을 선택해주세요"
                    slotProps={{textField: {size: "small",},}}
                    format="YYYY / MM / DD"
                    value={birth}
                    onChange={(newValue) => onChangeBirth(newValue)}
                />
            </LocalizationProvider>
            <View style={styles.button}>
                <Button
                    color={'#e2d2c1'}
                    textStyle={{textAlign: 'center', font: 40}}
                    title={`회원가입`}
                    onPress={onPressJoin}
                />
            </View>
        </View>
    );

}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#fff',
        alignItems: 'center',
        justifyContent: 'center',
    },
    input: {
        height: 40,
        margin: 12,
        borderWidth: 1,
        padding: 10,
    },
    button: {
        width: 170,
        height: 40,
        margin: 12,
        padding: 10,
    }
});

 

생일을 입력받는 부분은 MUI X의 Date Picker를 사용했다. 

npm install @mui/x-date-pickers

// Install date library (if not already installed)
npm install dayjs

npm install @mui/material @emotion/react @emotion/styled
더보기

 

Backend 

백엔드는... 프런트보다 손 볼 곳이 많은데... 

 

우선, request를 처리하는 MemberDto부터

model.dto.MemberDto

package com.calender.calenderproject_backend.model.dto;

import com.calender.calenderproject_backend.model.Member;
import lombok.Data;

@Data
public class MemberDto {
    private String id;
    private String userId;
    private String name;
    private String pw;
    private Date birth;
}

 

model.Member

package com.calender.calenderproject_backend.model;
import ...

@Document("members")
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class Member {
    @Id
    private ObjectId id;
    private String userId;
    private String pw;
    private String name;
    private Date birth;
}

 

 

mongoDB에서 id는 기본키 역할을 하기 때문에 랜덤 id를 설정해 주는 것이 좋다고 한다.

내가 따로 입력값을 주지 않아도 자동으로 id값이 할당된다.

 

repository.MemberRepository

package com.calender.calenderproject_backend.repository;

import com.calender.calenderproject_backend.model.Member;
import org.springframework.data.mongodb.repository.MongoRepository;

public interface MemberRepository extends MongoRepository<Member, String> {
	Member findByUserId(String userId);
}

이 부분은 id 중복 확인 할 때 사용된다.

service.MemberService

package com.calender.calenderproject_backend.service;

import ...

@RequiredArgsConstructor
@Service
public class MemberService {
    private final MemberRepository memberRepository;

    public String join(MemberDto dto){
        Member member = new Member();
        member.setUserId(dto.getUserId());
        member.setName(dto.getName());
        member.setPw(dto.getPw());
        member.setBirth(dto.getBirth());

        if (memberRepository.findByUserId(dto.getUserId()) != null){
            System.out.println("name is already exist!");
            return "fail";
        } else {
            System.out.println("New name!");
            memberRepository.save(member);
            return "success";
        }
    }

    public Member memberExist(String userId){
        return memberRepository.findByUserId(userId);
    }

}

 

controller.MemberController

@RequiredArgsConstructor
@RestController
public class MemberController {
    private final MemberService memberService;

    /**
     * 회원 가입 수행
     * @param dto dto 'id', 'pw', 'name'
     */
    @PostMapping("/join")
    public ResponseEntity<?> join(@RequestBody MemberDto dto){
        System.out.println("dto : " + dto);
        return ResponseEntity.ok(memberService.join(dto));
    }

    @GetMapping("/exist")
    public ResponseEntity<?> memberExist(@RequestParam String userId){
        System.out.println("userId : " + userId);
        return ResponseEntity.ok(memberService.memberExist(userId));
    }
}

 

 

자... 회원 가입을 하던 중 또 문제점(?)을 하나 발견했다. 

 

백엔드까지는 한국 시간으로 잘 넘어오는데,

Spring에서 MongoDB로 저장될 때 UTC의 시간으로 변환되어 들어간다는 점을 발견했다.

데이터를 출력할 때는 다시 한국 시간으로 변환되어서 출력된다고 하니, 우선은 놔둬야겠다ㅎ 

(한국 시간 전환 블로그)

 

 

 

 

자, 다음은 로그인...

728x90
반응형