Spring Boot (+ RESTful)

Spring Boot - spring boot application의 디렉토리 구조 / 주요 어노테이션 이해 /

wy-family 2024. 12. 12. 13:40
src/main/java
|-- com.example.demo
    |-- DemoApplication.java
    |-- controller
        |-- HelloController.java
    |-- service
        |-- HelloService.java
    |-- repository
        |-- HelloRepository.java
    |-- entity
        |-- HelloEntity.java
    |-- config
        |-- AppConfig.java

src/main/resources
|-- static
    |-- css
        |-- styles.css
    |-- js
        |-- app.js
    |-- images
        |-- logo.png
|-- templates
    |-- index.html
|-- schema
    |-- data.sql
    |-- schema.sql
|-- application.properties

pom.xml

각 구성요소의 설명

   
구성요소 역할 및 설명
DemoApplication.java 애플리케이션의 진입점. @SpringBootApplication으로 설정되며, 애플리케이션 전체를 실행.
controller 사용자 요청(HTTP 요청)을 처리하는 계층. REST API나 웹 요청을 처리하며, 비즈니스 로직(Service) 호출 후 결과를 반환.
service 비즈니스 로직을 처리하는 계층. ControllerRepository 간의 중간 계층으로, 데이터 처리와 비즈니스 규칙을 구현.
repository 데이터베이스와 상호작용하는 계층. CRUD 작업을 수행하며, JPA, Hibernate 등을 활용해 데이터 처리.
entity 데이터베이스의 테이블과 매핑되는 클래스. 데이터 구조를 정의하고, 애플리케이션에서 사용되는 도메인 객체로 동작.
config 애플리케이션 전역 설정 관리. Bean 등록, 보안 설정, 데이터베이스 설정 등을 포함하며, Spring IoC 컨테이너에서 필요한 객체를 생성 및 관리.
static 정적 자원(HTML, CSS, JS, 이미지 등)을 저장. 클라이언트 측 브라우저에서 직접 로드되며, URL로 접근 가능.
css 애플리케이션의 스타일(CSS 파일)을 저장.
js 클라이언트 측 JavaScript 파일을 저장.
images 애플리케이션에서 사용하는 이미지 파일을 저장.
templates Thymeleaf나 Freemarker 같은 템플릿 엔진 파일을 저장. 동적 HTML 생성에 사용됨.
schema/data.sql 애플리케이션 시작 시 데이터베이스 초기화(SQL 스크립트). schema.sql은 테이블 구조 생성, data.sql은 초기 데이터 삽입에 사용.
application.properties 애플리케이션 설정 파일. 포트, 데이터베이스 정보, 캐시 설정, 프로파일 등을 정의. 필요에 따라 YAML 형식의 application.yml로 대체 가능.
pom.xml Maven 프로젝트의 설정 파일. 프로젝트에서 필요한 라이브러리와 빌드 도구 설정을 관리.

예제 코드 및 파일

1. DemoApplication.java

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

2. Controller

@RestController
@RequestMapping("/api")
public class HelloController {
    private final HelloService helloService;

    @Autowired
    public HelloController(HelloService helloService) {
        this.helloService = helloService;
    }

    @GetMapping("/hello")
    public String sayHello() {
        return helloService.getHelloMessage();
    }
}

3. Service

@Service
public class HelloService {
    public String getHelloMessage() {
        return "Hello, Spring Boot!";
    }
}

4. Repository

@Repository
public interface HelloRepository extends JpaRepository<HelloEntity, Long> {
}

5. Entity

@Entity
public class HelloEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String message;

    // Getters and Setters
}

6. Config

@Configuration
public class AppConfig {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

7. application.properties

server.port=8080
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.h2.console.enabled=true

골격의 흐름

  1. DemoApplication이 Spring Boot 애플리케이션을 실행.
  2. Controller가 HTTP 요청을 받고, Service에 전달.
  3. Service가 비즈니스 로직을 수행하고, 필요 시 Repository를 통해 데이터를 처리.
  4. Repository가 데이터베이스와 상호작용하며 Entity를 기반으로 데이터를 저장/조회.
  5. Config에서 전역적으로 설정된 Bean을 활용해 필요한 기능을 구현.
  6. application.properties에서 설정된 값을 기반으로 애플리케이션 실행.

1. Static 파일

