묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결[초중급편] 안드로이드 데이팅 앱 만들기(Android Kotlin)
최신화 된 강의 요청합니다
안녕하세요, 이번에 강의를 구매한 학생입니다. 밑에 글에서 폼도 작성했습니다.강의를 진행하다 보니 강의가 출시된 지 시간이 꽤 지나 대부분의 구현 방식이 현재와 많이 달랐습니다. 특히 Firebase Cloud Messaging이나 CardStackView의 사용법이 강의 내용과 다릅니다. 이로 인해 별도로 혼자 많은 부분을 직접 새로 구현해야 했습니다. 앱은 구현했지만, 이 강좌 수강 목적인 FCM을 이용한 푸시 메시지 보내기가 실제 강의 내용과 많이 달랐습니다.해당 강의에 대한 아쉬움이 남는데 다른 질문글에서 강의를 최신화한다라는 답변을 봤습니다. 최신화 된 강의를 받거나 없으면 환불을 받고자 질문글 남겨요.
-
미해결스프링은 어려워! 코틀린과 Ktor로 백엔드/서버개발 기초정복 (커피주문시스템 개발)
코틀린 코드 보기
위 강사님 화면 에서의 코틀린 파일아래 재 인텔리제이 에서 코틀린 파일강사님 처럼 코틀린 파일의 소스 코드를 보고 싶은데 따로 설정하신 부분이 있을까요? 자바 파일처럼 라이브러리의 구현 코드를 직접 보고 싶네요.
-
미해결입문자를 위한 Spring Boot with Kotlin - 나만의 포트폴리오 사이트 만들기
Docker Compose 배포 시 Jasypt 암호화된 속성 복호화 문제 해결 방법
문제Docker Compose 환경에서 애플리케이션 배포 후, 데이터베이스에 연결할 때 암호화된 설정값을 복호화하지 못해 연결에 실패하는 문제.원인@EnableEncryptableProperties 어노테이션을 누락한 경우, 애플리케이션이 암호화된 속성을 복호화하지 않고 데이터를 사용하려고 시도합니다. 이로 인해 암호화된 패스워드로 데이터베이스에 접속하려 시도하면서 연결 오류가 발생하고, 컨테이너가 종료됩니다.해결 방법JasyptConfiguration.kt 파일에 @EnableEncryptableProperties 어노테이션을 추가합니다.import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties import org.jasypt.encryption.StringEncryptor import org.jasypt.encryption.pbe.PooledPBEStringEncryptor import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @Configuration @EnableEncryptableProperties // 추가해주세요. class JasyptConfiguration { @Bean("jasyptStringEncryptor") fun stringEncryptor(): StringEncryptor { val encryptor = PooledPBEStringEncryptor() val config = SimpleStringPBEConfig() config.password = System.getenv("jasypt.encryptor.key") config.algorithm = "PBEWithMD5AndDES" config.setKeyObtentionIterations("1000") config.setPoolSize("1") config.providerName = "SunJCE" config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator") config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator") config.stringOutputType = "base64" encryptor.setConfig(config) return encryptor } } 예제 소스 코드 Github에서 확인하기
-
미해결[2023 코틀린 강의 무료제공] 기초에서 수익 창출까지, 안드로이드 프로그래밍 A-Z
아름다운 joyce님께.. runonuithread 문의
start() 함수에서는 runonuithread를 사용하는데 pause랑 refresh 함수에서는 runonuithread 를 안써도 되는건가요? btn_start.text = getString(R.string.btn_start)이런 부분을 보게되면 메인화면에 텍스트를 변경하는것 같은데요??
-
미해결자바 개발자를 위한 코틀린 입문(Java to Kotlin Starter Guide)
타입캐스팅 궁금한점 질문드립니다.
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.안녕하세요 코틀린을 처음 접해봤습니다. 질문이 이상하더라도 양해를 구하며 상세히 알려주시면 정말 감사하겠습니다.fun printAgeIfPerson(obf:Any?){val person = obj as? Person......}여기서 질문 드립니다.앞에서 변수 선언을 할 때 val,var을 배웠는데, 매개변수를 선언하는 부분에서 obf:Any? 대신에 val obj:Any?로는 안 쓰나요? 앞에서 모든 변수에는 var/val 을 붙여서 선언한다고 하셨어서요. obj는 매개변수에서 선언된 변수 아닌가요?2.위 코드에서 obj as? Person 의 값이 결과값 또는 null로 나온다고 하셨는데, 그렇게 되면 lvalue인 val person에도 null이 들어갈 여지가 있으므로 val person? 나 val person:Person?으로 선언이 되어야 하는 것 아닌가요?자바와 다른 점이 많아서 헷갈립니다.
-
미해결코틀린으로 만드는 스프링부트
인텔리제이의 run 버튼이 활성화되지 않습니다.
계속 같은 문제가 발생하여 결국 터미널에 ./gradlew bootRun 을 입력하는 것으로 대체했는데, 왜 활성화되지 않는지 궁금합니다.
-
미해결[2023 코틀린 강의 무료제공] 기초에서 수익 창출까지, 안드로이드 프로그래밍 A-Z
viewBinding 관련 질문입니다.
안드로이드 스튜디오의 버전은 2024.2.1이고 viewBinding enabled 를 시도하는데 빨간색 글로 표시됩니다.어떻게 해결해야 하나요?.
-
해결됨[2023 코틀린 강의 무료제공] 기초에서 수익 창출까지, 안드로이드 프로그래밍 A-Z
0:30초 질문입니다.
private lateinit var binding : ActivityMainBinding을 하려고 하는데 불러오지 못합니다. 안드로이드 스튜디오 2024.2.1 버전을 사용 중이라 room 설치할 때도 제미나이 도움으로 진행하느라 build.gradle.kts(Module: app) 코드가 수업 내용과 많이 다릅니다. gradle 문제로 해당 클래스의 패키지가 다운로드 되지 않은거 같습니다.문제의 build.gradle.kts(Module: app) 전체 코드는 아래와 같습니다. ```plugins {alias(libs.plugins.android.application)alias(libs.plugins.kotlin.android)alias(libs.plugins.kotlin.compose)id("org.jetbrains.kotlin.kapt")}android {namespace = "com.example.kotlin06_todolist"compileSdk = 35defaultConfig {applicationId = "com.example.kotlin06_todolist"minSdk = 26targetSdk = 34versionCode = 1versionName = "1.0"testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"}buildTypes {release {isMinifyEnabled = falseproguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"),"proguard-rules.pro")}}compileOptions {sourceCompatibility = JavaVersion.VERSION_11targetCompatibility = JavaVersion.VERSION_11}kotlinOptions {jvmTarget = "11"}buildFeatures {compose = true}}dependencies {implementation(libs.androidx.core.ktx)implementation(libs.androidx.lifecycle.runtime.ktx)implementation(libs.androidx.activity.compose)implementation(platform(libs.androidx.compose.bom))implementation(libs.androidx.ui)implementation(libs.androidx.ui.graphics)implementation(libs.androidx.ui.tooling.preview)implementation(libs.androidx.material3)implementation(libs.androidx.appcompat)implementation(libs.material)implementation(libs.androidx.activity)implementation(libs.androidx.constraintlayout)testImplementation(libs.junit)androidTestImplementation(libs.androidx.junit)androidTestImplementation(libs.androidx.espresso.core)androidTestImplementation(platform(libs.androidx.compose.bom))androidTestImplementation(libs.androidx.ui.test.junit4)debugImplementation(libs.androidx.ui.tooling)debugImplementation(libs.androidx.ui.test.manifest)val room_version = "2.6.1"implementation("androidx.room:room-runtime:$room_version")// To use Kotlin annotation processing tool (kapt)kapt("androidx.room:room-compiler:$room_version")// optional - Kotlin Extensions and Coroutines support for Roomimplementation("androidx.room:room-ktx:$room_version")}```또한 깃허브 주소도 남겼습니다.https://github.com/KrillM/Kotlin06_TodoListFeat.build.gradle.kts(Module :app)에 두 가지 방법(깃 허브에는 없음)도 시도했습니다.1. android 내 databindingdataBinding { enable = true }2. android 내 buildfeature를 아래와 같이 수정buildFeatures {compose = truedataBinding = true}
-
미해결실전! 코틀린과 스프링 부트로 도서관리 애플리케이션 개발하기 (Java 프로젝트 리팩토링)
테스트 fixture
안녕하세요 강사님.코틀린을 배우는데 좋은강의 만들어주셔서 감사합니다. 테스트를 위한 fixture 코드 부분에 대해 의견 여쭤보고 싶습니다.강의에선 직접 엔티티 내부에 테스트를 위한 fixture 함수를 만들어 주셨는데, 팀 내부 의사결정에 따라 두어도 괜찮을 수도 있을 것 같지만 만약 테스트용 코드는 분리해야 한다고 하면아래처럼 테스트 코드 패키지쪽에 fixture 생성을 위한 유틸파일을 만들고, 테스트 코드에서만 Book.fixture(...) 같은 형태로 사용할 수 있도록 엔티티에 비어있는 companion object를 만든 뒤 확장함수를 작성하는 형태로 해도 괜찮을지 의견 여쭤보고 싶습니다.!테스트코드용 유틸 생성 User, Book 등의 엔티티에 비어있는 동행객체 선언엔티티별 Companion 확장함수 작성테스트 코드에서 엔티티.fixture() 형태로 사용
-
미해결실전! 코틀린과 스프링 부트로 도서관리 애플리케이션 개발하기 (Java 프로젝트 리팩토링)
./gradlew test 실행시 인식할수 없다고 뜹니다.
제목 그대로 ./gradlew test 실행시 인식할수 없다고 뜹니다. 이 경우 gradlew이 설치되지 않아서 발생하는 문제인지 궁금합니다.
-
미해결실전! 코틀린과 스프링 부트로 도서관리 애플리케이션 개발하기 (Java 프로젝트 리팩토링)
test 코드 실행시 경고가 발생합니다.
test 코드 실행시 12월 30, 2024 10:47:24 오후 org.junit.platform.launcher.core.EngineDiscoveryOrchestrator lambda$logTestDescriptorExclusionReasons$7INFO: 0 containers and 3 tests were Method or class mismatch라는 경고 메시지가 뜹니다. test 코드가 돌아가는 데 큰 무리는 없지만 개인적으로 궁금해서 질문드립니다.
-
해결됨코틀린 코루틴 완전 정복
[코틀린 코루틴의 정석 책 추첨 이벤트] 강의 구매 기간 관련 문의
안녕하세요 강사님! 책 추첨 이벤트 관련 내용을 보고 강의 구매 기간에 관련하여 여쭤보고 싶은 사항이 있어서 글을 남기게 됐습니다. 여기에 말씀해주신 기간(25.12.19 ~ 26.1.18)에 강의를 구매한 사람만 해당 이벤트에 참여할 수 있는 걸까요 ?? (기간 이전에 강의를 구매한 사람은 해당되지 않는 지 궁금합니다) 감사합니다.
-
해결됨코틀린 코루틴 완전 정복
[코루틴 테스트 심화] runTest의 스레드 관련 문의
안녕하세요 강사님!강의 복습 중에 runTest 관련 문의가 있어서 다음과 같이 질문을 남기게 됐습니다. 코루틴 테스트 심화강의의 4:07초에 시작되는 부분을 보면 runTest를 호출해 실행되는 코루틴은 메인 스레드를 사용한다라고 해주셨습니다. 제가 실제로 runTest를 이용해 코드를 실행시켜 보니 Test worker스레드를 사용하고 있다고 나왔습니다. 실행 코드 @Test fun `메인 스레드만 사용하는 runTest`() = runTest { println("[${Thread.currentThread().name}] 메인 시작") delay(100) println("[${Thread.currentThread().name}] 메인 종료") }결과[Test worker @kotlinx.coroutines.test runner#2] 메인 시작 [Test worker @kotlinx.coroutines.test runner#2] 메인 종료 실제 사용되는 스레드는 Test worker 스레드 이지만, 테스트 코드에서 실행될 때 Test worker 스레드가 메인 스레드 처럼 동작하기 때문에 메인이라고 말씀해주신 걸까요?? 감사합니다!
-
미해결2시간으로 끝내는 코루틴
suspend 함수에 관해 추가적인 질문 있습니다! (runcatching, Result)
9강을 듣고 이해한 바로는, suspend 함수는 Continuation으로 resumeWith의 Result를 통해 내부적으로 콜백을 진행한다고 이해하였습니다!그렇다면 suspend 함수를 사용할때에는 runCatching을 사용하거나, 반환값을 Result로 묶는것은 불필요한 행위라는 결론을 내렸는데, 맞는 생각인지가 궁금합니다!왜냐면 runCatching과 Result 반환값을 활용하게 된다면, 애초에 suspend로 한번 예외처리를 진행했기에 중복된 작업이라고 생각하였기 때문입니다!팀원들과 부트캠프를 통해 진행한 프로젝트를 개선하고자 하는데, suspend 함수에 runCatching을 사용 후 Result로 반환을 하였어서 불필요한 작업이라고 생각되어 개선하고자 하기에 질문드립니다!긴 글 읽어주셔서 감사합니다!
-
해결됨[LV1] Jetpack Compose - UI 연습하기
메인액티비티의 내용이 강의와 다른 것 같습니다.
프로젝트를 만들 때 사진의 Empty Activity를 통해 만들었는데강의에 있는 내용과 메인 액티비티의 내용이 다른 것 같습니다.현재 최신의 안드로이드 스튜디오를 사용 중인데 이것 때문에 그런 것인지그새 바뀐 내용들이 있는 건지 궁금합니다.
-
미해결코틀린 함수형 프로그래밍 - 입문편
실습 자료 부분 업로드 다시 부탁드립니다!
지금 올려주신 실습 자료가 문제가 있는 것 같습니다! 압축을 해제하면 .idea 디렉터리만 존재하고 내부 코드는 없는데 이 확인 부탁드려요!
-
해결됨
jooq로 auditing 구현하는방법
jpa, querydsl 을 완전 걷어내고 jooq 만 사용해보려 하는중인데, 아무래도 모든테이블에 "작성일, 작성자, 수정일, 수정자" 정보가 들어갈거 같아 auditing 기능을 구현 하려 하는중입니다.프로페셔널 상품을 사용하기는 어려운 상황이고, RecordListener 를 이용하여 구현해보려 하는데 리스너가 제대로 등록이 되질 않고 있네요 ㅠㅠ@Repository class UserRepository( private var dslContext: DSLContext, ) { init { val config = dslContext.configuration().derive() config.set(userRecordAuditListener()) dslContext = DSL.using(config) } private fun userRecordAuditListener(): RecordListener { val createAudit: (UsersRecord) -> Unit = { it.createdAt = LocalDateTime.now() it.createdBy = 1 } val updateAudit: (UsersRecord) -> Unit = { it.updatedAt = LocalDateTime.now() it.updatedBy = 2 } return RecordAuditListenerGenerator<UsersRecord>().generate( UsersRecord::class.java, createAudit, updateAudit, ) } fun insertUser(user: UsersRecord): Long? { return dslContext .insertInto( USERS, USERS.NAME, USERS.AGE, ).values( user.name, user.age ).returningResult(USERS.ID) .fetchOneInto(Long::class.java) } } class RecordAuditListenerGenerator<R : UpdatableRecordImpl<R>>( ) { fun generate( recordClass: Class<R>, insertStart: (R) -> Unit, updateStart: (R) -> Unit, ): RecordListener { return object : RecordListener { override fun insertStart(ctx: RecordContext) { println("============== 1 ==============") insertStart(recordClass.cast(ctx.record()) as R) } override fun updateStart(ctx: RecordContext) { println("============= 2 ===============") updateStart(recordClass.cast(ctx.record()) as R) } } } } 데이터는 insert 되는데 작성자, 작성일이 안들어가고 있네요. 찍어놓은 프린트도 호출이 안되구요..혹시 왜그런지 알 수 있을까요..?
-
해결됨코틀린 코루틴 완전 정복
job과 코루틴의 관계?
- 학습 관련 질문을 남겨주세요. 질문을 상세히 작성하면 더 좋습니다.- 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 먼저 좋은 강의 감사합니다! 혼자서 다음과 같이 마구마구 찍어보고있었습니다.이때 저희 예상과 다르게 돌아가서 질문을 드립니다.저의 가설로는 "withContext는 코루틴을 생성하지 않고 Context만 바꾸니 코루틴을 제어하고 추적하는데 사용되는 Job은 새로 만들어지지 않을 것이다. 따라서 job1과 job5는 같을 것이다." 이었습니다.하지만 결과는 새로운 job을 만들고 job의 부모에 job1을 연결시키더군요.동일한 코루틴에서 동작하는데 왜 새로운 Job을 만드는 것인가요?fun main() = runBlocking { val job1 = coroutineContext[Job] // 1 coroutineScope { val job2 = coroutineContext[Job.Key] val job3 = launch {} val job4 = launch {} println("job2 = ${job2}") // 2 println("job2 parent = ${job2?.parent}") println("job3 parent = ${job3.parent}") println("job4 parent = ${job4.parent}") } withContext(Dispatchers.Default) { val job5 = coroutineContext[Job.Key] println("job5 = ${job5}") println("job5 parent = ${job5?.parent}") } println("job1 = ${job1}") } // // job5 = DispatchedCoroutine{Active}@4311e223 // job5 parent = BlockingCoroutine{Active}@1c2c22f3 // job1 = BlockingCoroutine{Active}@1c2c22f3coroutineScope도 주석 1, 2 부분이 같은 코루틴이라 job1이랑 job2가 동일하게 나올 거라 생각했는데 다르군요.그렇다면 현재 상황에서 "하나의 코루틴에 여러 개의 job(?)을 가진 것 아닌가? 이러면 job으로 코루틴을 제어할 수 있나?" 라는 의문이 듭니다. job과 코루틴의 관계가 헷갈립니다😱
-
해결됨코틀린 고급편
지식공유자님 inline에 대해서의 질문과 추가적인 질문 1가지가 있습니다!
먼저 강의 정말 감사합니다.. 질문 폭탄을 드려서 매번 죄송할따름입니다..1번 질문// inline 프로퍼티 class InLinePropertyPerson(val name: String) { inline val uppercaseName: String get() = this.name.uppercase() // 가능 // get() = field.uppercase() // 불가능 }위의 코드처럼 inline 프로퍼티의 경우 this로의 접근은 가능한 반면, backing field 사용시에는 불가능하더라구요!이렇게 되는 이유or원리가 궁금합니다 2번 질문inline 사용의 경우 디버깅이 어렵다는 말을 어느 컨퍼런스의 코틀린 주제 네트워킹 세션때 들은 것 같습니다그런 경우 강의에서 나온 대로 invoke를 유발할 수 있는 함수 파라미터의 경우 noinline을 붙이면 해결되는 부분일지, 아니면 inline을 제외한 일반 함수로 만들어서 디버깅으로 문제점을 찾고 다시 inline fun으로 만드는게 나은지 궁금합니다(어떤 경우 차라리 메서드 콜스택을 만드는 편이 진입점을 파악하기 좋으니깐요!) 3번 질문inline 키워드와는 관계 없는 질문이긴하지만..!// 1번 listOf(1, 2, 3) .map { num -> val result = num + 1 result } // 2번 listOf(1, 2, 3) .map { num -> val result = num + 1 return@map result }위와 같은 코드에서 보면 map의 중간연산에 최종적으로 result가 반환될거야 라고 명시적으로 나타내는 2번 방식과kotlin의 특징인 scope { } 의 최종 line 값을 반환하는 자동기능이 쓰인 1번 방식이 있는데코틀린을 처음 접하거나 모르는 사람이 보면 저기 왜 뜬금없이 쓰이지도 않는 변수인 result가 있지? 이상하군! 이렇게 생각할수도있을것같아요(그냥 예시 중 하나.. 아마 이렇게 생각하시는 분은 없다고 예상)오히려 2번 방식에서 아 여기 map에서의 최종연산 결과는 result구나 하고 map라벨링을 달고 리턴하는게 좀 더 가독성이 있어보이는데요!2번 방식은 라벨링을 해서 jump를 하는 방식이라 안티패턴으로 봐야하는지? 아니면 그렇지 않은지?가 궁금합니다 강의 잘 보고있습니다! 감사합니다 :)
-
해결됨코틀린 고급편
안녕하세요 JMH 설정 관련 팁을 드릴까 합니다! (24년 12월 16일 기준)
jmh { threads = 1 fork = 1 warmupIterations = 1 iterations = 1 } JVM/JDK toolchain: 21kotlin { jvmToolchain(21) }.gradle 버전: 8.8kotlin 버전: 2.0(컴파일러, 언어, API) 위 세 버전 기준으로는id("me.champeau.jmh") version "0.7.2"버전으로 하고$ ./gradlew jmh 실행이 에러없이 잘 작동하고실행결과는 build/reports/jmh/results.txt의 경로가 아닌build/results/jmh/results.txt 경로에 파일이 생긴 것을 확인했습니다