우아한테크코스 미션을 하던 도중에 있던 CI/CD 에서 CD를 구축한 과정을 정리하게 되었습니다 코드는 여기서 확인하실 수 있습니다 CI/CD 란? 아주 간단한 설명을 드리겠습니다 CI(Continuous Integratoin) 지속적 통합으로, 자주자주 메인 코드베이스에 머지가 되어야 한다는 부분을 다루고 있는 부분입니다 이때 체크를 위해서 테스트를 만든다던가, 하는 과정을 거치죠 CD(Continuous Deploy) 프로덕션 환경에 자동으로 배포를 할 수 있어야 한다는 부분입니다 왜 CI/CD 가 필요한가? 우아한테크코스 환경에서는 외부에서 SSH 연결을 하지 못하게 막아두었습니다 허용해 둔다면, 어떤 사용자든 원하는 대로 SSH 연결을 해버려서, ec2를 마음대로 사용할 수 있으니 사실 당연한 거..
Oauth는 왜 나왔을까?? 바로 위와 같은 상황을 해결하기 위해서 Oauth 가 등장했는데요 그전까지는 API Access Deligation 이 있었다고 하는데요 회사마다 모두 다른 정책을 사용했기에, 웹 표준이 없어서 회사마다 다른 정책을 구현해야 했다고 합니다 이를 처음 비공식적으로 2006 년에 합의해서 나온 것이 Oauth1.0이고, 이후 보안 문제를 해결해서 나온 것이 Oauth1.0a입니다 Oauth 사용 방식의 변화 처음 oauth의 목적 위에 나왔던 것처럼 권한 부여에 목적을 가지고 등장한 프로토콜인데요 사용자의 ID와 패스워드를 타 서비스에 제공하지 않고, 구글캘린더 같은 기능을 사용할 수 있도록 하려고 했습니다 구글 캘린더 외에 Gmail 같은 서비스에 접근하는 것은 허가하지 않는 ..
JPA를 사용하지 않으면 어떻게 변경 감지를 해야 하지?? 변경감지는 어떻게 만들어져 있을까 생각해 보면서 작성한 코드이기에, 부족한 점이 많을 수 있습니다 나왔던 코드는 대부분 간소화된 코드입니다! 미리 잘 부탁드립니다 간단한 테이블 소개 노선과 구간이 1:N의 관계로 엮여있습니다 역과 구간이 1:N의 관계로 2번 엮여 있습니다 단 3개의 테이블만으로 이루어진 간단한 상황이라는 것을 기억해 주시면 좋을 것 같습니다 간단한 문제 상황 소개 처음에 코드를 짰을 때 도메인 엔티티에서 어떤 부분이 변경되어서 직접 저장해야 하는지를 파악할 방법을 쉽게 떠올리지 못해서, 가장 편한 방법을 거쳤는데요 도메인 엔티티를 변경하게 된 경우에, db에 저장하는 과정에서, 모두 삭제하고, 모두 새롭게 저장하는 과정을 거쳤습..
어떤 문제가 있었는가? 이럴 거면 왜 RefreshToken을 사용하는 거지? 과거의 로그인 과정에서 로그인을 진행하면, ResponseBody로 AccessToken과, RefreshToken 이 넘어가게 됩니다. 클라이언트는 이를 모두 LocalStorage에 저장해 두고, 필요에 따라 헤더에 추가하는 방식으로 로그인을 진행했습니다 무언가의 이유로 토큰의 탈취가 일어난다면, 같은 저장소에 저장이 되고 있기 때문에, 동시에 탈취가 진행될 수 있었습니다 그렇다면 AccessToken 만을 통해 관리해도 되지 않나? 왜 귀찮게 Refresh 하는 과정이 있는 거지?? 내가 해커라면? 1. 로컬 스토리지에 몰래 접근한다 2. AccessToken과 RefreshToken을 모두 가져간다 3. 다른 사람의 역..
1. filter와 interceptor 필터는 dispatcher servlet 바깥에 존재합니다. 인터셉터는 dispatcher servlet 안에 존재합니다. 필터와 인터셉터의 예외 처리 방식 필터는 기본적으로 서블릿 컨텍스트로 예외가 흘러갑니다. 인터셉터는 ResponseEntityExceptionHandler 라는 Spring MVC에서 제공하는 기본 예외에서 모든 예외가 잡힙니다 interceptor에서 prehandle에서 false 가 나오면, postHandle, postComplete메서드가 호출되지 않는다' 필터와 인터셉터의 기능 차이 filter : ServletRequest, ServletResponse 를 바꿔 끼울 수 있다 interceptor : 어떤 컨트롤러에서 실행되는지 ..
스프링 컨텍스트에는 2가지 종류가 있습니다 1. ApplicationContext 2. BeanFactory 간단하게 설명하면 Application Context는 Bean Factory를 확장했다고 볼 수 있습니다 BeanFactory BeanFactory 는 org.springframework.beans.factory 안에 정의된 인터페이스입니다 간단하게 bean 이름이나, 타입을 바탕으로 빈을 가져올 수 있는 기능을 가지고 있습니다 Object getBean(String name) throws BeansException; boolean isSingleton(String name) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String na..
문제 상황 아래 적힌 에러를 발생시키며 라이브 서버에서 계속 서버가 죽는 상황이 있었습니다 Caused by: org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR unknown command 'CONFIG', with args beginning with: 'GET' 'notify-keyspace-events' SpringDataRedis의 특징 SpringDataRedis에서는 CrudRepository에 있는 findBy*** 의 메서드를 지원하기 위한 방법으로 검색을 위한 데이터를 가지고 있는 S..
왜 리팩터링을 시작했을까? 우아한테크코스 과정을 진행하면서 간단한 애프리케이션은 많이 사용해 봤지만, 모두 너무 작은 규모의 프로젝트였는데요 짧다면 짧고, 길다면 긴 기간동안 작성했던 프로젝트를 과거 코드부터 출발해서 변경해 나가는 과정을 직접 겪어보고 싶었습니다 이 프로젝트를 선택하게 된 이유는 외부 API 호출 기능이 많았기에, 테스트를 하기 위해서는 필수적으로 추상화나, 모킹이 들어가야 했습니다. 이때 잘 설계를 하게 된다면 추상화의 장점을 정확하게 볼 수 있다고 생각했는데요 기존 프로젝트에는 어떤 기능이 있을까? 1. GPT 를 통해서 꼬리질문을 만들어주는 기능 2. 가입을 하는 과정에서 이메일 인증을 하는 기능 3. 닉네임을 외부 api를 통해서 가져오는 기능 4. Security 로 로그인 관..
지금까지 했던 부분입니다 오늘 해볼 부분은 HttpServletBean과 추가적인 부분입니다 HttpServletBean HttpServlet을 확장하고 있고, bean를 초기화하기 위한 init() 메서드가 정의되어 있습니다 핵심적인 메서드는 총 2가지입니다. 1.init() 메서드 @Override public final void init() throws ServletException { // Set bean properties from init parameters. PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); if (!pvs.isEmpty()) { try { BeanW..
문제 상황 SpringBootTest를 사용하던 상황에서 db 롤백이 이루어지지 않아서 테스트 간 격리가 이루어지지 않는 상황이 발생하였는데요 이를 바탕으로 어떻게 test 마다 어떻게 Transactional 이 적용되는지, 그리고 어떤 경우에 롤백이 되지 않는지, 이를 해결하기 위한 방법은 어떤 것이 있는지에 대해서 정리해 보겠습니다 Test에서 Transactional 은 롤백된다 test에서 transactional 이 사용되면 자동적으로 롤백이 됩니다. 여기 적혀 있는 것처럼 db 호출은 자동적으로 rollback이 되어 매 테스트마다 깨끗한 db 상태를 유지할 수 있습니다 Junit과 함께 사용될 경우에 메서드마다 호출되는 @BeforeEach와, @AfterEach는 트랜잭션으로 묶여 있습니..