본문 바로가기

🔓 영구 노트24

plain Jar 파일이 생성되지 않도록 하자 spring boot 프로젝트를 구성하고 build를 실행하면 아래와 같이 2개의 jar 파일이 생성되는 것을 알 수 있습니다. *-SNAPSHOT.jar *-SNAPSHOT-plain.jar 두 개의 jar파일 중 plain이 포함된 것을 `일반` jar 파일이라고 부르고, 포함되지 않은 것을 `실행 가능한` jar파일이라고 부릅니다. (경우에 따라 다르게 부를 수 있습니다) `일반` jar 파일: 일반 jar 파일은 라이브러리 형태의 Java 애플리케이션을 패키징 하기 위해 사용되는 것으로 다른 애플리케이션에서 라이브러리로 사용될 수 있도록 클래스와 리소스만을 포함됩니다. 즉, 애플리케이션을 실행하기 위한 모든 의존성과 실행 환경을 포함하지 않기 때문에 독립적으로 실행이 불가합니다. `실행 가능한` .. 2024. 1. 8.
git 브랜치 전략 톺아보기 git, gihub, gitlab, trunk based development 브랜치 전략에 대해 간략하게 소개하도록 하겠습니다. 각 전략의 장/단점을 파악하여 프로젝트 성격에 맞게 적용해 보면 좋을 것 같습니다. Git Flow Git Flow는 Vincent Driessen이 제안한 모델로, 기능 개발, 릴리스 준비, 유지보수, 핫픽스 등을 관리하기 위해 여러 종류의 브랜치를 사용합니다. 주요 브랜치는 master, develop, feature, release, hotfix입니다. master: 안정적인 릴리스 버전을 관리합니다. develop: 다음 릴리스를 위한 개발 작업이 진행됩니다. feature: 새로운 기능 개발을 위한 브랜치입니다. release: 릴리스 준비를 위한 브랜치입니다. ho.. 2024. 1. 4.
RuntimeException이 왜 기본 롤백인지 RuntimeException과 Error가 spring boot에서 org.springframework.boot:spring-boot-starter-data-jpa를 사용할 때 기본 롤백 설정인 것을 어렵지 않게 알 수 있습니다. spring boot에서 RuntimeException과 Error가 왜 기본 롤백으로 설정되어 있는지 Transaction 어노테이션의 noRollbackFor, RollbackFor 옵션을 넣어주는 것이 어떻게 롤백 여부를 결정할 수 있는 것인지 알아보도록 하겠습니다. 아래와 같은 순서로 글을 작성해 보겠습니다. RuntimeException, Error가 왜 기본 롤백인지 rollbackFor, noRollbackFor 값을 설정하면 어떻게 롤백 여부를 결정하는가? Ro.. 2023. 12. 21.
autoprefixer: start value has mixed support, consider using flex-start instead just release it 프로젝트 코드 구현을 하면서 github actions에 배포를 하는데. 항상 그렇듯 로컬에서는 문제가 없지만 액션이 실패했습니다. 예외 메시지가 친절하게 나와 있어서 해결에는 어려움이 없지만 autoprefixer가 하는 역할에 대해서 조사를 해봤습니다. autoprefixer는 css를 브라우저 간 호환성을 높이기 위해 자동으로 조정해주는 도구로 display: flex를 사용할 때 사용되는 aligh-items, justify-content가 브라우저 호환이 좋지 못할 때 warning 메시지를 내보내줍니다. 예를 들어 아래와 같은 css 코드가 있다고 할 때 .container { display: flex; align-items: start; /* 이 부분이 문제를 일.. 2023. 12. 17.
github actions는 ㄱr끔 대소문ㅈr를 구분ㅎr지 못한ㄷr. github actions가 분명히 있는 Header 컴포넌트를 찾지 못해 액션이 실패했습니다. 로컬에서는 npm run build가 문제없이 성공했기 때문에 이유를 쉽게 찾을 수 없었는데요. 그러다가 stackoverflow에서 다음 글을 찾게 되었습니다. (stackoverflow 1줄 요약 github config에 의해 가끔 디렉터리 이름 변경을 감지하지 못할 수 있다.) 글을 읽고 로컬에 저장된 디렉터리 이름과 원격 저장소에 저장된 디렉터리 이름을 확인해 봤더니 다르게 저장되어 있었습니다. 문제 해결을 위해서는 로컬과 원격 저장소에 저장된 디렉토리 이름을 동기화 주어야합니다. 다음 과정을 모두 수행해주면 해결할 수 있습니다. git config.ignoreCase false 명령어 입력 변경 내.. 2023. 12. 16.
코틀린 일급 컬렉션은 멋지지 일급 컬렉션은 하나의 컬렉션만 wrapping 하고, 그 외 다른 멤버 변수가 없는 클래스를 의미합니다. 일급 컬렉션은 비즈니스 로직을 캡슐화하여 관리하고, 불변성을 보장하여 데이터의 안정성을 향상합니다. 개념적인 부분은 위와 같고, 예시 코드를 살펴보겠습니다. // value는 1~13 값 저장, pattern은 스페이드, 클로버, 하트, 다이아몬드 저장 data class Card(val value: Value, val pattern: Pattern) 위와 같은 data class가 정의되어 있다고 할 때 // 일급 컬렉션 미적용 var deck: MutableList = mutableListOf() // 일급 컬렉션 적용 data class Deck( private val cards: Mutable.. 2023. 12. 14.
목록 관리는 단순하게 이 글을 읽고 있다면 카테고리를 상세하게 생성하여 관리해 봤던 경험이 있을 거라고 생각합니다. 저 또한 블로그를 관리할 때, 노트를 정리할 때 가장 먼저 하는 것이 카테고리를 나누는 것이었는데요. 이미 많이 경험 했겠지만 카테고리를 상세하게 나누면서 글을 깔끔하게 정리하는 것은 어렵습니다. 카테고리를 다음과 같이 나눴다고 가정해 보겠습니다. 데이터베이스 네트워크 알고리즘 생각정리 위와 같이 나눴을 때 1년 동안 알고리즘을 공부하지 않는 경우만 놓고 봐도 현재 무엇을 하고 있는지에 따라 카테고리에 새로운 항목이 추가되는 것이 결정됩니다. 특정 카테고리의 글은 1년이고, 2년이고 예전 그대로 그 수를 유지할 수 있다는 것입니다. 이 상태가 지속적으로 반복되면 이른바 "죽은 카테고리"가 됩니다. (죽은 카테고.. 2023. 12. 11.
git hooks를 사용하여 commit 메시지 검사하기 commit 메시지를 구조화하고 빠르게 이해하기 위해 commit 컨밴션을 많이 사용하는데요. 보통 컨벤션은 commit 메시지에 prefix를 작성하는 구조를 사용합니다. 가령 feat: 새로운 기능이 추가된 경우 docs: readme와 같은 문서를 수정한 경우 test: 테스트를 추가, 수정한 경우 와 같은 단어들을 prefix로 사용하는데요. 해당 단어들을 사용하여 commit 메시지를 작성하면 메시지를 읽는 것만으로 테스트를 수정했는지 새로운 기능을 추가했는지 이해할 수 있습니다. commit 컨밴션은 문서로 정의해 두고 실제로 commit을 할 때 검사하지 않는 경우도 존재합니다. 이런 경우 컨밴션을 사용하지 않은 commit이 repository에 반영될 수 있기 때문에 개발 중인 프로젝트에.. 2023. 2. 27.
모든 프로젝트에 .gitignore 적용 .gitignore는 Github 사용 시에 커밋하고 싶지 않은 파일들을 정의하는 용도로 많이 사용됩니다. 보통은 프로젝트 단위로 설정을 하게 되지만 spring boot, node + express, react와 같은 프로젝트에서 각각 커밋하고 싶지 않은 파일들이 다르기 때문인데요. 몇가지 파일들 예를 들어 intelliJ를 사용한다면 .idea 디렉터리 하위 파일들 그리고 mac을 사용한다면 .DS_Store와 같은 파일들을 각각의 프로젝트에서 설정하는 것보다는 전체 프로젝트에 적용하는 것이 편하고 효율적일 수 있습니다. 이런 경우 아래 명령어를 실행하여 .gitignore를 전역으로 설정할 수 있습니다. // 루트에 .gitignore 파일 생성 vi .gitignore // 생성된 .gitigno.. 2023. 2. 20.
유닛 테스트와 통합 테스트를 gradle 명령어로 분리하자 많은 테스트와 기능이 있는 프로젝트에서 리팩토링 또는 기능 추가를 하게 된다면 현재 작성하고 있는 코드가 다른 코드에 영향을 미치고 있지는 확인하기 위해 테스트를 여러 번 실행하게 됩니다. 이때, 통합 테스트와 유닛 테스트가 같은 패키지 하위에 있다면 통합 테스트 외부 의존성 설정 시간 때문에 테스트에 많은 시간을 사용합니다. (근처 카페에서 커피 포장해 와도 테스트가 실행 중일 수 있습니다...🤣🤣) 유닛 테스트와 통합 테스트의 실행 목적을 스피커에 빗대어 나름의 생각을 정리하면 다음과 같습니다. 유닛 테스트: 재생을 누르면 내부 회로가 재생 신호를 받는가? 내부 회로는 다음 재생해야 할 음성이 무엇인지 알 수 있는가? 내부 회로는 스피커로 재생해야 할 음성을 전송할 수 있는가? 통합 테스트: 재생 버.. 2023. 2. 18.
Jnit5 @Nested 사용하여 테스트 가독성 높이기 어떤 서비스를 개발해도 시간이 지남에 따라 서비스는 복잡해지고 규모는 커지게 됩니다. 점점 복잡한 기능을 가지면서 성장하다 보면 어느 순간 개발자 1명이 모든 기능을 이해하기 어려울 정도가 되고, 개발자가 기존의 기능을 수정하거나 새로운 기능을 추가하는 경우 코드가 서비스에 어떤 영향을 끼치는지 파악하기 힘들 정도가 됩니다. 여기까지 테스트 코드가 하나도 없다고 한다면 "진정한 기도 메타가 시작되지 않을까?"라는 생각이 듭니다. 이런 의미에서 테스트 코드는 개발자가 수정, 추가한 코드가 다른 코드에 영향을 주지 않는다는 보증의 의미로 "절대 뚫리지 않는 창"처럼 생각되기도 합니다. 하지만 이러한 테스트는 아무런 제약 없이 작성하면 코드를 작성한 개발자를 제외하고, 다른 사람들은 코드를 이해하는데 어려움이.. 2023. 2. 5.
코틀린 coroutine dispatcher 3종 비교 참고문서 kotlinx.coroutines 문서 launch, withContext, async 등 코틀린에서 coroutine을 사용하기 위해서는 Thrad를 어떻게 사용할지에 대한 정책을 설정해줘야 합니다. kotlin에서는 이러한 정책을 Dispatcher라고 부르며 다음과 같은 코드로 정의했습니다. public actual object Dispatchers { @JvmStatic public actual val Default: CoroutineDispatcher = DefaultScheduler @JvmStatic public actual val Main: MainCoroutineDispatcher get() = MainDispatcherLoader.dispatcher @JvmStatic publ.. 2023. 1. 1.