[문제 설명]

n 개의 음이 아닌 정수들이 있습니다. 이 정수들을 순서를 바꾸지 않고 적절히 더하거나 빼서 타겟 넘버를 만들려고 합니다. 예를 들어 [1, 1, 1, 1, 1]로 숫자 3을 만들려면 다음 다섯 방법을 쓸 수 있습니다.

-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3

사용할 수 있는 숫자가 담긴 배열 numbers, 타겟 넘버 target이 매개변수로 주어질 때 숫자르 적절히 더하고 빼서 타겟 넘버를 만드는 방법의 수를 return 하도록 solution  함수를 작성해주세요.

 

[제한 사항]

- 주어지는 숫자의 개수는 2개 이상 20개 이하입니다.

- 각 숫자는 1 이상 50 이하인 자연수입니다.

- 타겟 넘버는 1 이상 1000 이하인 자연수입니다.

 

[입출력 예]

numbers target return
[1, 1, 1, 1, 1] 3 5
[4, 1, 2, 1] 4 2

 

class Solution{
	static int answer = 0;
	public int solution(int[] numbers, int target){        
        dfs(numbers, target, 0, 0);
        
        return answer;
    }
    
    private static void dfs(int[] numbers, int target, int depth, int sum){
    	if(depth == numbers.length){
        	if(sum == target) 
            	answer++;
        }else{
        	dfs(numbers, target, depth + 1, sum + numbers[depth]);
            dfs(numbers, target, depth + 1, sum - numbers[depth]);
        }     
    }
}

 

DFS를 사용한 이유

- 'numbers' 배열의 모든 원소들에 대해 더하거나 빼는 모든 가능한 조합을 탐색할 수 있다. 이는 가능한 모든 경우의 수를 확인하는데 적합

- DFS를 사용하면 재귀적으로 문제를 간결하게 해결할 수 있다. 코드가 비교적 단순하며 가독성이 좋음.

'JAVA > java' 카테고리의 다른 글

프로그래머스 2단계_시소 짝꿍 (자바)  (1) 2024.06.25
자바로 크롤링 하는 방법  (0) 2023.01.20

문제)

어느 공원 놀이터에는 시소가 하나 설치되어 있습니다. 이 시소는 중심으로부터 2(m), 3(m), 4(m) 거리의 지점에 좌석이 하나씩 있습니다.
이 시소를 두 명이 마주 보고 탄다고 할 때, 시소가 평형인 상태에서 각각에 의해 시소에 걸리는 토크의 크기가 서로 상쇄되어 완전한 균형을 이룰 수 있다면 그 두 사람을 시소 짝꿍이라고 합니다. 즉, 탑승한 사람의 무게와 시소 축과 좌석 간의 거리의 곱이 양쪽 다 같다면 시소 짝꿍이라고 할 수 있습니다.
사람들의 몸무게 목록 weights이 주어질 때, 시소 짝꿍이 몇 쌍 존재하는지 구하여 return 하도록 solution 함수를 완성해주세요.


제한 사항

  • 2 ≤ weights의 길이 ≤ 100,000
  • 100 ≤ weights[i] ≤ 1,000
    • 몸무게 단위는 N(뉴턴)으로 주어집니다.
    • 몸무게는 모두 정수입니다.

입출력 예

weights result
[100,180,360,100,270] 4

 

문제 이해)

- 시소는 중심으로부터 2, 3, 4 거리의 지점에 좌석이 하나씩 있음.

- weights의 길이가 100,000 이기 때문에 시간 복잡도 고려해야 함.

 

import java.util.*;

