<< Back
blog 프로그래밍

:: Google Firebase 기반 웹 애플리케이션 개발




Firebase

Firebase 는 구글에서 만든 클라우드 기반 데이터베이스 서비스로 개발자들이 손쉽게 자신의 어플리케이션을 데이터베이스와 연동 할 수 있는 인프라를 제공해 주고 있다. 이 외에도 애널리틱스, 인증, 저장소, 호스팅 등 다양한 서비스들이 있으며 추가 서비스들이 베타로 개발되고 있음. 보다 자세한 사항은 https://firebase.google.com 을 참고.

Firebase 특징

일반적으로 클라우드 서비스라고 하면 아마존의 AWS 나 마이크로소프트의 Azure 등을 떠올릴 수 있다. 그러나 이들 클라우드 서비스를 통해 데이터베이스 서비스를 이용 하려면 먼저 윈도우나 리눅스 OS 기반으로 클라우드 서버 인스턴스를 생성해야 한다.

그리고 MySQL 이나 Maria DB 등을 설치하고 Tomcat + Java + JAX-RS 혹은 Node.js 기반으로 Rest API 를 구현한 다음 개발 하기를 원하는 안드로이드나 웹 기반의 프로그램에 Rest API 호출을 위한 라이브러리등을 이용해 프로그램을 구현해야 한다.

직접 자신의 서버를 구축하지 않아도 된다는 점을 빼면 단순히 모바일 이나 웹 개발에 데이터베이스가 필요한 개발자의 경우 부가적으로 해야 할 일이 너무 많다는 문제가 있다.

Firebase 의 주요 특징은 다음과 같다.

Firebase 시작하기

로그인 및 프로젝트 생성

데이터베이스 생성

Firebase REST API

- 전체데이터: https://mytwitter-a466c.firebaseio.com/twitter.json
- 특정 키값의 데이터: https://mytwitter-a466c.firebaseio.com/twitter/-LTAiugbwoOobawJMbm2.json
- 특정 키값의 특정 필드 데이터: https://mytwitter-a466c.firebaseio.com/twitter/-LTAiugbwoOobawJMbm2/msg.json

예제

예제는 twitter 와 비슷하게 간단한 메시지를 공유할 수 있는 웹 프로그램으로 구성되어 있다. 별도의 아이디없이 입력한 아이디로 로그인이 되며 로그인 후에는 등록된 메시지를 보고 자신의 메시지를 남길 수 있는 구조임.

build.gradle

Firebase 를 위해 특별하게 추가할 라이브러리는 없으며 REST API를 사용하기 위해 unirest 만 추가.

	....
	compile group: 'com.mashape.unirest', name: 'unirest-java', version: '1.4.9' 

TwitterController

기본 컨트롤러는 서블릿으로 구현 한다. 특이 사항은 없으며 action 패러미터를 통해 login, tweet 두가지 요청을 처리하도록 되어 있음.

package javaweb.twitter;
import... 생략

@WebServlet("/twitter")
public class TwitterController extends HttpServlet {
	private static final long serialVersionUID = 1L;
    HttpServletRequest request;
    HttpServletResponse response;
    HttpSession session;
    ServletContext application;
    
	String view;
	TwitterService service;
	
    private void processRequest(HttpServletRequest request, HttpServletResponse response) 
    		throws ServletException, IOException {
    	request.setCharacterEncoding("utf-8");
    	
    	this.request = request;
    	this.response = response;
    	session = request.getSession();
    	application = request.getServletContext();
    	
    	// 데이터 서비스 선택 지정.
    	service = new FirebaseService();
    	    	
    	String action = request.getParameter("action");
    	if(action == null) {
    		session.invalidate();
    		response.sendRedirect("/javaweb/twitter/twitter_login.jsp");
    		return;
    	}
        	switch (action) {
	        	case "login":	    		
	        		login();
	        		break;
	        	case "tweet":
	        		tweet();
        	}        	
          RequestDispatcher dispatcher = request.getRequestDispatcher(view);
          dispatcher.forward(request, response);
    }

    public void login() {
    	// HTML 폼에서 username으로 전달된 값을 가지고 옴 
    	String username = request.getParameter("username");    	
    	// username이 null 이 아닌 경우 세션에 값을 저장
    	if(username != null) {
    		session.setAttribute("user",username);
    	}
    	list();
    }

    public void list() {	
    	List<String> tweetlist = new ArrayList<String>();
    	tweetlist = service.getList();
    	request.setAttribute("tweetlist", tweetlist);
    	view = "/twitter/tweet_list.jsp";
    }
    
