월 19,800원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
수업과 관련이 없지만 물을 곳이 없어...교수님께 여쭙니다..
dto랑 이미지 파일을 dio로 이용하여 post 하려는데 뭘해도 400, 415 등등 에러가 나옵니다 혹시 이유를 알 수 있을까요?... 수업내용이 아닌 질문 죄송합니다. Future<void> postUser(UserInfo userDto, XFile? imageFile) async { try { // Dio 인스턴스 생성 Dio dio = Dio(); // 멀티파트 요청 생성 FormData formData = FormData(); // Add userDto as a JSON part formData.fields.add(MapEntry('userDto', jsonEncode(userDto.toJson()))); // Add image file if (imageFile != null) { formData.files.add(MapEntry( 'image', await MultipartFile.fromFile(imageFile.path), )); } // Dio를 사용하여 POST 요청 보내기 Response response = await dio.post( 'http://43.200.217.158:8080/bookstore-0.0.1-SNAPSHOT/user', data: formData, options: Options( headers: { "Content-Type": "multipart/form-data", }, ), ); // 응답 확인 if (response.statusCode == 200) { print("User Data sent successfully"); } else { print('response.statusCode: ${response.statusCode}'); throw Exception("Failed to send data"); } } catch (e) { print("Failed to send post data: $e"); } } ------------------------------------------------------------------------------- 서버 코드 스프링 @PostMapping(value = "/user", consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE}) public ResponseEntity<ApiResponse> save(@RequestPart UserDto userDto, @RequestPart MultipartFile image) { try { log.info("유저 생성 입장!!"); Long save = userService.save(userDto, image); return ResponseEntity.status(HttpStatus.OK).body(new ApiResponse("Created", "유저 생성 성공", save)); } catch (Exception e) { log.error("e={}", e); return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ApiResponse("NotFound", "유저 생성 실패", null)); } }
- 미해결Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
뷰모델 생성자로 리스트 불러오
class StoreViewModel with ChangeNotifier { String? regionName = ''; String barName = '지역별 서점'; bool isLoading = false; final StoreRepository repository; StoreViewModel(this.repository) { print('생성자호출'); _loadSimpleStores(); print(stores); } List<SimpleStore> stores = []; void onEvent(StoreEvent event, BuildContext context) { event.when(touchTile: (id) async { StoreInfo store = await repository.getStoreInfo(id); Navigator.push( context, MaterialPageRoute( builder: (context) => StoreDetailScreen(storeDetail: store)), ); }, searchStore: (query) async { }); } //지역 전체 Future<void> _loadSimpleStores() async { isLoading = true; notifyListeners(); stores = await repository.getStores(); isLoading = false; notifyListeners(); } } --------------------------------------------- class StoreViewScreen extends StatefulWidget { StoreViewScreen({ super.key, this.barName, this.regionName, }); String? barName; String? regionName; @override State<StoreViewScreen> createState() => _StoreViewScreenState(); } class _StoreViewScreenState extends State<StoreViewScreen> { TextEditingController _controller = TextEditingController(); @override Widget build(BuildContext context) { final customerInfoViewModel = context.watch<CustomerInfoViewModel>(); final storeViewModel = context.watch<StoreViewModel>(); return Scaffold( appBar: AppBar( centerTitle: true, title: Text( storeViewModel.barName, style: TextStyle( fontWeight: FontWeight.bold, ), ), leading: IconButton( onPressed: () { Navigator.pop(context); }, icon: Icon(Icons.close), ), ), body: Column(children: [ //입력창 + 검색창 Container( child: Row( children: [ Expanded( child: Container( decoration: BoxDecoration( border: Border.all(color: Colors.grey), // 테두리 색상 설정 borderRadius: BorderRadius.circular(8.0), // 테두리 둥글기 설정 ), child: TextField( controller: _controller, decoration: InputDecoration( hintText: '텍스트를 입력하세요.', // 힌트 텍스트 contentPadding: EdgeInsets.all(12.0), // 텍스트 입력 필드 내부의 여백 설정 border: InputBorder.none, // 기본 테두리 제거 ), ), ), ), TextButton(onPressed: () {}, child: Text('검색')) ], ), ), //지역 이름 or 내주변 Container( child: Row( children: [ Text( storeViewModel.regionName ?? '내 주변', style: TextStyle( fontSize: customerInfoViewModel.screenHeight / 20, fontWeight: FontWeight.bold), ), Text( '${storeViewModel.stores.length}가 검색 됨', style: TextStyle( fontSize: customerInfoViewModel.screenWidth / 20, fontWeight: FontWeight.bold), ), ], )), //서점 리스트 표시 Expanded( child: Container( child: !storeViewModel.isLoading ? ListView.builder( itemCount: storeViewModel.stores.length, itemBuilder: (BuildContext context, int index) { return GestureDetector( child: StoreSimpleInfo( id: storeViewModel.stores[index].id, profileUrl: storeViewModel.stores[index].imageUrl, storeName: storeViewModel.stores[index].name, storeAddr: storeViewModel.stores[index].address, category: storeViewModel.stores[index].category), onTap: () { storeViewModel.onEvent( StoreEvent.touchTile( storeViewModel.stores[index].id, ), context, ); }, ); }, ) : CircularProgressIndicator(), ), ), ]), ); } } 스크린을 열면 viewmodel 생성자로 리스트를 불러오고 싶은데 viewmodel 생성자가 작동을 안합니다 이유가 뭘까요 ㅠㅠ? 의존성주입 문제는 아닌것같아요
- 미해결Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
개남님 질문있씁니다! company_listing_entitiy가 왜 엔티티 인가요?
개남님 안녕하세요. 두 가지 여쭐 것이 있습니다!도메인 영역에 entitiy가 아니라 model 폴더를 위치하셨던데, freezed로 생성한 이상 각종 메소드가 들어가기에 "정석적인 속성만 존재하는 entitiy라고 보기엔 조금 그래서 model로 구분하셨구나~"하고 넘어갔습니다. 맞을까요?? 글구 company_listing_entitiy는 data 레이어에 속하는데 왜 entity인지 궁금합니다. 제가 아직 강의 초반이라 이해가 부족한 것인지.. 보통 data 레이어에서 api통신/로컬db와 관련된 비즈니스 로직에 사용할 model을 정의하고, 맵퍼가 도메인의 entity로 반환해 주는 구조로 이해했는데 이러면 CompanyListingEntity가 아니라, CompanyListingModel이 맞지 않나요? 제가 너무 시야를 좁게 보는 것 같기도하고.. 헷갈려 여쭙니다!
- 해결됨Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
안녕하세요 디버그 모드 관련 여쭤볼게 있어요
디버그모드에서 변수 이름에 커서를 대면 변수가 보여지는데 이거 어떻게 하나요 ..? ㅠ
- 해결됨Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
다음 로드맵 질문
안녕하세요! 강의 너무 잘듣고 있습니다.혹시 다음에 예정된 flutter 강의가 있을까요? 있다면 수강하고 싶어서 질문드립니다!
- 미해결Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
csv_parser라는 abstract를 작성하는 필요성이 궁금합니다
csv_parser라는 abstract를 작성하는 필요성이 궁금합니다
- 미해결Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
repository에 관하여
강사님 안녕하세요~ 항상 수업 잘 듣고 있습니다!공부를 하다보니 궁금한 점이 생겨서 이렇게 질문을 남기게 되었습니다.mvvm 패턴을 통해 개발을 할 때에는 repository를 사용하게 되는데, domain layer에서 repository 추상클래스를 만들고 data layer에서 구현하여 사용하는 이유가 뭔지 궁금합니다 ㅠㅠ
- 미해결Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
강의 예시에 대한 답변이 궁금합니다.
4:20초에서 '예) 로그인 작업시 얻은 Token 정보를 LoginViewModel에서 가지고 있다.~~' 라는 질문에 대한 답변이Token 정보가 필요한 스크린들에서 하나의 ViewModel을 공유하라는 것이 맞을까요?
- 미해결Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
flutter 실행 관련 질문드립니다.
window 환경에서 android studio로 flutter doctor -v를 치면 X Unable to find bundled Java version.위와 같은 에러?가 발생합니다.구글링하면 보통 mac 환경에서의 해결책은 많은데 window환경에서는 해결책이 없어 질문드립니다.몇 개 없는 것들 중에 오래된 android studio를 삭제하라고 해서 삭제도 해보았습니다.ㅠㅠ
- 미해결Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
폴더 구조에 대해 질문드립니다.
강사님의 강의를 통해 클린 아키텍처를 조금씩 도입하는 중인데,domain - model에 모든 model을 넣다보니 한 폴더에 너무 많은 파일들이 있어서 보기에 좋지 않더라구요.혹시 domain이 많아 지는 경우, 폴더 구조를 다르게 잡는 방법이 있으신지 궁금합니다.
- 해결됨Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
Repository test 관련해 질문이 있습니다.
안녕하세요! 강사님 덕분에 플러터 공부를 재미있게 하고 있는 수강생입니다. 다름이 아니라 클린 아키텍쳐를 이용하여 개인 프로젝트를 만들고 있는데 repository 테스트 코드를 만들다가 궁금한 점이 생겨 질문을 남깁니다. 현재 주식 앱처럼 리턴 타입이 Result인 Repository를 테스트 해도 되나요? 테스트 하려면 어떤 식으로 접근해야 할까요? 제가 이해한 바로는 Result 클래스는 viewmodel에서 성공 및 실패에 따라서 state를 다르게 적용하기 위해 만들어진 것인데 테스트 코드에서는 state가 따로 없어서 어떤 식으로 성공을 정의할지 잘 모르겠습니다. (hive를 통한 로컬 db 테스트 코드는 만들어진 상태입니다.) 1번과 이어지는 질문인데요, 레이어마다(데이터, 도메인, 프레젠테이션) dao, repository, viewmodel이 데이터를 다루는 역할을 하는데, 이것들의 테스트 코드를 만드는 게 맞을까요? 현재 계획은 위 세 개에 대한 테스트 코드, 위젯에 대한 테스트 코드를 만드려고 합니다. 혹시 잘못된 부분이나 또 필요한 테스트가 있다면 알려주시면 감사하겠습니다.앞으로도 강의 많이 만들어주세요! 매번 새롭게 배우고 있습니다. 감사합니다ㅎㅎ
- 미해결Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
stock_repository_impl.dart 에러
stock_repository_impl.dart아래부분 코드에서 Type 에러가 나는데 왜 에러가 발생하는지 알 수 있을까요?
- 미해결Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
viewModel에서 context를 받는 행위 질문
로그인을 생각해보았는데요.repository_impl에서 local 검사 후 정보가 있으면 따로 터치 상호작용이 없어도 화면에서 자동으로 메인화면으로 넘어가게 하고 싶습니다.그런 경우에는 viewModel 안에 메서드에 context를 받고 거기서 Navigator를 작성해도 문제 없을까요? 아니면 state에 로그인 여부를 하나 만들고 그것을 watch해서 screen에서 navigator를 쏘는게 맞을까요? 아니면 좀 더 이상적인 방법있을까요?
- 미해결Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
stockApi 질문 드립니다.
getListings는 http.Response를 반환하고 impl에서 null을 필터링하고,getCompanyInfo 는 dto클래스를 반환하고 impl에서 필터링해 주었습니다. 전자와 후자 차이는 로컬 캐시를 사용하냐 안하냐로 이해해도 될까요?
- 미해결Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
stockApi 질문
이전 강좌에서는 api에서도 Result클래스 처리를 해주셨었는데, 이번에는 그냥 Rsponse로 반환하시는 것 같아 질문드립니다.어차피 repository_impl에서 try catch에 걸러지기 때문에 사실은 api에 굳이 에러처리를 할 필요는 없을까요??
- 미해결Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
라이브 템플릿 영상
혹시 유튜브 채널 강의 영상 올릴 계획 있으신가요?!
- 미해결Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
StockApi 메서드 반환 타입에 대해
getCompanyInfo 메서드는 Dto를 반환하는데getgetCompanyListings 메서드는 Response를 반환합니다.(json 변환을 하는 곳이 서로 다른 곳에 있다고 생각)getCompanyListings 메서드도 List<Entity>(Dto)를 반환하는게 좀 더 일관성있다고 느껴지는데 이것도 좋은 코드라고 할 수 있을까요?
- 미해결Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
entity와 domain의 차이
친절한 답변 감사합니다.Entity와 domain의 차이에 대해 질문 드립니다.Entity와 domain이 같은 의미인줄 알았으나 구조를 보니 company_listing_entity와 company_listing(domain) 을 사용하는 것을 보고 다르게 사용 된다는 것을 알게 됐습니다.Entity는 db에 접근하기 위해 사용 되는 domain?의 느낌이고 domain은 비지니스 로직을 수행하기 위한 객체로 느껴졌는데 이것이 맞는지 궁금합니다.이전 강의인 클린 아키텍처에서는 Entity를 사용하지 않았는데 그 이유가 궁금합니다.캐시로 사용되는 객체와 원격으로 사용되는 객체의 차이, 들어오는 값의 차이 등으로 인해 2개로 나눠서 관리하는 것으로 설명해주셨는데 하나의 파일로 관리가 되지 않나 싶어 혼동이 생깁니다. model 객체가 2개라고 생각이 들기도 합니다.
- 미해결Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
dart의 불변 객체에 대해
불변 객체를 만든다는 의미가 변수들을 final로 선언하면 되는 것으로 알고 있었습니다.그런데 강의 20분 쯤에 다른 언어에서는 불변 객체를 다루는 문법을 제공한다고 하는데 어떤 것이 있는지 궁금합니다.(final로 다루는 것 외에 또다른 방법이 있는지?)dart에서는 일반 클래스를 만들고 나서 불변 객체로 다루기 쉽지 않다고 하셨는데 copyWith 같은 데이터 변경을 말하는 것인가요?