class Solution {
    public long solution(int[] weights) {
        long answer = 0;
    
        Arrays.sort(weights);
        Map<Double, Integer> map = new HashMap<>();
        
        for(int i : weights){
            double a = i * 1.0;
            double b = (i * 2.0) / 3.0;
            double c = (i * 1.0) / 2.0;
            double d = (i * 3.0) / 4.0;
            
            if(map.containsKey(a)) answer += map.get(a);
            if(map.containsKey(b)) answer += map.get(b);
            if(map.containsKey(c)) answer += map.get(c);
            if(map.containsKey(d)) answer += map.get(d);
            
            map.put((i * 1.0), map.getOrDefault((i * 1.0), 0) + 1);
        }
        
        
        return answer;
    }
}

 

 

- weights 정렬하였기 때문에 키값은 크거나 같을 수 밖에 없음. 그래서 [1.0], [2.0/3.0], [2.0/4.0 -> 1.0/2.0], [3.0/4.0] 으로 거리 고려하면 됨.

 

 

'JAVA > java' 카테고리의 다른 글

프로그래머스 2단계_타겟 넘버(자바)  (0) 2024.07.03
자바로 크롤링 하는 방법  (0) 2023.01.20

등록일자, 수정일자, ID 등과 같이 모든 테이블에서 공통으로 사용하는 칼럼이 존재한다. 공통된 매핑 정보를 각각의 엔티티 클래스마다 중복으로 작성하는 것을 방지하여 코드의 가독성을 높이고 유지보수에 용이하게 하는 어노테이션이 @MappedSuperClass이다.

 

@MappedSuperClass

부모 클래스가 데이터베이스 테이블과 매핑되지 않고, 자식 클래스에게 공통된 매핑 정보를 제공하는 데 사용된다. 즉, 자식 클래스들은 @MappedSuperClass가 적용된 부모 클래스를 상속받고, 자신만의 추가적인 매핑 정보를 가질 수 있다.

 

위 그림에서 Member와 Board 엔티티 클래스는 서로 연관없는 칼럼인 email, content와 공통으로 가진 created_date, updated_date 속성을 가지고 있다.

부모 클래스인 BaseEntity는 자식들에게 상속을 통해 칼럼 정보를 제공하는 역할을 한다. 즉, BaseEntity는 테이블로 매핑할 필요없고, 칼럼 정보만 자식에게 제공하면 된다.

 

@MappedSuperClass
public abstract class BaseEntity{
    @CreatedDate
    private LocalDateTime createdDate;
    @LastModifiedDate
    private LocalDateTime updatedDate;
}
@Entity
public Class Member extends BaseEntity{
   private String email;
   
   //createdDate, updatedDate 상속받음
}

 

BaseEntity는 테이블로 매핑할 필요가 없기 때문에 @Entity 대신 @MappedSuperClass를 사용하면 된다.

 

 

 

1. 주로 등록일, 수정일, 등록자, 수정자와 같은 전체 엔티티에서 공통으로 적용할 떄 사용

2. 테이블과 관계없이, 단순히 엔티티가 공통으로 사용하는 매핑 정보를 모을 수 있음

스프링 시큐리티
- 의미 : 스프링 기반의 애플리케이션 보안(인증, 인가, 권한)을 담당하는 스프링 하위 프레임워크로, 필터 기반으로 동작한다.
- CSRF 공격, 세션 고정 공격을 방어해주고, 요청 헤더도 보안 처리를 해주므로 개발자가 보안 관련 개발을 해야 하는 부담을 줄여준다.

 

 

 

Domain 패키지

@Table(name = "users")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Entity
public class User implements UserDetails{ //UserDetails를 상속받아 인증 객체로 사용

	...
    
    @Builder
    public User(String email, String password, String auth){
    	this.email = email;
        this.password = password;
    }
    
    ...
}

▶ User 클래스가 상속한 UserDetails 클래스는 스프링 시큐리티에서 사용자의 인증 정보를 담아 두는 인터페이스, 

스프링 시큐리티에서 해당 객체를 통해 인증 정보를 가져오려면 필수 오버라이드 메서드들을 여러 개 사용해야 한다.

 

 

Repository 패키지

