저는 15년 이상 안경을 착용하며 일상 생활에서 느꼈던 불편함이 상당히 많았습니다. 특히, 코로나와 겨울철 마스크 착용으로 인한 김서림은 물론, 여름철 땀으로 인해 안경이 흘러내려 시야가 흐려지는 경험은 많은 이들이 공감할 수 있을 것이라고 생각합니다.

라식 수술을 결심하게 된 계기

안경 착용의 불편함을 해소하기 위해 네이버 카페를 통해 정보를 수집한 후, 집에서 가까운 병원에서 사전 검사를 받았습니다. 검사 결과는 다음과 같습니다:

  • 좌안: 근시 -3.25, 난시 -2.00, 각막 두께 544µm
  • 우안: 근시 -3.25, 난시 -2.25, 각막 두께 532µm

난시가 -2.0 이하일 경우 병원에서는 고도 난시로 판단하여 라섹보다 라식을 권장한다고 들었습니다. 특히 우안은 좌안에 비해 난시가 더 심하고 각막 두께도 얇아 건조증이 더 심하다는 결과가 나왔습니다.

수술 전 준비 과정

사전 검사에서는 다양한 눈 상태를 상세히 확인할 수 있었습니다. 각막이 얇거나 고도 난시일 경우 라식과 라섹 모두 어려울 수 있으며, 렌즈 삽입술이 대안으로 제시된다는 점도 알게 되었습니다.

처음에는 각막에 뚜껑이 생긴다는 점 때문에 라섹을 선호했지만, 고도 난시로 인해 선택지가 제한되어 결국 라식을 결정했습니다. 스마일 라식도 검토했으나, 해당 기술이 비교적 최근에 도입된 점과 병원의 권고로 배제했습니다.

p.s 스마일 라식이 최근에 나온 기술이나, 일반 라식과 비교해서는 각막 절개량이 1/10 정도로 줄어들어서 비용만 괜찮으면 스마일 라식도 괜찮다고 생각합니다.

일반 라식과 스마일 라식 차이점은 다음 블로그 글에서 작성 예정입니다.

수술 당일의 경험

수술 전날에는 아벨리노 각막 이상증 검사를 진행했고 정상 판정을 받아 예정대로 수술을 받을 수 있었습니다. 수술 당일에는 추가 검사를 진행하며 렌즈를 여러 개 씌워 최적의 시야를 확인한 후 결과를 기계에 적용했습니다.

수술실에서는 눈을 강제로 벌리고 기계 속 초록색 불빛을 계속 보라는 지시를 받았습니다. 긴장감 속에서도 의사의 지시에 따라 눈을 뜨고 집중할 수 있었으며, 타는 냄새가 나는 순간에도 큰 통증 없이 수술이 마무리되었습니다.

수술 후에는 인공눈물과 처방 약물을 2시간 간격으로 사용해야 했습니다. 몇 시간 뒤부터 눈 뜨기가 힘들고 눈물이 계속 나왔지만, 6시간 정도 지나면서 점차 괜찮아졌습니다.

수술 후 회복 및 결과

다음 날 검사 결과는 만족스러웠습니다. 고도 난시로 인해 최저 시력 0.6 정도를 예상했지만 양쪽 모두 1.0 시력이 나왔습니다. 안경 없이 TV 시청과 컴퓨터 사용이 가능해진 점은 놀라운 변화였습니다.

다만, 컴퓨터나 스마트폰을 오래 사용할 경우 블루라이트 차단 안경과 인공눈물을 계속 사용하는 것이 필요하다는 점을 느꼈습니다. 안경을 벗고 일상 생활을 한다는 점에서 매우 만족스럽지만 아쉬운 점은 눈이 쉽게 피로하거나 건조해질수도 있어서 이에 대해서 의사 선생님과 상담을 많이 하는것이 좋습니다.

10년 전과 달라진 기술 발전

10년 전에는 부모님의 반대로 수술을 하지 않았지만, 현재는 스마일 라식 등 새로운 기술의 등장과 기존 라식·라섹 기술의 발전으로 인해 안전성이 크게 개선되었습니다.

부작용 및 주의사항

