이 코드는 React Native에서 로그인 기능을 구현하고, Spring Boot 서버와 JWT(JSON Web Token) 방식으로 통신하는 방법을 보여주고 있습니다.
로그인 후에는 JWT 토큰을 사용해 서버와 인증된 방식으로 통신할 수 있도록 설정하는 내용입니다.


1. Login.js 분석

코드 주요 흐름:

  • 사용자 입력 → 서버로 로그인 요청 → JWT 토큰 수신 → 토큰 저장 → 이후 요청에 토큰 사용

로그인 컴포넌트 구현

<자바스크립트>

import React, { useState } from 'react';
import { View, TextInput, Button, StyleSheet, Alert } from 'react-native';
import axios from 'axios';
import tokenStorage from '../../services/tokenStorage';
import createAxiosInstance from '../../services/axiosInstance';
  • 설명: 필요한 라이브러리와 서비스 파일들을 임포트하고 있습니다.
    • useState: React에서 상태 관리를 위한 훅입니다. 여기서는 usernamepassword 상태를 관리합니다.
    • axios: 서버와 통신을 위한 HTTP 클라이언트입니다.
    • tokenStorage: JWT 토큰을 저장하거나 불러오는 역할을 담당합니다.
    • createAxiosInstance: 인증된 API 요청에 사용할 axios 인스턴스를 생성하는 함수입니다.

상태 설정 및 로그인 요청

<자바스크립트>

const Login = ({ onLoginSuccess }) => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  • 설명:
    • usernamepassword라는 상태를 관리합니다.
      사용자가 로그인 폼에 입력한 값을 실시간으로 업데이트합니다.
    • onLoginSuccess: 로그인 성공 시 콜백 함수로, 부모 컴포넌트에서 전달받은 함수입니다.
const loginHandler = async () => {
  console.log('Sending login request for:', username);
  console.log('Password:', password);

  if (!username || !password) {
    Alert.alert("Error", "Please enter both username and password.");
    return;
  }
  • 설명:
    • loginHandler: 로그인 버튼을 눌렀을 때 실행되는 함수입니다.
    • 입력한 usernamepassword가 없는 경우, 오류 메시지를 띄웁니다.

서버로 로그인 요청

<자바스크립트>

try {
  const response = await axios.post('http://10.0.2.2:8080/login', { username, password }, {
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  });
  • 설명:
    • axios.post: 서버로 로그인 요청을 보냅니다.
    • 'http://10.0.2.2:8080/login': Spring Boot 서버의 로그인 API URL입니다. 10.0.2.2는 Android 에뮬레이터에서 localhost에 접속할 때 사용하는 주소입니다.
    • headers: { 'Content-Type': 'application/x-www-form-urlencoded' }: 로그인 요청의 헤더를 설정하여, 폼 데이터 형식으로 전송합니다.
  const token = response.data.token;
  await tokenStorage.setToken(token);  // 비동기 처리로 토큰 저장
  console.log('Login Success! Token:', token);
  • 설명:
    • 서버에서 받은 JWT 토큰을 response.data.token으로 추출합니다.
    • tokenStorage.setToken(token): 토큰을 저장소(AsyncStorage)에 저장하여 나중에 API 요청에 사용할 수 있도록 합니다.

Axios 인스턴스 재설정

  const axiosInstance = createAxiosInstance(token);  // 토큰을 사용한 axiosInstance 생성
  onLoginSuccess(token, axiosInstance);  // 로그인 성공 시 콜백 호출

  Alert.alert("Success", "Logged in successfully!");
} catch (error) {
  console.error('Login Error:', error.response ? error.response.data : error);
  Alert.alert("Error", "Login failed.");
}
  • 설명:
    • createAxiosInstance(token):
      JWT 토큰을 사용한 새로운 axios 인스턴스를 생성합니다.
      이 인스턴스는 이후 모든 요청에 JWT 토큰을 자동으로 포함합니다.
    • onLoginSuccess(token, axiosInstance):
      로그인 성공 시 부모 컴포넌트에서 전달된 콜백 함수를 호출합니다. 이 함수는 토큰과 axios 인스턴스를 전달받습니다.
    • 로그인 실패 시 오류 메시지를 콘솔에 출력하고, 사용자에게 실패 메시지를 띄웁니다.

UI 구현

return (
  <View style={styles.inputContainer}>
    <TextInput
      style={styles.textInput}
      placeholder="Username"
      value={username}
      onChangeText={setUsername}
    />
    <TextInput
      style={styles.textInput}
      placeholder="Password"
      value={password}
      onChangeText={setPassword}
      secureTextEntry={true}
    />
    <Button title="Login" onPress={loginHandler} />
  </View>
);
  • 설명:
    • TextInput:
      사용자로부터 아이디와 비밀번호를 입력받는 입력 필드입니다.
      입력한 값은 usernamepassword 상태로 업데이트됩니다.
    • Button:
      로그인 버튼으로, 클릭 시 loginHandler 함수가 실행됩니다.

스타일 설정

const styles = StyleSheet.create({
  inputContainer: {
    padding: 20,
    backgroundColor: 'white',
    borderRadius: 10,
    marginBottom: 20,
  },
  textInput: {
    borderBottomWidth: 1,
    borderBottomColor: '#cccccc',
    marginBottom: 12,
    paddingVertical: 8,
    paddingHorizontal: 5,
  },
});
  • 설명: 로그인 폼의 스타일을 정의한 코드입니다. padding, borderRadius, marginBottom 등을 사용하여 입력 필드와 버튼이 보기 좋게 디자인됩니다.

2. services/axiosInstance.js 분석

import axios from 'axios';
import tokenStorage from './tokenStorage';

const createAxiosInstance = async () => {
  const token = await tokenStorage.getToken();

  return axios.create({
    baseURL: 'http://10.0.2.2:8080',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json',
    }
  });
};
  • 설명:
    • tokenStorage.getToken():
      저장된 JWT 토큰을 가져옵니다.
    • axios.create():
      axios 인스턴스를 생성합니다.
      여기에서 기본 URL과 요청 헤더를 설정합니다. 모든 요청에 자동으로 JWT 토큰이 Authorization 헤더에 포함되도록 설정되어 있습니다.

