Git Flow 란?


  • 나처럼 Github에서 push, merge, pull 정도만 해본 초급개발자라면 이 Git flow라는 말을 한 번쯤은 들어보았을 수도 있다. (한 번도 들어보지 못했다면 이번 기회에 알아두는 것이 좋겠다)
  • 실무에서도 역시나 Git을 사용하는곳이 많고 각 회사별로 깃을 사용하는 방법도 다양할 것이라 생각한다. 그중에서도 규칙(?)처럼 "우리는 Git을 이러한 규칙으로 사용한다"는 전략이 존재한다.
  • 그 전략중 Git-flowGitHub-flow 그리고 *Gitlab-flow *세 가지 전략을 설명하려고 한다.

우선 이러한 전략(규칙)이 왜 필요한지에 대한 이야기부터 해보자.

Git Branch 전략이란?

  • 우리가 일반적으로 프로그램 혹은 어플리케이션을 개발할 때 혼자서 모든 것을 개발하지는 않는다. 그러면 공용저장소를 사용하게 될 것이며 이 공용저장소의 소스코드파일을 구현이 끝날 때마다 업데이트를 해줄 것이다.
  • 이러한 협업은 대부분은 Git을 사용해서 관리할 것이고 저장소는 GitHub, Gitlab 혹은 일반 서버컴퓨터의 Git만을 설치해서 활용하는 등의 여러 파일관리방법이 존재할 것이다.
  • 이때 이 Git을 여러 개 발자가 보다 잘 활용하기 위한 전략(규칙)으로써 생겨난 것이라 생각하면 좋겠다.

결론적으로 1개의 저장소에서 소스코드를 효율적으로 관리하고 협업을 수월하게 할 수 있도록 도와주는 규칙이다.

이제 각각 전략이 어떠한 특징과 차이점이 있는지 알아봅시다.

1. Github Flow

github flow는 git flow보다는 간결하게 활용할 수 있도록 등장한 전략입니다.

Screen Shot 2014-03-08 at 23.07.36img

