출처: https://typemin.tistory.com/7 [TypeLOG:티스토리]

xx.xx.xxx/app/sign 으로 요청을 보내게 되었을 때 "redirect: login" 으로 리디렉션이 되어야 하는 것인데.

xx.xx.xxx/app/login(정상) 이 아닌 xx.xx.xxx/login(비정상) 이렇게 가는 것이 아닌가 ?
프록시를 한 백엔드 서버의 리디렉션의 요청을 nginx 설정에서 다시 바꿔주면 된다.

location ^~/app/ {
    proxy_redirect http://xx.xx.xxx/ http://xx.xx.xxx/app/;

    proxy_pass http://xx.xx.xxx:8089/;
}

 

반응형

나는 프로젝트를 열심히 하던 찰나 변수의 위치를 바꿔버리는 어이없는 실수를 하였다.

function void hello(int a, int b){}
// 실수 
hello(b,a);
// expect
hello(a,b);

빠르게 찾을 순 있었고 문제는 해결했다. 하지만 이로인해 내 코드를 의심 할 수 있는 좋은 기회였다.

 

위 문제가 아니었더라도 협업하는 환경에서 문제가 자잘하게 많았다.
동시 병렬적으로 작업을 하다보니 코드의 충돌이 생기고 서로 빠른 주기로 개발은 하는데 리뷰시간이 아깝다는 핑계로 리뷰를 안하더니 막상 코드의 히스토리를 이해하기위한 리뷰가 더 길어지는 문제는 말해 뭐해다.

 

내가 겪은 경험들이 말해주는 바는 "지금까지 일해왔던 방식은 일하는 시간이 증가하고 코드의 품질을 높이지는 못한다." 이다

도입 허락해줘 ..

코드 스타일도 다르고. 쪼개서 해야하는 리뷰도 안하니 다른 사람이 짠 코드의 히스토리를 이해하지 못한다.
내가 짠 코드도 못 믿는다. 남이 짠 코드는 더더욱 신뢰할 수 없다. 누가 검증을 해 줄수 있는가 ?

- 개발 시간의 증가, 코드 신뢰도 하락

검증은 하지만 자기 PC에서만 한다는 것, 막상 배포하려고 하니 환경 문제가 생긴다.

- 개발 외 업무 증가

신뢰 할 수 없는 개발 주기안에서 열심히 개발을 하고 나니 남는 건 버그와 연장 근무뿐이 아니겠는가? from su8y

 

CICD 도구를 통해 개발 상태, 배포 상태 등을 한 눈에 확인이 가능하므로 매니저한테도 좋은 일이 아닐수가 없다.

 

일하는 사람이라면 효율적으로 일 할수 있는 방법에 대해서 고민을 해봐야한다. 이를 위해서 깃랩 CI/CD 파이프라인 구상을 해보려고 한다.

지속적인 통합/제공/배포

  • ci: application 코드의 변경사항이 정기적으로 빌드 및 테스트(품질 검사 등)을 거쳐 공유 Repository에 병합이 되는 프로세스로 버그가 없고 좋은 application을 고객에게 전달하기 위한 초석입니다.
  • cd: 개발을 신명나게 하고나서 배포하는 과정의 자동화 프로세스입니다.

전체적인 CI/CD 흐름

  • 개발 후 배포 해야되는 브랜치로 Pull Requests(PR)을 보냅니다.
  • 해당 PR에 대해서 build, test, image push 를 합니다.
  • 실패했다면 사유와 알림을 알려줍니다.
  • 해당 파이프라인을 통해 발생한 개발 서버의 URL을 댓글, 이메일, SMS 등으로 안내해줍니다.

 

 

반응형

문제 상황

  • 특정 route의 GatewayFilter를 개별적으로 등록.
  • 보통의 상황에서는 문제가 생기지 않음.
  • 비동기 응답(Streaming Response, Mono, Flux 등)을 받을때는 사전 처리는 잘 되지만 사후 처리는 비동기 응답을 기다리지 않는 상황.

