StateNotifierProvider.family를 사용하고 싶습니다.
해결됨
[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
stateNotifierProvider.family를 사용하려고 하는데, notifier를 리턴하다보니 상태값을 어떻게 리턴해야하는지? 궁금합니다.
- flutter
- 하이브리드-앱
172만명의 커뮤니티!! 함께 토론해봐요.
해결됨
[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
stateNotifierProvider.family를 사용하려고 하는데, notifier를 리턴하다보니 상태값을 어떻게 리턴해야하는지? 궁금합니다.
미해결
[LG유플러스] 앱 만들기 초급 과정 (Flutter)
구글 맵은 확대/축소 버튼 까지 뜨는데요, 흰색 빈 화면으로 나옵니다. 에러 원인을 찾다가 못 찾겠어서요 에러 내용 아래와 같이 올려 드립니다. 어떻게 해결하면 될지 문의 드립니다. [에러 문구] Launching lib\main.dart on sdk gphone x86 64 in debug mode... Running Gradle task 'assembleDebug'... √ Built build\app\outputs\flutter-apk\app-debug.apk. Installing build\app\outputs\flutter-apk\app-debug.apk... D/FlutterGeolocator( 8967): Attaching Geolocator to activity D/FlutterGeolocator( 8967): Creating service. D/FlutterGeolocator( 8967): Binding to location service. D/FlutterGeolocator( 8967): Geolocator foreground service connected D/FlutterGeolocator( 8967): Initializing Geolocator services Debug service listening on ws://127.0.0.1:51323/1PK6KOdyzYM=/ws Syncing files to device sdk gphone x86 64... I/ple.chool_check( 8967): Compiler allocated 4533KB to compile void android.view.ViewRootImpl.performTraversals() D/MapsInitializer( 8967): preferredRenderer: null D/zzcb ( 8967): preferredRenderer: null I/zzcb ( 8967): Making Creator dynamically W/ziparchive( 8967): Unable to open '/data/user_de/0/com.google.android.gms/app_chimera/m/00000002/DynamiteLoader.dm': No such file or directory W/ziparchive( 8967): Unable to open '/data/user_de/0/com.google.android.gms/app_chimera/m/00000002/DynamiteLoader.dm': No such file or directory I/DynamiteModule( 8967): Considering local module com.google.android .gms.maps_dynamite:0 and remote module com.google.android .gms.maps_dynamite:203115000 I/DynamiteModule( 8967): Selected remote version of com.google.android .gms.maps_dynamite, version >= 203115000 V/DynamiteModule( 8967): Dynamite loader version >= 2, using loadModule2NoCrashUtils W/ziparchive( 8967): Unable to open '/data/user_de/0/com.google.android.gms/app_chimera/m/00000006/MapsDynamite.dm': No such file or directory W/ziparchive( 8967): Unable to open '/data/user_de/0/com.google.android.gms/app_chimera/m/00000006/MapsDynamite.dm': No such file or directory I/Google Maps Android API( 8967): Google Play services client version: 12451000 D/CompatibilityChangeReporter( 8967): Compat change id reported: 183155436; UID 10160; state: ENABLED I/Google Maps Android API( 8967): Google Play services package version: 225014047 I/Google Maps Android API( 8967): Google Play services maps renderer version(legacy): 203115000 D/MapsInitializer( 8967): loadedRenderer: LEGACY D/zzcb ( 8967): preferredRenderer: null I/Google Maps Android API( 8967): Google Play services package version: 225014047 I/Google Maps Android API( 8967): Google Play services maps renderer version(legacy): 203115000 D/CompatibilityChangeReporter( 8967): Compat change id reported: 210923482; UID 10160; state: ENABLED D/CompatibilityChangeReporter( 8967): Compat change id reported: 171228096; UID 10160; state: ENABLED I/PlatformViewsController( 8967): Using hybrid composition for platform view: 0 W/Parcel ( 8967): Expecting binder but got null! E/GoogleMapController( 8967): Cannot enable MyLocation layer as location permissions are not granted D/EGL_emulation( 8967): eglMakeCurrent: 0x785afc957d10: ver 3 1 (tinfo 0x785d1cf4d080) (first time) I/bb ( 8967): Successfully registered with Phenotype. E/EGL_emulation( 8967): eglQueryContext 32c0 EGL_BAD_ATTRIBUTE E/EGL_emulation( 8967): tid 8967: eglQueryContext(2122): error 0x3004 (EGL_BAD_ATTRIBUTE) D/HostConnection( 8967): createUnique: call D/HostConnection( 8967): HostConnection::get() New Host Connection established 0x785afc95e850, tid 9046 D/HostConnection( 8967): HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_has_shared_slots_host_memory_allocator ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit ANDROID_EMU_vulkan_queue_submit_with_commands ANDROID_EMU_sync_buffer_data ANDROID_EMU_vulkan_async_qsri ANDROID_EMU_read_color_buffer_dma ANDROID_EMU_hwc_multi_configs GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_3_1 D/EGL_emulation( 8967): eglCreateContext: 0x785afc95e010: maj 1 min 0 rcv 1 D/EGL_emulation( 8967): eglMakeCurrent: 0x785afc95e010: ver 1 0 (tinfo 0x785d1cf4d280) (first time) D/EGL_emulation( 8967): eglMakeCurrent: 0x785afc95e010: ver 1 0 (tinfo 0x785d1cf4d280) (first time)
미해결
자바 개발자를 위한 코틀린 입문(Java to Kotlin Starter Guide)
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 안녕하세요! 선생님! 수업을 잘 듣고있는 백엔드 취준생 입니다! 자바를 공부하다가 코틀린도 공부하면 좋을꺼 같아서 같이 공부하고있는데요.. 혹시 좀더 코틀린을 딥하게 파보고 싶은데 추천하시는 사이트 혹시 있으실까요??
미해결
현재 구글 앱스 스크랩트를 활용해 특정한 셀의 내용을 다운받는 스크립트를 짜고 있습니다. 자꾸 작동이 되지 않아서 챗gpt에 물어보니 그러려면 자바와 연동을 하든 뭘 하든 구글 앱스 스크립트 내에서는 안된다고 하는데 이거 정말 안되는걸까요?ㅠㅠ
해결됨
[코드팩토리] [초급] Flutter 3.0 앱 개발 - 10개의 프로젝트로 오늘 초보 탈출!
인텔칩이 탑재된 맥을 사용하고 있습니다. 그런데 안드로이드 스튜디오를 실행하면 start failed라는 제목의 오류가 발생하며 실행되지 않습니다. 오류 내용은 이렇습니다. Internal error. Please refer to https://code.google.com/p/android/issues java.nio.file.AccessDeniedException: /Users/hanjaejune/Library/Application Support/Google/AndroidStudio2022.2 at java.base/sun.nio.fs.UnixException.translateToIOException(Unknown Source) at java.base/sun.nio.fs.UnixException.rethrowAsIOException(Unknown Source) at java.base/sun.nio.fs.UnixException.rethrowAsIOException(Unknown Source) at java.base/sun.nio.fs.UnixFileSystemProvider.createDirectory(Unknown Source) at java.base/java.nio.file.Files.createDirectory(Unknown Source) at java.base/java.nio.file.Files.createAndCheckIsDirectory(Unknown Source) at java.base/java.nio.file.Files.createDirectories(Unknown Source) at com.intellij.idea.SocketLock.lockPortFiles( SocketLock.java:202 ) at com.intellij.idea.SocketLock.lockAndTryActivate( SocketLock.java:131 ) at com.intellij.idea.StartupUtil.lockSystemDirs( StartupUtil.java:783 ) at com.intellij.idea.StartupUtil.start( StartupUtil.java:169 ) at com.intellij.idea.Main.bootstrap( Main.java:125 ) at com.intellij.idea.Main.main( Main.java:82 ) ----- Your JRE: 17.0.6+0-17.0.6b802.4-9586694 x86_64 (JetBrains s.r.o.) /Applications/Android Studio.app/Contents/jbr/Contents/Home 어떻게 해결하면 좋을까요?
미해결
[코드팩토리] [초급] Flutter 3.0 앱 개발 - 10개의 프로젝트로 오늘 초보 탈출!
import 'package:flutter/material.dart'; import 'package:navigation/layout/main_layout.dart'; import 'package:navigation/screen/route_three_screen.dart'; class RouteTwoScreen extends StatelessWidget { const RouteTwoScreen({super.key}); @override Widget build(BuildContext context) { final arguments = ModalRoute.of(context)!.settings.arguments; return MainLayout(title: 'Route Two', children: [ Text( 'arguments: ${arguments}', textAlign: TextAlign.center, ), ElevatedButton( onPressed: () { // [HomeScreen(), RouteOne(), RouteTwo()] stack 구조! Navigator.of(context).pop(); }, child: Text( 'Pop', ), ), ElevatedButton( onPressed: () { Navigator.of(context).pushNamed('/three', arguments: 999); }, child: Text('Push Named'), ), ElevatedButton( onPressed: () { // Navigator.of(context).pushReplacement( // MaterialPageRoute( // builder: (_) => RouteThreeScreen(), // ), // ); Navigator.of(context).pushReplacementNamed('/three'); }, child: Text('Push Replacement'), ), ElevatedButton( onPressed: () { // Navigator.of(context).pushAndRemoveUntil( // MaterialPageRoute(builder: (_) => RouteThreeScreen()), // (route) => route.settings.name == '/', // ); Navigator.of(context).pushNamedAndRemoveUntil( '/three', (route) => route.settings.name == '/one', ); }, child: Text('Push Named Replacement'), ), ]); } } Navigator.of(context).pushNamedAndRemoveUntil( '/three', (route) => route.settings.name == '/one', ); 제가 이런식으로 '/'이 아닌 '/one'으로 바꾸어 보았는데, route_three에서 pop()하면 one으로 가는게 아니라 그냥 검은 화면이 보여요. '/'은 잘 작동하고 main파일에서도 정확히 '/one'으로 잘 등록해 놓았는데 왜 작동이 안되는 걸까요??
미해결
[코드팩토리] [초급] Flutter 3.0 앱 개발 - 10개의 프로젝트로 오늘 초보 탈출!
강의 잘 듣고 있습니다. 정말 감사드립니다. 제가 블루투스를 이용해서 센서에서 데이터를 수집하는 app을 개발하려고 합니다. 아직 준비 중이라 이렇게 flutter 강좌를 듣고 있습니다. 블루투스를 이용한 데이터 수집과 관련된 강좌나 참고할만한 자료가 있을 까요?
미해결
Flutter 응용 - 공공 API를 활용한 앱 만들기 (MVVM 패턴)
이렇게 쓰면 됩니다..!
미해결
[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
FutureOr<String?> redirectLogic(BuildContext context,GoRouterState state){ final UserModelBase? user = ref.read (userMeProvider); //로그인 중 final logginIn = state.location == '/login'; //회원가입 페이지 이동중인지 final joinIn = state.location == '/login/join'; //유저 정보가 없는데 //로그인중이면 그대로 로그인 페이지에 두고 //만약 로그인중이 아니라면 로그인 페이지로 이동 if(user == null && !joinIn){ return logginIn ? null : '/login'; } //회원가입 페이지로 이동중이라면 if(user==null && joinIn){ return '/login/join'; } //user가 null이 아님 //UserModel //사용자 정보가 있는상태면 //로그인 중이거나 현재 위치가 SplashScreen이면 //홈으로 이동 if(user is UserModel){ return logginIn || state.location == '/splash' ? '/' : null; } //UserModelError if(user is UserModelError){ return logginIn ? null : '/login'; } return null; } } 위의 로직에서 splash화면을 인스타그램처럼 1초 지속되도록 하고싶은데 혹시 방법이 있을까요?
미해결
Flutter 응용 - 공공 API를 활용한 앱 만들기 (MVVM 패턴)
이렇게 ElevatedButton을 이용해보세요 그러면 이렇게 화면에 선생님 강의와 비슷하게 나옵니다! RaisedButton은 2.0 이후로 사용을 권장하지 않고 있다고 하네요!
미해결
[코드팩토리] [초급] Flutter 3.0 앱 개발 - 10개의 프로젝트로 오늘 초보 탈출!
안녕하세요 강사님. return query.watch().map( (rows) => rows .map( (row) => ScheduleWithColor( schedule: row.readTable(schedules), categoryColor: row.readTable(categoryColors), ), ) .toList(), ); 이 부분에 질문이 있어서 글 남깁니다. 제 생각에는 데이터 구조가 위와 같다고 생각했습니다. 이에 그냥 아래와 같이 작성하면 어떨까라는 생각이 들었습니다. return query.watch().map( (rows) => ScheduleWithColor(schedule: rows[0].readTable(schedules), categoryColor: rows[0].readTable(categoryColors)), ).toList(); 근데 이와 같이 작성하면 return 타입이 Stream이 아니라 Future가 되는 것 같더군요. 제가 어느 부분에서 혼란을 겪고 있는지 알고 싶습니다. + 추가 제가 이렇게 생각한 이유는 return query.watch().map((rows) { print(rows.length); return rows .map( (row) => ScheduleWithColor( schedule: row.readTable(schedules), categoryColor: row.readTable(categoryColors), ), ) .toList(); }); 코드를 이렇게 변경해 봤을 때, rows.length가 1이 출력되었기 때문입니다.
해결됨
[플러터 상태관리] Bloc 마스터 코스 기초부터 응용까지!
안녕하세요 강의 잘 보고 있습니다! 제가 초기에 아이폰 에뮬로 하기 귀찮아서 mac app이랑 chrome app으로 강의를 따라하고 있었는데요... 약 30분까지의 스크롤 해결 전까지 진행한 상태에서 발견한 에러입니다. 보니까 Mac App으로 하니 DioError: SockerException: Connection Failed가 되면서 아래 같이 에러가 발생합니다. chrome으로 하는 경우에는 데이터는 되는데 이미지를 못 읽는듯해요... 그래도 아이폰 에뮬로 하니 잘 되긴 하던데... 이 차이는 앱별로 동작하는게 달라서 그런가요?? 혹시 동일하게 다 가능하도록 해결하는 방법도 있을까요?
미해결
[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
처음 데이터를 가지고올때 if(state is! CursorPagination){ await this.paginate(); } 위의 코드를 실행하는데 만약 데이터가 없다면 final resp = await repository.paginate( paginationParams: paginationParams ); 여기서 캐스팅 오류가납니다. 혹시 따로 해결방법이있을까요?? 너무 어렵네요
미해결
[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
void init(){ state is CursorPaginationLoading; } 이런식으로 코드를 짜면 프로바이더 내용이 초기화 되는건가요?
미해결
[코드팩토리] [초급] Flutter 3.0 앱 개발 - 10개의 프로젝트로 오늘 초보 탈출!
children: [ 123, 456, 789, ].map((e) => Row( children:[ e.toString().split('').map((y) => Image.asset('asset/img/$y.png')).toList(), ] )).toList(), ), 이 부분에서 강사님이 children에 [] 부분을 빼고 코드 작성을 하셨지만 저는 안드로이드 스튜디오에서 children : [] 을 자동완성 시켜주기도 하고 []의 존재 이유가 복수의 위젯을 넣기 위함이니 그냥 하나만 넣어서 작성하여도 상관없을 것이라고 생각하였습니다. 하지만 막상 그렇게 작성해보니 오류가 나서 인터넷도 찾아보고 GPT한테도 물어봤지만 마땅한 해답은 못찾은 채 children 부분에 []를 지우니 오류가 사라지더군요. 왜 그런지 알 수 있을까요?
미해결
[코드팩토리] [초급] Flutter 3.0 앱 개발 - 10개의 프로젝트로 오늘 초보 탈출!
import 'package:flutter/material.dart'; class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @override State<HomeScreen> createState() => _HomeScreenState(); } class _HomeScreenState extends State<HomeScreen> { @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('랜덤숫자 생성기'), IconButton( onPressed: () {}, icon: Icon( Icons.settings, ), ), ], ), Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('123'), Text('456'), Text('789'), ], ), ), Container( width: double.infinity, child: ElevatedButton( onPressed: () {}, child: Text('생성하기!'), ), ), ], ), ), ); } } 그냥 수업 내용인데, 왜 첫번째 Column에서는 container나 sizedBox하지 않고 그냥 crossAxisAlignment가 바로 적용되는 건가요?? 혹시 SafeArea 영역이 width가 최대라서 바로 횡축 정렬이 가능해지나요?
미해결
실습으로 배우는 선착순 이벤트 시스템
분명 현재 없는 상태이고 결과가 자꾸 이상하게 나와서 sout 처리를 잠시 해보았습니다 package com.example.api.service; import com.example.api.domain.Coupon; import com.example.api.repository.CouponCountRepository; import com.example.api.repository.CouponRepository; import org.springframework.stereotype.Service; @Service public class ApplyService { private final CouponRepository couponRepository; private final CouponCountRepository couponCountRepository; public ApplyService(CouponRepository couponRepository, CouponCountRepository couponCountRepository) { this.couponRepository = couponRepository; this.couponCountRepository = couponCountRepository; } public void applyV1(Long userId) { Long count = couponRepository.count(); if(count > 100) { return; } couponRepository.save(new Coupon(userId)); } public void applyV2(Long userId) { Long count = couponCountRepository.increment(); System.out.println(count); if(count > 100) { return; } couponRepository.save(new Coupon(userId)); } } @SpringBootTest class ApplyServiceTest { @Autowired private ApplyService applyService; @Autowired private CouponRepository couponRepository; @Test public void applyOnce() { applyService.applyV1(1L); long count = couponRepository.count(); Assertions.assertEquals(1L, count); } @Test public void 여러명응모V1() throws InterruptedException { int threadCount = 1000; ExecutorService executorService = Executors.newFixedThreadPool(32); CountDownLatch latch = new CountDownLatch(threadCount); for(int i=0; i<threadCount; i++){ long userId = i; executorService.submit(() -> { try { applyService.applyV1(userId); } catch(Exception e) { System.out.println(e); }finally { latch.countDown(); } }); } latch.await(); long count = couponRepository.count(); assertThat(count).isEqualTo(100); } @Test public void 여러명응모V2() throws InterruptedException { int threadCount = 1000; ExecutorService executorService = Executors.newFixedThreadPool(32); CountDownLatch latch = new CountDownLatch(threadCount); for(int i=0; i<threadCount; i++){ long userId = i; executorService.submit(() -> { try { applyService.applyV2(userId); } catch(Exception e) { System.out.println(e); }finally { latch.countDown(); } }); } latch.await(); long count = couponRepository.count(); org.assertj.core.api.Assertions.assertThat(count).isEqualTo(100); } } 그런데 여러명응모V2 test를 실행시에 count를 출력시 다음과 같은 수가 나옵니다. 20003 20011 20012 20013 20015 20016 20017 20018 20020 20022 ??? 한번 할때마다 1000씩 쿠폰의 수가 증가중인데요;;; 조회했을때는 empty라 나오는데 이렇게 되는 연유를 잘 모르갰습니다. 테스트 코드라서 rollback이 되야할거 같은데 그렇지 않는것도 잘 모르겟네요;; ㅠㅠ
미해결
[코드팩토리] [초급] Flutter 3.0 앱 개발 - 10개의 프로젝트로 오늘 초보 탈출!
유튜브 다트 강의, 인프런 플러터 강의, 그리고 코드팩토리의 플러터 프로그래밍 책까지 잘 보고 있습니다. 양질의 컨텐츠와 친절한 답변에 매번 감사드립니다. 현재 챗gpt api를 이용한 간단한 앱을 만들었고 이것을 빌드하려고 합니다. 책 606쪽의 flutter build appbundle이라고 터미널에 치면 아래 에러가 납니다. mac@HanHoseokui-iMac kind_teacher_han % flutter build appbundle 💪 Building with sound null safety 💪 FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:mergeReleaseResources'. > Multiple task action failures occurred: > A failure occurred while executing com.android.build .gradle.internal.res.Aapt2CompileRunnable > Android resource compilation failed ERROR:/Users/mac/Documents/codefactory/kind_teacher_han/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: AAPT: error: file failed to compile. > A failure occurred while executing com.android.build .gradle.internal.res.Aapt2CompileRunnable > Android resource compilation failed ERROR:/Users/mac/Documents/codefactory/kind_teacher_han/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: AAPT: error: file failed to compile. > A failure occurred while executing com.android.build .gradle.internal.res.Aapt2CompileRunnable > Android resource compilation failed ERROR:/Users/mac/Documents/codefactory/kind_teacher_han/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: AAPT: error: file failed to compile. * Try: > Run with --stacktrace option to get the stack trace. > Run with --info or --debug option to get more log output. > Run with --scan to get full insights. * Get more help at https://help.gradle.org BUILD FAILED in 5s Running Gradle task 'bundleRelease'... 6.2s Gradle task bundleRelease failed with exit code 1 이미지 쪽에 에러가 있는 것 같아 보입니다. 저는 앱 아이콘 만들기 웹 사이트( https://www.appicon.co)에서 제가 만든 아이콘으로 안드로이드용 이미지를 만든 후 /Users/mac/Documents/codefactory/kind_teacher_han/android/app/src/main/res에 폴더 붙여넣기를 했었는데 이게 문제가 되었을까요? 옛날에 앱인벤터라는 교육용 블록코딩 앱 개발 플랫폼으로 했을 때는 앱 출시까지 그렇게 어렵지 않게 했었는데.. 한 달가량 헤메고 있으니 힘드네요ㅠㅠ 도와주세요!^^
미해결
스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
test 학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용] test 강의 내용으로 게시판 만들기를 병행하고 있습니다. 이번 강의에서 Spring Data Jpa로 변경을 하였는데 게시글 수정과 같은 수정 기능은 인터페이스인 SpringDataJpaMemberRepository에서 작성하나요? 아니면 Service단에서 Repository의 find를 통해서 수정하도록 작성하나요? SpringDataJpa에서 find, delete는 있는데 수정은 어떻게 이뤄지는지 궁금합니다..d
해결됨
자바 ORM 표준 JPA 프로그래밍 - 기본편
안녕하세요. 김영한 선생님의 강의를 참 잘 보고 있는 학생입니다. SQL 중심적인 개발의 문제점 편에서, 객체지향 프로그래밍에서 객체는 자유롭게 객체 그래프를 탐색할 수 있어야하 지만 SQL로 개발하는 경우에는 처음 실행하는 SQL에 따라 탐색 범위가 결정된다 는 문제가 있다고 말씀하셨습니다. 그리고 엄격한 도메인 주도 설계의 관점에서는 '도메인 객체'와 '엔티티 객체'를 분리 해야 한다고 알고 있습니다. 비즈니스 로직을 다루는 도메인 객체가 JPA 라고 하는 기술에 의존하는 것은 영 즐거운 일은 아니기 때문이죠.. ( https://stackoverflow.com/questions/24703756/having-separate-domain-model-and-persistence-model-in-ddd ) 그렇기 때문에 도메인 객체와 엔티티 객체를 분리하게 된다면 Repository 계층에서 예를 들어 findById 를 했을 경우 엔티티 객체를 도메인 객체로 매핑해서 돌려주어야 합니다. 그런데 이럴 경우, 기존의 SQL로 개발하는 경우와 비슷한 문제가 발생하게 되는 것 같습니다. 매핑을 어디까지해서 돌려주어야 하느냐는 점이죠. Member 를 조회했을 때, 객체 그래프 안에 있는 Category까지 싹싹 다 조회해와서 매핑을 해주기도 곤란한 노릇이고, MemberWithTeam , MemberWithOrderAndOrderItem... 와 같은 객체를 따로 따로 만드는 것도 요상해보입니다. 그렇다고 객체 그래프를 다 끊어놓자니 그것도 객체지향적이지 않은 것 같아보이구요.. 이런 상황에서는 어떤 식으로 도메인 객체를 설계하는지, 엔티티 객체의 매핑은 어떤 방법으로 이루어지는지가 너무 궁금합니다.