[JPA] λΈλ‘κ·Έ νλ‘μ νΈ λ§λ€κΈ° - 1
π‘
1. REST APIμ λν κ°λ κ³Ό μ£Όμ νΉμ§μΌ μ€λͺ ν μ μλ€.
2. application-dev.yml νμΌμ νμ±νν΄μ μ¬μ©ν μ μλ€.
REST APIλ
REST API(Representational State Transfer Application Programming Interface)λ λ€νΈμν¬ μμμ μμμ μμ²νκ³ μ‘°μνκΈ° μν μν€ν μ² μ€νμΌμ λλ€. REST APIλ μ£Όλ‘ HTTP νλ‘ν μ½μ κΈ°λ°μΌλ‘ νλ©°, ν΄λΌμ΄μΈνΈμ μλ² κ°μ ν΅μ μ λ¨μνκ³ ν¨μ¨μ μΌλ‘ μνν μ μλλ‘νλ νμ€ν λ μ½μμ λλ€.
REST APIμ μ£Όμ νΉμ§
- 무μνμ± (Statelessness): κ° μμ²μ λ 립μ μ΄λ©°, μλ²λ ν΄λΌμ΄μΈνΈμ μνλ₯Ό μ μ₯νμ§ μμ΅λλ€. λͺ¨λ μμ²μλ νμν λͺ¨λ μ λ³΄κ° ν¬ν¨λμ΄ μμ΄μΌ ν©λλ€.
- ν΄λΌμ΄μΈνΈ-μλ² κ΅¬μ‘°: ν΄λΌμ΄μΈνΈμ μλ²λ μλ‘ λ 립μ μΌλ‘ λμνλ©°, ν΄λΌμ΄μΈνΈλ μμ²μ 보λ΄κ³ μλ²λ κ·Έμ λν μλ΅μ μ 곡ν©λλ€.
- μμ κΈ°λ°: APIλ μμ(λ°μ΄ν°)μ λν΄ λμνλ©°, κ° μμμ κ³ μ ν URIλ₯Ό ν΅ν΄ μλ³λ©λλ€. μμμ μλ₯Ό λ€μ΄ μ¬μ©μ, νμΌ, κ²μλ¬Ό λ±μ΄ λ μ μμ΅λλ€.
- HTTP λ©μλ μ¬μ©:
- GET: μμμ μ‘°νν λ μ¬μ©
- POST: μλ‘μ΄ μμμ μμ±ν λ μ¬μ©
- PUT: κΈ°μ‘΄ μμμ μ λ°μ΄νΈν λ μ¬μ©
- DELETE: μμμ μμ ν λ μ¬μ©
- ννμ λ€μμ±: JSON, XML λ± λ€μν νμμΌλ‘ λ°μ΄ν°λ₯Ό μ£Όκ³ λ°μ μ μμΌλ©°, λλΆλΆμ REST APIλ κ°λ³κ³ μ§κ΄μ μΈ JSON ν¬λ§·μ μ νΈν©λλ€.
νλ‘μ νΈ μμ±
build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.10'
id 'io.spring.dependency-management' version '1.1.6'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.h2database:h2'
//runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}
μμ‘΄μ± λ²μ μ§μ (Dependency Scope) νμΈ
implementation: μ ν리μΌμ΄μ μ»΄νμΌ λ° λ°νμ μ νμν μμ‘΄μ±.
compileOnly: μ»΄νμΌ μμλ§ νμν μμ‘΄μ±, λ°νμ μ ν¬ν¨λμ§ μμ.
developmentOnly: κ°λ° μ€μλ§ νμν μμ‘΄μ±, νλ‘λμ λΉλμλ ν¬ν¨λμ§ μμ.
runtimeOnly: λ°νμ μμλ§ νμν μμ‘΄μ±, μ»΄νμΌ μμλ νμνμ§ μμ.
annotationProcessor: μ»΄νμΌ μμ μ΄λ Έν μ΄μ νλ‘μΈμ±μ νμν μμ‘΄μ±. (μ»΄νμΌ κ³Όμ μ€μ νΉμ μ΄λ Έν μ΄μ μ ν΄μνκ³ , κ·Έμ λ°λΌ μΆκ°μ μΈ μ½λλ₯Ό μμ±νκ±°λ κ²μ¦νλ μμ )
testImplementation: ν μ€νΈ μ½λμ μ»΄νμΌ λ° μ€ν μ νμν μμ‘΄μ±.
testRuntimeOnly: ν μ€νΈ μ€ν μμλ§ νμν μμ‘΄μ±, μ»΄νμΌ μμλ νμνμ§ μμ.
λΉλ μμ€ν μ΄λ?
λΉλ μμ€ν μ μννΈμ¨μ΄ κ°λ°μμ μμ€ μ½λλ₯Ό μ€ν κ°λ₯ν νλ‘κ·Έλ¨μΌλ‘ λ³ννλ μΌλ ¨μ κ³Όμ μ μλννλ λꡬ λλ νλ‘μΈμ€λ₯Ό λ§ν©λλ€.
- μ»΄νμΌ:
- κ°λ°μκ° μμ±ν μμ€ μ½λλ₯Ό κΈ°κ³κ° μ΄ν΄ν μ μλ λ°μ΄νΈ μ½λ λλ κΈ°κ³μ΄λ‘ λ³ννλ κ³Όμ μ λλ€. ( μλ° μμ€ νμΌ(.java)μ μ»΄νμΌνμ¬ .class νμΌλ‘ λ³ν)
- μμ‘΄μ± κ΄λ¦¬:
- νλ‘μ νΈμμ μ¬μ©νλ μΈλΆ λΌμ΄λΈλ¬λ¦¬(μ: JUnit, Spring λ±)λ₯Ό μλμΌλ‘ λ€μ΄λ‘λνκ³ , μ μ ν λ²μ μ μ μ§νλ©°, μ΄λ₯Ό νλ‘μ νΈμ ν¬ν¨μν΅λλ€. (Gradle, Maven κ°μ λꡬ μ¬μ©)
- ν¨ν€μ§:
- μ»΄νμΌλ μμ€ μ½λμ ν¨κ» νμν νμΌ(리μμ€, μ€μ νμΌ λ±)μ νλλ‘ ν¨ν€μ§νμ¬ λ°°ν¬ κ°λ₯ν ννλ‘ λ§λλλ€. (μλ° νλ‘μ νΈμ κ²½μ° JAR(Java ARchive) νμΌμ μμ±)
- ν
μ€νΈ μλν:
- μ½λκ° μμ±λλ©΄, λΉλ μμ€ν μ μλμΌλ‘ ν μ€νΈλ₯Ό μ€ννμ¬ μ½λκ° μ¬λ°λ₯΄κ² λμνλμ§ νμΈν©λλ€. (Gradleμ΄λ Mavenμμ JUnit ν μ€νΈλ₯Ό μλμΌλ‘ μ€ν)
- λ°°ν¬:
- λΉλκ° μλ£λλ©΄, νλ‘κ·Έλ¨μ μλ²λ λ°°ν¬ νκ²½μ μλμΌλ‘ λ°°ν¬νλ κΈ°λ₯μ μ§μν μ μμ΅λλ€.(CI/CD λꡬμ μ°κ³νμ¬ μ ν리μΌμ΄μ μ ν΄λΌμ°λ νκ²½μ λ°°ν¬)
Gradleκ³Ό Mavenμ λνμ μΈ λΉλ μμ€ν λꡬλ‘, κ°κ° μμ‘΄μ± κ΄λ¦¬, μ»΄νμΌ, ν μ€νΈ, ν¨ν€μ§, λ°°ν¬ λ±μ μμ μ μλννλ λ° μ¬μ©λ©λλ€.
application.yml
spring:
application:
name: class_blog_jpa_v1
server:
port: 8080
datasource:
url: jdbc:mysql://localhost:3306/jpa_demo?useSSL=false&serverTimeZone=Asia/Seoul
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: asd123
profiles:
active: dev # prod # κΈ°λ³Έ νμ±ν νλ‘νμΌμ devλ‘ μ€μ
application-dev.yml νμΌ μμ
server:
servlet:
encoding:
charset: utf-8 # μμ² λ° μλ΅μ UTF-8 μΈμ½λ©μ μ¬μ©νμ¬ νκΈ λ° νΉμλ¬Έμκ° κΉ¨μ§μ§ μλλ‘ μ€μ
force: true # κ°μ λ‘ UTF-8 μΈμ½λ©μ μ μ©, ν΄λΌμ΄μΈνΈκ° λ€λ₯Έ μΈμ½λ©μ μμ²νλλΌλ 무μνκ³ UTF-8μ μ¬μ©
port: 8080 # μλ²κ° 8080 ν¬νΈμμ μ€νλλλ‘ μ€μ
spring:
mustache:
servlet:
expose-session-attributes: true # Mustache ν
νλ¦Ώμμ μΈμ
μμ±μ μ κ·Όν μ μλλ‘ νμ©
expose-request-attributes: true # Mustache ν
νλ¦Ώμμ μμ² μμ±μ μ κ·Όν μ μλλ‘ νμ©
datasource:
driver-class-name: org.h2.Driver # λ°μ΄ν°λ² μ΄μ€ λλΌμ΄λ²λ‘ H2 DBλ₯Ό μ¬μ©
url: jdbc:h2:mem:test;MODE=MySQL # H2 μΈλ©λͺ¨λ¦¬ λ°μ΄ν°λ² μ΄μ€λ₯Ό MySQL νΈν λͺ¨λλ‘ μ¬μ© (ν
μ€νΈμ©)
username: sa # λ°μ΄ν°λ² μ΄μ€ μ°κ²° μ κΈ°λ³Έ μ¬μ©μ μ΄λ¦
password: # λ°μ΄ν°λ² μ΄μ€ κΈ°λ³Έ λΉλ°λ²νΈ (λΉμ΄ μμ)
h2:
console:
enabled: true # H2 λ°μ΄ν°λ² μ΄μ€ μ½μμ νμ±ννμ¬ λΈλΌμ°μ μμ λ°μ΄ν°λ² μ΄μ€λ₯Ό κ΄λ¦¬ν μ μλλ‘ ν¨
#sql:
#init:
#data-locations:
#- classpath:db/data.sql # μ ν리μΌμ΄μ
μ΄κΈ°ν μ μ€νν λ°μ΄ν° μ½μ
SQL νμΌμ κ²½λ‘ (data.sql)
jpa:
hibernate:
ddl-auto: create # μ ν리μΌμ΄μ
μ΄ μμλ λ λ°μ΄ν°λ² μ΄μ€ ν
μ΄λΈμ μλμΌλ‘ μμ±
show-sql: true # Hibernateκ° μ€ννλ SQL 쿼리λ₯Ό μ½μμ μΆλ ₯
properties:
hibernate:
format_sql: true # μΆλ ₯λλ SQL 쿼리λ₯Ό ν¬λ§·ν
νμ¬ μ½κΈ° μ½κ² μΆλ ₯
defer-datasource-initialization: true # λ°μ΄ν°λ² μ΄μ€ μ΄κΈ°νκ° μ§μ°λλλ‘ μ€μ νμ¬ JPA μ€μ νμ λ°μ΄ν° μ΄κΈ°ν
output:
ansi:
enabled: always # μ½μ μΆλ ₯ μ ANSI μμμ νμ μ¬μ©νλλ‘ μ€μ (μμμ ν΅ν΄ λ‘κ·Έλ₯Ό λ μ½κ² κ΅¬λΆ κ°λ₯)
logging:
level:
'[com.example.class_blog_jpa_v1]': DEBUG # νΉμ ν¨ν€μ§(com.tenco.blog_jpa_step1) μμ€μμ DEBUG λ λ²¨λ‘ λ‘κΉ
μ μ€μ