[이미지 출처] (https://lucamezzalira.com/2014/03/10/git-flow-vs-github-flow/)

위 그림과 같이 main 브렌치를 항상 배포가능한 최신상태로 유지하는 방법이며 브렌치를 생성할 경우 브렌치이름을 명확하게 정해야 합니다. 특별하게 feature 브렌치나 develop브렌치가 존재하지 않기 때문에 그때그때마다 상황에 맞게 특정 브렌치를 생성 -> 작업 -> 반영 -> 삭제 순으로 흘러가야 합니다. 또한 반영할 때 Pull Request를 생성하여 팀원들과의 코드리뷰 후 반영해야 합니다.

마스터브렌치는 라이브환경의 서버와 자동으로 동기화되어 있고 CI/CD가 자동화되어있어야 합니다. 수동으로 매번 main 브렌치를 반영하기에는 비효율적입니다.

이처럼 Github flow는 소규모 팀에서 선택하기 좋은 전략입니다.

2. Git Flow

git flow

[이미지 출처] (https://lucamezzalira.com/2014/03/10/git-flow-vs-github-flow/)

git flow전략은 위 그림과 같이 5개의 브렌치로 master, hofixes, release, develop, feature 브렌치가 존재합니다.

브렌치의 순서는 feature -> develop -> release -> master순으로 가게 되며 master브렌치의 운영 중 이슈가 발생할 경우 hotfixes브렌치로 이동합니다.

  • master : 라이브(운영) 서버에 제품으로 출시되는 브렌치
  • develop : 다음 출시 버전을 대비하여 개발 중인 브렌치
  • feature : 추가기능 개발 브렌치
  • release : 다음 버전 출시를 준비하는 브랜치 주로 QA, Test과정이 진행된다
  • hotfix : master브렌치에서 발생한 이슈를 수정하는 브렌치

브렌치는 위와 같이 목적에 맞게 사용되어야 하는 방식으로 이루어져 있습니다.

git flow의 흐름으로는 가장 핵심이 되는 master, develop 두 개를 운용해야 합니다. 나머지 feature, release, hotfix 브렌치는 사용하지 않는다면 지우더라도 문제가 되지 않기 때문에 프로젝트를 어떤 방식으로 활용하느냐에 따라 달라진다.

대부분의 작업은 develop에서 취합한다 생각하면 되며 테스트를 통해 정말 확실하게 변동사항이 없을 때 master와 병합한다.

3. Gitlab Flow

GitLab Flow Model - environment branch

[이미지 출처] (https://ujuc.github.io/2015/12/16/git-flow-github-flow-gitlab-flow/)

gitlab flow는 github flow에서 main 브렌치를 병합 후 바로 배포할 수 있는 상태로 만들어야 하지만 이를 gitlab flow에서는 바로배포하지 못하는 경우를 고려하여 production 브렌치라는 것이 존재하는 상황이고 이 production 브렌치역시나 master브렌치 사이의 preproduction 브렌치를 두어 브렌치반영에 시간을 두는 방식이다. 그림으로만 보게 되면 github < gitlab < git flow 순으로 복잡한 구조를 나타내는 것 같다

여러 Git Flow방법들 중 각 상황과 개발 목표에 맞춰 적절한 전략을 활용하는 것이 중요할 것이라 생각하며 나와 같은 초급개발자는 전략보다는 오히려 커밋, 푸쉬, 풀, 풀리퀘, 리베이스 등등.. 기본적인 기능을 더 명확하게 잘 사용할 수 있는 것이 우선이라 생각한다.

오늘은 여러 Git Flow 전략에 대하여 알아보았다.

Reference

  1. https://inpa.tistory.com/entry/GIT-%E2%9A%A1%EF%B8%8F-github-flow-git-flow-%F0%9F%93%88-%EB%B8%8C%EB%9E%9C%EC%B9%98-%EC%A0%84%EB%9E%B5
  2. https://brownbears.tistory.com/603
  3. https://docs.gitlab.com/ee/topics/gitlab_flow.html
  4. https://lucamezzalira.com/2014/03/10/git-flow-vs-github-flow/
  5. https://ujuc.github.io/2015/12/16/git-flow-github-flow-gitlab-flow/

MSA란 무엇일까?


MSAMicroService Architecture의 줄임말이다 즉 아주 작은 마이크로 단위의 서비스로 구성된 프레임워크라고 볼 수 있다.

기존에는 하나의 프로젝트에 모든 기능들을 구현해두었다면 여러 개의 작은 프로젝트를 조합하여 하나이 큰 프로젝트와 같이 구성하는 것이다.

MSA의 등장 배경

  • MSA는 언제부터 사용된 개념일까?
  • Monolithic Architecture라는 개념이 있다 쉽게말해 MSA가 등장하기 전 모든 서비스들은 Monolithic Architecture로 구성되어 제공했고 위 설명과 같이 모든 서비스들이 하나의 프로젝트에 통합되어있는 형태를 뜻한다.
  • 당연히 하나의 프로젝트에 모든 서비스가 포함되어있을 경우에 문제점도 존재하며 다음과 같다
    1. 프로젝트가 커지면 커질수록, 영향도 파악 및 전체 시스템구조 파악에 어려움이 있다.
    2. 각 서비스들을 부분적으로 scale-out 하기 힘들어진다.
    3. 부분의 오류가 서비스 전체의 오류로 이어지는 경우가 발생할 수 있다.
    4. 프로젝트 빌드 및 테스트 시간이 길어지고 배포파일 자체의 절대적인 시간이 늘어난다(당연히 용량이 커지기때문이라 생각한다)

이 두가지 Microservices Architecture와 Monolithic Architecture를 그림으로 보자면 아래와 같다.

Figure 1: Architecture differences between traditional monolithic applications and microservices

[이미지출처] (https://www.suse.com/c/rancher_blog/microservices-vs-monolithic-architectures/)

위 단점들을 보완, 해결 하고자 MicroServices Architecture를 사용하기 시작했고 장단점을 정리하자면 다음과 같다.

장점

  1. 각 서비스가 모듈화되어있기 때문에 모듈끼리 RPC 또는 message-driven API 등을 이용하여 통신한다.
  2. 각 서비스에따라 개발하기 때문에 유지보수가 쉽고 팀단위로 적절한 수준에서 기술스택을 선택할 수 있다.
  3. java Spring 기반으로 MSA를 적용하더라도 node.js 모듈과 연동함에 무리가 없다.
  4. 각 서비스별로 독립적인 배포가 가능하며 각서비스별 단위테스트 역시나 가능해진다.

단점

  1. MSA구조는 모놀리식에 비해 상대적으로 복잡하다.
  2. 서비스가 모두 분산되어있고 서비스별 통신이 필요하기에 개발과정에서 내부시스템의 통신을 어떤 방식으로 사용할지 표준을 정의해야 한다.
  3. 서버부하에 따라 transaction을 유지할지 결정하고 구현해야 한다.
  4. 단위테스트에는 장점이 있으나 통합테스트과정이 매우 어렵다.
  5. 또한 운영환경에 배포하는 것 또한 쉽지 않다.( 만들어두었던 모든 서비스들을 묶어서 배포해야 하고 유지보수측면에서 각서비스업데이트마다 배포파일을 교체해주어야 하는 작업이 필요하다 또한 업데이트순간 모든 서비스들이 정상작동하는지를 한번 더 확인해야 하기 때문에)

장점과 단점 모두 실무에서는 도메인에 맞게 활용할 수도 활용하지 않을 수도 있다고 생각한다.

무엇보다 고객의 트랜잭션관리 부분이 가장 어려울 거라 생각이 든다.

오늘은 MSA구조가 무엇인지 알아보았다.

Reference

  1. https://mydream72.tistory.com/entry/%EC%95%8C%EA%B3%A0%EB%B3%B4%EB%8B%88-MSA%EB%9E%80
  2. https://hahahoho5915.tistory.com/71

'지식 창고' 카테고리의 다른 글

REST API란?  (0) 2022.09.12
HLS protocol 이란 무엇일까?  (2) 2022.09.11
프레임워크랑 라이브러리는 뭐가 다를까??  (0) 2022.09.03

오랜만에 블로그 글을 쓰게 되었다.. 요즘 시간이 너무 바쁘게 흘러가고 있는지라 블로그 쓸 생각이 나지 않았던 것 같다 사실 귀찮은 것도 아주 컸다

 

스타트업 신입 개발자로 취업한 후기에 대해 작성하려고한다.

 

첫 직장이자 주관적인 내용이 담겨있기 때문에 "그럴 수 있구나"라고만 생각하고 넘어가 주길 바란다. 거시적 관점으로 "진짜 모든 스타트업이 혹은 모든 신입 개발자가 이렇구나?"라는 생각은 안 좋은 것 같다.

 

현재는 지방 파견근무로 업무를 진행하고 있다 처음 면접 때부터 전제조건이 지방 파견근무였기에.. 크게 불편함을 많이 느끼지는 않는 것 같다 업무적인 이야기로 넘어가자면 어떤 기업에 들어가던 처음은 항상 도메인 지식 공부로 시작한다. 내가 학교에서 스프링을 통한 웹페이지를 구성할 때와 조선소에서 사용하는 웹사이트를 구성할 때의 차이점을 생각해보자 특정 도메인에 사용되는 개념들과 수치들을 적절하게 활용하여 API로 제공하는 것과 혹은 웹사이트를 통해 시각화하는 것 등 범용적으로 모든 도메인을 사용할 수 있도록 구성하는 것보다 한 도메인의 초점으로 구성하되 확장성을 고려해 개발해두는 것이 더 맞는 것 같다. 사실상 모든 도메인을 이용할 수 있다는 게 가능한 것인지는 모르겠으나..

 

그리고 현재 나는 솔루션기업에서 근무를 진행중이기에 자사 솔루션 공부도 했었다. 어떤 서비스업에 종사하는 사람이라면 고객의 관점에서도 한번 서비스를 받아보아야 하지 않을까? 이런 느낌을 받았다. 실제로 고객의 입장인 것처럼 솔루션을 이용해보며 무슨 기능이 솔루션에 존재하는지, 어떻게 사용할 수 있는지 등 알아가는 시간이 필요했다.

 

그래서 약 1개월에서 1개월 절반 정도는 이러한 도메인 지식을 완벽하게 알기 위해 학습을 진행했던 것 같다. 이후 나는 API 개발 업무를 맡았으나 당장에는 진행되고 있지 않았기에 웹 개발자라기보다는 데이터 엔지니어의 업무적인 관점에서 데이 터전 처리를 위한 개발을 진행하고 있다

 

업무를 진행하며 느낀 점은 부족한 게 너무나도 많고 모르는 게 너무나도 많다는 것이다.  당연히 신입이기에 그렇겠지만 어느 정도 방향성은 맞춰서 직무를 선택해 입사를 결정하게 되었지만 그럼에도 불구하고 프로젝트를 진행했던 것들도 지금 다시 보면 너무 수박 겉핥기 식으로 스택을 사용했다는 것을 알게 되었다.

 

그래서 현재는 항상 검색하며 공부하면서 업무를 진행하는 게 일반적인 것 같다 진짜 모를 때만 주변 분들께 질문을 가끔 하기도 하고.. 모르는 채로 업무를 포기하거나 미루는 건 안 좋다고 느꼈기 때문이다.

 

그러면서도 또 문득 드는 생각은 내가 발전하고 싶은 방향과 연관이 있는 업무인지를 판단하는 시각이 아직 없는 것 같다 그래서 지금은 어떤 업무던 다 해결해보려고 노력하고 있고 여러 업무를 진행해보며 내가 원하는 방향으로의 업무 시각을 갖춰나가는 것도 중요하다고 생각한다.

'취업 이야기' 카테고리의 다른 글

의도치 않았던 이직  (0) 2023.06.03
SI직무 인턴쉽 후기  (0) 2022.09.08

<!doctype html>

[Java & DataBase] JDBC, JPA, Mybatis 차이점


스프링이나 이클립스를 통한 자바 개발을 진행하는 개발자라면 데이터베이스와 연동하는 과정을 개발해 본 경험이 있을 것입니다.

그중 관계형 데이터베이스(RDBMS)를 이용할 때 JDBC, JPA, Mybatis를 이용해 볼 수 있는데 구체적으로 어떠한 차이점이 있는지 궁금증이 생겨 개념 정리 및 학습을 진행하기 위해 한번 정리해볼까 합니다.

 

순서는 제가 학습했던 순서인 JDBC -> Mybatis -> JPA 순으로 설명하겠습니다

 

1. JDBC(Java Database Connectivity)


 

JDBC는 말 그대로 자바 프로그램이 데이터베이스와 연결할 수 있는 기능을 제공하는 프로그래밍 인터페이스입니다.

 

이러한 JDBC를 이용하기 위해서는 java.sql.Driver, java.sql.Connection, java.sql.Statement, ResultSet, PreparedStatement, CallableStatement 등을 이용 볼 수 있습니다. 실제 개발을 진행할 때는 import java.sql.*; 로 한 번에 가져와서 구현했습니다.

 

간단한 순서는 다음과 같습니다.

  1. Driver Load
  2. Connector Object Create -> Connection
  3. Statement Object Create
  4. Return Value Save Result Set Object
  5. Close

 

import java.sql.*;

public class ConnectDB{
  public static void main(String[] args)
  {
    try{
      //Connection Object Create
      Connection conn = null;

      //Connection
      String url = "jdbc:mysql://localhost/DB_Name";

      conn = DriverManager.getConnection(url, "DB_user", "DB_user_password");
      System.out.println("연결 성공");
    }
    catch(ClassNotFoundException e) // Error Case 1
    {
      System.out.println("Driver Loading Fail");
    }
    catch(SQLException e) // Error Case 2
    {
      System.out.println("Error : " + e);
    }
    finally
    {
      try
      {
        if(conn != null && !conn.isClosed())
        {
          conn.close();
        }
      }
      catch(SQLException e) // Error Case 3
      {
        e.printStackTrace();
      }
    }
   }
}

이러한 불편은 점차 jdbc의 역사가 발전해나가며 SQL Mapper와 ORM을 이용할 경우 코드상 활용하는 방식이 간결해졌습니다

추가로 jdbc를 이용할 때 Driver는 DataBase회사별 다르기 때문에 "com.mysql.jdbc.Driver" 와 같이 직접 찾아서 입력해야 합니다.

 

쿼리를 요청하는 코드를 확인해보겠습니다.

 

import java.sql.*;

public class SelectCase
{
  public static void main(String[] args)
  {
    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;
    
    try{
      // 1. Drvier Load
      Class.forName("com.mysql.jdbc.Driver");
      
      // 2. Connection
      String url = "jdbc:mysql://localhost/DB_Name";
      conn = DriverManager.getConnection(url, "DB_User", "DB_Password");
      
      // 3. Statement Object Create
      stmt = conn.createStatement();
      
      // 4. Write Query
        // 1) Select 할 때 * 로 모든 칼럼을 가져오기보단 특정 컬럼을 가져오는것이 좋다.
        // 2) 원하는 결과는 쿼리로써 정리하고 후작업은 권장되지않음
        // 3) 쿼리를 한 줄로 쓰기 어려운 경우 들여쓰기를 사용해도 되지만 띄어쓰기에 유의해야한다.
      String sql = "SELECT name, owner, data_format(birth, '%Y년%m월%d일' date FROM table)";
      
      // 5. Execute Query
      rs = stmt.executeQuery(sql);
      
      // 6. 실행결과 출력하기
      while(rs.next())
      {
        //Record colunm은 1부터 시작하며 DataType에 맞게 getInt, getString등을 이용
        String name = rs.getString(1);
        String owner = rs.getString(2);
        String date = rs.getString(3);
        
        System.out.println(name + " " + owner + " " + date);
      }
    }
    catch( ClassNotFoundException e){
      System.out.println("드라이버 로딩 실패");
    }
    catch( SQLException e){
      System.out.println("에러 " + e);
    }
    finally // Close Phase
    {
      try
      {
          if( conn != null && !conn.isClosed())
          {
            conn.close();
          }
          if( stmt != null && !stmt.isClosed())
          {
            stmt.close();
          }
          if( rs != null && !rs.isClosed())
          {
            rs.close();
          }
      }
      catch( SQLException e)
      {
        e.printStackTrace();
      }
  }
}

 

 

 

물론 간결하다고 항상 좋은 것은 아니고 장, 단점이 존재합니다

위 코드는 MySQL 일 경우의 과정이고 이 JDBC 역시 Java에서 제공하는 API이기에 개발자 입장에서는 데이터베이스마다 사용 쿼리를 각 DB마다 작성해주어야 합니다(DB의존적인 쿼리문).

 

또한 연결, 연결 해제 등의 과정의 코드를 반복적으로 작성해야 하기에 코드가 많이 길어집니다.

 

이 방식도 역시나 기존 애플리케이션의 디비 연동 과정 보다도 간소화되었지만 여기서 끝이 아닌 새로운 2가지 기술이 또 등장합니다.

 

SQL Mapper , ORM

 

SQL Mapper

SQL Mapper의 대표적인 기술로는 아래에서 설명할 MyBatis가 있으며 쿼리문을 파일로 관리할 수 있다는 점에서 장점이 있습니다.

또 위 JDBC의 단점인 반복적인 코드를 줄이고 응답 결과 자체를 객체로 반환합니다.

 

ORM(Object-Relational Mapping)

ORM은 SQL문을 작성하지 않아도 동적으로 생성해주며 DB마다 다르게 사용하는 SQL도 동일하게 작성 가능합니다.

단점으로는 러닝 커브가 존재하고, SQL 작성이 없지만 테스트 과정이나 기타 여러 상황을 고려해 개발자는 알아야 합니다.

자세한 내용은 밑에 3. JPA에서 더 설명하겠습니다

 

2. Mybatis


 

  • Mybatis는 Persistence framework입니다.
  • MyBatis는 위 사용했던 JDBC를 통해 데이터베이스에 액세스 하는 작업을 캡슐화하고 일반 SQL 쿼리, 저장 프로 시저 및 고급 맵핑을 지원해 중복작업을 제거합니다.
  • 또 SQL Query문은 한 파일에 구성해서 프로그램 코드와 SQL을 분리해 개발할 수 있는 장점이 있습니다.
  • 이렇게 파일에 구성하기 때문에 복잡한 쿼리나 다이내믹한 쿼리에 강하며 단점으로는 비슷한 쿼리가 많아질 수 있는 단점이 있습니다.

 

JDBC와는 다르게 ResultType, ResultClass 등 VO를 사용하지 않고 결과를 DTO, MAP에 맵핑해 사용할 수 있습니다.

mybatis

공식 문서는 다음과 같습니다. - https://mybatis.org/mybatis-3/getting-started.html

 

 

3. JPA


아래 사진은 NoSQL인 MongoDB를 JPA인 MongoRepository를 활용하기 위해 제가 그렸던 Class Diagram입니다.

mongo

사실 간결하게 표현되어 이해하기 어려울 수 있으나 실제 공식문서를 들어가 보면 인터페이스들이 많이 엮여있는 구조로 되어있다는 걸 알 수 있습니다. (비어있는 interface도 존재합니다)

JPA는 위 Mybatis와 JDBC와는 다르게 사용 명세를 많이 참조해야 한다는 단점이 있었습니다.

개인적으로 프로젝트에 적용하기 위해 쿼리문을 작성해보고 이를 함수 명세로 표현하기 위해서 다시 JPA공식문서를 뒤져보는 작업에 시간을 많이 소요했습니다.

이러한 JPA는 익숙해지기에는 시간이 오래 걸렸으나 한번 익숙해진다면 개발 속도는 빨랐기에 저도 가장 많이 사용해보았습니다.

이런 JPA의 특징으로는 ORM 기술 표준의 인터페이스 모음이며 인터페이스이기 때문에 Hibernate, OpenJPA 등이 JPA를 구현합니다.

또 프로젝트의 규모가 커질 경우 속도 저하, 일관성을 무너뜨리는 문제점, 학습 비용이 비싼 점 등이 존재합니다.

추가로 제가 구현할 때 중첩 쿼리문처럼 복잡할 경우에는 @Query 어노테이션으로 직접 Query를 작성할 수 있어 매우 유연한 구현 방식을 제공하고, 팀원들과 협업 시에도 JPA를 이용하기 위한 함수 네이밍 기준이 있어 가독성도 좋았습니다.

 

코드를 하나씩 다 쳐보며 설명하고 싶으나 시간적인 여유가 없어 현재는 특징 정리 정도로만 하고 추후 재 업데이트를 진행할 예정입니다

 

Reference


 

 

'JAVA' 카테고리의 다른 글

[Java] 언어의 특징  (2) 2022.09.09
[JAVA]직렬화 - Serializable란?  (0) 2022.05.16
[JAVA]DAO, DTO, VO 정리.  (0) 2021.12.25

+ Recent posts