본문 바로가기

Full Stack 교육 회고록

11/25- 안드로이드스튜디오(계산기, 로그인) / Node.js(Sequelize)

728x90
SMALL

<계산기 기능>

package com.example.ex20221124

import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast

// : Kotlin에서 상속
class ConstraintActivity : AppCompatActivity() {

    // 전역변수(뷰)로 만들기
    lateinit var tvResult: TextView
    // 뷰에 대해서는 선언만 하는건 불가능! 초기화가 꼭 이루어져야 함
    // 그런데 lateinit이라는 키워드로 나중에 꼭 초기화를 하겠다
    // 라는 약속을 할 수 있다!
    lateinit var etNum1 : EditText
    lateinit var etNum2 : EditText


    // OnCreate()는 Activity가 실행될때 최초 딱 한번(가장 먼저) 호출되는 메서드
    // : Activity 생명주기
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ***** xml이랑 KotlinClass랑 연결하는 코드. 없으면 화면 안뜸! *****

        setContentView(R.layout.activity_constraint)

        // 1. xml의 View에 id를 지정
        // 2. id값을 이용해서 view를 찾아온다 (findViewById)
        // R.id.tvResult = 리소스.id.tvResult
//        val tvResult: TextView = findViewById<TextView>(R.id.tvResult)
        tvResult = findViewById(R.id.tvResult)
        val btnMinus = findViewById<Button>(R.id.btnMinus)
        etNum1 = findViewById<EditText>(R.id.etNum1)
        // btnMul, btnDiv 가져오기
        val btnMul = findViewById<Button>(R.id.btnMul)
        val btnDiv = findViewById<Button>(R.id.btnDiv)
        etNum2 = findViewById(R.id.etNum2)
        // id값은 문자열로 정해줬는데 받아오는 값이 Int
        // R 폴더에 모든 뷰(리소스)들의 id값이 저장되는데 주소값이 저장
        // 16진수 상수형태로 저장이 되어있다 (Int)

        // ** setContentView 위로 find할 수 없다!! **
        tvResult.setTextColor(Color.BLUE)
        tvResult.setTextColor(Color.parseColor("#ff9999"))
        // textSize에는 Float자료형이 들어가야 한다! (f : 형변환)
        tvResult.textSize = 40.0f
        tvResult.text = "안녕하세요!"
        // charSequence 인터페이스 - String은 CharSequence 인터페이스를 상속받는 중

        // 더하기 버튼을 눌렀을 때 "더하기 버튼이 눌렸습니다"라는 Toast를 띄우기!
        // 이벤트를 주는 방법
        // 1) 이벤트 메소드 설계 후 뷰에 연결하기
        // 2) innerClass (Listener OnClick 구현)
        btnMinus.setOnClickListener {
            // {}안에다가 기능 구현만 하면 됨! 람다식을 사용한 방법
            // 버튼을 눌렀을 때 "마이너스 버튼이 눌렸습니다" 토스트 띄우기
            Toast.makeText(this, "마이너스 버튼이 눌렸습니다",Toast.LENGTH_SHORT).show()

            // 1. EditText에 적혀있는 내용 가져오기
            var num1 = etNum1.text.toString().toInt()
            var num2 = etNum2.text.toString().toInt()
            // etNum1, etNum2 에 있는 내용 변수 num1, num2에 저장
            // 실제로 getText --> Editable --> 문자열로 형변환 --> 정수형
            // 2. num1, num2 연산 결과를 tvResult에 set해주세요!
            //  : num1, num2 연산 결과를 문자열로 바꿔서 set해주세요
            // 3) interface를 상속받게 만들어서 OnClick 구현
            tvResult.text="연산결과 : ${num1-num2}"
        }

        btnMul.setOnClickListener {
            val num1 = etNum1.text.toString().toInt()
            val num2 = etNum2.text.toString().toInt()
            tvResult.text = "연산결과 : "+(num1 * num2)
        }

        btnDiv.setOnClickListener {
            val num1 = etNum1.text.toString().toInt()
            val num2 = etNum2.text.toString().toInt()
            tvResult.text = "연산결과 : "+(num1 / num2)
        }


    } // onCreate 밖

    // 1번 방법
    // 이벤트 리스너는 무조건 View 매개변수를 가지고 있어야 한다.
    fun myClick(view: View){
        // Toast 띄우기!
        // 1) this : ConstraintActivity.this : Toast를 띄울 화면 정보
        // 2) 문구 (무조건 String, Int가 허용되는 경우는 id값만)
        // 3) Toast에 Short(3초), Long(5초) 속성 사용 : 지속시간
        Toast.makeText(this,"더하기 버튼이 눌렸습니다",Toast.LENGTH_SHORT).show()

        var num1 = etNum1.text.toString().toInt()
        // Emulator를 처음 실행시키면 EditText에는 아무 값도 없음 ""
        // "".toInt() NumberFormatException
        // 버튼을 눌렀을 때 적혀있는 값을 가지고 와줘야 함!!!
        var num2 = etNum2.text.toString().toInt()
        var result = num1 + num2
        tvResult.text = "연산 결과 : $result"
    }
}

package com.example.ex20221124

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.TextView
import android.widget.Toast

class LoginActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        //1. View 들의 id 값을 찾아오자 (findViewById)
        val etemail = findViewById<TextView>(R.id.etemail)
        val etpw = findViewById<TextView>(R.id.etpw)
        val btnlogin = findViewById<Button>(R.id.btnlogin)

        //2. Button에 Event 달아주기 (setOnclickListener)
        btnlogin.setOnClickListener {
            //2-1. EditText에 적혀있는 email, password 값을 가져오기
            // (email, pw : 변수 )--> 문자열로 형변환
            val email = etemail.text.toString()
            val pw = etpw.text.toString()
            //2-2. 가져온 email, pw가 smhrd@smhrd.or.kr, qwer1234 가 맞는지 판단( 조건식)
            //맞다면 Toast로 "로그인 성공"
            //틀리면 Toast로 "로그인 실패"를 띄워주세요!
            if (email=="smhrd@smhrd.or.kr"&& pw == "qwer1234")
                Toast.makeText(this, "로그인성공", Toast.LENGTH_SHORT).show()
            else
                Toast.makeText(this, "로그인 실패", Toast.LENGTH_SHORT).show()

        }

    }
}

package com.example.ex20221124

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.ImageView

class ImageActivity : AppCompatActivity() {

    val imgArray = intArrayOf(R.drawable.pink, R.drawable.black,
    R.drawable.blue, R.drawable.yellow, R.drawable.red)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_image)

        //View의 id값 다 찾아오기
        val img = findViewById<ImageView>(R.id.img)
        val btnPre = findViewById<Button>(R.id.btnPre)
        val btnNext = findViewById<Button>(R.id.btnNext)
        var indexNum = 0

        //img.setImageResource(R.drawable.pink)

        // 1. Pre버튼을 눌렀을 때! (setOnClickListener)
        // 1-1. index -1 감소
        // 해당 index에 있는 img의 id를 가져와서
        // ImageView에 set하자!
        // index의 조건 : 0보다 작으면 다시 index값을 size-1으로 돌리자

        btnPre.setOnClickListener {
            if(indexNum==0) indexNum = 5


            img.setImageResource(imgArray[--indexNum])
        }


    //Next버튼을 눌렀을 때 (setOnClickListener)    `
        btnNext.setOnClickListener {
            if(indexNum==4) indexNum = 0

            img.setImageResource(imgArray[++indexNum])
        }

        //2. Next 버튼을 눌렀을 때
        // 2-1 index +1 증가
        // 해당 index에 있는 img의 id를 가져와서
        // ImageView를 set하자
        // index의 조건: size -1보다 크면 다시 index 값을 0으로


    }
}

[Ex11ORM/config/confog.json]

{
  "development": {
    "username": "test",
    "password": "1234",
    "database": "testdb",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "test": {
    "username": "root",
    "password": null,
    "database": "database_test",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "production": {
    "username": "root",
    "password": null,
    "database": "database_production",
    "host": "127.0.0.1",
    "dialect": "mysql"
  }
}

[Ex11ORM/models/index.js]

const Sequelize = require("sequelize");
const User = require("./user");
const env = "development";
const config = require("../config/config")[env];

//db 연결 정보
const sequelize = new Sequelize(
  config.database,
  config.username,
  config.password,
  config
);

const db = {}; //sequelize, object;

//key        //value(db정보)
db.sequelize = sequelize;

db.User = User; //db와 테이블 연결

User.init(sequelize); //table 초기화
User.associate(db); //관계 설정

module.exports = db;

[Ex11ORM/models/index.user.js]

const Sequelize = require("sequelize");

module.exports = class User extends Sequelize.Model {
  //init : user 필드 자료형 지정, 테이블 관련 설정
  //associate : 테이블 간의 관계 설정
  static init(sequelize) {
    return super.init(
      {
        id: {
          type: Sequelize.STRING(50),
          primaryKey: true,
        },
        pw: {
          type: Sequelize.STRING(50),
          allowNull: false,
        },
        age: {
          type: Sequelize.INTEGER,
          allowNull: false,
        },
      },
      {
        //테이블에 대한 설정 지정
        sequelize, //init 매개변수
        modelName: "User", // 프로젝트에 사용할 모델의 이름
        tableName: "users", //실제 데이터베이스 테이블 이름
        charset: "utf8",
      }
    );
  }
  static associate(db) {
    //User / Project
    //db.User.hasMany(db.Project, {foreignKey:'id', sourceKey: 'id'});//1:N
    //db.User.hasOne//1:1
    //db.User.belongsToMany //N:M
    //db.Project.belongsTo(db.User,{foreignKey:'id', targetKey: 'id'});//1:1
    //db.Project.belongsToMany //N:M
  }
};

[Ex11ORM/seeders/app.js]

const express = require("express");
const { sequelize } = require("./models"); //./models/index
const app = express();

app.set("port", process.env.PORT || 8888);

//force : 서버 실행 시마다 테이블을 재생성 할 것인지 아닌지
sequelize
  .sync({ force: false })
  .then(() => {
    console.log("DB 연결 성공!");
  })
  .catch((err) => {
    console.error(err);
  });

app.listen(app.get("port"), () => {
  console.log(app.get("port"), "번 포트에서 서버 연결 대기중...");
});

[Ex11ORM/seeders/orm.txt]

ORM(Object Relational Mapping : 객체-관계 매핑)
: Object(model) - Relational(관계형 데이터베이스)
-> 자동으로 연결(매핑)

ex) node - Sequelize
    spring - JPA

1. Sequelize 설치
- npm install -g sequelize
- npm install -g sequelize -cli

2. sequelize 초기화
- npx sequelize init
config : DB 연결에 필요한 정보
migrations: DB 변동 기록 담은 파일 보관 (이전 설정으로 되돌릴 때)
models : 테이블에 대한 객체
seeders : 테이블에 자동으로 기본 데이터 넣고 싶을 때 

3. config.js 수정: dev

4. model 작성: models/User 

5. model/index 수정 : db - User Object 연결

6. app.js - index 연결
728x90
LIST