public interface UserRepository extends JpaRepository<User, Long>{
	Optional<User> findByEmail(String email); //email로 사용자 정보를 가져옴
}

▶ 이메일로 사용자를 식별할 수 있다. 

▶ findByEmail() : FROM user WHERE email = #{email}

 

 

Service 패키지

@RequiredArgsConstructor
@Service
public class UserDetailService implements UserDetailsService{
	private final UserRepository userRepository;
    
    //사용자 이름(email)으로 사용자의 정보를 가져오는 메서드
    @Override
    public User loadUserByUsername(String email){
    	return userRepository.findByEmail(email).orElseThrow(() -> new IllegalArgumentException((email)));
    }
}

UserDetailsService 인터페이스 : 스프링 시큐리티에서 사용자 정보를 로드하기 위한 메서드를 정의한 인터페이스로, 이 인터페이스를 구현하려면 loadUserByUsername() 메서드를 반드시 구현해야 한다.

loadUserByUsername() : 주어진 사용자 이름(또는 식별자)을 기반으로 사용자 정보를 로드하는 역할을 한다.

만약, 이 메서드를 오버라이딩 하지 않는다면 스프링 시큐리티가 'UserDetailsService'를 사용할 때 해당 메서드가 적절한 사용자 정보를 로드할 수 없게 되어, 사용자 인증 및 권한 부여와 관련된 동작이 제대로 이루어지지 않아 컴파일 오류가 발생하게 된다.

 

 

Config 패키지

@RequiredArgsConstructor
@Configuration
public class WebSecurityConfig{
	
    private final UserDetailService userService;
    
    //스프링 시큐리티 기능 비활성화
    @Bean
    public WebSecurityCustomizer configure(){
    	return (web) -> web.ignoring()
        	.requestMatchers(toH2Console())
                .requestMatchers("/static/**");
    }
    
    //특정 HTTP 요청에 대한 웹 기반 보안 구성
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
    	return http
        	.authorizeHttpRequests() //인증, 인가 설정
                .requestMatchers("/login", "/signup", "/user").permitAll()
                .anyRequest().anthenticated()
                .and()
                .formLogin() //폼 기반 로그인 설정
                .loginPage("/login")
                .and()
                .logout() //로그아웃 설정
                .logoutSuccessUrl("/login")
                .invalidateHttpSession(true)
                .and()
                .csrf().disable() //csrf 비활성화
                .build();
    }
    
    //인증 관리자 관련 설정
    @Bean
    public AuthenticationManager authenticationManager(HttpSecurity http, 
    BCryptPasswordEncoder bCryptpasswordEncoder, UserDetailService userDetailService) throws Exception{
    	return http.getSharedObject(AuthenticationManagerBuilder.class)
        	.userDetailsService(userServicie)
                .passwordEncoder(bCryptPasswordEncoder)
                .and()
                .build();
    }
    
    //패스워드 인코더를 사용할 빈 등록
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
    	return new BCryptPasswordEncoder();
    }
}

 

= 메서드 부가 설명

confugrure() - static 하위 경로에 있는 리소스와 h2-console 하위 url 대상으로 스프링 시큐리티의 모든 기능(인증, 인가) 서비스를 적용하지 않음
filterChain() - 특정 Http 요청에 대한 웹 기반 보안을 구성.
- 인증, 인가 및 로그인, 로그아웃 관련 설정
authenticationManager()  - 인증 관리자 관련 설정
- 사용자 정보를 가져올 서비스를 재정의하거나, 인증 방법(JDBC 기반 인증) 등을 설정할 때 사용

 

= filterChain() 메서드 부가 설명

