일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 즉시로딩
- BOJ
- 힙
- 이진탐색
- 다대다
- dfs
- 낙관적락
- 연관관계
- 스토어드 프로시저
- 동적sql
- execute
- 백트래킹
- JPQL
- 지연로딩
- 일대다
- 연결리스트
- shared lock
- 데코레이터
- CHECK OPTION
- FetchType
- eager
- querydsl
- 비관적락
- exclusive lock
- 다대일
- 유니크제약조건
- PS
- 스프링 폼
- fetch
- SQL프로그래밍
- Today
- Total
목록전체 글 (555)
흰 스타렉스에서 내가 내리지
![](http://i1.daumcdn.net/thumb/C150x150.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/cQ1HnR/btstG7bhtwA/1mp21TUwBz32ck3qkl993k/img.png)
도메인 모듈을 분리해보자 Storage 모듈을 Runtime Only로 의존하게 하고, Storage 모듈은 Domain 모듈을 Compile Only로 의존하게 된다. 이렇게 되면 실제 Runnable 한 HTTP API모듈 쪽은 Storage 모듈이 Runtime 의존이기 때문에 Storage 모듈의 존재 자체를 모른다. 오직 Domain 모듈만을 아는 구조가 되는 것이다. 그리고 Storage 모듈이 Domain 모듈을 Compile로 의존한다. 일단 다음과같은 폴더 구조를 만들고, 그전에 settings.gradle에 include 하는거 잊지말고 api 모듈에 의존성 다음과 같이 추가하고, db 모듈은 runtimeOnly로 바꾼다. 또 storage 모듈에서도 compileOnly로 domai..
![](http://i1.daumcdn.net/thumb/C150x150.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/luuqL/btstxQIjMaX/x4RS0ig0JXJyVtzOaZ0pD0/img.png)
DB 모듈을 추가해보자 만약 에플리케이션 모듈을 하나로 운영하는 곳을 보면 의존성이 이렇게 되어 있을 것이다. 이렇게 보다는, 다음과 같이 DB 모듈을 추가로 만들어보자 db 모듈을 분리하지 않으면, demo-api의 설정파일에 데이터베이스 관련된 설정들(엔드포인트, 아이디, 비번)이 들어갈 것이다. API 모듈에서는 실제 실행되는 모듈의 관심사와 밀접하게 연관된 설정들만 넣도록 하자. Kotlin에서 jpa를 사용하기 위해서 allOpen{}을 gradle 파일에 넣어준다. 위와 같이 jpa를 implementation 이 아닌 api 키워드를 이용해서 하면, 상위(여기서는 demo-api)에서 직접적으로 JPA Repository 같은 거를 사용할 수 있는 형태가 된다. 격리를 하는 것이 좋아보인다...
![](http://i1.daumcdn.net/thumb/C150x150.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/Cnc8X/btstx7i2qvP/fZKWkbDrzvFQCp0jkBKEC1/img.png)
플러그인 버전이나 각종 변수들, 의존성 버전 같은 것들을 한 곳에 모아서 관리하는 방식을 알아보자. 루트에 gradle.properties 파일 추가 옆에 보고 작성 이렇게 변수를 작성해서 매핑 플러그인 같은 경우에도 예를들어 코틀린 버전을 올리거나 스프링부트 버전을 올리거나 할 때, 버전 정보가 파편화되있으면 관리하기 까다로운 부분이 있는데, 그것을 gradle.properties에 모아서 사용한다. 이것은 settings.gradle.kts에서 한다. 이렇게 하면 build.gradle.kts 에 plugins에 버전을 지울 수 있다. 이대로 demo-api 를 run 해보면 잘 실행이 되는 것을 볼 수 있다. 이런 식으로 관리하면 스프링 버전을 올리거나 코틀린 버전이 올라갈 때 대응이 쉬워진다. d..
![](http://i1.daumcdn.net/thumb/C150x150.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/xOMxQ/btstw1jktr1/caJ6Y3LNpsP0SwUdhKcKX0/img.png)
include 추가 같은 이름의 디렉토리 추가 전체 src 폴더를 demo-api로 옮긴다. 원래 이런 구조로 되어있는 build.gradle 을 allprojects{}, subprojects{} 구조로 변경 spring-boot-starter-web 의존성은 모든 서브 모듈에 필요한게 아니라면 지운다. plugins{}는 지금 이런 구조로 되어 있는데, Root에 적용될 필요가 없다면 apply false 를 추가해준다. 모든 서브 모듈에 적용되어야 하는 플러그인을 추가해준다. apply(plugin = "org.jetbrains.kotlin.jvm") apply(plugin = "org.jetbrains.kotlin.plugin.spring") apply(plugin = "org.springfram..
![](http://i1.daumcdn.net/thumb/C150x150.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/dn9px9/btstwGsHFg8/LWsxZK1m2bZMQILcPQ8QQK/img.png)
# 멀티 모듈 프로젝트 구조가 왜 중요한가? - 나중에 변경하기 어렵다 - 리스크를 줄이기 위한 시작 멀티모듈 프로젝트는 빌드와 배포 프로세스에 밀접한 영향을 미친다. 시스템이 커져갈수록 빌드와 배포 프로세스도 복잡해지면서 나중에 이 프로젝트의 구조를 변경하게 되면, 빌드와 배포 프로세스 모두 변경해야한다. 우선은 META 라는 하나의 멀티모듈 프로젝트로 구성한다. META 모듈은 서비스의 기반이 되는 공통 도메인이다. 모든 모듈들에서 필요로 한다. Track 이라는 도메인은 MySQL에 적재를 하고, Lyric 이라는 가사 도메인은 MongoDB에 적재를 한다면, META 모듈은 어디에 위치시키고 어떻게 구현을 해야할까? META 모듈은 또 다른 멀티 모듈을 필요로 한다. 바로 유관 부서 및 업체 연동..
마이크로서비스 아키텍처는 서로 연결된 미세한 도메인별 작업을 수행하는 여러 컴포넌트로 구성된 애플리케이션을 구축하는 방식을 제공한다. 이 아키텍처는 애플리케이션 전체를 한 덩어리로 디플로이하는 monolithic 한 애플리케이션을 만드는 전통적인 기법과 상반된 기법이다. 마이크로서비스는 각 부분을 물리적으로 분리함으로써 개발과 테스트, 배포, 갱신이 더 쉬운 모듈화된 개발을 돕는다. 마이크로서비스 아키텍처의 아이디어는 monolithic 애플리케이션을 느슨하게 결합된 경량 서비스들의 집합으로 바꾸는 것이다. 각 서비스는 구체적인 작업을 수행하며, 잘 정의된 프로토콜을 사용해 다른 서비스와 통신한다. * monolithic 애플리케이션의 단점 - 애플리케이션 크기가 커짐에 따라 몇 가지 문제가 발생한다. ..
코틀린 컬렉션 타입은 기본적으로 네 가지로 분류할 수 있다. 배열, 이터러블, 시퀀스, 맵 이다. # 이터러블 fun main(){ val list = listOf("red", "green", "blue") for (item in list){ print(item + " ") } } # 컬렉션, 리스트, 집합 - 리스트는 인덱스를 통한 원소 접근이 가능한, 순서가 정해진 원소의 컬렉션이다. 일반적인 리스트 구현은 인덱스를 통한 임의 접근이 가능한 ArrayList와 원소를 빠르게 추가하거나 삭제할 수 있지만, 인덱스로 원소에 접근할 때는 선형 시간이 걸리는 LinkedList가 있다. - 집합은 유일한 원소들로 이뤄진 컬렉션이다. 원소의 순서는 구현에 따라 다르다. - HashSet은 해시 테이블이 기반인..
# 원시 타입(Primitive Types) 장점: 메모리 효율성: 원시 타입은 작은 메모리 공간을 차지하므로, 객체 래퍼 타입보다 메모리 효율적입니다. 특히 배열 등 큰 데이터 집합을 다룰 때 이점이 큽니다. 속도: 연산이나 계산에서 원시 타입을 사용하면 래퍼 타입보다 빠른 처리 속도를 얻을 수 있습니다. 단점: Null 값 처리: 원시 타입은 null 값을 가질 수 없으므로, 값이 없음을 나타내는 데 래퍼 타입에 비해 제한적입니다. 기능의 부족: 원시 타입은 메서드나 기능을 호출할 수 없으므로, 객체 래퍼 타입을 사용할 때와 비교해 기능적인 제약이 있을 수 있습니다. # 래퍼 타입(Wrapper Types) 장점: Null 값 처리: 래퍼 타입은 null을 허용하므로 값이 없음을 나타내는 데 유용합니..
# enum class enum class WeekDay{ MON, TUE, WED, THU, FRI, SAT, SUN } fun WeekDay.isWorkDay() = this == WeekDay.SAT || this == WeekDay.SUN fun main(){ println(WeekDay.MON.isWorkDay()) // false println(WeekDay.SAT.isWorkDay()) // true } # when when을 사용하면 이넘 변수를 각각의 값과 비교할 수 있다. when 식에서 모든 이넘 상수를 다룬 경우에는 else 가지를 생략해도 된다. enum class Direction{ NORTH, SOUTH, WEST, EAST } fun rotateClockWise(directi..
백킹 필드(Backing Field)는 객체 지향 프로그래밍에서 변수 또는 속성의 실제 데이터를 저장하는 데 사용되는 내부 저장 공간입니다. 백킹 필드는 주로 프로퍼티(Property) 또는 멤버 변수의 값을 저장하고 읽거나 쓰는데 사용됩니다. 다른 말로, 백킹 필드는 프로퍼티에 대한 데이터를 실제로 저장하고 있는 곳이며, 프로퍼티의 getter와 setter에서 이 백킹 필드에 접근하여 값을 읽거나 쓸 수 있습니다. 프로퍼티는 사용자가 간편하게 값을 읽고 쓸 수 있도록 getter와 setter를 추상화한 것이며, 이러한 추상화를 통해 필요한 경우 실제 데이터 저장 위치(백킹 필드)를 변경할 수 있습니다. 예를 들어, 다음은 Kotlin에서 백킹 필드를 사용하는 간단한 프로퍼티의 예입니다: class ..