라식 수술은 개인별로 부작용이 다를 수 있습니다. 대표적인 부작용으로는 안구 건조증, 야간 빛 번짐 등이 있으며, 저의 경우에는 다른 증상은 크게 없지만 모니터를 많이 보면 눈이 쉽게 피로해짐을 느끼고 있습니다. 대표 부작용들에 대해서는 사전 검사에서 충분히 고려해야 합니다. 또한 근시 퇴행 가능성도 있으므로 꾸준한 눈 관리가 중요하다고 생각합니다.

결론

안경 착용으로 일상 생활에서 많은 답답함을 느끼신다면 라식 수술을 고려해볼 만합니다. 하지만 사전 검사에서 본인의 눈 상태를 정확히 파악하고 적합한 수술 방법을 선택하는 것이 필수적입니다.

저는 신뢰할 수 있는 병원을 선택해 만족스러운 결과를 얻었으며 앞으로도 눈 건강 관리를 지속적으로 할 계획입니다. 여러분도 자신의 상황에 맞는 결정을 내리길 바랍니다!

 

Spring Batch에 대해서 설명하자면, 대량의 데이터를 효율적으로 처리할 수 있는 배치 프레임워크로, 다양한 사용 사례와 장점이 있습니다. 먼저 Spring Batch 사용이 필요한 경우에 대해 알아봅시다.

Spring Batch 사용이 필요한 경우

  1. 대용량 데이터 처리
    • 데이터베이스, 파일, 또는 메시지 큐에서 대량의 데이터를 읽고 처리한 뒤 저장해야 할 때 유용합니다. 예를 들어, 수백만 개의 레코드를 변환하거나 마이그레이션하는 작업에 적합합니다.
  2. ETL(Extract, Transform, Load) 작업
    • 여러 데이터 소스에서 데이터를 추출하고 변환한 뒤 데이터 웨어하우스에 로드하는 작업을 자동화할 때 사용됩니다. Spring Batch는 데이터 변환과 로드 과정을 효율적으로 처리할 수 있습니다.
  3. 주기적인 배치 작업
    • 매일, 매주 또는 특정 시간에 실행되는 배치 작업(예: 보고서 생성, 이메일 발송)을 처리할 때 유용합니다. Spring Batch는 스케줄링과 재시작 기능을 지원하여 안정적인 운영을 보장합니다.
  4. 복잡한 워크플로우 관리
    • 여러 단계로 구성된 의존적 작업을 순차적으로 실행하거나 병렬로 처리해야 할 때 적합합니다. 예를 들어, 데이터 로드 후 검증 및 통계 생성과 같은 작업을 단계별로 수행할 수 있습니다.

위에서는 Spring Batch 사용이 필요한 경우에 대해서 알아보았고, Spring Batch 를 사용하면 어떤 장점이 있을까요?

Spring Batch 사용하면 좋은 점

  1. 재사용 가능한 구성 요소 제공
    • ItemReader, ItemProcessor, ItemWriter와 같은 구성 요소를 활용하여 데이터를 읽고 변환하며 저장하는 과정을 간소화합니다.
  2. 트랜잭션 관리 및 오류 복구
    • 트랜잭션 기반으로 데이터를 처리하며, 실패 시 재시작 및 복구 기능을 제공합니다. 이는 데이터 손실을 방지하고 안정성을 높입니다.
  3. 확장성과 성능 최적화
    • Chunk 기반 처리와 파티셔닝(partitioning)을 통해 대량 데이터를 병렬로 처리하여 성능을 극대화할 수 있습니다.
  4. 유연한 스케줄링 및 제어
    • Quartz 또는 Spring Scheduler와 통합하여 배치 작업의 실행 시점을 유연하게 관리할 수 있습니다.

Spring Batch 활용 개발 방식

Spring Batch 를 개발하면서, Tasklet 혹은 Chunk 방식으로 개발을 많이 하게됩니다.
전체 작업이 하나의 트랜잭션으로 처리되는 Tasklet 방식과 Chunk 단위로 대용량 데이터들을 여러 트랜잭션으로 나눠서 처리할 수 있는 Chunk 방식이 있습니다.

Tasklet 방식과 Chunk 방식을 표로 설명하면, 다음과 같습니다.