  • static/css/styles.css
body {
    font-family: Arial, sans-serif;
    background-color: #f4f4f9;
}
  • static/js/app.js
document.addEventListener("DOMContentLoaded", () => {
    console.log("Spring Boot with Static Resources!");
});
  • static/images/logo.png: 애플리케이션 로고 파일.

2. Templates

  • templates/index.html (Thymeleaf 사용)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Welcome</title>
    <link rel="stylesheet" href="/css/styles.css">
    <script src="/js/app.js"></script>
</head>
<body>
    <h1>Welcome to Spring Boot!</h1>
    <img src="/images/logo.png" alt="Logo">
</body>
</html>

3. Schema 파일

  • schema/schema.sql
CREATE TABLE users (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL
);
  • schema/data.sql
INSERT INTO users (name, email) VALUES ('John Doe', 'john.doe@example.com');
INSERT INTO users (name, email) VALUES ('Jane Smith', 'jane.smith@example.com');

4. pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

Thymeleaf란 무엇인가?

1. 개념

  • Thymeleaf는 Java 기반의 템플릿 엔진으로, 동적 HTML 콘텐츠를 생성할 수 있도록 돕는 도구야.
  • Spring Boot와 자연스럽게 통합되며, templates 디렉터리에 있는 HTML 파일에서 사용.

2. 특징

  1. HTML 친화적:
    • Thymeleaf 템플릿은 정상적인 HTML 파일로 동작하므로, 디자이너와 개발자가 함께 작업 가능.
  2. Spring과 통합:
    • Spring MVC와 잘 통합되어 컨트롤러에서 넘겨준 데이터를 쉽게 활용.
  3. 표현식 지원:
    • 데이터를 표현하거나 조건부 렌더링을 위해 다양한 표현식을 제공.
    • 예: ${}, th:if, th:each 등.

3. 예제

  • Controller:
@Controller
public class HomeController {
    @GetMapping("/")
    public String home(Model model) {
        model.addAttribute("message", "Hello, Thymeleaf!");
        return "index";
    }
}
  • templates/index.html:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Thymeleaf Example</title>
</head>
<body>
    <h1 th:text="${message}">Placeholder</h1>
</body>
</html>
  • 결과: 브라우저에서 "Hello, Thymeleaf!"라는 메시지가 렌더링된 HTML로 표시됨.

요약

Spring Boot의 확장된 골격은 백엔드, 정적 자원, 데이터베이스, 동적 HTML을 아우르는 구조로 구성돼.
Thymeleaf는 Spring Boot와 자연스럽게 연동되어 HTML 기반의 동적 콘텐츠를 생성하는 데 매우 유용한 템플릿 엔진이야.


Maven과 Gradle: 개념과 역할

Maven과 Gradle은 모두 **빌드 도구(Build Tool)**야.
빌드 도구는 소스 코드를 컴파일하고, 의존성(라이브러리)을 관리하며, 배포 가능한 애플리케이션 패키지(예: .jar, .war)를 생성하는 작업을 자동화해줘.
둘 다 Java 생태계에서 널리 사용되지만, 각각의 특징과 차이점이 있어.


1. Maven이란?

1.1 정의

  • Maven은 Apache Software Foundation에서 만든 Java 기반 프로젝트 관리 및 빌드 도구야.
  • 주로 XML 기반의 설정 파일(pom.xml)을 사용해서 프로젝트를 정의하고, 의존성 관리 및 빌드 작업을 수행해.

1.2 주요 특징

  1. 의존성 관리:
    • 프로젝트에 필요한 라이브러리를 Maven 중앙 저장소(Central Repository)에서 자동으로 다운로드.
    • pom.xml 파일에 필요한 의존성을 정의하면, 해당 라이브러리와 그 하위 의존성(transitive dependencies)도 자동으로 가져옴.
  2. 표준 디렉터리 구조:
    • Maven은 디렉터리 구조를 표준화해, 모든 Maven 프로젝트는 동일한 구조를 따름.
     
  3. 목표 기반 빌드:
    • 빌드 작업을 "목표(goal)" 단위로 실행. 예: mvn clean, mvn package.
  • Maven은 spring-boot-starter-web 의존성을 다운로드하고, 프로젝트에서 사용할 수 있도록 설정.

1.4 Maven의 단점

  • XML 문법이 복잡하고, 설정 파일이 길어질수록 관리가 어려워질 수 있음.
  • 빌드 속도가 Gradle에 비해 느린 편.

2. Gradle이란?

2.1 정의

