스프링 프레임워크 실습 및 프로젝트

noyo0123·2021년 2월 20일
0

OS X, linux에서 java, maven설치

sdkman를 사용해서 java 설치가능
참조: https://phoby.github.io/sdkman/

위에 블로그에 나온대로
SDMMAN!은 대부분의 유닉스 기반 시스템에서 여러가지 SDK(Software Development Kits)의 병렬 버전을 관리하기 위한 도구입니다.

이전에 오라클에서 설치한 java1.8 버전이 있는데 또 설치해봄
https://devkimgoon.tistory.com/3

java 특정 버전으로 설치

sdk list로 조회

# 설치할 Java 버전 조회
$ sdk list java

# 설치할 버전으로 설치
$ sdk install java 11.0.10.j9-adpt

심볼릭 링크로 사용할 자바 버전을 가리킴.

intellij에서 SDK JDK 경로 설정하기

ln -s ~/.sdkman ~/sdkman
https://cjred.net/2019-07-14-intellij-sdkman-jdk/


command + ;

sdk 설정

maven 특정 버전으로 설치

# 설치할 Java 버전 조회
$ sdk list maven

$ sdk install maven 버전

maven, logback

java hello world

에디터 없이 java 컴파일, 빌드 해보기

cd <프로젝트 디렉토리 생성할 PATH>
mkdir helloMaven && cd helloMaven
touch Main.java && vi Main.java

Main.java

class Main {
    public static void main(String [] args) {
        System.out.println("hello world");
    }
}

컴파일 javac Main.java
실행 java Main

maven은 디렉토리 구조가 정해져있음

Main.java 파일에 있는 Main 클래스를 패키지안에 넣어줍니다.
패키지는 디렉토리로 구분되고 패키지 이름의 규칙은 "도메인의 역순"

mkdir com
cd com
mkdir playground
cd playground
mkdir yobs
cd yobs
#다시 프로젝트 루트 디렉토리로 돌아와서 Main.java 복사함
cp Main.java ./com/playground/yobs/

Main.java 파일 수정 패키지를 입력해줌

package com.playground.yobs;
class Main {
    public static void main(String [] args) {
        System.out.println("hello world");
    }
}

다시 컴파일 해주고, java 실행시 classpath를 루트디렉토리로 지정하고 실행하면 hello world가 찍힘.

javac com/playground/yobs/Main.java
java -cp . com.playground.yobs.Main
hello world

클래스가 여러개 만들어지기 때문에 jar로 클래스들을 묶음
jar -> 아카이빙 목적 여러가지 파일을 하나의 파일로 묶어서 관리용이
-c : create
-f : file명

