묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
master, replica 구성할 때 EntityManagerFactory 빈 등록 관련 질문드립니다.
안녕하세요.강의 내용과 조금 별개의 질문일 수 있는데 마땅히 물어볼 곳이 없어 질문드리게 되었습니다.@Transactional(read-only) 로 설정했을 때, replication db 에서 조회하도록 Master, Replica 데이터 소스를 구성해보려고 하는데요,Master 와 Replica 각각의 데이터소스와 AbstractRoutingDataSource를 상속받는 routingDataSource 를 빈으로 등록 후,EntityManagerFactory 도 빈으로 등록했습니다.@Bean public EntityManagerFactory entityManagerFactory(DataSource dataSource) { LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setPackagesToScan("com.example.domain"); factory.setDataSource(dataSource); HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter(); factory.setJpaVendorAdapter(jpaVendorAdapter); factory.afterPropertiesSet(); return factory.getObject(); }이렇게 모두 설정하면 동작은 잘 되는데 application.yml 에 설정한 auto-ddl 이나 show_sql, form_sql 과 같은 프로퍼티 설정을 읽어오지 못하더라구요.그래서 아래와 같이 HibernateJpaVendorAdapter 에 직접 설정을 추가해줘야지 동작했습니다.HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter(); jpaVendorAdapter.setGenerateDdl(true); jpaVendorAdapter.setShowSql(true);그런데 이렇게 직접적으로 설정값을 넣어서 구성하면 profile 에 따라 설정 값 적용을 분리하지 못하게되는데,그럼 아래와 같이 Properties 를 직접 가져와서 설정 값에 넣어줘야하는걸까요? 이러한 방식이 맞는지 의문이 들어서 질문하게 되었습니다. HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter(); jpaVendorAdapter.setGenerateDdl(jpaProperties.isGenerateDdl()); jpaVendorAdapter.setShowSql(jpaProperties.isShowSql()); factory.setJpaVendorAdapter(jpaVendorAdapter);그리고 구글링 했을 때 블로그 예제들은 현업에서 정말 사용하는 구성인지 Master, replica 를 설정하는데 참고할만한 좋은 레퍼런스 있으면 추천 부탁드립니다.
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
SpringBoot 3점대 버전 Spring Security 설정
Spring Security 가 3점대 버전으로 오면서 상당한 변화가 있습니다. 강의 내용을 따라 하다보니 순환참조나, 현재는 지원하지 않는 기능이 상당수 존재하였습니다. 현재 작업한 코드가 문제 해결에 많은 도움이 되면 좋겠어서 글을 첨부합니다. SecurityConfig.class 입니다.@Configuration @EnableWebSecurity @RequiredArgsConstructor public class SecurityConfig{ private final CustomAuthenticationManager customAuthenticationManager; private final UserFindPort userFindPort; private final Environment environment; @Bean public WebSecurityCustomizer webSecurityCustomizer() { return (web) -> web.ignoring(). requestMatchers(new AntPathRequestMatcher("/h2-console/**")) .requestMatchers(new AntPathRequestMatcher( "/favicon.ico")) .requestMatchers(new AntPathRequestMatcher( "/css/**")) .requestMatchers(new AntPathRequestMatcher( "/js/**")) .requestMatchers(new AntPathRequestMatcher( "/img/**")) .requestMatchers(new AntPathRequestMatcher( "/lib/**")); } @Bean protected SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { http.csrf(AbstractHttpConfigurer::disable); http.authorizeHttpRequests(authorize -> authorize.requestMatchers(new MvcRequestMatcher(introspector, "/**")).permitAll() // requestMatchers(new MvcRequestMatcher.Builder(introspector).pattern(HttpMethod.GET, "/users/**")).permitAll() // .requestMatchers(new MvcRequestMatcher(introspector, "/greeting")).permitAll() // .requestMatchers(new MvcRequestMatcher(introspector, "/welcome")).permitAll() // .requestMatchers(new MvcRequestMatcher(introspector, "/health-check")).permitAll() // .requestMatchers(new MvcRequestMatcher.Builder(introspector).pattern(HttpMethod.POST, "/users")).permitAll() .anyRequest() .authenticated()) .addFilter(getAuthenticationFilter()) .httpBasic(Customizer.withDefaults()); return http.build(); } private AuthenticationFilter getAuthenticationFilter() { return new AuthenticationFilter(customAuthenticationManager, userFindPort, environment); } }requestMatcher에서 AntPathRequestMatcher, MvcRequestMatcher에 관한 설명은부족하지만 https://velog.io/@dktlsk6/Spring-Security-RequestMatcher에서 확인 가능하십니다. CustomUserDetailService.class 입니다. 순환참조 문제가 발생하여 강의와 달리 새로 CustomService를 생성하여 implements 하였습니다.@Component @RequiredArgsConstructor public class CustomUserDetailService implements UserDetailsService { private final UserFindPort userFindPort; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { UserDto userByEmail = userFindPort.findUserByEmail(username); if (userByEmail == null) { throw new UsernameNotFoundException("User Not Found"); } return new User(userByEmail.getEmail(), userByEmail.getEncPasswd(), true, true, true, true, new ArrayList<>()); } } CustomAuthenticationManager.class 입니다. AuthenticationFilter의 AuthenticationManager로 사용할 것입니다.@Component @RequiredArgsConstructor @Slf4j public class CustomAuthenticationManager implements AuthenticationManager { private final CustomUserDetailService customUserDetailService; @Bean protected PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { UserDetails userDetails = customUserDetailService.loadUserByUsername(authentication.getName()); if (!passwordEncoder().matches(authentication.getCredentials().toString(), userDetails.getPassword())) { throw new BadCredentialsException("Wrong password"); } return new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities()); } } AuthenticationFilter.class 입니다. 해당 부분은 강의와 차이점이 없습니다.@Slf4j public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter { private final UserFindPort userFindPort; private final Environment environment; public AuthenticationFilter(AuthenticationManager authenticationManager, UserFindPort userFindPort, Environment environment) { super.setAuthenticationManager(authenticationManager); this.userFindPort = userFindPort; this.environment = environment; } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { try { LoginRequestDto creds = new ObjectMapper().readValue(request.getInputStream(), LoginRequestDto.class); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(creds.getEmail(), creds.getPassword(), new ArrayList<>()); return getAuthenticationManager().authenticate(token); } catch (IOException e) { throw new RuntimeException(e); } } @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { String username = authResult.getName(); UserDto user = userFindPort.findUserByEmail(username); if (user == null) { throw new UsernameNotFoundException(username); } log.debug("user id {}", user.getUserId()); String token = Jwts.builder() .setSubject(user.getUserId()) .setExpiration(new Date(System.currentTimeMillis() + Long.parseLong(environment.getProperty("token.expiration.time")))) .signWith(SignatureAlgorithm.HS512, environment.getProperty("token.secret")) .compact(); response.addHeader("token", token); response.addHeader("userId", user.getUserId()); } } 아래는 실제 결과입니다.404가 뜨는 이유는 login 성공시 redirect url을 설정해주지 않아서 /(루트) 경로로 이동해서입니다. 해당 경로와 매핑되는 resource나 api가 없기 때문에 해당 오류가 발생한것이므로 정상작동으로 생각하시면 됩니다.아래는 잘못된 정보를 기입하여 실패 테스트 입니다. 추후 강의를 들으며 업데이트 하도록 하겠습니다.
-
미해결[개정판] 딥러닝 컴퓨터 비전 완벽 가이드
CityscapeDataset으로 변경 시 오류
선생님 안녕하세요 저는 현재 cityscape dataset을 바탕으로 kaggle mask_rcnn_nucleus 코드를 활용하여 segmentation을 해보려고 하고 있습니다.차량으로 활영한 스트릿뷰에서 나무와 도로를 분리해내어 온도 차이를 보고자 해당 작업을 진행 중인데요,이에 cityscape에 맞는 config 파일과 pretrained model, Cityscapedataset을 활용하려고 하고 있는데, 기존 Nucleusdataset을 Cityscapedataset으로 대체해서 코드를 돌리니 config와 계속 충돌이 있어 train을 할수가 없어 어느 부분을 수정해야할지 모르겠어서 질문드립니다.활용한 config, checkpoint 파일# config_file (/content/mmdetection/configs/cityscapes/mask_rcnn_r50_fpn_1x_cityscapes.py 활용) mask_rcnn_r50_fpn_1x_cityscapes.py # checkpoint_file (cityscape웹에서 다운로드) mask_rcnn_r50_fpn_1x_cityscapes_20201211_133733-d2858245.pth https://download.openmmlab.com/mmdetection/v2.0/cityscapes/mask_rcnn_r50_fpn_1x_cityscapes/mask_rcnn_r50_fpn_1x_cityscapes_20201211_133733-d2858245.pth1차 수정한 dataset 코드# 기존 dataset 코드 from mmdet.datasets.builder import DATASETS from mmdet.datasets.coco import CocoDataset @DATASETS.register_module(force=True) class NucleusDataset(CocoDataset): CLASSES = ['nucleus'] # 변경한 dataset 코드 # Copyright (c) OpenMMLab. All rights reserved. # Modified from https://github.com/facebookresearch/detectron2/blob/master/detectron2/data/datasets/cityscapes.py # noqa # and https://github.com/mcordts/cityscapesScripts/blob/master/cityscapesscripts/evaluation/evalInstanceLevelSemanticLabeling.py # noqa from mmdet.datasets.builder import DATASETS from mmdet.datasets.coco import CocoDataset from typing import List @DATASETS.register_module() class Cityscape_Dataset_2(CocoDataset): """Dataset for Cityscapes.""" METAINFO = { 'classes': ('road', 'vegetation', 'sidewalk', 'car', 'building', 'person', 'sky', 'bicycle'), 'palette': [(128,64,128), (107,142,35), (152,251,152), (0,0,142), (70,70,70), (255,0,0), (70,130,180), (119,11,32)] } def filter_data(self) -> List[dict]: """Filter annotations according to filter_cfg. Returns: List[dict]: Filtered results. """ if self.test_mode: return self.data_list if self.filter_cfg is None: return self.data_list filter_empty_gt = self.filter_cfg.get('filter_empty_gt', False) min_size = self.filter_cfg.get('min_size', 0) # obtain images that contain annotation ids_with_ann = set(data_info['img_id'] for data_info in self.data_list) # obtain images that contain annotations of the required categories ids_in_cat = set() for i, class_id in enumerate(self.cat_ids): ids_in_cat |= set(self.cat_img_map[class_id]) # merge the image id sets of the two conditions and use the merged set # to filter out images if self.filter_empty_gt=True ids_in_cat &= ids_with_ann valid_data_infos = [] for i, data_info in enumerate(self.data_list): img_id = data_info['img_id'] width = data_info['width'] height = data_info['height'] all_is_crowd = all([ instance['ignore_flag'] == 1 for instance in data_info['instances'] ]) if filter_empty_gt and (img_id not in ids_in_cat or all_is_crowd): continue if min(width, height) >= min_size: valid_data_infos.append(data_info) return valid_data_infos1차 수정한 코드로 시도한 train 시 오류from mmdet.datasets import build_dataset from mmdet.models import build_detector from mmdet.apis import train_detector # train, valid 용 Dataset 생성. datasets_train = [build_dataset(cfg.data.train)] datasets_val = [build_dataset(cfg.data.val)] --------- TypeError Traceback (most recent call last) /usr/local/lib/python3.10/dist-packages/mmcv/utils/registry.py in build_from_cfg(cfg, registry, default_args) 68 try: ---> 69 return obj_cls(**args) 70 except Exception as e: TypeError: CustomDataset.__init__() got an unexpected keyword argument 'times' During handling of the above exception, another exception occurred: TypeError Traceback (most recent call last) 2 frames /usr/local/lib/python3.10/dist-packages/mmcv/utils/registry.py in build_from_cfg(cfg, registry, default_args) 70 except Exception as e: 71 # Normal TypeError does not print class name. ---> 72 raise type(e)(f'{obj_cls.__name__}: {e}') 73 74 TypeError: Cityscape_Dataset_2: CustomDataset.__init__() got an unexpected keyword argument 'times'2차 수정한 코드 (chatGPT의 도움)도 또 다른 오류 뜸@DATASETS.register_module() class Cityscape_Dataset_times(CocoDataset): """Dataset for Cityscapes.""" METAINFO = { 'classes': ('road', 'vegetation', 'sidewalk', 'car', 'building', 'person', 'sky', 'bicycle'), 'palette': [(128,64,128), (107,142,35), (152,251,152), (0,0,142), (70,70,70), (255,0,0), (70,130,180), (119,11,32)] } def __init__(self, *args, times=1, **kwargs): self.times = times super().__init__(*args, **kwargs) def __getitem__(self, idx): # Get the real index by considering the 'times' argument. idx = idx % len(self.data_list) return super().__getitem__(idx) def __len__(self): # The length is the original length times the 'times' argument. return len(self.data_list) * self.times ..이하 동일from mmdet.datasets import build_dataset from mmdet.models import build_detector from mmdet.apis import train_detector # train, valid 용 Dataset 생성. datasets_train = [build_dataset(cfg.data.train)] datasets_val = [build_dataset(cfg.data.val)] --------- TypeError Traceback (most recent call last) /usr/local/lib/python3.10/dist-packages/mmcv/utils/registry.py in build_from_cfg(cfg, registry, default_args) 68 try: ---> 69 return obj_cls(**args) 70 except Exception as e: 3 frames TypeError: CustomDataset.__init__() got an unexpected keyword argument 'dataset' During handling of the above exception, another exception occurred: TypeError Traceback (most recent call last) /usr/local/lib/python3.10/dist-packages/mmcv/utils/registry.py in build_from_cfg(cfg, registry, default_args) 70 except Exception as e: 71 # Normal TypeError does not print class name. ---> 72 raise type(e)(f'{obj_cls.__name__}: {e}') 73 74 TypeError: Cityscape_Dataset_times: CustomDataset.__init__() got an unexpected keyword argument 'dataset'dataset 코드 자체를 전반적으로 수정해야하는 걸까요 아니면 config 파일을 수정해야하는 건지 알 수 있을까요?아니면 cocodataset의 class를 'road'와 'vegetation'으로 두는 방식으로 가능할까요? (cocodataset에는 도로나 나무를 분류하는 카테고리가 딱히 없어 보여서 가능한지 모르겠어서 cityscapedataset 코드를 따로 들고 온거긴 합니다.)졸업이 달려 있는 과제이다보니 마음이 급해지는데 너무 막막해서 도움을 청합니다. 감사합니다.
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
Spring Boot 최신 3.XX 버전 Security 설정 공유드립니다.
최신 버전 진행하시는 분들을 위해 공유드립니다.Spring Security Configuration 설정 내용이 변경되었습니다. WebSecurityConfigurerAdapter 클래스가 deprecated되었는데요. 해당 클래스를 상속 받아 config 메소드를 구현하는 대신 SecurityFilterChain을 반환하고 직접 Bean으로 등록하도록 설정 방법이 바뀌었습니다. package com.example.userservice.security; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity public class WebSecurity { private static final String[] WHITE_LIST = { "/users/**", "/**" }; @Bean protected SecurityFilterChain config(HttpSecurity http) throws Exception { http.csrf().disable(); http.headers().frameOptions().disable(); http.authorizeHttpRequests(authorize -> authorize .requestMatchers(WHITE_LIST).permitAll()); return http.build(); } } 강의 내용을 진행하기 위해서 강의에 나온 설정을 위처럼 설정해보았는데요. 일단 이렇게 설정하면 강의를 진행하는데 문제 없을 것이니 참고 바랍니다~
-
미해결[개정판] 딥러닝 컴퓨터 비전 완벽 가이드
모델 파일을 불러와서 실행시킬시 config 파일
수업내용을 보면 config를 오버라이드 해서 수정해서 학습하고 모델을 사용하여 결과를 도출하였는데 학습을 따로 테스트 따로 시킬시에 테스트 할때 저장한 모델을 불러오고 config를 다시 오버라이드 시켜서 사용 해야 하나요? 또 config도 저장 시켜서 사용 할 수 있나요?
-
해결됨Vue로 Nodebird SNS 만들기
Nginx Cookie 설정
안녕하세요. 현재 강의를 수강 중에 https 설정 후 발생하는 문제가 있어서 질문드립니다. 현재 모든 강의를 수강하고 SSL 인증서를 적용하는 제로초님 블로그의 글을 따라 하고 있는데로그인은 되지만 로그아웃이 되지 않는 현상이 발생합니다.개발자도구 - 네트워크에 응답으로 withcredential 예외 응답이 오는 걸로 봐서는 쿠키 설정에 문제가 있는 것으로 추측됩니다.(Nginx 설정은 블로그에 있는 설정에 도메인만 바꿔서 적용하였고 다른 부분은 바꾼 것이 없습니다.)Nginx 설정에 쿠키를 보낼 수 있도록 적용하면 될거 같은데 혹시 다른 문제이진 않은가 걱정이 되어 글을 남깁니다.또한 혹시 https를 적용하고 또 설정해줘야 하는 부분이 짐작되는 것이 있으시다면 조언해주시면 감사하겠습니다.
-
미해결[개정판] 딥러닝 컴퓨터 비전 완벽 가이드
mmdetection config 질문드립니다.
data = dict( samples_per_gpu=2, workers_per_gpu=2, train=dict( type=dataset_type, ann_file=data_root + 'annotations/instances_train2017.json', img_prefix=data_root + 'train2017/', pipeline=train_pipeline), 안녕하세요. 선생님 config 관련 정보를 보다가 samples_per_gpu 와 workers_per_gpu에 대해서 알고 싶어 질문드립니다.GPU 하나를 쓴다고 하였을 때,samples_per_gpu의 경우는 batch_size와 동일해진다고 해석을 하였는데...이 해석이 맞는지 헷갈려서 문의드립니다.그리고 workers_per_gpu 부분은 정확히 무슨 의미인지, 그리고 숫자 증가에 따라 어떤 차이가 발생하고어떻게 선정을 하는 것인지 궁금합니다.단순 구글 검색해서 nums_worker 같은 경우, cpu에서 gpu로 데이터를 넘기는데 cpu 코어를 얼마나 할당해서 gpu로 데이터를 넘길 것인가 부분이라고 나왔는데이 내용이 config의 workers_per_gpu랑은 다른 내용인 것 같아 질문드립니다.항상 좋은 강의 감사드립니다.
-
미해결[개정판] 딥러닝 컴퓨터 비전 완벽 가이드
inferece를 할 때 config가 필요한 이유는 무엇인가?
pretrained 모델을 기반으로 해서 이미지를 돌릴 때 모델을 만들 때, 왜 config가 필요한지 헷갈려서 문의드립니다. 제가 이해한 내용으로는 pretrained 모델이란 결국 네트워크의 각 weight에 대한 데이터의 집합이기 때문에 config를 통해서 해당 구조에 대한 정보를 입력하지 않으면 전체 모델을 설계 할 수 없기 때문에 그런 것으로 이해하면 될지 아니면 다른 의미가 있는 것인지 알고 싶어 문의드립니다. 기초적인 질문을 해서 죄송합니다.
-
미해결비전공자를 위한 진짜 입문 올인원 개발 부트캠프
config 파일
간단한 질문하나 드립니다. config 파일이 생성이 안되어있어 직접 만들었습니다. 문제 소지가 되나요? 선생님과 같은 파일 그림은 없이 그냥 폴더로 직접 만들었습니다...