  • Gradle은 더 현대적인 빌드 도구로, Maven의 단점을 보완한 도구야.
  • GroovyKotlin DSL을 사용하여 빌드 스크립트를 작성하며, 유연성과 간결성을 제공.

2.2 주요 특징

  1. 유연한 빌드 스크립트:
    • Groovy 기반의 스크립트를 사용해 설정을 작성하며, Maven의 XML보다 간결하고 읽기 쉬움.
  2. 빠른 빌드 속도:
    • Gradle은 **증분 빌드(Incremental Build)**를 지원해 변경된 부분만 빌드.
    • 빌드 속도가 Maven보다 빠른 편.
  3. 플러그인 중심:
    • Gradle은 플러그인 시스템을 통해 다양한 기능을 확장 가능.
    • 예: java 플러그인, application 플러그인 등.
  4. 의존성 관리:
    • Maven과 동일하게, 의존성을 중앙 저장소에서 다운로드하고 관리.
    • Groovy/Kotlin DSL로 간결하게 의존성을 정의 가능.

2.3 Gradle의 단점

  • Groovy/Kotlin DSL이 강력하지만, 초보자에게는 초기 학습 곡선이 있음.
  • 너무 유연해서 복잡한 설정을 작성하면 관리하기 어려워질 수 있음.

3. Maven과 Gradle 비교

     
항목 Maven Gradle
설정 언어 XML Groovy 또는 Kotlin DSL
빌드 속도 느림 빠름 (증분 빌드 지원)
유연성 제한적 (표준화된 구조를 따름) 매우 유연 (빌드 스크립트를 자유롭게 작성 가능)
학습 곡선 낮음 (XML 기반, 직관적) 다소 높음 (스크립트 언어 이해 필요)
의존성 관리 Maven Central Repository Maven Central Repository (같은 저장소 사용)
사용 사례 전통적인 Java 프로젝트 (Spring, Hibernate 등) 현대적인 대규모 프로젝트 (Spring, Android 등)
커뮤니티 지원 크고 안정적 빠르게 성장 중

4. Spring Boot에서 Maven과 Gradle