    public void tweet() throws IOException {
    	// HTML 폼에서 전달된 msg 값을 가지고 옴
    	String msg = request.getParameter("msg");
    	
    	// 세션에 저장된 로그인 사용자 이름을 가지고 옴
    	String username = (String)session.getAttribute("user");
    	
    	// 사용자 이름, 메시지, 날짜 정보를 포함하여 ArrayList에 추가
    	LocalDateTime date = LocalDateTime.now();
    	DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    	msg = username+" :: "+msg+" , "+ date.format(f);
    	
		service.write(msg);
		
    	// 톰캣 콘솔을 통한 로깅
    	application.log(msg+"추가됨");
    	
    	// 목록 화면 데이터 로딩
    	list();
    }
    		
	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
		processRequest(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
		processRequest(request, response);
	}
}

FirebaseService

Twitter Service Interface

package javaweb.twitter;

import java.util.List;

public interface TwitterService {

	void write(String msg);

	List<String> getList();

}

FirebaseService

package javaweb.twitter;
import.. 생략

public class FirebaseService implements TwitterService {
	Logger log = Logger.getGlobal();
	String baseurl="https://mytwitter-a466c.firebaseio.com/twitter.json";
	
	@Override
	public void write(String msg) {
		JSONObject bodyMsg = new JSONObject();
		bodyMsg.put("msg", msg);
		
		HttpResponse<String> jsonResponse;
		try {
			jsonResponse = Unirest.post(baseurl)
			        .header("Accept", "application/json")
			        .header("Content-Type", "application/json")
			        .body(bodyMsg)
					.asString();
			log.info(jsonResponse.getBody().toString());
		} catch (UnirestException e) {
			e.printStackTrace();
		}
	}
	
@Override
	public List<String> getList() {
		List<String> tweetlist = new ArrayList<String>();
		HttpResponse<JsonNode> retmsg;
		try {
			retmsg = Unirest.get(baseurl).asJson();
			JSONObject msglist = retmsg.getBody().getObject();
			Iterator<String> keys = msglist.keys();
			while(keys.hasNext()) {
				JSONObject msg = (JSONObject) msglist.get(keys.next());
				tweetlist.add(msg.getString("msg"));
			}
		} catch (UnirestException e) {
			e.printStackTrace();
		}
		return tweetlist;
	}
}

JSP 구현

예제 프로그램은 로그인 화면인 twitter_login.jsp 와 목록인 tweet_list.jsp 로 구성 됨.

inc_header.html

bootstrap 등 공통으로 필요한 외부 css 나 js 를 포함하기 위한 파일. 여기서는 bootstrap.min.css 만 필요하지만 bootstrap 의 모든 기능을 사용하려면 아래의 js 를 포함해야 한다.

<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">

<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<!-- Popper JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>

<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>

twitter_login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>    
<html>
<head>
<%@ include file="inc_header.html" %>
<title>twitter_login.jsp</title>
</head>
<body>
<div class="container mx-auto m-5 p-5  w-50 shadow bg-info">
	<H2>Twitter::Login</H2>
	<form name="form1" method="post" action="/javaweb/twitter">
		<input type="hidden" name="action" value="login" />
		<div class="input-group">
		<input class="form-control" type="text" name="username" placeholder="login id"/>
		<input class="btn btn-warning" type="submit" value="Login"/>
		</div>
	</form>
</div>
</body>
</html>

tweet_list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<html>
<head>
<%@ include file="inc_header.html" %>
<title>Tweet List</title>
</head>
<body>
<div class="container shadow mx-auto mt-5 p-5 w-60">
<H3>My Simple Twitter!!</H3>
<HR>
<form action="/javaweb/twitter" method="post">
<input type="hidden" name="action" value="tweet">

	<div class="input-group w-75">
	<button type="button" class="btn btn-outline-success">@${user}</button>&nbsp;
	<input class="form-control" type="text" name="msg">
	<input class="btn btn-warning" type="submit" value="Tweet">&nbsp;
	<a class="btn btn-secondary" href="/javaweb/twitter">Sign out</a>
	</div>
</form>
<HR>
<div align="left">
<ul class="list-group">
<c:forEach var="msg" items="${tweetlist}">
	<li class="list-group-item list-group-item-action">${msg}</li>
</c:forEach>

</ul>
</div>
</div>
</body>
</html>

실행결과

참고 자료

<< Back