특성 Tasklet Chunk
구성 요소 단일 Tasklet 구현체 ItemReader, ItemProcessor, ItemWriter
트랜잭션 관리 전체 작업이 하나의 트랜잭션으로 처리 청크(Chunk) 단위로 트랜잭션 분할 및 커밋
재시작 지원 레코드 단위 재시작 불가 레코드 카운트 기반 재시작 가능
메모리 효율성 대량 데이터 처리 시 메모리 부하 가능성 높음 청크 단위로 메모리 최적화
적합한 작업 유형 단순 작업(파일 삭제, 프로시저 호출 등) 대용량 데이터 처리(ETL, 리포트 생성 등)

이와 관련해서 자세한 내용들은 아래 블로그 링크들을 참고하시면 됩니다.

위에 내용처럼 블로그 글을 올리려고 하는데 사용자가 더 읽기 쉽도록 글을 수정해줘

Spring Batch는 대량 데이터를 효율적으로 처리할 수 있는 강력한 배치 프레임워크입니다. 이 글에서는 Spring Batch가 필요한 경우, 사용하면 좋은 점, 그리고 개발 방식(Tasklet과 Chunk)을 중심으로 정리해보겠습니다.


Spring Batch 사용이 필요한 경우

Spring Batch는 다음과 같은 상황에서 유용하게 활용됩니다:

1. 대용량 데이터 처리

데이터베이스, 파일, 메시지 큐 등에서 대량 데이터를 읽고 처리한 뒤 저장해야 할 때 적합합니다. 예를 들어, 수백만 개의 레코드를 변환하거나 마이그레이션하는 작업에 효과적으로 사용할 수 있습니다.

2. ETL(Extract, Transform, Load) 작업

여러 데이터 소스에서 데이터를 추출하고 변환한 뒤 데이터 웨어하우스에 로드하는 작업을 자동화할 때 유용합니다. Spring Batch는 데이터를 효율적으로 변환하고 로드하는 데 최적화되어 있습니다.

3. 주기적인 배치 작업

매일, 매주 또는 특정 시간에 실행되는 배치 작업(예: 보고서 생성, 이메일 발송)을 처리할 때 적합합니다. Spring Batch는 스케줄링 및 재시작 기능을 통해 안정적인 작업 운영을 지원합니다.

4. 복잡한 워크플로우 관리

여러 단계로 구성된 의존적 작업을 순차적으로 실행하거나 병렬로 처리해야 할 때 유리합니다. 예를 들어, 데이터 로드 후 검증 및 통계 생성을 단계별로 수행하는 복잡한 워크플로우를 구현할 수 있습니다.


Spring Batch 사용하면 좋은 점

Spring Batch를 사용하면 다음과 같은 장점을 누릴 수 있습니다:

1. 재사용 가능한 구성 요소 제공

ItemReader, ItemProcessor, ItemWriter와 같은 구성 요소를 활용해 데이터를 읽고 변환하며 저장하는 과정을 간소화할 수 있습니다.

2. 트랜잭션 관리 및 오류 복구

트랜잭션 기반으로 데이터를 처리하며, 실패 시 재시작 및 복구 기능을 제공합니다. 이는 데이터 손실을 방지하고 안정성을 높이는 데 큰 도움이 됩니다.

3. 확장성과 성능 최적화

Chunk 기반 처리와 파티셔닝(partitioning)을 통해 대량 데이터를 병렬로 처리하여 성능을 극대화할 수 있습니다.

4. 유연한 스케줄링 및 제어

Quartz 또는 Spring Scheduler와 통합하여 배치 작업 실행 시점을 유연하게 관리할 수 있습니다.


Spring Batch 개발 방식: Tasklet vs Chunk

Spring Batch에서는 배치 작업을 구현할 때 Tasklet 방식과 Chunk 방식을 사용할 수 있습니다. 두 방식의 차이점은 아래 표와 같습니다:

특성 Tasklet Chunk
구성 요소 단일 Tasklet 구현체 ItemReader, ItemProcessor, ItemWriter
트랜잭션 관리 전체 작업이 하나의 트랜잭션으로 처리 청크(Chunk) 단위로 트랜잭션 분할 및 커밋
재시작 지원 레코드 단위 재시작 불가 레코드 카운트 기반 재시작 가능
메모리 효율성 대량 데이터 처리 시 메모리 부하 가능성 높음 청크 단위로 메모리 최적화
적합한 작업 유형 단순 작업(파일 삭제, 프로시저 호출 등) 대용량 데이터 처리(ETL, 리포트 생성 등)

Tasklet 방식이 적합한 경우

  • 단순한 작업(예: 파일 삭제, 데이터 초기화 등)을 수행해야 할 때.
  • 전체 작업이 하나의 트랜잭션으로 처리되어야 하는 경우.

Tasklet 예제

@Bean
public Step fileCleanupStep() {
    return stepBuilderFactory.get("fileCleanupStep")
            .tasklet((contribution, chunkContext) -> {
                Files.deleteIfExists(Paths.get("/tmp/sample.txt"));
                return RepeatStatus.FINISHED;
            })
            .build();
}

Chunk 방식이 적합한 경우

  • 대량 데이터를 읽고 변환하며 저장해야 하는 경우.
  • 청크 단위로 트랜잭션을 분리하여 메모리를 효율적으로 사용하고자 할 때.
  • 실패 시 특정 레코드부터 재처리가 필요한 경우.

Chunk 예제

@Bean
public Step processOrdersStep() {
    return stepBuilderFactory.get("processOrdersStep")
            .<Order, ProcessedOrder>chunk(100)
            .reader(orderReader())
            .processor(orderProcessor())
            .writer(orderWriter())
            .build();
}

결론

Spring Batch는 대량 데이터 처리와 복잡한 워크플로우 관리에 최적화된 프레임워크입니다.

  • 단순 작업에는 Tasklet 방식이 적합하며,
  • 대량 데이터 처리는 Chunk 방식이 더 효과적입니다.

Spring Batch의 강력한 기능을 활용하면 안정적이고 확장 가능한 배치 애플리케이션을 쉽게 개발할 수 있습니다!

SourceTree 를 Windows 10 환경에서 사용하면서 SourceTree 가 오픈되지 않을 때 어떻게 해야되는지 아래와 같이 공유합니다.

 

관련 참고 : https://community.atlassian.com/t5/Sourcetree-questions/Source-tree-not-starting-in-windows-10/qaq-p/1023302

 

Source tree not starting in windows 10

Hi Attlasian,       My source tree did not start in my windows 10 local and so I troubleshooted by deleting the attlasian folder in the ......./Local/AppData directory,uninstalled sourcetree and then I tried installing the Sourcetree again but while ins

community.atlassian.com

 

요약하자면, 아래와 같다.

  • window + R 입력 후 %APPDATA% 입력
  • C:\Users\{name}\AppData\Local\Atlassian 이동 후 SourceTree.exe_ 로 시작하는 폴더 제거 후 SourceTree 열기

 

관련 참고에 있는 가이드대로 하면 SourceTree GUI 를 활용할 수 있다.

'개발' 카테고리의 다른 글

Jira 하위 테스크 -> 일반 테스크로 바꾸기  (0) 2022.12.28
백엔드 개발자 첫 이직 후기  (0) 2022.12.27

필자는 Spring WebFlux, Spring MVC 도 모두 경험하였고, 각각의 특징 및 장단점 그리고 예제 코드를 아래와 같이 공유합니다.

TL;DR

 

Spring WebFlux 는 고도로 동시성에 요구되는 대규모 어플리케이션에 적합하고, 비동기 및 반응형 개발에 익숙하고 성능 및 확장성이 중요한 경우 유리합니다.

반면, Spring MVC 는 전통 웹 개발에 익숙하거나 기존 Spring MVC 기반 어플리케이션 유지 및 개선할 경우 적합합니다.

결론은 Reactive Programming 경험 및 대규모 어플리케이션을 목표로 하고 있다면 WebFlux 도입을 권장해볼 수는 있을 것 같습니다.

 

Spring WebFlux

 

Spring 5 부터 도입된 비동기 및 반응형 웹 프레임워크이며, 논블로킹 IO 모델을 기반으로 스레드 효율 향상시키고, 요청 처리량 및 응답시간 또한 개선 가능합니다.

 

