Spring

Spring & React 결합 (최종)

오잎 클로버 2022. 1. 14. 02:15
728x90

드디어 끝냈습니다.

 

리액트를 다루는 것이 이번이 처음이라서 제대로 이런 간단한 것도 못 끝낼 줄 알았지만

역시 노력(이하 삽질이라고 부른다.)은 배반하지 않는 것 같습니다.

 

일단 리액트 코드를 좀 많이 개판으로 만들어놨긴했는 데.... 잘 돌아가니 된건가..

...너무 개판인데?

 

 

각설하고 코드를 조금 살펴보면

패키지 2개로 input파트(라고 하지만 실제로는 개판오분전인 막장 코드) 그리고 request(대충 Spring Rest API에게 POST 혹은 GET request 보내기 위한 파트) 이렇게 2개입니다.

 

일단 Spring 코드를 어떤 방식으로 구성했는 지 간단하게 설명하자면

회원가입을 합니다. (PasswordEncoder로 비밀번호 암호화)

로그인을 합니다. (Access, Refresh 토큰 발행해줌 & Refresh 토큰은 서버DB에 저장함)

그리고 /home으로 GET 요청 (토큰 없으면 에러 발생)

 

 

스프링 코드 핵심적인 것들만 요약하자면

Controller들 만들어주고

BaseTimeEntity는 날짜 적용시킬려고 만들었지만 사용안함

Entity 만들어주고

response 모델들, 그리고 repository Entity에 맞춰서 만들고 해서

그에 맞는 Service들 만들어줬습니다.

그리고 예외처리까지 합니다.

 

마지막으로 Config까지 해주면 스프링은 끝납니다.

(말로 설명하면 단순한데 코드로 하면 33개의 클래스와 2개의 인터페이스로 구현해야함)

 

자세한 코드들은 깃허브 확인해주세요. (Spring 코드 깃허브 링크)

그리고 아래는 요청에 따른 결과들입니다. 그냥 참고용으로 접어놨습니다.

더보기
회원가입
동일한 이메일로 회원가입할 경우
로그인
토큰없이 home에 접근할 경우
토큰있이 home에 접근한 경우

 

리액트로 다시 돌아와서 request패키지에 저 같은 경우에는 3개의 js로 나누었는 데

이제와서 보니 그냥 function 여러개 있는 하나의 js로 하지 왜 굳이 나누었을 까 싶네요.

(리액트 코드 깃허브 링크)

 

import axios from "axios";

export function SignUp(email, name, nickname, password) {
    let webUrl = "http://localhost:8080";

    function request() {
        const data = {
            email: email,
            name: name,
            nickname: nickname,
            password: password
        };

        axios.post(webUrl + "/api/sign/signup", data)
            .then(response => {
                alert(response.status + " 성공적입니다.")
            }).catch(error => {
                console.log("요청한 data: " + data.email + ", " + data.name + ", " + data.nickname + ", " + data.password)
                alert(error);
        });
    }
    request();
}

export default SignUp;

회원가입 POST 요청을 하는 친구입니다.

 

import axios from "axios";

export function Login(email, password) {
    let webUrl = "http://localhost:8080";

    function request() {
        const data = {
            email: email,
            password: password
        };

        axios.post(webUrl + "/api/sign/login", data)
            .then(response => {
                axios.defaults.headers.common['X-AUTH-TOKEN'] = response.data.data.accessToken;

                alert(response.status + " 성공적입니다.")
            }).catch(error => {
            console.log(data.email + ", " + data.password)
            alert(error);
        });
    }
    request();
}

export default Login;

위 회원가입과 굉장히 유사한데 다른 점이 있다면 토큰을 받아서 axios 해더에다가 넣는 건데

저같은 경우에는 

으로 해서 ["AUTHENTICATION"] = "Bearer ${accessToken}" 처럼 처리하지 않았습니다.

 

그리고 최종적으로

const axios = require("axios");

export function Home() {
    return axios.get("http://localhost:3000/home");
}

export default Home;

Home을 만들었습니다.

 

그리곤 UI라고는 눈을 씻고봐도 정말 별로인 UI를 가진 InputSample.js를 만들었습니다.

(그냥 Input이라고 할려다가 다 공부하자고 하는 건데 싶어서 뒤에 Sample를 붙였습니다.)

import React, {useState} from "react";
import SignUp from "../request/SignUp";
import Login from "../request/Login";
import Home from "../request/Home";

