서론
Flutter에서 User의 값을 입력받아 Spring을 이용하여 로컬 DB에 User를 간단하게 저장하는 방법을 포스팅하려고 합니다.
저도 Flutter와 Spring를 공부하고 있는 입장에서 작성하는 것이라 패스워드나 아이디 체크 기능이 들어간 회원가입 화면은 추후에 작성할 예정입니다. 간단하게 Flutter과 Spring가 이러한 형식으로 동작한다 정도 확인해 주시면 감사하겠습니다.
사용 IDE
- VSC (Flutter)
- STS (Spring)
아래는 Flutter와 Spring를 간단하게 나타낸 로직입니다.
Flutter(View)에서 User가 데이터를 입력하면 Spring(Server)을 통하여 DB에 저장하는 방식입니다.
소스 코드는 마지막에 작성해두었습니다.
비전공자분들은 순차적으로 보시면서 전체적인 프로젝트 흐름을 보시는 것을 추천드립니다.
View 생성 (Flutter)
먼저 Flutter 프로젝트를 생성해 줍니다. 다음에 pubspec.yaml 파일의 해당 부분에 http: ^0.13.5를 추가합니다.
다음에는 View를 만들어줍니다. 'StatefulWidget' 위젯을 사용하여 main.dart 부분에 만들어 주었습니다.
그리고 Flutter에서 입력받는 값은 3가지입니다. 대학교 이름 & 학생 이름 & 이메일입니다.
입력받을 값을 TextEditingController를 사용하여 저장합니다.
어느 정도 view가 완성되었습니다.
onPressed()를 이용하여 controller에 데이터가 전달이 잘 되는지를 console에 출력해 보는 view test를 진행하겠습니다.
정상적으로 입력값을 받아오는 것을 확인할 수 있습니다. 이제 Spring을 이용하여 controller를 만들어주겠습니다.
Spring (Server)
스프링 프로젝트를 생성해 줍니다. type은 maven으로 지정해 주었으며, 4가지 Dependencies를 추가했습니다.
그리고 다음 패키지를 생성해 줍니다.
생성할 패키지
- controller
- entity
- repo
- service
User.java를 entitiy 패키지에 생성해 주고 User class를 작성합니다. id는 pk( 기본키 )입니다. 밑에 나머지 3가지는 Flutter에서 넘겨받아 저장할 값입니다.
스프링 리소스 파일을 수정해 줍니다. DB와 연결하는 설정이라고 생각하시면 됩니다.( DB Config )
그 외에 코드를 모두 작성해 줍니다.
postman을 이용하여 api 테스트를 진행해 보겠습니다.
성공적인 메시지가 나타납니다. DB에 저장이 되었는지도 확인을 해봅니다.
세 번을 시도했지만 null 값을 받아옵니다..( 정확한 이유를 알지 못하였습니다. )
혹시 몰라서 User 소스 코드도 수정해 보았지만 구글링을 해본 결과 lombok @Data 어노테이션의 문제라는 가능성이 커서 getter와 setter를 직접 만들어주겠습니다..
어차피 id는 자동으로 지정해 주니깐 3가지만 추가해 줍니다.
소스 코드 수정 후 다시 api test를 진행해보겠습니다.
정상적으로 DB에 저장이 되는 걸 확인할 수 있습니다.
이로써 Spring와 DB는 정상적으로 작동되는 것을 확인할 수 있었습니다.
이제 Flutter과 spring을 연동할 차례입니다.
Flutter & Spring 연동
flutter에서 spring으로 data를 보내줘야 하기 때문에 service 폴더를 만들어 service.dart 파일을 생성하고 작성해 줍니다.
그리고 test를 해줍니다.
정상적으로 flutter console에 회원가입이 성공적으로 되었다고 나타납니다.
DB에 역시 정상적으로 저장된 걸 확인할 수 있었습니다.
소스 코드
Flutter 소스 코드
pubspec.yaml에 http dependencies를 추가해 주세요.
main.dart
import 'dart:developer';
import './service/service.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
//primarySwatch 추가
primarySwatch: Colors.blue,
),
home: const RegisterPage(),
//debug 표시 삭제 속성
debugShowCheckedModeBanner: false,
);
}
}
class RegisterPage extends StatefulWidget {
const RegisterPage({super.key});
@override
State<RegisterPage> createState() => _RegisterPageState();
}
class _RegisterPageState extends State<RegisterPage> {
TextEditingController schoolController = TextEditingController();
TextEditingController nameController = TextEditingController();
TextEditingController emailController = TextEditingController();
Service service = Service();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('회원가입 화면'),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Center(
child: SizedBox(
height: 50,
),
),
SizedBox(
height: 20,
),
SizedBox(
width: 250,
child: TextField(
controller: schoolController,
decoration: InputDecoration(hintText: "대학교이름"),
),
),
SizedBox(
height: 10,
),
SizedBox(
width: 250,
child: TextField(
controller: nameController,
decoration: InputDecoration(hintText: "이름"),
),
),
SizedBox(
height: 10,
),
SizedBox(
width: 250,
child: TextField(
controller: emailController,
decoration: InputDecoration(hintText: "이메일"),
),
),
SizedBox(
height: 80,
),
SizedBox(
width: 250,
child: ElevatedButton(
child: const Text('전송'),
onPressed: () {
service.saveUser(
schoolController.text,
nameController.text,
emailController.text,
);
},
),
),
],
),
));
}
}
service.dart
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
class Service {
Future<http.Response> saveUser(
String schoolname, String name, String email) async {
var uri = Uri.parse("http://localhost:8080/register");
Map<String, String> headers = {"Content-Type": "application/json"};
Map data = {
'schoolName': '$schoolname',
'email': '$email',
'name': '$name'
};
var body = json.encode(data);
var response = await http.post(uri, headers: headers, body: body);
print("${response.body}");
return response;
}
}
Spring Java 소스 코드
리소스 파일에 DB config를 추가해주세요.
User.java
package com.example.demo.entity;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "user_table")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String schoolName;
private String name;
private String email;
public String getSchoolName() {
return schoolName;
}
public void setSchoolName(String schoolName) {
this.schoolName = schoolName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
UserRepo.java
package com.example.demo.repo;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.entity.User;
public interface UserRepo extends JpaRepository<User, Integer>{
}
UserService.java
package com.example.demo.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.demo.entity.User;
import com.example.demo.repo.UserRepo;
@Service
public class UserService {
@Autowired
private UserRepo repo;
public String saveUser(User user) {
repo.save(user);
return "회원가입이 성공적으로 되었습니다.";
}
}
UserController.java
package com.example.demo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
@RestController
@CrossOrigin
public class UserController {
@Autowired
private UserService service;
@PostMapping("/register")
private ResponseEntity<String> registerUser(@RequestBody User user){
String msg = service.saveUser(user);
return new ResponseEntity<String>(msg,HttpStatus.OK);
}
}
부족한 실력이지만 혹시나 궁금한 점이 있으시면 제가 아는 선에서 최대한 답변 해드리겠습니다. 감사합니다.
'Dart&Flutter' 카테고리의 다른 글
[ Flutter ] 사용자 비밀번호 ( 패스워드 ) 암호화 설정 ( obscureText & Hash ) (2) | 2023.09.03 |
---|---|
[Flutter] PathExistsException: Cannot create link, path 오류 해결 방법 (0) | 2023.08.31 |
[Flutter] appbar 색상 변경하기 / primarySwatch 속성 (0) | 2023.08.31 |
[ Flutter ] Flutter 프로젝트 만들기, 프로젝트 생성 하는 방법 (0) | 2023.08.23 |
[Flutter][VSC]No suitable Android AVD system images are available 에러 해결 방법 (0) | 2023.08.21 |
댓글