예제 코드는 다음과 같습니다.

@RestController
public class WebFluxController {
    @GetMapping("/hello")
    public Mono<String> hello() {
        return Mono.just("Hello, WebFlux!");
    }
}

 

WebFlux 의 장점으로 높은 동시성 처리(논블로킹 모델), 경량성(제한된 수의 쓰레드로 많은 요청을 처리할 수 있음)이 있고, 단점으로는 러닝 커브(적응에 시간이 다소 필요), 작은 생태계(Spring MVC 와 비교하여 작은 생태계) 등이 있습니다.

 

 

Spring MVC

 

Spring Framework 의 일부이고, 전통적 서블릿 기반 웹 어플리케이션 개발 모델 지원합니다. 동기 방식으로 동작하고, 동시성이 낮고 IO 작업이 많지 않은 어플리케이션에 적합합니다.

 

예제 코드는 다음과 같습니다.

 

@Controller
public class MvcController {
    @GetMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("message", "Hello, MVC!");
        return "hello";
    }
}

 

 

MVC 의 장점으로 성숙한 생태계(다양한 레퍼런스, 다양한 라이브러리 기능 제공), 개발 생산성(전통 웹 개발 모델) 등이 있고, 단점으로는 동시성 처리(많은 요청 처리 시 많은 쓰레드가 필요하므로 리소스 소비가 높을 수 있음), 높은 부하에 대한 확장성(많은 동기 쓰레드로 높은 부하에 대해 확장성이 제한될 수 있음) 등이 있습니다.

 

Spring WebFlux 가 반드시 Spring MVC 보다 나은 선택일까??

 

그렇지 않다. 다만 WebFlux 가 MVC 의 대안이 될 수는 있다.

Rossen Stoyanchev 가 QCon SF 2017 에서 발표한 내용에 의하면 다음과 같다.

Spring MVC와 Spring WebFlux 중에서 선택할 때 주의할 것을 제안합니다. 현재 애플리케이션이 spring-mvc에서 제대로 실행되고 있고 스택 변경을 요구하는 문제가 없다면 Stoyanchev는 spring-mvc를 유지해야 한다고 제안합니다. 그는 또한 애플리케이션 종속성에 대해 생각하는 것이 좋은 생각이라고 제안합니다. 애플리케이션에 차단 종속성이 있는 경우 Spring MVC 스택을 유지하는 것이 좋습니다

 

 

참고

 

Spring Boot vs Spring Webflux: Performance comparison for hello world case

Find out the performance benefits brought in by reactive programming (webflux) when compared to Spring Boot for a simple hello world case.

medium.com

 

Servlet vs. Reactive: Choosing the Right Stack - Rossen Stoyanchev Presents at QCon SF 2017

Spring Framework 5 introduced a brand new reactive web framework spring-webflux, which resides alongside the traditional servlet based web framework spring-mvc.In his presentation, Rossen Stoyanchev talked about the differences in these two frameworks’ e

www.infoq.com

 

 

 

 

https://school.programmers.co.kr/learn/courses/30/lessons/157339

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

테이블 분석

 

주어진 3개의 테이블을 조합하여, 2022년 11월 기준 30일 기준 렌트하였을 때 특정 조건에 만족하는 차량 리스트를 뽑아내는 문제입니다.

테이블 설명 및 필드 설명은 아래와 같으며, 아래 작성할 쿼리에서 사용할 필드는 BOLD 처리하였습니다.

  • CAR_RENTAL_COMPANY_CAR (렌트차 정보 테이블)
    • CAR_ID (차량ID)
    • CAR_TYPE (차종)
    • DAILY_FEE (일일 이용요금)
    • OPTIONS (차량옵션)
  • CAR_RENTAL_COMPANY_RENTAL_HISTORY (렌트차 렌트 이력 테이블)
    • HISTORY_ID (히스토리 ID)
    • CAR_ID (차량ID)
    • START_DATE (차량 대여시작일자)
    • END_DATE (차량 대여종료일자)
  • CAR_RENTAL_COMPANY_DISCOUNT_PLAN (렌트차 대여기간 별 할인정책)
    • PLAN_ID (할인정책ID)
    • CAR_TYPE (차종)
    • DURATION_TYPE (대여기간 종류)
    • DISCOUNT_RATE (할인율)