3. services/tokenStorage.js 분석

import AsyncStorage from '@react-native-async-storage/async-storage';

const tokenStorage = {
  getToken: async () => {
    try {
      const token = await AsyncStorage.getItem('jwtToken');
      return token;
    } catch (e) {
      console.error("Failed to get token:", e);
      return null;
    }
  },
  setToken: async (token) => {
    try {
      await AsyncStorage.setItem('jwtToken', token);
    } catch (e) {
      console.error("Failed to save token:", e);
    }
  },
  clearToken: async () => {
    try {
      await AsyncStorage.removeItem('jwtToken');
    } catch (e) {
      console.error("Failed to remove token:", e);
    }
  }
};

export default tokenStorage;
  • 설명:
    • AsyncStorage:
      모바일 앱에서 데이터를 영구적으로 저장하는 로컬 저장소입니다.
      여기서는 JWT 토큰을 저장, 읽기, 삭제하는 기능을 담당합니다.
    • getToken(): 저장된 JWT 토큰을 불러옵니다.
    • setToken(): JWT 토큰을 저장합니다.
    • clearToken(): JWT 토큰을 삭제합니다.

4. App.js 분석

<자바스크립트>

import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, Button } from 'react-native';
import Login from './components/login/Login';
import HomeScreen from './components/home/HomeScreen';
import tokenStorage from './services/tokenStorage';
import createAxiosInstance from './services/axiosInstance';
  • 설명: Login, HomeScreen 컴포넌트를 가져와 사용하며, JWT 토큰을 관리하기 위한 tokenStorage와 API 요청에 사용할 axios 인스턴스를 가져옵니다.

로그인 상태 관리

const [token, setToken] = useState(null);
const [axiosInstance, setAxiosInstance] = useState(null);

useEffect(() => {
  const loadToken = async () => {
    const storedToken = await tokenStorage.getToken();
    if (storedToken) {
      setToken(storedToken);
      const instance = createAxiosInstance(storedToken);
      setAxiosInstance(instance);
    }
  };
  loadToken();
}, []);
  • 설명:
    • useState: 현재 JWT 토큰과 axios 인스턴스를 상태로 관리합니다.
    • useEffect: 앱이 처음 실행될 때 저장된 JWT 토큰이 있는지 확인하고, 있으면 axios 인스턴스를 생성합니다.

로그인 성공 처리

const handleLoginSuccess = (token) => {
  tokenStorage.setToken(token);  // 토큰 저장
  setToken(token);
  const instance = createAxiosInstance(token);  // 토큰으로 axiosInstance 생성
  setAxiosInstance(instance);
};
  • 설명: Login.js에서 로그인 성공 시 호출되는 함수입니다. 로그인 후 토큰을 저장하고, axios 인스턴스를 생성하여 인증된 상태로 전환합니다.

로그아웃 처리

const handleLogout = async () => {
  await tokenStorage.clearToken();  // 토큰 삭제
  setToken(null);  // 로그아웃 상태로 변경
  setAxiosInstance(null);  // axiosInstance 초기화
};
  • 설명: 사용자가 로그아웃할 때 호출되는 함수입니다. JWT 토큰을 삭제하고 인증 상태를 해제합니다.

렌더링 처리

if (!token) {
  return (
    <View style={styles.container}>
      <Login onLoginSuccess={handleLoginSuccess} />
    </View>
  );
}

return (
  <View style={styles.container}>
    {axiosInstance ? (
      <>
        <HomeScreen axiosInstance={axiosInstance} />
        <View style={styles.buttonContainer}>
          <Button title="Logout" onPress={handleLogout} />
        </View>
      </>
    ) : (
      <Text>Loading...</Text>
    )}
  </View>
);
  • 설명:
    • 로그인 상태(token)에 따라 로그인 화면 또는 홈 화면을 보여줍니다.
    • 로그인 후에는 HomeScreen과 로그아웃 버튼을 렌더링합니다.

마무리

이 코드는 React Native에서 JWT 기반 인증을 구현하는 방법을 보여줍니다. 로그인 후 발급된 JWT 토큰을 저장하고, 이후 모든 API 요청에서 인증된 사용자로 서버와 통신할 수 있도록 axios 인스턴스를 설정하는 방식입니다. 각 코드가 어떻게 작동하는지 잘 이해하고 적용해 보세요!

0개의 댓글