3. flutter homepage https://flutter.dev

최종 업데이트 : 2025-01-12

main.dart

      
          
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: SignupPage(),
    );
  }
}

class SignupPage extends StatefulWidget {
  const SignupPage({super.key});

  @override
  State<SignupPage> createState() => _SignupPageState();
}

class _SignupPageState extends State<SignupPage> {
  final TextEditingController idController = TextEditingController();
  final TextEditingController passwordController = TextEditingController();
  final TextEditingController passwordCheckController = TextEditingController();

  Future<void> signupRequest() async {
    if (!mounted) return;

    final url = Uri.parse('http://127.0.0.1:8000/api/signup');
    final data = {
      'id': idController.text,
      'password': passwordController.text,
    };

    try {
      final response = await http.post(
        url,
        headers: {'Content-Type': 'application/json; charset=UTF-8'},
        body: jsonEncode(data),
      );

      if (!mounted) return;

      final decodedBody = jsonDecode(utf8.decode(response.bodyBytes));

      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content:
              Text('${decodedBody["status_code"]} ${decodedBody["content"]}'),
        ),
      );
    } catch (e) {
      if (!mounted) return;

      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text('Error: $e'),
        ),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Material(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const Text("아이디"),
              TextField(
                controller: idController,
              ),
              const Text("패스워드"),
              TextField(
                controller: passwordController,
                obscureText: true,
              ),
              const Text("패스워드확인"),
              TextField(
                controller: passwordCheckController,
                obscureText: true,
              ),
              TextButton(
                onPressed: signupRequest,
                child: const Text("회원가입"),
              ),
            ],
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    idController.dispose();
    passwordController.dispose();
    passwordCheckController.dispose();
    super.dispose();
  }
}
  
      
    

작업순서

    
      
import 'package:flutter/material.dart';

void main() {
  runApp(const MainApp());
}

class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
        body: Center(
          child: Text('Hello World!'),
        ),
      ),
    );
  }
}
      
    
  

기본 프로젝트를 생성하면 생성되는 코드를 우선 실행해봅니다.

runApp을통해서 StatelessWidget인 MainAPP Class를 실행하게됩니다.

    
      
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
        body: Center(
          child: Text('Hello World!'),
        ),
      ),
    );
  }
}
      
      
    

MainApp Class를 MyApp으로 변경해서 실행해봅니다.

    
      
home: Scaffold(
  body: Center(
    child: Text('Hello World!'),
  ),
),
      
    
  

이 부분을 Page로 만들어보겠습니다.

    
      
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: SignupPage(),
    );
  }
}

class SignupPage extends StatefulWidget {
  const SignupPage({super.key});

  @override
  State<SignupPage> createState() => _SignupPageState();
}

class _SignupPageState extends State<SignupPage> {
  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Text('Hello World!'),
      ),
    );
  }
}
      
    
  

StatefulWidget의 규칙을 이해하고 createState 메서드로 State 객체를 반환하였습니다.

    
      
class _SignupPageState extends State<SignupPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: [
            const Text("아이디"),
            const TextField(),
            const Text("패스워드"),
            const TextField(),
            const Text("패스워드확인"),
            const TextField(),
            TextButton(onPressed: () {}, child: const Text("회원가입"))
          ],
        ),
      ),
    );
  }
}
      
    
  

페이지에 추가하여 실행해봅니다.

    
      
final TextEditingController idController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
final TextEditingController passwordCheckController = TextEditingController();

          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const Text("아이디"),
              TextField(
                controller: idController,
              ),
              const Text("패스워드"),
              TextField(
                controller: passwordController,
                obscureText: true,
              ),
              const Text("패스워드확인"),
              TextField(
                controller: passwordCheckController,
                obscureText: true,
              ),
              TextButton(onPressed: () {}, child: const Text("회원가입"))
            ],
          ),

      
    
  

해당컨트롤들을 변경값을 위해 변수를 적용해봅니다.

패스워드는 obscureText 속성을 추가하여 비밀번호를 마스킹 처리합니다.

    
              
import 'package:http/http.dart' as http;
import 'dart:convert';

  Future<void> signupRequest() async {
    if (!mounted) return;

    final url = Uri.parse('http://127.0.0.1:8000/api/signup');
    final data = {
      'id': idController.text,
      'password': passwordController.text,
    };

    try {
      final response = await http.post(
        url,
        headers: {'Content-Type': 'application/json; charset=UTF-8'},
        body: jsonEncode(data),
      );

      if (!mounted) return;

      final decodedBody = jsonDecode(utf8.decode(response.bodyBytes));

      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content:
              Text('${decodedBody["status_code"]} ${decodedBody["content"]}'),
        ),
      );
    } catch (e) {
      if (!mounted) return;

      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text('Error: $e'),
        ),
      );
    }
  }

  TextButton(
    onPressed: signupRequest,
    child: const Text("회원가입"),
  ),
      
    
  

signupRequest함수에 필요한 패키지를 선언하고

signupRequest함수를 만들고 회원가입버튼에 적용합니다.

SnackBar말고 다른걸 하고싶으시면 그걸 사용하셔도됩니다

    
      
@override
void dispose() {
  idController.dispose();
  passwordController.dispose();
  passwordCheckController.dispose();
  super.dispose();
}
      
    
  

선언했던 자원들을 정리하는 로직을 추가합니다.

flet과 flutter는 별도의 css개념이 없습니다.

web을 만들기에는 아직 적합하다고 보진 않지만

간단한 웹도 가능하며 데스크탑이나 모바일의 경우

css를 사용하지 않고 widget개념으로 레이어를 생각하면

화면 구성을 조금 더 쉽게 진행가능하지 않을까 싶습니다

Related Pages

© 2024 Coding Stairs. All rights reserved.