Home

0

Spring Batch - 01. @EnableBatchProcessing

출처 해당 포스트는 정수원 강사님의 스프링 배치 - Spring Boot 기반으로 개발하는 Spring Batch 강의를 바탕으로 작성 됐습니다. 목차 Spring Batch - 14. 배치 초기화 설정 (application.properties) Spring Batch - 13. JobLauncher Spring Batch - 12. JobRepository Spring Batch - 11. ExecutionContext Spring Batch - 10. StepContribution Spring Batch - 09. StepExecution 와 STEP_EXECUTION 테이블 Spring Batch - 08. Step Spring Batch - 07. JobExecution 와 JOB_EXECUTION 테이블 Spring Batch - 06. JobParameter 와 JOB_EXECUTION_PARAM 테이블 Spring Batch - 05. JobInstance 와 JOB_INSTANCE 테이블 Spring Batch - 04. JobLauncher Spring Batch - 03. Job Spring Batch - 02. Batch 에서 사용하는 Table Spring Batch - 01. @EnableBatchProcessing @EnableBatchProcessing @EnableBatchProcessing 을 이용해 어플리케이션이 Spring Batch 로 실행될 수 있도록 자동으로 설정해준다. @SpringBootApplication@EnableBatchProcessing // Spring Batch 활성화public class SpringBatchApplication { public static void main(String[] args) { SpringApplication.run(SpringBatchApplication.class, args); }} Spring Batch 초기화 과정@EnableBatchProcessing 을 명시해주면 Batch 관련 설정 클래스 SimpleBatchConfiguration, BatchConfigurerConfiguration, BatchAutoConfiguration 를 실행시켜 Spring Batch 초기화 및 실행 구성이 이뤄진다.

0

Spring Data JPA - Convertor

목차 Spring Data JPA - 벌크성 수정 쿼리 Spring Data JPA - Convertor Spring Data JPA - Auditing Spring Data JPA - Paging Request Paramater Spring Data JPA - 페이징과 정렬 Post not found: spring/spring-data-jpa/07-spring-data-jpa Spring Data JPA - 반환 타입 Spring Data JPA - Query 파라미터 바인딩 Spring Data JPA - Query 를 이용한 조회 결과를 특정 값으로 반환하기 Spring Data JPA - JPQL (Java Persistence Query Lange) 사용하기 Spring Data JPA - 메소드 이름으로 쿼리 생성하기 Spring Data JPA - 시작하기 BooleanToYNConverterBoolean 으로 저장 되는 값을 True, false 로 변경해 값을 저장하기 위한 Convertor @Converterpublic class BooleanToYNConverter implements AttributeConverter<Boolean, String> { @Override public String convertToDatabaseColumn(Boolean attribute){ return (attribute != null && attribute) ? "Y" : "N"; } @Override public Boolean convertToEntityAttribute(String dbData){ return "Y".equals(dbData); }} @Entity@Getter@Builder@NoArgsConstructor@AllArgsConstructor@EntityListeners(AuditingEntityListener.class)public class Post extends BaseEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column private Long id; @Column(name = "POST_TITLE", length = 100, nullable = false) private String title; @Column(name = "POST_SUBTITLE") private String subTitle; @Lob private String content; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "username", nullable = false, referencedColumnName = "username") @CreatedBy private UserInfo author; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "CATEGORY", nullable = true, referencedColumnName = "CATEGORY_NAME") private Category category; @Column(name = "isDeleted") @ColumnDefault("false") @Convert(converter = BooleanToYNConverter.class) private boolean isDeleted; // ==== 연관관계 편의 메서드 ==== // public void changeCategory(Category category){ this.category = category; // 새로운 카테고리에 해당 포스트 추가 category.getPosts().add(this); } public void setAuthor(UserInfo author){ this.author = author; author.getPosts().add(this); } public Post updatePost(Post post) { this.title = post.title; this.subTitle = post.subTitle; this.content = post.content; changeCategory(post.getCategory()); return this; }}

0

Spring boot - 메시지 국제화 MessageSource

