본문 바로가기

Study/Spring & Spring Boot

[Spring Boot] 프로젝트 구조 및 초기 설정

개발환경 : IntelliJ IDEA
운영체제 : macOS Monterey 12.x.x
CPU : Apple Silicon (ARM 64)

Spring Framework


MVC

MVC는 Model, View, Controller 구성으로 Model은 Service와 DAO(Data Access Object)로 구성되어 있다.

DAO가 MyBatis를 통해 DB로 부터 데이터를 가져오며 Service를 거쳐 Controller로 View에 뿌려주는 형식을 갖는다.

스프링 프레임워크의 문제점

구조적으로 위 그림처럼 DB에서 끄집어낸 정보를 서비스, 컨트롤러를 거쳐서 뷰로 가져가기 때문에 setAttribute로 전달해줄 값을 받아서 jsp에서 getAttribute로 뿌려주는 과정을 거쳤다. 때문에 컨트롤러가 매우 복잡하기도 하였고 어떤 부분에서 수정이 발생하면 모든 로직을 휘저어 다니며 전부 수정해 주어야 했다.

그리고 초기에 설정해 주어야 할 프로젝트 세팅이 매우 번거롭기도 하다. 실제로 의존성 관리를 위해 pom.xml에 프로젝트에 필요한 다양한 것들을 하나씩 집어넣어야 하는데 여간 번거로운 일이 아니다.

그리고 JSP를 기반으로 한다면 프론트엔드단에 자바 코드가 난입하는 등 지금의 웹개발 트렌드에서 다소 벗어나기 때문에 혼란스러운 것도 없지 않아 있는 것 같다.

프로젝트를 좀 더 간결하게, 사용하기 쉽게 하기 위해 스프링 프레임워크의 다양한 부분을 자동화 및 개선한 것이 스프링 부트라고 말할 수 있다.

기존 스프링 프레임워크 프로젝트에서는 Tomcat이 프론트엔드와 백엔드를 한 서버에서 모두 작동시켰다면, 스프링 부트에서는 각각을 별도의 서버에서 운영한다.

MVC라는 구조적인 맥락과 작동 방식은 같지만 스프링 프레임워크에 비해 컨트롤러의 역할이 줄어들었다. 위에서 말한 것처럼 백엔드단에서 프론트엔드단으로 값을 넘겨주기 위해 Model 객체나 HttpServletRequest 등을 컨트롤러에서 사용하여 값을 넘겨주기 때문에 컨트롤러에 대한 의존도가 높았다. 뿐만 아니라 *.do 패턴을 찾아서 페이지를 이동시켜 주는 역할도 컨트롤러가 했다.

스프링부트에서 컨트롤러는 이제 값을 전달해주는 역할만 할 뿐이며 어떤 페이지를 찾아가라고 하는 역할은 프론트엔드 단에서 모두 끝나게 된다.

또한 스프링 프레임워크에서는 인터페이스와 구현체를 각각 모두 만들어주었지만 스프링부트에서는 그렇게 할 필요는 없는 것 같다. 이렇게 스프링부트는 스프링 프레임워크를 보다 편리하게 사용할 수 있게 해주는데 초점을 맞추었다고 보면 될 것이다.

여기에서 다룰 스프링 부트에 관련된 모든 내용은 Maven 기반으로 작성될 것이며 데이터베이스는 MySQL을 사용할 것이다.


초기 세팅


pom.xml

pom.xml은 프로젝트의 의존성을 관리하는 파일이다. 개발 시 필요한 플러그인들을 다운로드 받아 적용시키는 것이다.
Node.js라면 npm, Python이라면 pip를 떠올릴 수 있다.

여기에 추가할 태그들은 Maven Repository(https://mvnrepository.com)에서 얻을 수 있다.

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>sample02</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sample02</name>
    <description>sample02</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- spring boot web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.6.3</version>
        </dependency>

        <!-- spring boot tomcat -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <version>2.6.3</version>
        </dependency>

        <!-- JSON 라이브러리 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.10.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.10.1</version>
        </dependency>

        <!-- lombok 사용 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
            <scope>provided</scope>
        </dependency>

        <!-- JDBC 설정 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
            <version>2.6.3</version>
        </dependency>

        <!-- MyBatis 사용 설정 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.7</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.9</version>
        </dependency>

        <!-- mysql 사용 설정 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.27</version>
        </dependency>

          <!-- oracle db 사용 시 -->
        <dependency>
            <groupId>com.oracle.database.jdbc</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0.4</version>
        </dependency>

        <!-- slf4j 로거 사용 설정 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.36</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.10</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.properties

톰캣 포트 번호를 수정하기 위해서 스프링 레거시를 사용했을 때는 매우 복잡한 과정을 거쳐 수정했지만, 스프링 부트에서는 application.properties에서 수정할 수 있다.

server.port=3000

# MySQL 사용을 위한 설정
spring.datasource.hikari.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.hikari.jdbc-url=jdbc:mysql://localhost:3306/mysql
spring.datasource.hikari.username=root
spring.datasource.hikari.password=1234

# Oracle DB를 사용한다면
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.url=jdbc:oracle.thin:@localhost:1521:xe
spring.datasource.username=admin
spring.datasource.password=1234

데이터베이스를 사용하기 위해 스프링 레거시에서 사용했던 jdbc.properties가 이에 해당한다.

Logger 사용

보통 어떤 로직이 정상적으로 작동하는지 살펴보기 위해 콘솔창에 메시지를 출력해볼 때가 있다.

이 때 System.out.println();을 사용할 경우 상황별로 메시지를 남기거나 출력해주기 어렵고 무엇보다도 무조건 출력해버리기 때문에 혼란스럽다.

pom.xml에서 slf4jlogback을 추가했는데 이것이 로그를 사용하기 위한 것이다.

로그 사용을 위해 resource 디렉터리에 logback.xml을 추가해주고 다음 내용을 입력한다.

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) %magenta(%-4relative) --- [ %thread{10} ] %cyan(%logger{20}) : %msg%n </pattern>
        </encoder>
    </appender>

    <appender name="WEBAPP" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>webapp.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>

        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %-4relative --- [ %thread{10} ] %logger{35} - %msg%n</pattern>
        </encoder>
    </appender>

    <logger name="org.springframework" level="info"/>

    <root level="debug">
        <appender-ref ref="CONSOLE"/> <!-- Console 창-->
        <appender-ref ref="WEBAPP"/> <!-- File -->
    </root>

</configuration>

참고문헌
https://blog.naver.com/youngram2/221771535515 (2022.02.21.)
https://livenow14.tistory.com/63 (2022.02.21.)