실행시키는 Proxied Service 비동기로 Streaming응답 형식을 하게되고 총 5초가 걸리게 했습니다.
(시간은 이해를 돕기위해 간소화)

0초 API 요청 
0초 GlobalFilter 사전 처리 동작 
0초 GatewayFilter 사전 처리 동작
0초 GatewayFilter 사후 처리 동작
5초 GlobalFilter 사후 처리 동작

즉, StreamResponse의 끝나는 시점에 GatewayFilter가 작동하면 되는 문제였습니다.

왜 그럴까 ?

GlobalFilter의 우선순위는 -1로 설정한 상황이었고.

스프링 공식문서 Combined Global Filter and GatewayFilter Ordering링크로 들어가보면 친절하게 우선순위를 GlobalFilter와 같이 사용하는 것이 있고 GatewayFilter도 똑같이 -1로 주어서 사용해봤더니 실패했습니다.

@Component
public class UserReqeustThrottlingFilter implements GatewayFilter, Ordered {
    private static final String REDIS_UNIQUE_USER = "unique_user::";

    @Autowired
    RedisTemplate<String, Integer> redisTemplate;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
       // ...
    }

    @Override
    public int getOrder() {
        return -1;
    }
}

스프링의 공식문서 내용 중 WebHandlerfilterChain을 통해서 요청이 실행된다고 합니다.

Gateway WebHandler의 구현체 FilteringWebHandler

FilteringWebHandler는 내부의 GatewayFilterAdapter를 통해서 실행이 됩니다. 우선순위를 잘 찾아보면

제가 등록한 UserRequestThrottlingFilter가 우선순위가 정상적으로 된 걸 보았는데NettyWriteResponseFilter 보다는 낮을 걸 확인 할 수 있습니다.

NettyWriteResponseFilter클래스가 비동기 응답을 처리하는 필터였고 해당 필터보다 위쪽에 있어야지 제가 원하는 응답을 얻을 수 있습니다.

해결

이제야 문제는 해결됩니다. 이유를 몰랐던 우선순위에 따른 응답이 달라지는 것은 NettyWriteResponseFilter와의 우선순위 문제였고 커스텀한 글로벌 필터는 항상 NettyWriteReponseFilter보다 위 입니다.

하지만 GatewayFilter는 아니었던 거죠 우선순위를 NettyWriteResponseFilterorder값인 -1로 주는 것이 아닌 확실하게 -2를 주면서 문제는 해결됩니다.

index 2 에 위치하게 됩니다.

ㅜㅜ

새로운 Spring Project인 Cloud Gateway에 대해서 알게된지 3일차지만 많은 공부가 되었습니다.
이 문제 해결법이 도움이 됐으면 좋겠네요.

반응형

'Programming > Spring' 카테고리의 다른 글

Spring MVC(2). 프론트컨트롤러(DispatcherServlet)  (0) 2023.04.19
Spring MVC(1). 서블릿  (0) 2023.04.19

두 개의 LinkedList L1, L2를 통한 덧셈을 구현하면 됩니다.
이 부분은 자료구조 LinkedList를 잘 사용하면 되는데요.
L1 과 L2 를 가르키는 포인터를 순차적으로 같이 움직이면서 덧셈을 구현해나가면 됩니다.

덧셈에서 중요한 부분인 $9 + 9$ 를 하였을때 1의 자리수에서 10의 자리수로 1을 올려주는 것을 잘 해결해나가면 되는데요.

올림수를 별도로 따로 처리한다기보다는 앞으로 이어질 Node에 미리 값 1을 세팅을 해주는 것으로 해결하였습니다.

반응형

안녕하세요 오늘은 LeetCode의 TwoSum 문제를 리뷰하려고 합니다.
이 문제는 아주 간단한데요