목차 Post not found: spring-boot/spring-framework/springboot-actuator Post not found: spring-boot/spring-framework/springboot-messageresource Post not found: spring-boot/spring-framework/configuration/springboot-WebMvcConfigurer Post not found: spring-boot/spring-framework/configuration/springboot-autoconfiguration 참고 https://gist.github.com/dlxotn216/cb9fe1e40c7961da9d7147d9ebc876d6 메시지 관리를 위한 MessageSource어플리케이션 개발을 진행하다가 보면 메시지를 보낼때 하드 코딩으로 넣다 보면 같은 맥략으로 쓰인 메시지들이 서로 상이하게 관리되는 것을 느낄 수 있었고 무엇보다 가장 큰 문제는 메시지를 변경하게 될 경우 해당 메시지가 사용된 소스를 전부 찾아 변경해 줘야 하는 문제점이 있다. 이런 메시지 파편화를 막고 한 곳에서 모든 메시지를 관리할 수 있도록 Spring 에서는 MessageSource 를 제공한다. MessageSource 메시지를 한 파일 message.properties 에서 관리할 수 있다. 경로 : main/resource/message.properties 메시지에 대한 다국어 처리 를 지원한다. 사용법 : message_[언어코드].properties 영어 : message_en.properties 한국어 : message_ko.properties 메시지 등록 경로 : main/resource/message.properties

0

Spring Security OAuth2를 이용한 로그인 구현 - Spring boot OAuth2 인증 살펴보기

목차 Spring Security OAuth2 - Handler Spring Security OAuth2 - Login 페이지 Customizing 하기 Spring Security OAuth2를 이용한 로그인 구현 - 사용자 정보 가져오기 Spring Security OAuth2를 이용한 로그인 구현 - Spring boot OAuth2 인증 살펴보기 Spring Security OAuth2를 이용한 로그인 구현 - OAuth2를 이용한 인증 사용하기 Google OAuth2 인증 방식 이해하기 OAuth2를 이용한 로그인 구현 이해하기 참고 https://www.baeldung.com/spring-security-5-oauth2-login https://www.docs4dev.com/docs/en/spring-security/5.1.2.RELEASE/reference/jc.html#oauth2client OAuth2LoginAuthenticationFilter OAuth2 인증을 진행하기 위한 Filter OAuth2 인증 방식도 UsernamePassword 인증과 같이 인증을 진행하기 위한 Filter 가 존재한다. OAuth2LoginAuthenticationFilter 에서는 Authentication Server 로부터 Authorization Code 를 받은 후 Acess Token 과 Reflesh Token 을 받기 위한 과정을 진행한다. ClientRegistrationRepository ClientRegistration 정보를 저장 및 가져오기 위한 Class OAuth2AuthorizedClient 인증된 Client 정보를 관리하기 위한 Class Access Token, Reflesh Token, ClientRegistration 정보를 관리하는 Class OAuth2AuthorizedClientRepository OAuth2AuthorizedClient 정보를 저장 및 가져오기 위한 Class 인증이 진행중인 Client 정보를 가져온다. 기본 구현체는 HttpSessionOAuth2AuthorizedClientRepository OAuth2AuthorizedClientService Application Level 에서 OAuth2AuthorizedClient 정보를 가져오기 위한 Class 인증이 완료된 Client 정보를 저장소 에서 가져올 때 사용한다. 메모리에 OAuth2AuthorizedClient 객체를 저장하는 InMemoryOAuth2AuthorizedClientService 데이터 베이스에 OAuth2AuthorizedClient 객체를 저장하는 JdbcOAuth2AuthorizedClientService AuthorizationRequestRepository 인증 요청에서 인증 응답을 받을때 까지 OAuth2AuthorizationRequest 의 지속성을 보장하기 위한 Class 기본 구현체는 Session 에 저장하는 HttpSessionOAuth2AuthorizationRequestRepository OAuth2AuthorizationRequestResolver registrationId 와 HttpServletRequest 를 OAuth2AuthorizationRequest 객체를 생성하기 위한 Class 기본 구현체는 DefaultOAuth2AuthorizationRequestResolver OAuth2AccessTokenResponseClient Authorization Code 를 Access Token 으로 교환하는데 사용하는 Class 기본 구현체는 DefaultAuthorizationCodeTokenResponseClient 인증 과정

0

컴퓨터 구조 - 메모리 관리 Paging 기법

