운영중인 체계에서 11월 20일부터 DB에 메일 발송 내역이 쌓이지 않는 것을 발견하였다.
깃에 올라와있는 당일 변경 내역은 메일 발송에 크게 영향을 주는 부분이 아니었어서 약간 당황스러웠다.
변경 내역이 DB쪽과 충돌을 일으키나 싶어서 DB에 입력되어있는 ID값을 확인해봤는데 DB에도 잘 적용이 되어있었다.
흠… 디버깅 모드를 켰지만 내가 아직 디버그에 미숙한건지 발견해내지 못했다.
포스트맨으로 확인해보려고 했으나 body에 넣어줘야할 값들이 41개정도 들어가는 걸로 확인을 해서 다른 방법을 찾으려 했다.
일단 크론탭으로 돌아가는 시스템이기에 서버로그에 메일발송 관련 로그가 찍혀있을것이라고 생각을 했다.
그런데 메일발송완료 로그는 찍혀있었다. 당일로부터 5일 내외를 확인해봤는데 모두 로그가 찍혀있었다.
서버 로그 확인시에 11월 20일자에 서버가 한번 셧다운되었다가 다시 작동하기는 했었다.
그 이후로 NoSuchMethodError가 발생하기 시작했다.
관련해서 자료를 찾아보았는데, 아마 최신 버전 수정후 배포할때 문제가 있지 않았을까 생각이들었다.
다음 내역들을 하나하나 확인해보려고 했다.

  • 매개 변수를 잘못 사용했을까?
  • 메소드가 아예 없는가?
  • 타이핑 오류가 있는가?
  • 클래스,  jar가 정상적으로 올라가 있는가?
  • 내부에서 참조하는 lib가 빠졌는가?
  • classpath 상에서 중복되는 class가 있어서 메서드를 정상적으로 찾지 못하는가?

우선 1~3 까지 인텔리제이에서 확인했을때는 문제가 없었다.
매개변수 잘못 사용했는지 확인하려고 스택트레이스 에러메시지를 읽으면서 관련부분을 찾았다.
Djava. Ljava 이런식으로 나오는 로그에 대해서도 알게되었다.


https://okky.kr/articles/338405
이 글을 참고하니 도움이 많이 되었다.

따라서 이때 코드상의 문제가 아니라 배포하면서 문제가 생겼을 것이라고 확신했다.

이때 자바 디컴파일러를 처음 사용해봤다. gui버전이라서 그렇게 어렵지 않았다.
파일질라에서 운영 서버 접속후 문제가 되는 것처럼 보이는 클래스를 로컬에 저장하고, 디렉토리 따라 파일만 찾아주면 디컴파일하는데 시간은 걸리지만 바로 어떤 클래스가 돌아가고 있었는지를 확인 할 수 있었다.

확인해본 결과 깃에 올라온 버전은 수정이 된 버전인데 서버에 붙어있는 파일은 예전 버전이라서 실제로 메소드가 없었던 것이다.

깃에 올라온 코드를 전적으로 신뢰하면 안된다는 것을 느꼈다. CICD가 구축되는 환경이라면 이런일도 없었을텐데.. 라는 아쉬움도 들고 나중에 CI/CD 공부를 해보긴 해야겠다는 생각도 하게되었다.

'웹 개발 > Spring Boot' 카테고리의 다른 글

톰캣이란 무엇일까요?  (0) 2023.08.14
HTTP가 무엇일까요?  (0) 2023.08.03
OOP 관점에서 모델링이란 무엇일까요?  (0) 2023.08.01
영속성 컨텍스트란 무엇인가요?  (0) 2023.07.31
ORM이란 무엇인가요?  (0) 2023.07.31

1. 스프링은 프레임워크이다.
Frame(틀) Work(동작하다) -> 틀 안에서 동작을 한다.
프레임워크가 왜 나왔냐 -> 이 틀을 벗어나지 말고 만들어라 라는 의미가 있음.

2. 스프링은 오픈소스이다.
오픈소스란 소스코드를 공개한 것이다. 스프링의 내부를 볼 수 있는 것.-> 내부를 뜯어 고칠수 있는 것.
스프링을 공부하다가 깊숙한 곳까지 알게되었다. -> 불편한 점을 찾는다. -> 불편한 점을 고쳐서 컨트리뷰트(기여)할 수 있다. 

3. 스프링은 IoC 컨테이너를 가진다.
IoC(Inversion of Controll, 제어의 역전). -> 주도권을 스프링이 가지고 있다.
Class -> 설계도
Object -> 실체화가 가능한 것
Instance -> 실체화 된 것

class 누누 {
	변수
	변수
}

abstract class 캐릭터 {
	추상적인 의미
} ->  실체화가 불가능, object가 아님

가구는 실체화가 불가능함. 추상적이기 때문.
실체화 가능한 것은 의자, 침대 등이고 이것들이 object임.
그리고 주변에 있는 진짜 의자, 침대가 instance임.

오브젝트를 heap이라는 메모리 공간에 올리게 되면(new) 

public void make() {
    의자 s = new 의자();
}

의자를 new했기 때문에 의자 오브젝트를 실체화 시킨거임. 의자를 실체화시켜서 메모리에 띄움. 주소는 s가 가리키고 있음. 근데 s는 메서드가 실행되는 순간에만 메모리에 떠있음.

public void use(){
	의자 s = new 의자();
}

이렇게 하는 경우 make의 의자와 use의 의자는 서로 다른 주소값을 갖게 된다.

make의 의자를 쓰려면 어떻게든 넘겨 받아야함. 근데 이런 로직을 짜기가 굉장히 힘들다.

수많은 오브젝트들 (의자, 붕어빵, 사자, 기린 ....) 을 스프링이 스캔을 해서 읽고 객체들을 직접 heap에 넣는다.

4. 스프링은 DI를 지원한다.
Dependency Injection (의존성 주입): 내가 원하는 모든 클래스의 모든 메소드에서 오브젝트를 가져와서 사용할 수 있다. 만들어진 오브젝트 (의자)가 있으면 어느 클래스에서든 같은 의자를 사용하는 것이다. (싱글톤 패턴) 한번 뜬 의자를 어디서든 공유해서 쓸 수 있다. 

다음 시간에 배울 것

5. 스프링은 엄청나게 많은 필터를 가지고 있다.

6. 스프링은 엄청나게 많은 어노테이션을 가지고 있다.

7. 스프링은 MessageConverter를 가지고 있다. 기본값은 현재 Json이다.

8. 스프링은 BufferedReader와 BufferWriter를 쉽게 사용할 수 있다.

9. 스프링은 계속 발전중이다.

이 블로그 포스팅은 인프런 최주호님의 스프링부트 개념정리(이론) 강의에 대한 정리 포스팅입니다. 
다음은 강사님의 강의 링크입니다. 무료 강의라서 가입만 하면 볼 수 있습니다. (강의 링크)

'웹 개발 > Spring Boot' 카테고리의 다른 글

영속성 컨텍스트란 무엇인가요?  (0) 2023.07.31
ORM이란 무엇인가요?  (0) 2023.07.31
JPA란 무엇인가요?  (0) 2023.07.30
메시지 컨버터가 무엇인가요?  (0) 2023.07.30
필터란 무엇인가요?  (0) 2023.07.29

+ Recent posts