배열 nums에서 2개의 중복되지 않은 임의의 위치의 숫자를 더해 target을 만드는 인덱스를 반환하면 되는 문제입니다.

조건을 봐보겠습니다.

  • $2 <= nums.length <= 10^4$
  • $10^9 <= nums[i] <= 10^9$
  • $10^9 <= target <= 10^9$

nums.size 같은 경우에는 최대 1만이고, 각 요소는 1_000_000_000 입니다.
2개의 합을 처리하는 자료로 int형으로 충분하고, nums에서 단순하게 2개의 요소를 뽑는 방법을 나이브하게 Broute Forcing 방식으로 접근해도 100 _000_000 이므로 $N^2$ 으로 안전하게 구할 수 있을거 같습니다

반응형

 

 

첫 문제를 풀었을 때가 생각이 납니다. 처음에는 그냥 재밌고 뭔가 멋있어 보였던 "개인적인 욕심"이 들어있었습니다.

별 찍기 문제를 풀었었는데 너무 재밌었죠. 이렇게 시작했던 문제풀이가 어느덧 4년 차가 되었습니다.

문제를 풀기가 너무 어려워  책도 읽고 관련 블로그도 찾아보고, 푸는 방식에 대한 변화도 주고 여러 방법으로 접근을 했었습니다. 

언어의 선택


처음에는 C언어로 시작하였고 C++ 그리고 Java, Python 등 많은 언어로 문제를 풀어봤습니다. 

어떤 글에서는 그냥 Python쓰세요,  C++ 쓰세요 , 현업에서 사용하시는 언어 사용하세요 등 많은 의견이 있었습니다. 

저도 현업에서는 Java를 써서 Java로 100문제 가량 풀어봤는데요. 

사실 Java는 내가 표현하고 싶은 알고리즘을 표현하기 위해 많은 코드를 작성해야 돼서 "저한테는 좀 난해한"면이 있어 , 첫 시작 그리고 가장 익숙했던 C언어 계열인 C++을 사용하여 문제풀이를 지속하였습니다. 

사실 언어 자체가 어려웠던 것을 제외하면 가장 편하고, 직관적으로 제가 코드를 조작할 수 있어서 빠르게 실력이 늘 수 있었습니다.

코딩보단 생각을 


대학교 시절부터 개발을 꾸준히 해왔지만 항상 느꼈던 것은 "생각의 부족함" 이었습니다. 

개발뿐만이 아니라 실 인생에 걸쳐서 항상 배워왔던 것이었습니다.

늘 후회했어요. "이러기 전에 한번 더 생각해볼걸" 이라고요, 항상 생각의 부족함으로 시작한 문제 해결은 점차 꼬여버린 문제 마주하게 되고 해결하는 비용은 늘 더 많이 들었습니다. 

문제풀이를 하면서도 뼈저리게 느꼈는데요.. 문제에서 제공되는 작게는 N의 크기라든가 시간복잡도, 공간복잡도, 자료구조 등 조금만 생각을 하고 계산을 하고 코딩을 시작했더라면 코드를 돌려보기 전에 빠르게 캐치하여 더 빠르게 성장할 수 있었을 거 같습니다. 

사실 이 부분에 있어서는 아직도 많이 부족하지만, 계속해서 성장해나가고 있습니다. 

 

조금 더 성장하기 위해


사실 아직 나는 백준 플레다!라고 말하기에는 많이 부족합니다. 실버, 골드 문제 티어와 상관없이 저한테는 어려운 문제는 늘 있었으니까요. 

앞으로는 이러한 컨디션의 기복을 많이 없애기 위해서 날을 예리하게 가는 시간을 가지려고 합니다. 

 

감사합니다.

반응형

풀이 찍 .. 

vector<int> inputs(n, 0);
stack<int> s;
queue<int> store;
while (true) {
    if (s.size() > 0 && inputs[p] == s.top()) {
        output += "-\n";
        s.pop();
        p++;
        continue;
    }
    if(p == n || store.empty()) break;
    
    int front = store.front();
    store.pop();
    output += "+\n";

    s.push(front);
}

 