Paging 기법 프로세스가 사용하는 메모리를 일정한 크기로 잘라 메모리에 할당 하는 방식, 기존 논리 주소 공간이 하나의 연속된 물리 주소 공간에 들어가야 하는 제약을 해소하기 위해 생긴 방식 프로세스의 주소 공간을 나누는 단위는 page, 메모리를 나누는 단위는 frame 이라 한다. page 와 frame 의 크기는 항상 같다. 메모리에 프로세스 주소 공간 전체를 올릴 필요가 사라졌다. 연속된 메모리로 관리하지 않기 때문에 Page Table 을 이용해 여러개로 나뉜 Page 정보를 관리한다. 외부 단편화 가 발생하지 않지만 내부 단편화 가 발생하게 된다. Page Table Virtual Page Number 를 Physical Frame Number 로 변환 시켜주는 Mapping 정보와 현재 Memory 적재 여부를 확인할 수 있는 Table MMU(Memory Management Unit) 는 Page Table 정보를 이용해 논리 주소를 물리 주소로 변환시킨다. Page Table 을 프로세스 마다 하나씩 존재하고 메모리에 올라가 있다. 실행된고 있는 프로세스가 많을 수록 메모리에 올라가 있는 Page Table 정보도 많게 된다. Page Fault Page Fault 란 프로세스가 요청하는 Page 정보가 현재 Memory 에 없는 경우를 뜻한다.

0

컴퓨터 구조 - 메모리 관리 Segmentation 기법

Segmentation 기법 Paging 기법과 달리 프로세스가 사용하는 메모리를 서로 크기가 다른 논리적 단위인 세그먼트로 분할 하고 메모리에 할당하는 기법 Segmentation 은 프로세스를 세그먼트(code, data, stack)의 집합으로 보고 의미가 같은 논리적 내용 단위로 자른다. 자르는 방식에서의 차이가 있고, 메모리에 할당하는 방식은 Paging 과 같다. Segmentation 은 Segmentation Table 을 이용해 여러개로 나뉜 Segment 들을 관리 한다. Paging Table 과의 차이는 Segmentation Table 은 서로 다른 크기로 나뉘었기 때문에 Limit 정보도 같이 관리된다.

0

Spring Security OAuth2 - Handler

목차 Spring Security OAuth2 - Handler Spring Security OAuth2 - Login 페이지 Customizing 하기 Spring Security OAuth2를 이용한 로그인 구현 - 사용자 정보 가져오기 Spring Security OAuth2를 이용한 로그인 구현 - Spring boot OAuth2 인증 살펴보기 Spring Security OAuth2를 이용한 로그인 구현 - OAuth2를 이용한 인증 사용하기 Google OAuth2 인증 방식 이해하기 OAuth2를 이용한 로그인 구현 이해하기 참고Success Handler 만들기Oauth2 인증 후 특정 작업을 진행하기 위해서는 SuccessHandler 가 필요하다. AuthenticationSuccessHandler 를 구현해 인증 후 사용자 정보를 로그로 출력하는 Handler 를 만들어 보려고 한다. 인증 후 Authentication 객체 내 Principal 에는 OAuth2User 객체 정보가 들어가게 된다. (OAuth2LoginAuthenticationProvider 에서 확인) @Slf4jpublic class Oauth2AuthenticationSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { OAuth2User oAuth2User = (OAuth2User) authentication.getPrincipal(); log.info("oAuth2User name = {}", (String) oAuth2User.getAttribute("email")); log.info("oAuth2User name = {}", (String) oAuth2User.getAttribute("name")); }} Security Config 추가oauth2AuthenticationSuccessHandler Bean 을 생성 후 successHandler 에 추가한다.

0

Spring Security OAuth2 - Login 페이지 Customizing 하기

목차 Spring Security OAuth2 - Handler Spring Security OAuth2 - Login 페이지 Customizing 하기 Spring Security OAuth2를 이용한 로그인 구현 - 사용자 정보 가져오기 Spring Security OAuth2를 이용한 로그인 구현 - Spring boot OAuth2 인증 살펴보기 Spring Security OAuth2를 이용한 로그인 구현 - OAuth2를 이용한 인증 사용하기 Google OAuth2 인증 방식 이해하기 OAuth2를 이용한 로그인 구현 이해하기 참고 https://www.baeldung.com/spring-security-5-oauth2-login Security Config@EnableWebSecurity@Slf4jpublic class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/oauth_login") .permitAll() .anyRequest() .authenticated() .and() .oauth2Login() .loginPage("/oauth_login"); }} Controller@Controllerpublic class LoginController { private static String authorizationRequestBaseUri = "oauth2/authorization"; Map<String, String> oauth2AuthenticationUrls = new HashMap<>(); @Autowired private ClientRegistrationRepository clientRegistrationRepository; @GetMapping("/oauth_login") public String getLoginPage(Model model) { Iterable<ClientRegistration> clientRegistrations = null; ResolvableType type = ResolvableType.forInstance(clientRegistrationRepository) .as(Iterable.class); if (type != ResolvableType.NONE && ClientRegistration.class.isAssignableFrom(type.resolveGenerics()[0])) { clientRegistrations = (Iterable<ClientRegistration>) clientRegistrationRepository; } clientRegistrations .forEach(registration -> oauth2AuthenticationUrls .put(registration.getClientName(), authorizationRequestBaseUri + "/" + registration.getRegistrationId()) ); model.addAttribute("urls", oauth2AuthenticationUrls); return "oauth_login"; }} 로그인 페이지