requestMatchers() 특정 요청과 일치하는 url에 대한 액세스를 설정
permitAll() 누구나 접근이 가능하게 설정. (/login, /signup, /user로 요청이 오면 인증,인가 없이 접근 가능
anyRequest() 위에 설정한 url 이외의 요청에 대해서 설정
authenticated() 별도의 인가는 필요하지 않지만 인증이 성공된 상태여야 접근 가능
loginPage() 로그인 페이지 경로 설정
defaultSuccessUrl() 로그인이 완료되었을 때 이동할 경로 설정
logoutSuccessUrl() 로그아웃이 완료되었을 때 이동할 경로 여부 설정
invalidateHttpSession() 로그아웃 이후에 세션을 전체 삭제할지 여부를 설정

 

 

 

1. 카카오톡 개발자 페이지에서 애플리케이션을 생성한다.

 

2. 플랫폼에서 Web 플랫폼 등록

 

3. Redirect URI 등록

- 두 개 모두 활성화시켜준다. 


[----> 여기서 Redirect URI를 내 마음대로 정했더니 이때부터 삽질 시작됨.. 2 ~ 3시간 동안 오류가 발생하는 원인을 찾고 고치고 엄청 고생함. 카카오톡 로그인 완료 후 토큰 값은 잘 나오는데 404페이지 에러가 발생함. 그래서 URI를 잘못 지정한 줄 알고 다시 수정.. 그래도 같은 오류가 발생.. 로그인 Controller에 카카오톡 리다이렉트 URI에서 루트 지정함. 404 에러는 발생하지 않지만, DB에 저장이 안 되고, Controller에서 view로 지정한 곳으로 이동만 함. 구글링에서는 토큰 값을 받아와 따로 저장하고 백엔드에서 다시 불러와야 된다고 나옴. 근데 공부할 때 OAuth2는 방금 언급한 토큰 값을 받아오고 사용하는 과장이 포함되는 라이브러리라고 배웠음. 처음부터 다시 차근차근해보니 Redirect URI와 Spring Security  OAuth2 Client 라이브러리를 잘 몰라서 실수한 오류였음...ㅜㅜ]


-> Spring Security OAuth2 Client 라이브러리를 사용할 때 Redirect URI는 OAutth2.0 에섯 사용자를 인증 서버로 리다이렉션 시키고, 사용자의 동의를 받은 후에 애플리케이션으로 다시 보내는 데 사용된다. 그래서 Redirect URI은 기본적으로 /localhost:8080/oauth2/code/{registrationId}로 리다이렉트 해준다. 이때 {registrationId}는 등록된 OAuth2.0 공급자의 아이디(Google, Kakao 등)이다.

 

4. REST API 키 저장

 

5. 내 애플리케이션 -> 보안 -> Client-Secret 발급받고 활성화시키기.

 

6. 내 애플리케이션 -> 동의항목 -> 개인정보 사용할 거 설정하기.

7. application.yml

security:
    user:
      name: test
      password: 1234
      
    oauth2:
      client:
        registration:
          kakao:
            client-id: 00000000000000000000
            client-secret: 00000000000000000000000
            scope:
              - profile_nickname
            authorization-grant-type: authorization_code
            redirect-uri: http://localhost:8080/login/oauth2/code/kakao
            client-name: Kakao
            client-authentication-method: POST
        
        provider:
          kakao:
            authorization-uri: https://kauth.kakao.com/oauth/authorize
            token-uri: https://kauth.kakao.com/oauth/token
            user-info-uri: https://kapi.kakao.com/v2/user/me
            user-name-attribute: id

- client-id : Rest API 키

- client-secret : 보안에서 받아온 Client-secret 키

- scope : 개인정보 동의 항목에서 받아온 값

===> 카카오톡은 provider를 작성해야 함.

 

8. SecurityConfig.java

.and()

.oauth2Login() : OAuth2.0 로그인 

.userInfoEndpoint() : OAuth2 공급자로부터 사용자 정보를 가져올 때의 구성을 설정(Scope에 해당하는 부분)

.userService(oauth2DetailService) : 사용자 정보를 가져오는 데 사용할 서비스 지정

 

9. OAuth2UserInfo.java

public interface OAuth2UserInfo {
	String getProviderId();
	String getProvider();
	String getEmail();
	String getName();
}

받아올 값은 같기 때문에 인터페이스를 만들어 준다.

 

10. KakaoUserInfo.java

카카오톡 개인 정보를 받아올 클래스 지정.. (OAuth2.0 공급자마다 제공하는 타입과 변수가 다르기 때문에)

@AllArgsConstructor
public class KakaoUserInfo implements OAuth2UserInfo{
	private Map<String, Object> attributes;

	@Override
	public String getProviderId() {
		return attributes.get("id").toString();
	}

	@Override
	public String getProvider() {
		return "kakao";
	}

	@Override
	public String getEmail() {
		return null;
	}

	@Override
	public String getName() {
		//kakao_account라는 Map에서 추출
		return (String)((Map)attributes.get("properties")).get("nickname");
	}
}

 

 

11. OAuth2DetailsService.java

@RequiredArgsConstructor
@Service
@Slf4j
public class OAuth2DetailsService extends DefaultOAuth2UserService{
	private final UserRepository userRepository;
	
	@Override
	public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException{
		OAuth2User oauth2User = super.loadUser(userRequest);
		log.info("getAttributes: {}", oauth2User.getAttributes());
		
		OAuth2UserInfo oAuth2UserInfo = null;
		
		String provider = userRequest.getClientRegistration().getRegistrationId();
		
		if(provider.equals("kakao")) {
			log.info("카카오 로그인 요청");
			oAuth2UserInfo = new KakaoUserInfo((Map)oauth2User.getAttributes());
		}
		
		String providerId = oAuth2UserInfo.getProviderId();
		String password = new BCryptPasswordEncoder().encode(UUID.randomUUID().toString());
		String email = oAuth2UserInfo.getEmail();
		if(email == null) {
			email = " ";
		}
		String username = provider + "_" + providerId;
		String name = oAuth2UserInfo.getName();
		
		User userEntity = userRepository.findByUsername(username);
		
		log.info(username);
		if(userEntity == null) { //최초 로그인
			User user = User.builder()
				.username(username)
				.password(password)
				.email(email)
				.name(name)
				.role("ROLE_USER")
				.build();
			
			return new PrincipalDetails(userRepository.save(user), oauth2User.getAttributes());
		}else {
			return new PrincipalDetails(userEntity, oauth2User.getAttributes());
		}
		
		
	}
}

이런 식으로 저장이 된다.

 

12. href = '/oauth2/authorization/kakao'  

Spring Security란?

- 스프링 기반 웹 애플리케이션에서 보안을 처리하기 위한 강력하고 포괄적인 프레임워크이다. 사용자 인증과 권한 부여를 관리하며, 웹 애플리케이션에서 발생할 수 있는 다양한 보안문제에 대응하기 위한 다양한 기능을 제공한다.

 

[주요 기능과 특징]

1. 인증 : 사용자가 누구인지 확인하는 과정으로 사용자의 아이디와 비밀번호를 사용하여 로그인하는 것이 대표적이다. Spring Security는 다양한 인증 메커니즘을 지원하며, 사용자 인증이 성공하면 보안 컨텍스트를 생성하여 사용자의 정보를 저장한다.

2. 권한 부여 : 사용자에 대한 권한을 관리하고, 특정 리소스 또는 기능에 접근 권한을 부여한다. Spring Security는 권한 기반 접근 제어를 제공하며, 사용자가 특정 권한을 갖고 있는지 학인하는 메커니즘을 제공한다.

3. 보안 설정 및 필터 체인 : 보안 관련 설정을 통해 애플리케이션의 보안 정책을 정의할 수 있다. 내장된 필터 체인을 사용하여 요청에 대한 보안 검사 및 처리를 수행한다.

=> 보안 설정) java 또는 xml 설정 파일을 통해 이루어진다. 예로 특정 URL 패턴에 대한 접근 권한, 사용자 로그인 및 인증 방법, 세션 관리 등이 설정된다.=> 필터 체인) Spring Security는 내부적으로 여러 보안 관련 필터를 사용하여 요청에 대한 처리를 수행한다. 예로 사용자 인증, 권한 부여, CSRF 방어, 세션 관리 등을 다루는 필터들이 있다.