문제 : 2022년 11월 대여 가능한 차량들 중 차종이 세단 혹은 SUV이고, 30일 대여를 할 경우 일일대여료, 할인율을 고려하여 50만원 이상 200만원 미만 차량 목록 출력하기.

 

유의사항

  • CAR_RENTAL_COMPANY_RENTAL_HISTORY (렌트차 렌트 이력 테이블) 에서 END_DATE > '2022-10-31' AND START_DATE < '2022-11-01' 인 차량들은 2022년 11월에 렌트가 불가하다.
  • CAR_TYPE(차종) 이 세단 혹은 SUV 만 가능하다.
  • CAR_RENTAL_COMPANY_DISCOUNT_PLAN 테이블에 있는 리스트 중에, DURATION_TYPE(30일 이상)이고 CAR_TYPE(세단 or SUV) 데이터를 가져와야 한다.
  • FEE(최종요금) 필드에 소수점 제거해야 한다.

 

쿼리 작성하기

 

고려조건

  • CAR_ID 중에 11월 렌트 이력이 있는 ID 는 리스트에서 제외한다.
  • 총 금액 ( = 일일 대여료 * 30 * (100 - 할인율) / 100 ) 기준, 50만원 이상 200만원 미만
  • 정렬 순은 FEE 내림차순, 차종 오름차순, 차량 ID 내림차순

 

Query Example

SELECT crcc.CAR_ID, crcc.CAR_TYPE, ROUND(crcc.DAILY_FEE * ((100 - crcdp.DISCOUNT_RATE) / 100) * 30) AS FEE 
    FROM CAR_RENTAL_COMPANY_CAR as crcc
    JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN as crcdp ON crcdp.CAR_TYPE = crcc.CAR_TYPE
    WHERE crcc.car_type IN ('세단','SUV') 
    AND crcc.CAR_ID NOT IN (SELECT DISTINCT CAR_ID FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY 
    WHERE END_DATE > '2022-10-31' AND START_DATE < '2022-12-01'
    ORDER BY CAR_ID)
    AND crcdp.DURATION_TYPE = '30일 이상' AND ROUND(crcc.DAILY_FEE * 30 * (100 - crcdp.DISCOUNT_RATE) / 100)  >= 500000 AND ROUND(crcc.DAILY_FEE * 30 * (100 - crcdp.DISCOUNT_RATE) / 100)  < 2000000
    ORDER BY FEE DESC, crcc.CAR_TYPE, crcc.CAR_ID DESC;

 

회고

쿼리를 하나하나 작성하는 과정에서 렌트 이력에 없는 데이터들을 고려하지 않아서, 초반에 실패한 쿼리들이 존재하는데 

이런 세세한 부분까지 고려해서 작은 쿼리부터 하나하나씩 작성해야 성공적으로 쿼리를 작성할 수 있는것 같습니다.

 

kubernetes ingress 를 통해 api 를 호출할 때, nginx 에서 403 에러를 발생하는 경우를 종종 볼수 있다.

(403 = 권한없음 에러)

<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>

 

이런 경우에는 여러가지 봐야되지만, 그중에 한가지로 ingress 설정에서 ip 가 whitelist 로 등록되었는지 확인하는 것이 필요하다.

api 서버들 경우에는 whitelist 로 호출하는 대상을 제한 두는 경우가 많기 때문에, 아래 설정에 ip 대역을 추가하면 해결 가능하다.

(허용할 Ip 대역에 호출할 서버의 worker node ip 대역을 넣으면 됩니다)

 

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/whitelist-source-range: >-
    {허용할 ip 대역 - ex. 127.0.0.1/32,10.0.0.0/8}

 

'개발 > k8s' 카테고리의 다른 글

k8s 기초 튜토리얼  (0) 2020.12.18
쿠버네티스(k8s) 컴포넌트  (0) 2020.12.17
쿠버네티스(k8s) 개요  (0) 2020.12.17

+ Recent posts