티스토리 뷰
회사에서 개발하는 레거시 프로젝트의 Version Migration 작업을 준비하기 위해 Spring (boot) Version별 변경 내역을 조사하고 있는 내용입니다. 누락되거나 잘못 기술된 내용이 있을 수 있는 점 양해 부탁드립니다.
Spring Boot 2.1.x
- Java 11 지원 (Spring Framework 5.1)
- Spring Boot 2.1 Release Notes · spring-projects/spring-boot Wiki
- 포함 의존성 변경, 삭제 등 (Junit 4.12 → Junit 5.2, Tomcat 8.5.39 → 9.x, Hibernate 5.2 → 5.3)
- Spring Framework 5.1
- Java 8 ~ 11
- CGLIB 3.2 fork(Java 9+ API로 위임)
- @Profile에 and, or expression 지원
- Hibername와 read-only transaction 사용 시 Memory에 Entity Snapshot이 남지 않습니다.
- 로거 설정 개선, 컴포넌트 스캐닝 성능 개선 용도의 컴포넌트 인덱스 기능 제공, 함수형 프로그래밍 스타일 지원, 코틀린 지원, 리액티브 프로그래밍 모델 지원, DataSize Type 등
- 포함 프로퍼티 변경 (servlet path, HibernateProperties 별도 분리)
- Spring JCL - JCL Interface가 잘 사용되지 않음으로써 (Runtime Logger Lookup이 복잡도 등의 문제) JCL을 사용하던 기존 코드를 쉽게 SLF4J로 전환하기 위해 추가한 JCL 용 브리지 모듈이다. (JCL-over-SLF4J 대체)
- Auto-Configuration Exclusion
@EnableAutoConfiguration
,@SpringBootApplication
,@ImportAutoConfiguration
spring.autoconfigure.exclude
에서 적용된 제외 설정이 이제 Local 환경에서만 적용되는 것이 아니라 모든 환경에서 일관되게 적용됩니다. - Log Group application.property, yml에서
logging.group.{group-name}={Loggers...}
동일한 Logging 구성 정보를 적용할 Logger 들의 그룹을 정의하는 속성이 지원됩니다.loging.level.{group-name}=DEBUG
- 기본 제공 그룹으로는 org.springframework.web, org.jooq.tools.LoggerListener 등이 있습니다.
- @EnableAsync, @EnableScheduling, spring-boot-starter-data-jdbc 등 추가 지원
- Bean Override 비 허용 - 동일한 이름의 Bean을 중복으로 정의하고 ApplicationContext에 등록할 때 기존에 등록된 Bean을 덮어 쓸지 말지 결정하는 옵션입니다.
spring.main.allow-bean-definition-overriding = false
(default, BeanDefinitionOverrideException 발생)- Spring Boot의 Auto Configuration과 사용자의 Configuration, Component 등이 중복됨으로써 발생하는 상황으로 @ConditionalOnMissingBean와 같은 필터링 용 제약을 거는 것을 권장합니다.
- Spring Data JPA 저장소 초기화에 대해서 Lazy mode 지원 (bootstrap mode)
- Spring Actuator /info, /health end-point 사용자의 Spring Security 설정으로 인가 처리가 적용되지 않는 한 /info, /health end-point는 인증, 인가 없이 접근 가능한 공개 API가 됩니다.
- @WebMvcTest and @WebFluxTest Security Configuration @WebMvcTest, @WebFluxTest Slice Test에서 사용자가 정의한 보안 설정인
WebSecurityConfigurer, ServerHttpSecurity
bean을 자동으로 구성 정보에 포함합니다. - Context ApplicationConversionService Support
ApplicationConversionService
가 기본적으로 등록되며, @Value Annotation에 사용할 수 있습니다. - h2 Compatibility mode 사용 방법 변경 - 이전 버전까지는
spring.jpa.properties.hibernate.dialect
설정에 따라 Compatibility mode가 설정되었으나 현재는spring.datasource.url=jdbc:h2...;MODE=MYSQL
직접 설정해주어야 mode type이 적용되도록 변경되었습니다. - Property Migrator 달라진 property 정보를 반영하지 않아도 정상적으로 Application을 수행할 수 있도록 도와주는 Module입니다. (Runtime에서 동작)
Spring Boot 2.2.x
- Java 13 지원 (Spring Framework 5.2)
- Spring Boot 2.2 Release Notes · spring-projects/spring-boot Wiki
- 포함 의존성 변경, 삭제 등
- Jakarta EE dependencies 추가 및 기존 JavaEE dependencies 이전
ReactiveWebServerApplicationContext
사용 중단
- Spring Framework 5.2
- Spring WebFlux Support for Kotlin Coroutines - Spring WebFlux에서 이제 Kotlin의 Coroutines을 지원합니다.
- RSocket, R2DBC 지원
- Spring MVC Router Support for Kotlin DSL Web Flux에서의 DSL을 통한 Router 등록 방식과 유사한 모델을 MVC에서도 지원합니다.
- @Configuration에 대한 Bean Lite Mode 지원 (proxyBeanMethods = false) - Configuration 생성 시 Proxy를 통해 Configuration Instance를 Wrapping 하는 작업을 수행하지 않도록 설정하는 속성으로 기본 제공되는 AutoConfiguration에 적용하기 위해 추가되었습니다.
- 성능 향상 (구동 시간 감소)가 있으나, Configuration Method를 여러 번 호출할 경우 매번 Instance를 생성해 반환하기 때문에 조심하여야 합니다.
- Spring Security 5.2
- Oauth 2.0 Client, Resource Server, Authorization Server(별도 프로젝트) 추가
- Hello Spring Security 5.2
- Spring Data Moore
- 선언적 리액티브 트랜잭션 지원
PlatformTransactionManager에서 ReactiveTransactionManager
로 전환되었습니다.TransactionalOperator
및@Transactional
구성이 통합되었습니다.
- 리액티브 QueryDSL 지원
- 기타 성능 향상
- What's new in Spring Data Moore?
- 선언적 리액티브 트랜잭션 지원
- 프로퍼티 변경
- Spring Actuator HTTP Trace disable by default - 많은 리소스를 소모하고, in-memory에 저장하는(기본 구현) 방식이 Clustering 구조에 맞지 않아 기본적으로 비활성화되었습니다.
- Spring Cloud Sleuth 사용을 권장합니다.
- Spring Cloud Sleuth
- Prometheus Push Gateway를 위한 https end-point 추가
- Lazy initialization by Global
spring.main.lazy-initialization
property를 통해 Application 전역에 Lazy initialization를 지원할 수 있으며,@Lazy(false)
나LazyInitializationExcludeFilter
를 통해 지연 초기화 대상에서 제외할 수 있습니다. - JMX disabled by default spring.jmx.enabled=false
- spring-boot-starter-test default by JUnit 5 기본 사용하는 Junit Version이 4에서 5로 변경되었습니다.
- Hibernate Dialect - Hibernate가 감지한 Database dialect를 사용하던 설정에서 사용자 정의를 통해 선택 가능하도록 변경되었습니다.
- jOOQ RecordListenerProvider 다수의
RecordListenerProvider
Bean을 등록하던 구조에서RecordListenerProvider[]
방식으로 반환하는 Bean을 정의하는 방식으로 변경되었습니다. - Shutdown configuration of task execution and scheduling 자동 구성된
TaskExecutor, TaskScheduler의
종료 시 필요한 설정을 적용할 수 있도록spring.task.execution.shutdown
andspring.task.scheduling.shutdown
이 추가되었습니다. (gracefully-shotdown) - Kubernetes detection @ConditionalOnCloudPlatform을 통해 현재 Application이 Kubernetes 위에서 동작하고 있는 상태인지 감지할 수 있습니다.
- Test Application Arguments in integration tests 통합 테스트에서 사용할 Application Argument를 정의할 수 있는
ApplicationArguments
Bean이 추가되었습니다. - @ConfigurationProperties scanning @ConfigurationProperties이 적용된 Class를 Scan 하여 Bean으로 등록할 수 있는 @ConfigurationPropertiesScan, @EnableConfigurationProperties이 추가되었습니다.
- Immutable @ConfigurationProperties binding @ConfigurationProperties이 붙은 Class를 불변 객체로 선언할 수 있는 @ConstructorBinding을 지원합니다. (이는 Records에도 적용됩니다.)
- 생성자를 통한 객체 생성을 지원하며 여러 생성자가 존재할 경우 특정 생성자 위에 정의하면 됩니다.
- Callback for Redis cache configuration ****RedisCacheManager의 불변 설정을 위한 RedisCacheManagerBuilderCustomizer가 추가되었습니다.
- Qualifier for Spring Batch datasource Spring Batch에서 사용될 DataSource Bean을 설정하기 위한 @BatchDataSource 가 추가되었습니다. ****
- Idle JDBC connections metrics 현재 대기 상태에 있는 DataSource Connection Pool의 크기를 확인할 수 있는 Metric 정보가 추가되었습니다.
Spring Boot 2.3.x
- 자바 14 지원
- Gradle 5.6.x (Legacy), 6.3+
- Spring Boot 2.3 Release Notes · spring-projects/spring-boot Wiki
- 포함 의존성 변경, 삭제 등
- Spring Cloud Connectors starter has been removed
- Junit Jupiter 5.6
- Mockito 3.3
- Jackson 2.11
- Date, Calendar의 Timezone 표현 방식이 표준에 맞게 변경되었습니다.
+00:00
- 필드 명 없이 JSON Array를 만들 수 없도록 변경되었습니다.
- JSON 생성 시 Serialization 순서를 결정할 수 있습니다.
@JsonProperty(index = )
- 표준 통화에 대한 객체를 제공하는 Joda Money를 지원하기 위해 새로운 모듈이 추가되었습니다.
jackson-datatype-joda-money
- Date, Calendar의 Timezone 표현 방식이 표준에 맞게 변경되었습니다.
- Spring Integration 5.3
- RSocket support for Spring Integration
spring-integration-rsocket
의존성 추가 및 해당 의존성 사용 시IntegrationRSocketEndpoint, RSocketOutboundGateway
을 통한 end-point 설정이 가능합니다.
- RSocket support for Spring Integration
- Spring Security 5.3
- Oauth 2.0 Client, Resource Server 개선
- Spring Kafka 2.5, Spring HATEOAS 1.1
- Spring Data Neumann
- Cassandra v4 이전 버전과 호환되지 않는 요소들이 다수 추가되었습니다.
- Couchbase SDK v3 이전 버전과 호환되지 않는 요소들이 다수 추가되었습니다.
- Elasticsearch 7.5
- MongoDB 4 -
MongoClientSettingsBuilderCustomizer
bean이 필수 드라이버(Mongo Operations) 설정에 적용됩니다.spring-boot-starter-data-mongodb-reactive
의존성의 경우 Mongo Operations이 구성되지 않기 때문에spring-boot-starter-data-mongodb
의존성을 추가하는 것을 권장합니다. - Neo4j Neo4j의 Open Session이 기본적으로 Default 됩니다.
spring.data.neo4j.open-in-view
property를 통해 설정할 수 있습니다. - Data JDBC 2.0
- 낙관적 락 지원,
PagingAndSortingRepository
지원, H2 지원 (모든 기능), 식별자 따옴표, Query Derivation 지원 (query method)
- 낙관적 락 지원,
- R2DBC support
- auto-configuration, health indicator for Connection Factory,
@DataR2dbcTest
- auto-configuration, health indicator for Connection Factory,
- Validation Starter no longer included in web starters - validation 관련 의존성(
javax.validation.*
)은spring-boot-strater-web
에서spring-boot-starter-validation
라는 별도의 의존성으로 분리되었습니다. - Build OCI images with Cloud Native Buildpacks Cloud Native Buildpack을 사용한 Docker Image 구축 방식 지원 및 spring-boot:build-image, bootBuildImage 가 추가되었습니다. (Maven, Gradle)
- Build layered jars for inclusion in a Docker image Jar에서 자주 변경되는 부분을 식별하여 Layer를 분할해 재 사용할 수 있도록 개선되었습니다. (효율적인 Docker Image build를 위함)
- JDK → Library → Application Code 순으로 Layer를 생성합니다.
- Support of wildcard locations for configuration files Configuration File load시 *를 지원합니다.
- Graceful shutdown embedded Jetty, Reactor Netty, Tomcat, Undertow 및 Servlet, Reactive 기반 Application에서 Gracefully shutdown이 지원됩니다.
server.shutdown=graceful, spring.lifecycle.timeout-per-shutdown-phase=10s
- WebServerInitializedEvent and ContextRefreshedEvent - Graceful shutdown 기능 지원의 일환으로 Web Server의 초기화 시점이 변경되었습니다. (새로 고침 이후 → Application Context 새로 고침 이후)
- Spring Actuator Liveness and Readiness probes Application의 활성, 처리 가능 상태를 추적할 수 있는 end-point가 추가되었습니다. (kubernetes 위에서 실행될 경우 자동 설정)
/actuator/health/readiness, management.health.probes.enabled=true
- Date-Time conversion in web applications Application.properties, yml을 통해 시간 및 날짜 변환 시 형식을 지정할 수 있습니다.
ex) spring.mvc.format.date=iso
,spring.mvc.format.date-time, spring.mvc.format.time, spring.webflux.format.date, spring.webflux.format.date-time, spring.webflux.format.time
- Unique DataSource Name By Default 자동 구성된 DataSource가 고유한 이름으로 생성되며, H2 DB 사용 시 Database URL이 testdb를 참조하지 않아 기존(H2를 자동 구성에 의존하여 사용 중이던) Project에서 해당 Version으로 Migration 수행 시 영향을 받습니다.
- Embedded Servlet web server threading configuration Embedded Web Server의 Thread를 구성하는 속성이
server.{tomcat, jetty...}.threads
로 이동되었습니다. - Changes to the Default Error Page’s Content Error Message 및 Binding Error는 기본 Error Page에 포함되지 않습니다.
server.error.include-message, server.error.include-binding-errors
설정을 통해 포함하거나 상황에 따라 제어할 수 있습니다. (always, on-param, never
) - ApplicationContextRunner disables bean overriding by default
SpringApplication
을 통한 실행 방식과 일관성을 제공하기 위해ApplicationContextRunner
에서도 Bean Override를 비 허용합니다.withAllowBeanDefinitionOverriding
을 통해 허용할 수 있습니다. - Activating multiple profiles with @ActiveProfiles @ActiveProfiles에서 쉼표를 통한 다중 Profile을 지원합니다.
@ActiveProfiles({"p1","p2"})
Spring Boot 2.4.x
- 자바 15 지원
- Spring Boot 2.4 Release Notes · spring-projects/spring-boot Wiki
- 포함 의존성 변경, 삭제 등
- Flyway 7 Overall ordering of Java and SQL Callbacks · Issue #2785 · flyway/flyway
- Logback Configuration Properties Logback properties들이
logging.pattern.rolling-file-name
→logging.logback.rollingpolicy.file-name-pattern
과 같은 형대로 변경되었습니다.- logging.logback.{기존 속성 path}
- Hazelcast 4 내부 의존성이 Hazelcast 3.2.x → 4.x로 변경되었습니다. 하위 버전이 필요한 경우
hazelcast.version
property를 통해 사용할 버전을 설정할 수 있습니다. - Neo4 j Spring Data Neo4j
- 버전 관리 체계 변경 Updates to Spring Versions
- Spring Framework 5.3
- Spring Framework 5.3.x가 LTS로 계속 유지되며, 5.4.x를 만들지 않습니다.
- GraalVM 관련 개선
- Spring-R2DBC Module 제공
- Spring Data 2020.0 버전 명명을 Calander 기반으로 변경하였으며, 코드명은 수학자의 이름을 사용하는 것을 유지합니다.
- Neo4j
- R2DBC
- Supported RxJava 3
- Spring Batch 4.3
- Spring Security 5.4
- Spring Integration 5.4
- Spring Kafka 2.6, Spring HATEOAS 1.2, Spring Session 2020.0, Spring Security 5.4…
- Config File Processing (application properties and YAML files) application.properties 및 application.yml 파일의 처리 방법이 변경되었습니다. (properties 파일 안에서 여러 profile 정의 가능) 또한 spring.profiles 대신 spring.config.activate.on-profile을 사용하도록 변경되었습니다.
- 옛날 파일 처리 방식을 사용하려면
spring.config.use-legacy-processing=true
를 사용합니다.
- 옛날 파일 처리 방식을 사용하려면
- Supported Configuration Tree
spring.config.location, spring.config.import
속성 설정 시 configtree, optional 등의 prefix를 지원합니다. - Custom property name support configtree, optional 이외에도 Custem prefix를 정의하여 기능을 확장할 수 있는 방법을 제공합니다.
ConfigDataLoader, ConfigDataLocationResolver
- Layered jar enabled by default Spring Boot 2.3.x 에서 추가되었던 Build layered jars 기능이 기본적으로 활성화되었습니다.
- Importing Additional Application Config application.properties 또는. yml 파일에서
spring.config.import
속성을 통해 Spring 환경을 구성하는 상황에서 같이 참조할 하나 이상의 구성 파일을 지정할 수 있습니다. (spring.config.use-legacy-processing=true
를 사용하지 않는 경우) - Volume Mounted Config Directory Trees
spring.config.import
속성을 통해 ConfigMaps와 같은 Key:Value 형식의 Directory Tree를 가져올 수 있습니다. - Importing Config Files That Have no File Extension 파일 확장자를 작성할 수 없는 Cloud Platform에서
[.extension]
형식의 Hint를 지정하여 파일의 확장자를 특정할 수 있습니다. - Origin Chains
- Startup Endpoint Actuator에서 Application의 시작 정보를 제공하는
startup
end-point를 지원합니다. 제공되는 timeline object의events
array를 통해 생성되는 Bean의 이름이나 시작 및 초기화 지연 시간 등을 식별할 수 있습니다. - Docker/Buildpack Support Maven의
spring-boot:build-image
, gradle의bootBuildImage
task를 통해 생성된 Docker Image를 Docker Registry에 등록하는 기능이 추가되었습니다. - Maven Buildpack Support Maven에서
spring-boot:build-image
을 통해 Docker Image를 생성할 때 모든 Project Module Dependency를 Application Layer에 포함합니다. (여러 Project Module이 존재하는 경우 하나의 Layer에 집약됩니다.) - Gradle Buildpack Support Gradle에서
bootBuildImage
task를 통해 Docker Image를 생성할 때 모든 Project Module Dependency를 Application Layer에 포함합니다. (여러 Project Module이 존재하는 경우 하나의 Layer에 집약됩니다.) - Redis Cache Metric Redis Cache를 사용하는 경우 Micrometer가 응답하는 Metric 정보에서 Cache hit, miss, Cache put, Cache evict 등의 모든 통계 정보를 확인할 수 있습니다.
spring.cache.redis.enable-statistics=true
- Web Configuration Properties Spring MVC, Spring WebFlux에서 지정하는 locale 및 Resource path 등의 Properties 속성들이 해당 Module 여부와 상관없이 일관적으로 구성될 수 있도록 변경되었습니다.
spring.mvc.locale, spring.mvc.locale-resolver, spring.resources.*
→spring.web.locale, spring.web.locale-resolver, spring.web.resources.*
등 - Register @WebListeners in a way that allows them to register servlets and filters Servlet Container가 자체적으로 @WebListener 이 적용된 클래스를 인스턴스화 합니다. 이를 통해 @WebListener가 붙은 객체에게 제공하던 Spring Container를 통한 의존성 주입이 지원되지 않습니다.
- Slice Test for Cassandra
@DataCassandraTest
를 통한 Cassandra Slice Test를 사용할 수 있습니다. - Configuration property for H2 Console’s web admin password H2 Console Admin의 Password를 지정 가능한
spring.h2.console.settings.web-admin-password
속성이 추가되었습니다. - CqlSession-Based Health Indicators for Apache Cassandra Spring Data Cassandra에서 제공하던 Health Indicator가 지원되지 않으며,
CqlSession
기반의CassandraDriverHealthIndicator, CassandraDriverReactiveHealthIndicator
가 추가되었습니다. - Filtered Scraping with Prometheus
/actuator/prometheus
end-point에서 응답하는 Sample을 Filter 하는 용도로 새로운 query parameter가 지원됩니다.? includedNames=jvm_memory_used_bytes - Spring Security SAML Configuration Properties SAML2 관련 acs와 decryption 속성이 추가되었습니다.
- Failure Analyzers 이제 FailureAnalizers가 ApplicationContext 등이 구성되지 않는 경우도 포함합니다. BeanFactoryAware 또는 EnvironmentAware를 구현하여 추가하는 분석기는 ApplicationContext가 만들어지지 않는 경우 사용되지 않습니다.
- Jar Optimizations Spring Boot jar를 생성할 때 모든 비어있는 (마킹 용도의) starter dependencies들이 제거됩니다.
spring-boot-autoconfigure-processor
또한 Build 시에만 유효하며 이후 제거됩니다. - Spring Boot Gradle Plugin Gradle bootJar task의 DSL이 설정 속성이 변경되었습니다.
mainClassName → mainClass
- JUnit 5’s Vintage Engine Removed from spring-boot-starter-test Junit4 vintage engine이 해당 의존성에서 제거되었습니다. (org.junit.Test 등 사용 시 Compile Error 발생) 해당 버전에서 Junit4를 사용하려면 별도의 vintage 의존성을 추가하여야 합니다.
- Support K8s ConfigMap @ConfigurationProperties나 environment 객체를 통해 K8s ConfigMap에 저장된 설정에 접근할 수 있습니다.
- Embedded database detection in-memory로 띄워진 Database가 아닌 경우 Database 초기화 및 사용자 이름 설정 (default = sa)가 사용되지 않습니다. (Server, Hybrid H2, File based Derby, HSQL 등)
spring.datasource.initialization-mode
를 통해 데이터베이스 초기화를 하도록 구성할 수 있습니다.
- User-defined MongoClientSettings no longer customized MongoClientSettings를 Bean으로 정의하여 사용하는 경우 Auto-configuration을 통한 properties가 적용되지 않습니다. 그렇기에
MongoPropertiesClientSettingsBuilderCustomizer
를 활용해 properties, environment를 인자로 넘겨 설정한 다음 반환하여야 합니다. - Metrics export in integration tests
- Elasticsearch RestClient -
RestClient
bean이 더 이상 Auto-configuration 되지 않습니다.RestHighLevelClient
bean은 계속 지원됩니다. - Default Servlet Registration 해당 버전부터 Servlet Container에서 제공하는
DefaultServlet을
등록하지 않습니다.- 사용을 위해서는
server.servlet.register-default-servlet=true
property를 정의하여야 합니다.
- 사용을 위해서는
- HTTP traces no longer include cookie headers by default
- Supported Profile Group 특정 Profile에 여러 Profile들을 묶어 Grouping 하여 같이 사용할 수 있습니다.
spring.profiles.group.{profile}={sub profiles...}
Spring Boot 2.5.x (WIP)
참고 자료
- https://github.com/spring-projects/spring-framework/wiki/What's-New-in-Spring-Framework-5.x
- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.1-Release-Notes
- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.2-Release-Notes
- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes
- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.4-Release-Notes
- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.5-Release-Notes
- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.6-Release-Notes
'Programming' 카테고리의 다른 글
RESTful 설계 원칙에 대한 못다 한 이야기 (1) | 2024.06.15 |
---|---|
Performance : 기본적인 Application Cache 개념과 종류 (0) | 2022.06.25 |
Performance & Scalability : 기본적인 Sharding 개념과 구현 방식 (0) | 2022.04.11 |
소소한 글 : Spring4Shell? 이건 또 뭔지... (0) | 2022.03.31 |
소소한 글 - Java Version 별 변경 내역 정리하기 (9~18) (0) | 2022.03.24 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- URN
- spring AOP
- spring
- lambda
- hypermedia
- THP
- 게으른 개발자 컨퍼런스
- RESTful
- cglib
- java
- Switch
- Distributed Cache
- AMQP
- JDK Dynamic Proxy
- configuration
- Url
- HTTP
- 소비자 관점의 api 설계 패턴과 사례 훑어보기
- Global Cache
- rabbitmq
- 근황
- Local Cache
- JVM
- URI
- Cache Design
- RPC
- mybatis
- JPA
- Data Locality
- 게으른개발자컨퍼런스
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
글 보관함