4. 세션 관리 : 사용자의 세션을 관리하고, 세션 고정 공격으로부터 보호하며, 세션 타임 아웃 등을 설정할 수 있다.

5. CSRF 방어 : CSRF 공격으로부터 보호하기 위한 기능 제공한다.

=> CSRF 공격) 공격자가 특정 사용자의 권한을 이용하여 사용자가 의도하지 않은 동작을 수행하게 하는 공격이다.

------ 사용자가 이미 인증된 상태에서 이루어지고(쿠키 정보),  사용자의 동의 없이 웹에서 특정 동작 수행하게 하거나, 악의적인 웹 사이트를 통해 공격을 시도하는 것이다.(이때 이미 다른 사이트에 로그인되어 있어 있는 상태) ------

=> CSRF 방어 방법) [1] 서버에서 사용자의 세션과 연관된 CSRF 토큰이 생성되어 각 요청마다 이 토큰을 검증함으로써 방어가 가능한다. [2] SameSite 쿠키 속성을 활용하여 쿠키가 어떤 상황에서 전송될 수 있는지를 제한하는 데 사용한다. [3] Secure 및 HttpOnly 속성을 쿠키에 적절히 설정하고, CSP(Content Security Policy) 등의 보안 헤더를 사용하여 공격을 어렵게 만들 수 있다. 

