#1 Firebase의 기본 설정
1. Firebase 프로젝트 생성
- firebase 홈페이지 접속 후 '프로젝트 추가' 버튼 클릭
- 프로젝트 이름 선정 후 모두 '다음' 버튼 눌러서 생성
2. Firebase Realtime Database 생성
- 프로젝트 대시보드 왼쪽의 'Build - Realtime Database' > 'Database 만들기' 클릭
- 보안 규칙 설정(상단의 '규칙' 탭) > read와 write를 true로 설정

3. Database URL 확인
- 상단의 '데이터' 탭에서 url 주소 확인 가능

4. Firebase Secret Key(비번) 가져오기
- 왼쪽의 프로젝트 개요 (톱니바퀴) → 프로젝트 설정
- 서비스계정 탭 → 데이터베이스 비밀번호 확인 가능

#2 Firebase와 연동을 위한 Visual Programming 초기 설정
1. VS에서 NuGet Package 추가(FireSharp)
2. VS에서 using문 추가(FireSharp 라이브러리 안의 기능)
using FireSharp.Interfaces;
using FireSharp.Config;
using FireSharp.Response;
- Interfaces: 인터페이스 파일 사용
- Config: 설정 관련 파일 사용
- Response: 응답 관련 파일 사용
3. Firebase DB에 연결
[1] Firebase 비밀번호와 주소 세팅(config)
public partial class Form1 : Form
{
IFirebaseConfig config = new FirebaseConfig
{
AuthSecret = "oLPxEiYHLQUtZpgXuvCLYl6PZTX0WZnOyhYDgTZ8", //firebase 비번
BasePath = "https://vp01-10b6c-default-rtdb.firebaseio.com/" //firebase 주소
};
- IFirebaseConfig: 인터페이스(규릭칙, 설계도) (형식을 지키기로 약속해놓은 것) = 설계도
- FirebaseConfig: 구체적인 내용(데이터) - 진짜 데이터를 채워 넣는 것 = 실제로 만드는 것
- config 라는 변수에 Firebase 서버 정보 저장 ▶ Firebase 설정(config) 파일 생성
- AuthSecret: 비밀 번호
- BasePath: Firebase Realtime Database 주소(URL)
[2] Firebase에 연결(성공 시 메시지박스 띄우기)
IFirebaseClient client; //<1>
private void Form1_Load(object sender, EventArgs e)
{
client = new FireSharp.FirebaseClient(config); //<2>
if(client != null) //<3>
{
MessageBox.Show("Connection 성공!");
}
}
- <1> IFirebaseClient Client: Firebase랑 대화할 객체 만듦
- <2>: 설정(config)을 이용해 Firebase랑 연결하는 client 실제 생성(서버에 연결 시도)
- <3>: 연결이 성공할 시(client != null) 메시지박스 띄워 사용자에게 알리기
★비유
- IFirebaseConfig = 계약서 양식 (형식만 있음)
- FirebaseConfig = 계약서 작성 (진짜 비번, 주소 적음)
- IFirebaseClient = 전화기 대리점 등록 (아직 통화 안 함)
- FirebaseClient(config) = 전화 연결 (이제 Firebase랑 말할 수 있음)
★ Point
| using FireSharp.Interfaces | 인터페이스(설계도) 가져옴 |
| using FireSharp.Config | 설정(config) 관련 가져옴 |
| using FireSharp.Response | 응답(response) 관련 가져옴 |
| IFirebaseConfig | 설정의 설계도 (틀) |
| FirebaseConfig | 실제 설정 내용 (비번, 주소 적음) |
| IFirebaseClient | Firebase랑 통신하는 클라이언트 설계도 |
| FirebaseClient | 설정을 가지고 실제 통신 연결 시도 |
#3 데이터 추가(Insert) 버튼
1. 프로젝트에 Data 클래스 추가(기본 설정)
internal class Data
{
//속성 : get; set; 으로 값을 가져오고 세팅도 가능
public string Id { get; set; }
public string SId { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
}
- 데이터를 Firebase로 한 번에 묶어서 송/수신 하기 위해 클래스 생성
- Get, Set 메소드를 별도로 만들 필요 없이 '속성'으로 간략하게 작성해 이용 가능하다
속성 ▶ public 자료형 변수명 {get; set;}
2. 비동기 데이터 저장
private async void btninsert_Click(object sender, EventArgs e)
{
//여러개를 한 꺼번에 초기화 → {}; 사용
Data data = new Data
{
Id = txtid.Text,
SId = txtsid.Text,
Name = txtname.Text,
Phone = txtphone.Text
};
SetResponse response = await client.SetAsync("Phonebook/" + txtid.Text, data);
Data result = response.ResultAs<Data>();
MessageBox.Show(String.Format("Data Inserted : Id = {0}, Name = {1}", result.Id, result.Name));
}
- Data 클래스의 4개의 속성(Id, SId, Name, Phone)에 각각 txt의 입력된 값을 넣어준다
- client.SetAsync("Phonebook/"+txtid.Text, data): client 객체 통해 "Phonebook/"+txtid.Text 주소에 data를 저장하라
(비동기: Async) - await: 저장이 끝날때까지 기다렸다가 넘어감을 의미 + async 처리 됨
▷ 비동기 처리 하는 이유: Firebase 서버랑 통신하는데 시간이 걸릴 수 있기 때문(다른 작업 막지 않게) - SetResponse: Firebase에 데이터를 저장할 때 사용하는 응답 객체("주소"에 값을 저장하고 응답을 반환함)
▶ txtid.Text에 입력된 값을 이용해 'Phonebook/아이디' 경로에 data 객체를 서버에 저장하고,
서버로부터 저장 완료 응답을 받아온다.
- response.ResultAs<Data>(): 응답 내용(response)을 Data란 클래스로 변환
(서버에서 받은 데이터를 Data 클래스 모양으로 변환해 꺼내오는 과정) - 변환된 Data 타입의 result 라는 변수에 저장
→ result.Id / result.SId의 형태로 꺼내서 쓸 수 있게 됨
▶ 저장이 완료된 후, 서버가 응답해준 데이터를 다시 Data 형태로 변환해(reuslt) 가져온다
(▽) Firebase 저장된 예시


#4 데이터 검색(Select) 버튼
1. 비동기적으로 데이터 가져오기(검색)
- FirebaseResponse: Firebase에서 데이터를 가져올 때 사용하는 응답 객체("주소"에 있는 값을 받아옴)
- client.GetAsync("주소"): 주소에 있는 서버 데이터를 Firebase에서 비동기적으로 가져온다
▶ client.GetAsync("Phonebook/"+txtid.Text) 이러한 구조는 ID(=키)로만 직접 접근 가능함(정확한 경로 필요) - response.ResultAs<Data>: 응답 내용(response)을 Data란 클래스로 변환
- if문: 없는 데이터를 조회할 시 Data not Found 메시지 박스가 뜨도록 실행(obj가 null일 경우)
#5 데이터 수정(Update) 버튼
1. 비동기적으로 데이터 수정하기
private async void btnUpdate_Click(object sender, EventArgs e)
{
Data data = new Data()
{
Id = txtid.Text,
SId = txtsid.Text,
Name = txtname.Text,
Phone = txtphone.Text
};
FirebaseResponse response = await client.UpdateAsync("Phonebook/"+txtid.Text, data);
Data result = response.ResultAs<Data>();
MessageBox.Show("Data updated successfully: ID = " + result.Id);
}
- FirebaseResponse: Firebase에서 데이터를 가져올 때 사용하는 응답 객체("주소"에 있는 값을 받아옴)
- client.UpdateAsync("주소", data): 주소의 서버 데이터를 비동기적으로 수정할 때 사용한다
▷ 주소의 일부 필드만 data 값으로 수정 ((여기서 data 객체는 기존X, 새롭게 입력된 객체))
#6 데이터 삭제(Delete/All Delete) 버튼
1. 비동기적으로 데이터 수정하기
private async void btnDelete_Click(object sender, EventArgs e)
{
FirebaseResponse response = await client.DeleteAsync("Phonebook/" + txtid.Text);
MessageBox.Show("Deleted ID = "+txtid.Text);
txtid.Text = "";
txtsid.Text = "";
txtname.Text = "";
txtphone.Text = "";
}
private async void btnDeleteAll_Click(object sender, EventArgs e)
{
FirebaseResponse response = await client.DeleteAsync("Phonebook");
txtid.Text = "";
txtsid.Text = "";
txtname.Text = "";
txtphone.Text = "";
MessageBox.Show("All Data at /Phonebook node deleted!");
}
- FirebaseResponse: Firebase에서 데이터를 가져올 때 사용하는 응답 객체("주소"에 있는 값을 받아옴)
- client.DeleteAsync("주소"): 주소의 서버 데이터를 비동기적으로 삭제할 때 사용한다
▶ ("Phonebook"+00) → 해당 주소의 항목만 삭제 / ("Phonebook") → 목록 자체를 삭제
★ Point
| SetAsync(“주소”,data) | 비동기적으로 주소에 있는 서버 데이터 저장 |
| GetAsync(“주소”) | 비동기적으로 주소에 있는 서버 데이터 가져옴 |
| UpdateAsync(“주소”, data): |
비동기적으로 주소에 있는 일부 필드를 data 값으로 수정
|
| DeleteAsync(“주소“) | 비동기적으로 주소에 있는 서버 데이터를 삭제 * “주소” → “목록명/…” : 해당 데이터만 삭제 | “목록”: 목록 자체를 삭제 |
| Await – Async | 비동기 처리 |
| SetResponse |
Firebase에 데이터를 저장할 때 사용하는 응답 객체("주소"에 값을 저장하고 응답을 반환함) <SetAsync와 함께 쓰임> |
| FirebaseResponse |
Firebase에서 데이터를 가져올 때 사용하는 응답 객체("주소"에 있는 값을 받아옴) <GetAsync, UpdateAsync, DeleteAsync와 함께 쓰임> |
| ResultAs<Data>() |
응답내용(response)을 Data란 클래스로 변환 |
#9 Counter 추가
firebase에 자동으로 증가하는 카운터 생성하기
1. Count 클래스 추가
- Firebase는 전부 객체로 저장하기 때문에 class 생성
internal class Counter
{
public int cnt { get; set; }
}
2. 데이터 새로 추가할 때, cnt 증가해서 추가 <<추가 버튼 수정>>
private async void btninsert_Click(object sender, EventArgs e)
{
//Firebase에서 cnt 값 가져오기
FirebaseResponse resp = await client.GetAsync("Counter/");
Counter c = resp.ResultAs<Counter>();
//여러개를 한 꺼번에 초기화 → {}; 사용
Data data = new Data
{
Id = (c.cnt+1).ToString(),
SId = txtsid.Text,
Name = txtname.Text,
Phone = txtphone.Text
};
SetResponse response = await client.SetAsync("Phonebook/" + data.Id, data);
Data result = response.ResultAs<Data>();
MessageBox.Show("Data Inserted : Id = ", result.Id);
var obj = new Counter { cnt = c.cnt + 1 };
SetResponse response1 = await client.SetAsync("Counter/", obj);
dt.Rows.Clear();
export();
}
- FirebaseResponse: Firebase에서 데이터를 가져올 때 사용하는 응답 객체("주소"에 있는 값을 받아옴)
- SetResponse: Firebase에 데이터를 저장할 때 사용하는 응답 객체("주소"에 값을 저장하고 응답을 반환함)
- response.ResultAs<Counter>(): 응답 내용(response)을 Couter란 클래스로 변환
(서버에서 받은 데이터를 Counter 클래스 모양으로 변환해 꺼내오는 과정) - var: 자동 형식 추론 키워드
(변수 선언 시 오른쪽 값을 보고 자동으로 자료형을 추론함.) - dt.Rows.Cler(): 데이터 초기화
- export(): Firebase에 데이터 새로 불러오기
▶ dt에 관한 내용은 아래 DataGridView를 추가하는 과정에서 생성 됨
#10 DataGridView 추가
public partial class Form1 : Form
{
DataTable dt = new DataTable();
...//firebase주소 및 비번 설정
private void Form1_Load(object sender, EventArgs e)
{
client = new FireSharp.FirebaseClient(config);
if(client != null)
{
MessageBox.Show("Connection 성공!");
}
dt.Columns.Add("Id");
dt.Columns.Add("학번");
dt.Columns.Add("이름");
dt.Columns.Add("전화번호");
dataGridView1.DataSource = dt;
dt.Rows.Clear();
export();
}
- DataTable dt = new DataTable() : 데이터를 저장하고 표시하는 표(DataTable) 객체 생성
▶ dt는 dataGridview1에 연결되어 데이터를 보여주는 용도로 사용될 예정 - client: Firebase에 연결하는 객체 생성
- dt.Colums.Add("문자"): DataTable에 Column(열) 추가 (테이블 구조 정의)
- dataGridView1.DataSource = dt: DataGridView1에 dt 적용
- dt.Rows.clear(): 데이터 초기화
- export(): Firebase에 데이터 새로 불러오기
▶ export()함수는 View All 버튼의 구현 part에서 생성 되는 함수
#11 ViewAll 버튼 구현
private void btnViewAll_Click(object sender, EventArgs e)
{
dt.Rows.Clear();
export();
}
- dt.Rows.clear(): 데이터 초기화
- export(): Firebase에 데이터 새로 불러오는 함수
★ export 메서드 생성
private async void export()
{
int i = 0;
FirebaseResponse response = await client.GetAsync("Counter/");
Counter obj = response.ResultAs<Counter>();
int cnt = obj.cnt;
while(i != cnt)
{
i++;
FirebaseResponse resp = await client.GetAsync("Phonebook/" + i);
Data d = resp.ResultAs<Data>();
if (d != null)
{
DataRow row = dt.NewRow();
row["Id"] = d.Id;
row["학번"] = d.SId;
row["이름"] = d.Name;
row["전화번호"] = d.Phone;
dt.Rows.Add(row);
}
}
while문을 통해 cnt:0 ~ n까지 DataGridView에 출력
- DataRow row = dt.NewRow(): DataRable에 새로운빈 행 생성
▶ DataRow라는 클래스의 row 객체 생성한 것, dt는 DataTable의 객체로 NewRow() 메서드를 통해 테이블 구조에 맞는 DataRow 객체(한 행)을 만들어준다. - dt.Rows.Add(객체): row(한 행의 data)를 dt(DataTable)에 넣음
#11 모두 삭제 버튼 수정
- counter가 생김에 따른, counter 초기화 + Phonebook 초기화
private async void btnDeleteAll_Click(object sender, EventArgs e)
{
DialogResult answer = MessageBox.Show("저장된 모든 데이터가 삭제됩니다. 계속하시겠습니까?",
"Warning",MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (answer == DialogResult.No) return;
//count도 0으로 초기화
var obj = new Counter { cnt = 0 };
SetResponse response1 = await client.SetAsync("Counter/", obj);
//phoebook 모두 삭제
FirebaseResponse response = await client.DeleteAsync("Phonebook");
MessageBox.Show("All Data at /Phonebook node deleted!");
dt.Rows.Clear();
export();
}
#12 dataGridView1 클릭 이벤트
dataGridview를 클릭할 때 관련 내용이 textbox에 자동으로 표기될 수 있도록 event 설정
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
DataGridView dgv = (DataGridView)sender;
txtid.Text = dgv.Rows[e.RowIndex].Cells[0].Value.ToString();
txtsid.Text = dgv.Rows[e.RowIndex].Cells[1].Value.ToString();
txtname.Text = dgv.Rows[e.RowIndex].Cells[2].Value.ToString();
txtphone.Text = dgv.Rows[e.RowIndex].Cells[3].Value.ToString();
}
- sender: 이벤트가 발생한 객체로, 이벤트가 호출된 컨트롤or객체가 무엇인지 알려줌
- e.RowIndex: 클릭한 행(row)의 인덱스 번호를 의미
- DataGridView dgv = (DataGridView)sender: 이벤트가 발생한 컨트롤을 DataGridView 형식으로 변환
- dgv.Rows[e.RowIndex].Cells[0].Value.ToString(): 클릭한 행의 각 셀의 값을 읽어와서 textbox에 입력
<전체 code>
using FireSharp.Interfaces;
using FireSharp.Config;
using FireSharp.Response;
using System.Runtime.InteropServices;
namespace _031_PhoneBook
{
public partial class Form1 : Form
{
DataTable dt = new DataTable();
IFirebaseConfig config = new FirebaseConfig
{
AuthSecret = "oLPxEiYHLQUtZpgXuvCLYl6PZTX0WZnOyhYDgTZ8", //firebase 비번
BasePath = "https://vp01-10b6c-default-rtdb.firebaseio.com/" //firebase 주소
};
IFirebaseClient client; //C#에서 firebase의 database를 대신하는 이름
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
client = new FireSharp.FirebaseClient(config);
if(client != null)
{
MessageBox.Show("Connection 성공!");
}
dt.Columns.Add("Id");
dt.Columns.Add("학번");
dt.Columns.Add("이름");
dt.Columns.Add("전화번호");
dataGridView1.DataSource = dt;
dt.Rows.Clear();
export();
}
//추가 버튼
private async void btninsert_Click(object sender, EventArgs e)
{
//Firebase에서 cnt 값 가져오기
FirebaseResponse resp = await client.GetAsync("Counter/");
Counter c = resp.ResultAs<Counter>();
//여러개를 한 꺼번에 초기화 → {}; 사용
Data data = new Data
{
Id = (c.cnt+1).ToString(),
SId = txtsid.Text,
Name = txtname.Text,
Phone = txtphone.Text
};
SetResponse response = await client.SetAsync("Phonebook/" + data.Id, data);
Data result = response.ResultAs<Data>();
MessageBox.Show("Data Inserted : Id = ", result.Id);
var obj = new Counter { cnt = c.cnt + 1 };
SetResponse response1 = await client.SetAsync("Counter/", obj);
dt.Rows.Clear();
export();
}
//clear 버튼
private void btnClear_Click(object sender, EventArgs e)
{
txtid.Text = "";
txtsid.Text = "";
txtname.Text = "";
txtphone.Text = "";
}
//검색버튼
private async void btnSearch_Click(object sender, EventArgs e)
{
FirebaseResponse response = await
client.GetAsync("Phonebook/" + txtid.Text);
Data obj = response.ResultAs<Data>();
if (obj != null)
{
txtid.Text = obj.Id;
txtsid.Text = obj.SId;
txtname.Text = obj.Name;
txtphone.Text = obj.Phone;
MessageBox.Show("Data reteribed successfully!");
}
else MessageBox.Show("Data not Found");
}
private async void btnUpdate_Click(object sender, EventArgs e)
{
Data data = new Data()
{
Id = txtid.Text,
SId = txtsid.Text,
Name = txtname.Text,
Phone = txtphone.Text
};
FirebaseResponse response = await
client.UpdateAsync("Phonebook/"+txtid.Text, data);
Data result = response.ResultAs<Data>();
MessageBox.Show("Data updated successfully: ID = " + result.Id);
dt.Rows.Clear();
export();
}
//일부삭제
private async void btnDelete_Click(object sender, EventArgs e)
{
FirebaseResponse response = await
client.DeleteAsync("Phonebook/" + txtid.Text);
MessageBox.Show("Deleted ID = "+txtid.Text);
dt.Rows.Clear();
export();
}
private async void btnDeleteAll_Click(object sender, EventArgs e)
{
DialogResult answer = MessageBox.Show("저장된 모든 데이터가 삭제됩니다. 계속하시겠습니까?",
"Warning",MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (answer == DialogResult.No) return;
//count도 0으로 초기화
var obj = new Counter { cnt = 0 };
SetResponse response1 = await client.SetAsync("Counter/", obj);
//phoebook 모두 삭제
FirebaseResponse response = await client.DeleteAsync("Phonebook");
MessageBox.Show("All Data at /Phonebook node deleted!");
dt.Rows.Clear();
export();
}
private void btnExit_Click(object sender, EventArgs e)
{
this.Close();
}
private void btnViewAll_Click(object sender, EventArgs e)
{
dt.Rows.Clear();
export();
}
private async void export()
{
int i = 0;
FirebaseResponse response = await client.GetAsync("Counter/");
Counter obj = response.ResultAs<Counter>();
int cnt = obj.cnt;
while(i != cnt)
{
i++;
FirebaseResponse resp = await client.GetAsync("Phonebook/" + i);
Data d = resp.ResultAs<Data>();
if (d != null)
{
DataRow row = dt.NewRow();
row["Id"] = d.Id;
row["학번"] = d.SId;
row["이름"] = d.Name;
row["전화번호"] = d.Phone;
dt.Rows.Add(row);
}
}
}
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
DataGridView dgv = (DataGridView)sender;
txtid.Text = dgv.Rows[e.RowIndex].Cells[0].Value.ToString();
txtsid.Text = dgv.Rows[e.RowIndex].Cells[1].Value.ToString();
txtname.Text = dgv.Rows[e.RowIndex].Cells[2].Value.ToString();
txtphone.Text = dgv.Rows[e.RowIndex].Cells[3].Value.ToString();
}
}
}
'Visual Programming' 카테고리의 다른 글
| WPF (0) | 2025.05.12 |
|---|---|
| Visual Programming #4 (0) | 2025.03.17 |
| Visual Programming #3-2 (0) | 2025.03.16 |
| Visual Programming #3-1 (0) | 2025.03.13 |
| Visual Programming #1-#2 (0) | 2025.03.11 |