안녕하세요, Brad입니다. 오늘 공부한 내용 정리해볼게요!
Q & A
@OneToOne
,@ManyToOne
의 차이?내부적으로 동작은 같습니다.
User
가 One 이라는 점에서 동작은 같을 수 밖에 없습니다.'mappedBy' 라는 설정이 없으면 두 테이블 간 하나의 테이블이 새로 만들어집니다.
백엔드 멤버들로부터 어느 정도 정리를 할 수 있었습니다. 한 마디로 정리할 수 있는데요. '나의 관점에서 상대방을 바라볼 것!!'
- 예를들어 (질문 - 유저)의 관점에서 다음과 같이 볼 수 있습니다.
- 질문 하나에 대해 유저는 한 명만 바라봅니다(유저는 One)
- 유저 한명에 대해 질문 여러 개를 바라봅니다(질문은 Many)
- 자기의 관점으로 자신을 바라보진 않습니다. 이 관점으로 바라본다면 제가 생각했던 '질문 하나에 대해 유저 한명만 매치된다'에서 벗어날 수 있을 것 같네요!
Question과 User가 조인 될 때도 잇고 따로 불러올 떄도 있는데 왜 차이가 발생할까요?
- JPA 내부정책에 따라 다릅니다.
- 보통 N개를 불러올 때는 따로 불러오고, 하나를 불러오면 조인해서 가져오기도 합니다.
외래키 제약조건 왜 사용하는 걸까요?
- 그렇지 않으면 이름이 랜덤값으로 부여됩니다.
- 외래키가 뭘 참조하고 있는지, 키는 무엇을 쓰고 있는지의 내용을 담습니다.
Process vs Thread
프로세스와 쓰레드의 차이는 뭘까요?
프로세스 한 개당 여러 개의 쓰레드가 만들어집니다.
한 개의 프로세스로 쓰면 되지 왜 여러 개의 쓰레드를 쓸까요?
프로세스는 메모리 내 특정 영역을 차지하고, 쓰레드는 프로세스 내에 특정 영역을 차지하게 됩니다. 프로그램을 여러 개 띄운다고 했을 때 쓰레드는 프로세스 내에서 공유된 정보를 같이 사용되고 있는 반면, 프로세스는 자원을 여러개 같은 자원을 각각 가지고 있습니다(메모리 낭비). 쓰레드 내 다른 자원의 경우만 띄워주는 것입니다. 그렇기 때문에 프로세스가 중복 자원이 많고 또 매번 실행할 때마다 새로 자원을 다 실행시켜야 하기 때문에 비용이 큽니다.
멀티쓰레드의 단점은 뭘까요?
공유한 자원에 여러 개의 쓰레드가 동시에 접근하게 되면 문제가 발생할 가능성이 있습니다(데드락). 그리고 문제가 생기면 전체 프로세스가 다운되지만, 멀티 프로세스의 경우엔 하나의 프로세스가 다운되었더라도 영향이 없습니다. 백엔드 개발자이기 때문에 공유된 자원에 여러 쓰레드가 접근할 때를 잘 고려해야 합니다.
Context Switching
프로그램에서 Context는 뭘까요?
현재 실행시점의 메모리의 상태를 말합니다.
Context Switching은 1개의 CPU가 있다고 했을 때 여러 쓰레드를 짧게 짧게 실행하는데, 이 때 짧게 실행하고 한데까지 Context를 어디에 보관해서 다시 그 차례가 오면 그 Context를 가져와서 실행을 다시 짧게 하는데 이러한 과정을 말합니다. Context Switching은 너무 자주 실행되면 메모리 사용량이 많아지고 성능이 느려집니다. Tomcat서버에서 이러한 점을 제한하는데 default는 200개(쓰레드 수, Thread Pool에서 쓰레드 최대 개수)입니다. 만약 10만명의 서비스를 한다면 그 만큼 서버가 많이 필요하게 되는 겁니다. 멀티쓰레드에서는 1명의 사용자당 1개의 쓰레드라고 생각하면 됩니다.
Thread pool
쓰레드를 매번 생성, 해제하는 것도 어느 정도 비용이 들기 때문에 서버 실행시 Thread Pool을 만들어서 일정 개수의 쓰레드를 미리 만들어두고 이를 재사용합니다.
만약 Thread Pool 에 만들어둔 쓰레드보다 많은 사용자가 들어오면 어떻게 될까요?
보통 초과한 사용자의 경우 대기에 태웁니다. 자료형은 Queue(큐)를 주로 사용합니다. 여기 대기자 명단(Tomcat은 100개를 default로 합니다) 중 Thread Pool에 남는 자리가 있으면 이후 쓰레드가 그 사용자에게 부여되어 실행되는 것입니다.
다음 코드의 문제점은 무엇일까요?
@Controller
@RequestMapping("/questions")
public class QuestionController {
private static final Logger log = getLogger(QuestionController.class);
@Resource(name = "qnaService")
private QnaService qnaService;
private Question question;
@GetMapping("/{id}")
public String show(@PathVariable Long id, Model model) {
question = qnaService.findQuestionById(id);
model.addAttribute("question", question);
return "qna/show";
}
// 이하 코드
}
가장 큰 특징은 private Question question;
이 인스턴스 변수로 나와있다는 점입니다. 이 때 발생할 수 있는 문제는 몇몇의 사용자가 동시에 질문을 클릭할 때 사용자가 원하는 질문을 못 볼 수 있다는 것입니다. Bean이 하나의 싱글톤으로 하나의 인스턴스 변수를 사용하고 있기 때문에 이런 문제가 발생하는 것입니다.
Stack vs Heap
위 QuestionController도 하나의 인스턴스 변수가 만들어지는데 위와 같은 문제가 발생하지 않는걸까요
힙은 쓰레드가 공유하지만 스택은 각 쓰레드마다 각각의 스택을 가지고 있기 때문에 그런 문제가 발생하지 않는 것입니다. 인스턴스 변수는 Heap에 들어가기 때문에 공유됩니다. 반면 지역변수는 스택에서 관리하는데요. 이 지역변수에서는 각각의 Question
, Answer
를 바라보기 때문에 문제가 발생하지 않습니다.
중요한 작업시 가장 신경써야 하는 부분이 이런 부분이고 이 Stack과 Heap부분을 신경쓰지 않았을 때 오류를 일으킬 가능성이 큽니다.
'TIL' 카테고리의 다른 글
Today's Dev Notes(2018-12-30) (0) | 2018.12.30 |
---|---|
Todays' Dev Notes(2018-12-29) (0) | 2018.12.30 |
Today's Dev Notes(2018-12-24) (0) | 2018.12.24 |
Today's Dev Notes(2018-12-20) (0) | 2018.12.20 |
Today's Dev Notes(2018-12-19) (0) | 2018.12.19 |