6. Remember-Me 기능 : 사용자가 로그인 정보를 기억할 수 있는 기능을 지원한다.

7. LDAP, OAuth 등과의 통합 : 다양한 외부 인증 및 권한 부여 메커니즘과의 통합을 지원한다.

8. 암호화 및 해시 기능 : 사용자 비밀번호를 안전하게 저장하기 위한 암호화 및 해시 기능을 제공한다.

 

 

Spring Security 설정

1. Spring Security 의존성 추가 : 프로젝트의 의존성 관리 도구(Maven 또는 Gradle)를 사용하여 Spring Security 의존성 추가한다.

2. Spring Security 설정 : application.yml 또는 application.properties 파일에서 Spring Security에 관한 설정을 추가한다. 사용자 인증, 권한 부여, 세션 관리 등을 다룬다. 기본적으로 Spring Security는 메모리 임베디드된 사용자 정보를 사용하여 테스트 용도로 제공된다.

3. 로그인 페이지 자동 생성 : Spring Security가 활성화되면, 사용자가 인증되지 않았을 때 자동으로 로그인 페이지가 생성된다. 이는 일반적으로 '/login' 경로에 해당된다.

===> Spring Security의 인증 메커니즘이 사용자를 인증하고, 제공된 이름 및 비밀번호로 로그인을 수행하기 때문에 로그인 창으로 이동한다. 개발 중에는 간편하게 테스트용으로 사용하도록 설정되어 있지만, 운영 환경에서는 보안을 강화해야 한다.

 

 

GitHub Action 

: 깃헙에서 제공하는 CI/CD 및 자동화 서비스로 깃헙 레파지토리에서 발생하는 이벤트에 따라 워크플로우를 정의하고 이틍 통해 소트프웨어 빌드, 테스트, 배포 등을 자동으로 수행할 수 있다. 

  1. 깃헙에 업로드한 걸 로컬 컴퓨터에 Clone
  2. 코드를 수정해서 기능을 변경 또는 추가
  3. 깃헙에 Push
  4. CI 서버에서 자동으로 우분투 설치, JDK 설치, 코드 다운로드, 코드 테스트, build
  5. 정상이면 배포