0

Spring Test - @WithMockUser, @WithAnonymousUser

목차 Spring Test - @WebMvcTest Spring Test - @DataJpaTest Spring Test - @WithMockUser, @WithAnonymousUser Controller@RestControllerpublic class HelloController { @GetMapping("/hello") public String hello(){ return new String("hello"); }} @WithMockUser@WithMockUser 는 Security Test 를 진행할 때 인증된 Authentication 객체를 만들어 인증된 상태로 Test 를 진행할 수 있게 도와준다. 속성 username : Authentication 객체에서 사용할 username 을 설정 password : Authentication 객체에서 사용할 password 을 설정 roles : Authentication 객체에서 사용할 role 을 설정 authorities : Authentication 객체에서 사용할 authorities 을 설정 @WebMvcTest@AutoConfigureMockMvcclass HelloControllerTest { @Autowired MockMvc mockMvc; @Test @WithMockUser(username = "user", password = "1234") void mockUserTest() throws Exception { mockMvc.perform(get("/hello")) .andDo(print()) .andExpect(status().isOk()); }} @WithMockUser 권한 사용 하기

0

프로그래머스 - 양과 늑대 Cpp

문제 링크 : https://programmers.co.kr/learn/courses/30/lessons/92343 프로그래머스 - 양과 늑대 Cpp 문제 풀이이 문제의 가장 어려운 점은 한번 방문한 노드를 여러번 방문할 수 있다는 것이다. 중복을 허용한 탐색을 진행하면 탐색이 끝나지 않으므로, 최대한 중복 방문을 제거하기 위해 비트마스크 를 이용해 방문한 노드들을 관리하면서 같은 상태에서 같은 노드 방문을 못하게 하는게 이 문제의 핵심이다.그 다음으로 어려웠던 부분은 이 탐색의 끝은 항상 루트 노드에서 끝나야 한다는 점이고, 반대로 생각하면 루트 노드에서 탐색 가능한 범위만 정답이 될 수 있는 것이다. 처음에 이 부분을 염두하지 않아서 계속 틀렸다. 이 두 부분만 잘 염두 하면 이 문제를 해결하는데 큰 어려움은 없다. 전체 소스 코드#include <iostream>#include <string>#include <vector>using namespace std;int maxValue = 0;void dfs(int sheep, int woof, int start, int state, vector<int> info, vector<vector<int>>& grape, vector<vector<bool>>& check) { if (woof >= sheep) { return; } maxValue = max(maxValue, sheep); for (int i = 0; i < info.size(); i++) { int node = 1 << i; int isVisited = state & node; int nextState = state | node; if (grape[start][i] == 0) { continue; } if (check[nextState][i] == true) { continue; } check[nextState][i] = true; if (isVisited) { dfs(sheep, woof, i, nextState, info, grape, check); } else { if (info[i] == 0) { dfs(sheep + 1, woof, i, nextState, info, grape, check); } else { dfs(sheep, woof + 1, i, nextState, info, grape, check); } } check[nextState][i] = false; }}int solution(vector<int> info, vector<vector<int>> edges) { int answer = 0; vector<vector<int>> grape = vector<vector<int>>(info.size() + 1, vector<int>(info.size() + 1, 0)); vector<vector<bool>> check = vector<vector<bool>>((1 << 18) - 1, vector<bool>(17 + 1, false)); for (vector<int> edge : edges) { int from, to; from = edge[0]; to = edge[1]; grape[from][to] = 1; grape[to][from] = 1; } maxValue = 0; int state = 1 << 0; check[state][0] = true; dfs(1, 0, 0, state, info, grape, check); answer = max(maxValue, answer); return answer;}