  • Spring Boot 프로젝트는 Maven이나 Gradle 중 하나를 선택해 관리할 수 있어.
  • Spring Initializr(https://start.spring.io)에서 프로젝트를 생성할 때 Maven 또는 Gradle을 선택 가능.

5. 언제 Maven과 Gradle을 선택할까?

  1. Maven이 적합한 경우:
    • 전통적인 Java 프로젝트.
    • 복잡한 빌드 스크립트가 필요하지 않은 경우.
    • 팀원이 Maven에 익숙한 경우.
  2. Gradle이 적합한 경우:
    • 대규모 프로젝트(빌드 속도가 중요한 경우).
    • 동적이고 유연한 빌드 스크립트를 작성해야 하는 경우.
    • 최신 트렌드와 높은 성능이 필요한 경우.

6. 요약

  • Maven: XML 기반의 표준화된 빌드 도구. 사용이 간단하고 안정적.
  • Gradle: Groovy/Kotlin 기반의 현대적인 빌드 도구. 유연하고 빌드 속도가 빠름.

Spring Boot에서는 둘 다 널리 사용되며, 프로젝트의 요구사항과 팀의 선호도에 따라 선택하면 돼.


Spring Boot 주요 애노테이션 이해

1. @SpringBootApplication

  • 설명: Spring Boot 애플리케이션의 시작점을 표시.
  • 역할: 내부적으로 @Configuration, @EnableAutoConfiguration, @ComponentScan을 포함.
  • 사용 위치: main() 메서드를 가진 클래스에 붙임.

2. @RestController

  • 설명: REST API를 처리하는 컨트롤러임을 표시.
  • 역할: JSON 형식의 데이터를 반환.
  • 특징: @Controller와 @ResponseBody가 합쳐진 형태.

3. @RequestMapping

  • 설명: 특정 URL 경로와 컨트롤러 메서드 또는 클래스 매핑.
  • 역할: 클라이언트 요청을 메서드로 연결.
  • : @RequestMapping("/api") → /api로 시작하는 URL 처리.

4. @Autowired

  • 설명: Spring이 Bean을 자동으로 주입(DI).
  • 역할: 의존성 객체를 개발자가 생성하지 않아도 Spring이 제공.

5. @GetMapping

  • 설명: GET 요청(데이터 조회)을 처리.
  • : 브라우저에서 URL로 접속 시 주로 사용.

6. @PostMapping

  • 설명: POST 요청(데이터 생성 또는 서버에 데이터 전송)을 처리.
  • : 클라이언트가 폼 데이터를 제출할 때 사용.

7. @Entity

  • 설명: 클래스가 데이터베이스의 테이블과 매핑됨을 표시.
  • 역할: JPA가 이 클래스의 데이터를 관리하도록 함.

8. @Id

  • 설명: 데이터베이스의 기본 키를 표시.
  • 역할: JPA가 테이블의 고유 식별자로 인식.

9. @GeneratedValue

  • 설명: 기본 키의 값을 자동 생성하도록 설정.
  • : AUTO_INCREMENT 같은 기능.

10. @Configuration

  • 설명: 설정 클래스임을 표시.
  • 역할: Bean을 정의하거나 설정을 관리.

11. @Bean

  • 설명: Spring IoC 컨테이너에서 관리할 Bean을 생성.
  • 역할: 개발자가 직접 정의한 객체를 Spring에서 관리.

12. @ConditionalOnProperty

  • 설명: 특정 속성이 존재하거나 특정 값일 때만 Bean을 등록.
  • 역할: 조건부 Bean 등록.

13. @Service

  • 설명: 비즈니스 로직을 처리하는 서비스 계층임을 표시.
  • 역할: Controller와 Repository 사이에서 데이터를 처리.

JPA와 ORM

1. JPA (Java Persistence API)

  • 설명: Java의 데이터베이스 처리 표준(인터페이스 기반).
  • 역할: SQL을 직접 작성하지 않고, Java 객체로 데이터베이스를 조작.
  • 특징: Spring Boot에서는 JPA 구현체(Hibernate)를 사용.

2. ORM (Object-Relational Mapping)

  • 설명: 객체(Object)와 데이터베이스 테이블 간의 매핑 기술.
  • 역할: 객체 지향 프로그래밍과 관계형 데이터베이스를 연결.
  • 장점:
    • SQL 대신 객체로 데이터 처리.
    • 생산성 증가, 유지보수 용이.

요약

  1. 애노테이션: Spring Boot의 주요 기능을 간결하고 선언적으로 제공.
  2. JPA와 ORM: SQL 작성 없이 Java 객체로 데이터베이스를 조작하도록 도와주는 기술.

Spring Boot와 Spring Framework: 공통점과 차이점

Spring Boot와 Spring Framework는 밀접하게 연결된 기술이지만, 그 목적과 사용 방식에 차이가 있어. 아래에서 공통점과 차이점을 명확히 설명할게.


1. 공통점

1.1 같은 기반

  • Spring Boot는 Spring Framework 위에 구축된 기술로, Spring Framework의 모든 핵심 기능을 포함하고 확장.
  • 둘 다 의존성 주입(DI), IoC 컨테이너, AOP와 같은 Spring의 핵심 개념을 사용.

1.2 목적

  • 둘 다 애플리케이션 개발을 단순화하고, 유지보수를 쉽게 하기 위해 설계됨.

1.3 오픈소스와 커뮤니티

  • 둘 다 오픈소스 프로젝트이며, 광범위한 커뮤니티 지원과 풍부한 문서를 제공.

1.4 주요 기술과 통합

  • Spring Framework와 Spring Boot는 Spring Data, Spring Security, Spring MVC, Spring Batch 같은 모듈을 지원.

2. 차이점

     
항목 Spring Framework Spring Boot
설정 방식 XML 또는 Java Config 설정이 필요. 기본적으로 자동 설정(Auto Configuration) 제공.
복잡성 많은 설정과 구성 작업이 필요함. 설정이 단순화되어 빠르게 시작 가능.
의존성 관리 개발자가 필요한 라이브러리를 개별적으로 추가. Starter Dependencies로 필요한 라이브러리를 묶음으로 제공.
내장 웹 서버 별도의 웹 서버(Tomcat, Jetty 등)를 설치해야 함. **내장 웹 서버(Tomcat, Jetty)**를 포함하여 바로 실행 가능.
실행 방식 주로 WAR 파일로 패키징하여 외부 서버에서 실행. JAR 파일로 패키징하여 자체적으로 실행 가능.
애플리케이션 유형 대규모, 복잡한 애플리케이션 개발에 적합. 소규모에서 대규모까지 신속한 개발이 필요한 프로젝트에 적합.
배포 시간 설정 작업과 외부 서버 배포가 추가로 필요해 시간이 오래 걸릴 수 있음. 기본 설정으로 실행 가능해 배포 시간이 짧음.
초보자 접근성 학습 곡선이 가파르고, 설정 작업이 번거로울 수 있음. 초보자에게 친화적이며, 설정 없이 빠르게 프로토타이핑 가능.

트랜잭션(Transaction)

1. 개념

  • 트랜잭션은 데이터베이스에서 데이터를 일관성 있게 유지하기 위해 실행되는 작업의 단위야.
  • 트랜잭션은 다음 4가지 특성(ACID)을 만족해야 해:
    • 원자성(Atomicity): 트랜잭션 내의 모든 작업은 성공하거나 모두 실패해야 함.
    • 일관성(Consistency): 트랜잭션 실행 전후 데이터베이스는 항상 일관된 상태여야 함.
    • 격리성(Isolation): 트랜잭션은 서로 간섭하지 않아야 함.
    • 내구성(Durability): 트랜잭션 완료 후 데이터는 영구적으로 저장돼야 함.

2. 예제

  • 은행에서 돈을 송금하는 경우:
    1. 계좌 A에서 돈을 인출.
    2. 계좌 B에 돈을 입금.
    • 이 두 작업은 하나의 트랜잭션으로 묶여야 함. 하나라도 실패하면 두 작업 모두 취소돼야 함(롤백).

하이버네이트(Hibernate)

1. 개념

  • Hibernate는 ORM(Object-Relational Mapping) 도구로, 객체(Object)와 관계형 데이터베이스(Table)를 매핑해준다.
  • 즉, SQL을 직접 작성하지 않고, Java 객체로 데이터베이스를 조작할 수 있게 해주는 라이브러리야.

2. 주요 특징

  1. JPA(Java Persistence API) 구현체:
    • Hibernate는 JPA 표준을 구현한 대표적인 라이브러리.
  2. SQL 자동 생성:
    • Hibernate는 Java 객체와 데이터베이스 테이블을 매핑하여, 필요한 SQL을 자동 생성.
  3. 캐싱:
    • Hibernate는 1차/2차 캐싱을 지원해 성능을 최적화.
  4. 트랜잭션 관리:
    • Hibernate는 트랜잭션 관리 기능을 제공하며, JPA와 연동해 더 쉽게 사용할 수 있음.

트랜잭션과 Hibernate의 관계

Hibernate는 데이터베이스 작업을 수행하기 위해 트랜잭션을 관리하고 실행해.
트랜잭션 없이 데이터베이스 작업을 수행하면 데이터 일관성이 깨질 가능성이 높아.

1. Hibernate에서 트랜잭션 사용 예제

Session session = sessionFactory.openSession();
Transaction transaction = null;

try {
    transaction = session.beginTransaction(); // 트랜잭션 시작
    User user = new User();
    user.setName("John Doe");
    session.save(user); // 데이터베이스에 저장
    transaction.commit(); // 트랜잭션 커밋
} catch (Exception e) {
    if (transaction != null) {
        transaction.rollback(); // 에러 시 롤백
    }
    e.printStackTrace();
} finally {
    session.close();
}

2. Spring과 Hibernate 트랜잭션

Spring은 트랜잭션 관리 기능을 제공하며, Hibernate와 잘 통합된다.

  • @Transactional 애노테이션으로 트랜잭션을 선언적으로 관리.

예제:

@Service
@Transactional // 트랜잭션 관리
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public void createUser(User user) {
        userRepository.save(user);
    }
}

트랜잭션 + Hibernate + Spring의 동작 원리

  1. Spring이 트랜잭션 시작.
  2. Hibernate가 Java 객체를 데이터베이스 작업(SQL)으로 변환.
  3. 작업 완료 시 트랜잭션을 커밋하여 데이터베이스에 반영.
  4. 오류 발생 시 트랜잭션을 롤백하여 데이터베이스 상태를 복원.

정리

  • 트랜잭션은 데이터 작업의 일관성을 보장하기 위한 작업 단위.
  • Hibernate는 Java 객체와 데이터베이스를 연결해주는 ORM 도구.
  • Hibernate는 트랜잭션을 통해 데이터의 안정성과 무결성을 보장하며, Spring과 함께 사용하면 트랜잭션 관리를 더 간단히 처리할 수 있어.