반응형

'PS-Algorithm > Algorithm' 카테고리의 다른 글

선 긋기 해설  (0) 2024.01.28
모바일 광고 입찰 해설  (0) 2024.01.28
[LeetCode]GenerateParentheses  (0) 2022.12.09
[BOJ/C++] 1759 암호 만들기  (0) 2022.01.16
[그리디 알고리즘] BOJ-10610 30  (0) 2021.11.22

문제링크

매우 큰 도화지에 자를 대고 선을 그으려고 한다. 선을 그을 때에는 자의 한 점에서 다른 한 점까지 긋게 된다. 선을 그을 때에는 이미 선이 있는 위치에 겹쳐서 그릴 수도 있는데, 여러 번 그은 곳과 한 번 그은 곳의 차이를 구별할 수 없다고 하자.

이와 같은 식으로 선을 그었을 때, 그려진 선(들)의 총 길이를 구하는 프로그램을 작성하시오. 선이 여러 번 그려진 곳은 한 번씩만 계산한다.

N = 1,000,000

문제 해설


스포일러: 이 문제는 N이 100만 이므로 O(N*log(N))의 시간복잡도보다 작은 알고리즘을 사용해야 합니다. 무식한 방법으로는 해결하지 못합니다.

 

"여러번 그은 곳과 한 번 그은 곳의 차이는 구별할 수 없다고 하자." 라는 문장에서 우리는 중복된 선의 관계를 처리해줘야 한다고 할수 있습니다.

 

Line에는 x1 과 x2(x1 < x2)가 있습니다.

이때 선(Line)의 중복된 관계를 인식하는 메커니즘에 대해서 생각을 해봅시다.

  1. Line A와 Line B의 관계에 대에서 중복 혹은 intersection(교차) 하는가를 확인합니다.
  2. Line A와 Line B를 교차하는지 확인 후 교차 한다면 합쳐줍니다.
  3. A와 B의 min(A.x1, B.x1)을 구하고 max(A.x2, B.x2)를 구하면 됩니다.

위 과정을 거치면 A와 B의 합인 S(minX1, minX2)가 생성이 됩니다

 

최적화

하지만 위의 방법으로는 N^2 만큼 for Loop를 돌면서 확인을 해야지 결과값이 보장이 됩니다.( 무식한 방법으로는 풀 수 없습니다.)

 

더 최적화 할수 있는 방법으로는 "정렬"을 하여서 두개씩 비교를 해주면 됩니다.
또한 정렬을 하면 A와 B의 min,max를 구하는 연산 조차 간단하게 (A < B)라면 S(A.x1, B.x2)로 구할 수 있습니다.

 

정렬에 대한 시간복잡도는 표준라이브러리를 사용하여 O(Nlog(N)) 으로 해결 할 수 있고

비교하는데 드는 시간 복잡도는 처음부터 끝까지 이동하며 검색을 하기 때문에 시간복잡도 O(N) 만큼 소요가 됩니다.

 

총 시간 복잡도는 O(Nlog(N))이므로 시간복잡도로는 충분한 거 같습니다.

 

그리고 비교를 하는데에 있어서 사용할 공간복잡도 O(N)이 필요합니다. 이 또한 O(1) 으로 최적화 할 수 있습니다.

반응형

'PS-Algorithm > Algorithm' 카테고리의 다른 글

[BOJ] 스택 수열(1874)  (0) 2024.09.06
모바일 광고 입찰 해설  (0) 2024.01.28
[LeetCode]GenerateParentheses  (0) 2022.12.09
[BOJ/C++] 1759 암호 만들기  (0) 2022.01.16
[그리디 알고리즘] BOJ-10610 30  (0) 2021.11.22

+ Recent posts