CI 서버를 사용하기 위한 스크립트 deploy.yml 파일 작성

===> 프로젝트 이름에 main 브랜치에 푸시

===> 여러 작업은 'jobs' 섹션에서 정의하고 각 작업은 'steps'로 구성된다. steps에는 워크플로의 각 단계에 해당하는 작업을 정의한다.

== uses : actions/checkout@v3 (actions 라이브러리에서 제공하는 명령어로 먼저 저장소를 체크아웃해준다.)

== uses : actions/setup-java@v3 (actions 라이브러리 에서 제공하는 명령어로  java 설치)

== run : chmod + x ./gradlew (gradlew 파일 권한 부여)

===> 한국시간으로 시간 설정

===> run : | 은 여러 줄로 명령어를 작성하겠다는 의미

mkdir deploy : deploy 파일 생성

cp build/libs/*.jar deploy/application.jar : build/libs/*.jar에서 생성된 jar 파일을 deploy/application.jar에 복사

cp procfile deploy/procfile : procfile를 deploy/procfile에 복사

cp -r .ebextensions deploy/.ebextensions : ebextensions 폴더를 deploy.ebextensions 폴더로 복사

(엘라스틱 빈스톡의 .ebextensions 폴더가 프로젝트의 특정 디렉토리로 정리되어 배포를 위한 설정 파일들이 별도의 위치에 저장될 때 사용할 수 있는 명령어)

cp deploy && zip -r deploy.zip : 두 개의 명령어를 사용하여 실행하려는 듯한 구문이지만, 명령어 간의 &&로 연결되어 첫 번째 명령어가 성공하면 다음 두 번째 명령어가 실행되도록 하는 것.

 

 

 

 

 

 

 

 

[K-디지털] AWS 리눅스 기반 클라우드 데브옵스 기초 실무 과정 참고하며 작성하였습니다.

롤링 

: 여러 컴퓨터 과학 및 소프트웨어 배포 컨텍스트에서 사용되며, 일반적으로 연속적이고 부드러운 업데이트 또는 배포를 의미한다. 

 

롤링 배포 정책 

1. 한 번에 모두

: 모든 서버 또는 인스턴스에 대해 동시에 새로운 버전을 배포하는 전략

===> 모든 서버가 동시에 업데이트되므로 배포 시간이 매우 짧지만, 모든 서버가 동시에 다운될 가능성이 있어 가용성에 영향을 줄 수 있다. 오류가 발생하면 모든 서버에 동시에 영향을 미칠 수 있다. 

 

2. 추가 배치 (무중단)

: 일부 서버를 먼저 업데이트하고, 그 후 추가 배치를 통해 나머지 서버를 업데이트하는 전략

===> 새로운 버전이 일부 서버에서 검증된 후에 전체로 확장된다. 이는 가용성을 높이며 롤링 업데이트의 안전성을 유지하는 방법이다. 배포하는 과정에서 한 개의 EC2에서 에러가 발생할 경우 롤백이 진행되는데, 이때 한 개의 EC2의 롤백이 나닌 전체 EC2의 롤백이 진행되기 때문에 자원이 많이 소요된다. 

 

3. 변경 불가_블루/그린 (무중단)

: 새로운 버전의 소프트웨어를 포함한느 새로운 인스턴스를 생성하고 이전 버전의 인스턴스로 교체하는 전략

===> 이전 버전의 인스턴스를 중지하고 새로운 버전의 인스턴스를 시작하여 변경을 불가능하게 만든다. 이는 롤백이 간단하며, 배포 전과 후의 상태가 완전히 분리되어 있다. 배포하는 시간동안 4개의 EC2가 가동하고 정상으로 배포가 되면 2대가 종료된다. 에러가 있을 경우 배포하던 새로운 EC2를 제거하면 되기 때문에 자원 소요가 적다. 

+ Recent posts