function InputSample() {

    /*
    input에 작성하고
    button을 눌르면 SignSample에서 axios으로 Post하여 회원가입하는 로직
    로그인도 마찬가지
    토큰으로 Home.js Response까지 가져오는 게 목표
    토큰은 헤더에 저장
     */

    const [email, setEmail] = useState("");                 // email
    const [name, setName] = useState("");                   // name
    const [nickname, setNickname] = useState("");           // nickname
    const [password, setPassword] = useState("");           // password
    const [loginEmail, setLoginEmail] = useState("");       // 로그인 시 사용할 email
    const [loginPassword, setLoginPassword] = useState(""); // 로그인 시 사용할 password

    const inputSignUpEmail = (e) => {
        setEmail(e.target.value);
    };

    const inputLoginEmail = (e) => {
        setLoginEmail(e.target.value);
    }

    const inputName = (e) => {
        setName(e.target.value);
    }

    const inputNickname = (e) => {
        setNickname(e.target.value);
    }

    const inputSignUpPassword = (e) => {
        setPassword(e.target.value);
    }

    const inputLoginPassword = (e) => {
        setLoginPassword(e.target.value);
    }

    const onSignRequest = () => {
        SignUp(email, name, nickname, password);
    }

    const onLoginRequest = () => {
        Login(loginEmail, loginPassword);
    }

    const onHome = () => {
        Home()
            .then(response => {
                alert(response.data.toString())
            }).catch(error => {
                alert(error)
        });
    }

    const onReset = () => {
        setEmail("");
        setName("");
        setNickname("");
        setPassword("");
        setLoginEmail("");
        setLoginPassword("");
    };

    return (
        <div>
            <div>
                이메일
                <input onChange={inputSignUpEmail} value={email}/>
            </div>
            <div>
                이름
                <input onChange={inputName} value={name}/>
            </div>
            <div>
                닉네임
                <input onChange={inputNickname} value={nickname}/>
            </div>
            <div>
                비밀번호
                <input onChange={inputSignUpPassword} value={password}/>
            </div>
            <button onClick={onSignRequest}>회원가입</button>
            <b/>
            <div>
                <div>
                    이메일
                    <input onChange={inputLoginEmail} value={loginEmail}/>
                </div>
                <div>
                    비밀번호
                    <input onChange={inputLoginPassword} value={loginPassword}/>
                </div>
                <button onClick={onLoginRequest}>로그인</button>
            </div>
            <b/>
            <div>
                <button onClick={onHome}>토큰 테스트</button>
            </div>
            <b/>
            <div>
                <button onClick={onReset}>초기화</button>
            </div>
        </div>
    );
}

export default InputSample;

네, 제가 봐도 별로에요.

근데 귀차니즘이..음

 

그건 그렇다고 치고 App.js로 가서

최종적으로 결합시키고 Spring, React 둘 다 실행했습니다.

import './App.css';
import {Component} from "react";
import InputSample from "./input/InputSample";

class App extends Component {
    render() {
        return (
            <div className="App">
                <InputSample/>
            </div>
        );
    }
}

export default App;

React 화면

 

정말 이건 아니다 싶은 건 작성하고 있는 지금도 느끼네요;;

 

일단 지금 시도해볼 순서는 아래와 같습니다.

  1. 그냥 /home에 접근해본다.
  2. 회원가입을 시도해본다.
  3. 만일 2번이 성공할 경우, 동일한 내용으로 또 회원가입을 시도해본다.
  4. 존재하지않는 이메일로 로그인을 시도해본다.
  5. 존재하는 이메일이지만 비밀번호는 다르게 하여 로그인을 시도해본다.
  6. 회원가입한 내용으로 로그인을 시도해본다.
  7. 로그인이 성공적으로 이루어졌다면 /home에 접근해본다.

1번 시도 결과

회원가입시 사용한 내용들

 

2번 시도 결과

 

3번 시도 결과
4번 시도 결과 (user@gmail.com으로 시도했습니다.)

 

5번 시도 결과
6번 시도 결과
7번 시도 결과

성공적으로 잘 작동합니다.

이제 스프링 log를 한 번 확인해봅시다.

 

나름 성공적이게 완성이 되었습니다.

 

 

다음 글은 제가 이를 개발하면서 발생한 버그들, 그리고 상황들에 대해서 적을 예정입니다.

 

 

이상입니다.

'Spring' 카테고리의 다른 글

Spring Entity 날짜 자동 저장  (0) 2022.01.19
Spring & React 결합 (버그와 오류들)  (0) 2022.01.14
Spring & React 결합 (f. CORS해결)  (2) 2022.01.12
Spring & React 결합  (0) 2022.01.12
스프링 어노테이션 Value  (0) 2022.01.10