jar -cf helloMaven.jar com/*

java -jar helloMvn.jar
helloMvn.jar에 기본 Manifest 속성이 없습니다.

manifest.txt를 생성하고 다음과 같이 생성합니다.

vi manifest.txt
Main-class: com.playground.yobs.Main

jar 파일 추가
jar -cmf manifest.txt helloMvn.jar com/*
jar 파일 실행
java -jar helloMvn.jar

logback 설치

자바 로깅 라이브러리
이건 패스
이건 스프링에서 사용하는 log 라이브러리인 logback를 사용하기 위해
logback-classic.jar, logback-cor.jar, slf4j-api.jar 등을 설치해서 lib폴더에 넣고

Main.java에서 slf4j import 해서 LoggerFactory로 logger 만들고 logger로 info레벨의 로그를 찍어보는 것

jar로 묶으려면
manifest.txt 파일을 수정해줘야함
Class-path: lib/logback-classic.jar lib/logback-core.jar lib/slf4j-api.jar

jar 파일 수정
jar -cmf manifest.txt helloMvn.jar com/*

그리고 이렇게 의존성을 추가하고, xml로 되어있는 설정파일들을 추가할 수 있음.
설정파일을 추가함으로써 logback의 경우 로그 format, 로그 레벨들을 설정파일로 관리할 수 있음.
로거를 info레벨로 해두었는데, 설정파일에서 error레벨로 해두었다면, 앱을 실행할때 info로그는 error보다 낮은 단계의 로그이기에 찍히지 않을거에요.

결론

이렇게 cli 환경에서 java 컴파일, 의존성 추가, 패키지 생성, 적용, java class파일을 실행하는 걸 해보고 jar로 아카이빙 했는데 엄청 귀찮다는것을 알 수 있음.

maven을 통해 build, 아카이빙, 의존성 추가해보기

https://maven.apache.org/guides/getting-started/maven-in-five-minutes.html

maven은 디렉토리 구조가 정해져있어요.

pom.xml 파일 생성
위에 사이트에 나와있는 pom.xml 내용을 복붙합니다.
groudId만 내 프로젝트 패키지에 맞게 수정해줍니다.
pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.playground.yobs</groupId>
  <artifactId>helloSpring</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
  </dependencies>
</project>

pom.xml이 존재하는 프로젝트 루트 디렉토리에서 다음과 같이 해줍니다.
mvn validate
빌드 success가 나오면 pom.xml이 문제가 없는지 판단할 수 있습니다.

디렉토리 구조를 다음과 같이 만들었습니다.

.
├── Main.class
├── Main.java
├── helloMvn.jar
├── manifest.txt
├── pom.xml
└── src
    ├── main
    │   └── java
    │       ├── playground
    │       │   └── yobs
    │       │       ├── Main.class
    │       │       └── Main.java
    │       └── resources
    └── test
        └── java
            └── resources

mainfest.txt는 maven이 자동으로 만들어 줄겁니다. 제거해줍니다.
logback과 같은 라이브러리를 설치하기 위해서 maven central 에서 logback-classic 검색후 버전을 알아냅니다.
pom.xml의 의존성을 추가해줍니다.


여길 복사해서 pom.xml에 dependencies사이에 추가해주면 됩니다.

maven으로 컴파일을 해줍니다. 그러면 의존성 다운로드 받고, 빌드해줍니다.
mvn compile
build가 완료되면 target 폴더가 생성되고, 그 안에 빌드된 내용을 확인할 수 있습니다.
mvn clean을 통해 target폴더를 제거할 수 있습니다.

jar파일을 넣지 않았는데, 어떻게 maven에서 jar파일을 인식하냐?
home 디렉토리에 .m2 디렉토리에 의존성들이 받아진 것을 볼 수 있음.
maven은 .m2 디렉토리에 모든 의존성들을 받아놓고, pom.xml에서 필요한 jar파일을 불러다 빌드합니다.

executable jar를 만들기 위해서는 maven plugin을 설치해야함.
maven shade를 사용할 것임
https://javacan.tistory.com/entry/mavenshadeplugin

shade 사용법

빌드 부분 설정을 pom.xml로 복붙합니다.
이렇게 하면 shade가 동작하게만 되고

maven 사이트에 executable jar에 아래 부분을 pom.xml에 복붙해줍니다.

그러면 pom.xml이 이렇게 됩니다. mainClass부분을 내 프로젝트 맡게 바꿔줍니다.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.playground.yobs</groupId>
  <artifactId>helloSpring</artifactId>
  <version>1.0-SNAPSHOT</version>
 
  <properties>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>
 
  <dependencies>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.3.0-alpha5</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <configuration>
          <!-- put your configurations here -->
        </configuration>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                  <mainClass>com.playground.yobs.Main</mainClass>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  
</project>

mvn package로 프로젝트 jar로 아카이빙 합니다.

mvn compile : javac를 이용해서 class file만 생성
mvn package : jar로 아카이빙 해줌.

target 파일에 가보면 jar 파일 생성된거 볼 수 있음.

 solarconnect-yosephnoh  ~/Documents/practices/fastcampus/helloMvn  java -jar target/helloSpring-1.0-SNAPSHOT.jar
00:41:20.241 [main] INFO com.playground.yobs.Main - Hello world

database(h2), jdbc

https://developerhive.tistory.com/34

자바로 작성된 관계형 데이터베이스.
장점 : 간단하게 설치 및 실행, DB client 설치없이 web에서 SQL문 작성해서 실행해볼 수 있음.
file 모드 -> 간단하게 데이터베이스 실행을 멈춰도 데이터 남길 수 있음.
memory 모드 -> 데이터베이스 실행을 멈추면 데이터 날아감.

h2 database> features compatibility -> h2 ANSI SQL(표준)을 지원하고 다른 데이터베이스와 호환성을 갖음
h2 데이터베이스로 테스트 코드를 작성해서 테스트했으면 mysql에서도 동작한다는 얘기 -> 테스트 용이

jdbc: jdbc 만들어지기 전에는 mysql, oracle, mssql 등 관계형 데이터베이스를 만드는 벤더들마다 자바로 db 관련 프로그래밍에 필요한 jar파일을 각각 제공했었음.
java 1.1부터는 jdbc라는 interface를 이용하여 다양한 DB에서 하나의 interface를 통해 개발을 할 수 있게 제공되었음.

jdbc interface를 기반으로 mybatis, hibernate 같은 도구들이 생겨나게 되었음.

jdbc는 자바 스펙에 있기 때문에 따로 의존성 추가할 필요가 없음.

프로젝트 내비게이션에서 External Libraries에서 java.sql 패키지를 볼 수 있음.
이 패키지의 classes, interfaces들을 이용해서 jdbc를 이용해서 db 관련 프로그래밍을 할 수 있음.


h2 database 다운로드
https://www.h2database.com/html/download.html

압축풀고 h2.sh 실행
permission denied 발생하면 -> chmod u+x h2.sh
터미널켜서 cd <targetDirectory>/bin
./h2.sh

file 모드로 사용하기 위해서
jdbc url에 다음과같이 프로토콜 맞춰주고, db를 저장할 파일 path도 명시해줍니다.

h2 데이터베이스에서 table 생성하기

CREATE TABLE member (
  id int auto_increment,
  username varchar(255) not null,
  password varchar(255) not null,
  primary key(id)
);

test 데이터 추가

insert into member (username, password) values ("yobs", "1234");

jdbc 프로그래밍

class Main {
    public static void main(String [] args) {
      Logger logger = LoggerFactory.getLogger(Main.class);
      logger.info("Hello world");

        // DB와 연결
        Connection connection = null;
        Statement statement = null;
        // 각각의 DB 벤더들이 제공하는 Driver 로드
        try {
            Class.forName("org.h2.Driver");
            // 접속할 DB url MySQL 호환모드 설정 MySQL DB를 h2에서 사용가능함
            String url ="jdbc:h2:~/data/fastcampus;MODE=MySQL;";
            // 커넥션 객체 생성
            connection = DriverManager.getConnection(url, "sa", "");
            // DB에서 SQL문 실행하기 위해 statement 작성
            statement = connection.createStatement();

            // ResultSet 인터페이스를 이용해서 record단위 데이터를 참조할 수 있음.
            ResultSet resultSet = statement.executeQuery("select id, username, password from member");
            // next 메서드를 시작으로 cursor가 첫번쨰 row부터 참조하게 됌.
            while(resultSet.next()){
              int id = resultSet.getInt("id");
              String username = resultSet.getString("username");
              String password = resultSet.getString("password");

              logger.info("id" + id + ", username" + username + ", password" +password);
            }


        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        finally {
            // 사용한 resource 반환
            try {
                statement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

인텔리제이 Edit Configuration Intellj: Module not specified

https://medium.com/@ufamily/intellij-module-not-specified-351c2964928a

실행하려는 프로젝트 artifact 선택해주고 JDK 선택해주면 됌.


h2 memory 모드로 사용

커넥션 url 수정

String url ="jdbc:h2:mem:fastcampus;MODE=MySQL;";

DDL 추가, 트랜잭션 추가

class Main {
    public static void main(String [] args) {
      Logger logger = LoggerFactory.getLogger(Main.class);
      logger.info("Hello world");

        // DB와 연결
        Connection connection = null;
        Statement statement = null;
        // 각각의 DB 벤더들이 제공하는 Driver 로드
        try {
            Class.forName("org.h2.Driver");
            // 접속할 DB url MySQL 호환모드 설정 MySQL DB를 h2에서 사용가능함
            String url ="jdbc:h2:mem:fastcampus;MODE=MySQL;";
            // 커넥션 객체 생성
            connection = DriverManager.getConnection(url, "sa", "");
            // DB에서 SQL문 실행하기 위해 statement 작성
            statement = connection.createStatement();

            // 트랜잭션 설정 -> commit이란 명령어가 실행되야 DB에 저장됌.
            connection.setAutoCommit(false);

            // memory 모드로 사용하기에 DDL를 추가해줌
            statement.execute("create table member(id int auto_increment, username varchar(255) not null, password varchar(255) not null, primary key(id))");
            statement.executeUpdate("insert into member(username, password) values('yobs', '1234')");


            // ResultSet 인터페이스를 이용해서 record단위 데이터를 참조할 수 있음.
            ResultSet resultSet = statement.executeQuery("select id, username, password from member");
            // next 메서드를 시작으로 cursor가 첫번쨰 row부터 참조하게 됌.
            while(resultSet.next()){
              int id = resultSet.getInt("id");
              String username = resultSet.getString("username");
              String password = resultSet.getString("password");

              logger.info("id:" + id + ", username:" + username + ", password:" +password);
            }
            // commit 실행
            connection.commit();

        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
            try {
                // rollback 추가
                connection.rollback();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        finally {
            // 사용한 resource 반환
            try {
                statement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

db커넥션 및 CRUD기능하는 코드에서 try 문이 복잡한데,
connection.close, statement.close등 close관련기능 때문에 try catch가 많이 보이는데, close에서 exception을 던지기 때문에 try catch문을 넣어줘야하는데 java7이후부터는 close가 필요한 부분에서는 AutoClosable이란 인터페이스를 추가해서 AutoClosable을 상속받은 객체들은 자동으로 close메서드가 호출됌.

intellij에서 action사용 ( cmd + shift + a ) : contructor나 override Method등 바로 할 수 있음.

java11에서는 로컬 타입 추론
var url = "jdbc:h2:mem:test;MODE=MySQL;"; value가 String이기 때문에 알아서 타입추론해버림.

lombok

반복작업 제거

servlet

https://jeong-pro.tistory.com/222

Ioc


AOP

https://docs.spring.io/spring-framework/docs/5.2.0.RELEASE/spring-framework-reference/

wiki aop
https://ko.wikipedia.org/wiki/%EA%B4%80%EC%A0%90_%EC%A7%80%ED%96%A5_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D

횡단 관심사의 분리를 허용함으로써 모듈성을 증가시키는 것이 못적인 프로그래밍 패러다임.

try catch rollback 과 같은 코드들을 소스코드에 넣지 않고, 반복적인 코드를 외부에서 관리함으로써 반복되는 코드를 줄이고 코드 관리가 더욱 편리해짐.

profile
서로 아는 것들을 공유해요~

0개의 댓글