내 생에서 가장 행복하고 울컥했던 순간을 뽑으라면 올해, 4월 11일이 아닐까 싶다.
이전의 글에서도 한번 적었던 적이 있지만, 나는 수 많은 동아리에 지원했었고 그만큼 떨어졌다.
하지만, 이번에는 나의 노력이 빛을 바랬던 것인지 얍 22기 서버파트에 면접을 볼 기회가 주어져 상당히 떨리는 마음으로 면접을 준비하였다.
참고로 자소서에는 최대한 개발자로서 지향하는 방향과 우선시 하는것, 그리고 얍에서 가장 얻어 가고싶은 것들을 위주로 작성하였다.
우선 제일먼저 했던 것은 이전 기수들의 면접 질문들을 찾아보고 예상 면접 질문 리스트를 만들어 연습하는 것이었다.
평소 지식을 남에게 가공하여 설명하는 것에는 자신이 있었으나, 면접이라고 생각하니 떨리지 않을 수 없었다.
그렇게 4월 15일 면접일이 다가오게 되었고, 너무나도 긴장한 탓에 깔끔한 답변을 하지못했다.
"처음으로 기술 면접을 보기도 했고, 이정도면 괜찮지 않을까?"라는 안일한 자기 합리화에 잠깐 빠졌었지만, 조금더 확실히 준비 할 수 있었던 점에 후회가 생겨 과거로 부터 배우기위해 보완시켜보고자한다.
면접 질문 개선하기
아래의 리스트가 내가 받았던 질문의 전부는 아니지만, 가장 머릿속에 맴도는 질문들을 산출해왔다. 알고 있지만, 당황한 탓에 제대로 답변하지 못한 것들과 꽤나 제대로 관통당한 질문들을 가져와봤다.
1. Client로 부터 스프링으로 요청이 들어오면 무슨일이 일어나는가?
- 내가 생각한 질문의도 : Filter 단에서 작업을 거친 후 일어나는 요구사항을 얘기한다고 생각하였다.
- 원래 답변 : 프로젝트의 요구사항에 따라 다르나, 일반적으로 Spring Security를 이용하여 Filter 단을 구현한 경우, 해당 요청에 대한 유효성을 검사한 후, 만약 해당 요청이 유효한 경우 Dispatcher Servlet이 Handler Mapping을 따라 Controller로 요청의 흐름이 넘어간다고 대답했다.
1. 개선된 답변
Filter
가 요청을 받는다. 클라이언트로부터 들어온 요청을 Filter에서 최우선적으로 응답받는다.- 이후 Filter에 작성 된 요청로직에 따라 유효성 검사를 수행한후 만약 해당 요청이 유효하다면, 다음 Filter 혹은 Controller에게 요청을 전달
- Dispatcher Servlet으로 넘어온 흐름에 맞춰 URI를 분석하여 Handler Mapping으로 전달한다.
- HandlerMapping은 Dispatcher Servlet으로 부터 전달 받은 URI에 해당하는 컨트롤러로 이를 전달한다.
- 컨트롤러는 해당 요청을 처리하고 여기서 MVC와 Rest의 구조로 반환값이 나뉘게 된다.
MVC의 경우
- 결과를 ModelAndView 객체에 담아 반환한다.
- 이후, Filter에 후처리가 존재한다면 이를 수행한다.
- ViewResolver에서 현재 작업이 끝난 ModelAndView에 적합한 View를 찾아 View 객체를 반환한다.
Rest의 경우
- 결과를 MessageConvertor를 통해
application/json
또는text/plain
등 알맞는 형태로 처리한다.
1-1.(꼬리) Filter와 Interceptor의 차이
- 내가 생각한 질문의도 : Filter와 Interceptor의 차이와 왜 굳이 Filter를 사용하여 인증/인가을 만들었는가?
- 원래 답변 : Filter와 Interceptor의 차이에 대해 명확히 인지하고 있지 않으나, filter를 사용한 이유는 SpringSecurity에서 제공하는 Filter가 존재하기 때문이다.
SpringSecurity에서 제공하는OncePerRequestFilter
에서 ServletRequest와 Response로 요청에 대한 응답 처리가 가능하기 때문에 이를 사용했다.
1-1. 개선된 답변
Filter와 Interceptior 모두 클라이언트의 요청을 가로채어, 처리할 수 있는 컴포넌트이다.
하지만, 처리되는 영역이 다르며, 사용용도 또한 다르다.
Filter
의 경우 Servlet API에서 제공하는 컴포넌트로, Servlet Container 내부에서 동작하며, 요청의 전처리 및 후처리 작업을 수행한다.- 그렇기 때문에 Spring Context 외부에서 실행되고 주로 보안과 로깅등의 공통 작업에 사용된다.
- 반면
Interceptor
의 경우 Spring MVC에서 제공하는 컴포넌트로, Dispatcher Servlet이 Controller로 요청을 전달 및 응답을 호출할 때 사용된다.- Interceptor의 경우 SpringContext 내부에서 실행되며, 보통 로그인 체크,권한 체크등의 작업을 수행한다.
한마디로, 시점의 차이라고 말할 수 있다.
둘의 가장 큰 차이로는 SpringContext 내외부 즉, 처리되는 영역이 다르다.
만약 요구사항이 요청 자체에 대한 처리를 앞단에서 처리를 해야한다면 Filter를 이용하는 것이 맞으나, Controller에 전달되는 그 영역에 처리가 필요하다면 Interceptor를 사용해어야한다.
💡 Spring Context 내부 외부
Spring Context의 내부와 외부에서 동작하는 가장 큰 차이점으로는
Bean의 Life Cycle
관리 유무이다.내부에서는 Application Context가 생성되는 시점에 관리가 시작되지만, 외부에서는 이 과정이 실행되지 않는다.
또한, 내부에서는 스프링 프레임워크에서 제공하는 기능들을 사용할 수 있지만, 외부에서는 사용이 불가하다.
🤔 그럼 무조건 내부에 위치해야 좋은 것 아닌가요?
하지만, Spring Security를 구현하기위해 사용되는 OncePerRequestFilter
를 사용하여 필터를 구현하게 된다면, Spring Security
필터 체인 내부에서 동작함으로 Filter ChainProxy에 의해 생성되고 관리된다.
그렇기 때문에 Bean
의 생명주기를 별도로 관리하지 않아도 되며, 스프링부트의 기능 또한 사용할 수 있다.
2. 3 tier architecture와 clean architecture의 차이
- 내가 생각한 질문 의도 : 3 tier architecture와 clean architecture의 정의에 대해서는 알고 있었으나 차이점에 대해서는 고려하지 못하였다.
- 원래 답변 : 차이점에 대해서는 완벽히 인지하지 못하고 있어 학습후 얍에 들어가면 대답 가능하게 공부하겠다.
2. 개선된 답변
- 3tier architecture는 모듈화와 재사용성에 초점을 맞춘 아키텍처 구조인 반면에, 클린 아키텍처의 경우 확장성과 DIP,인터페이스 분리원칙을 적용하여 깔끔하게 분리된 아키텍처를 만드는 관점에서 차이가 존재한다.
3. N+1이슈
- 내가 생각한 질문 의도 : N+1이슈를 정의하고 해결방법을 말하는 것으로 생각했다.
- 원래 답변 : N+1이슈는 ORM을 사용할 때 보통 지연로딩에서 일어나며, 예상했던 쿼리의 수보다 +1 개의 쿼리가 호출되는 이슈를 일컫는 말이다. 이를 해결하기 위해선 로딩 전략을 바꾸는 것보단 fetch Join을 사용하면 된다.
3. 개선된 답변
즉시 로딩과, 지연 로딩에서 모두 N+1 이슈는 발생가능하다.
즉시 로딩
의 경우 영속성 컨텍스트가 아닌 데이터 베이스에서 데이터를 직접 조회한 후 로딩전략이 동작하기에 생겨난다.
지연 로딩
의 경우 객체간의 매핑이슈에 의해 생겨날 수 있다.
이러한 N+1 이슈를 해결하기위해선 근본적인 발생원인을 알아야한다.
JPQL의 특성 때문인데, JPQL은 조회작업을 마친 후에 FetchType
을 별도로 읽어들이기 때문에 문제가 되어 N+1이슈가 발생한다.
이러한 N+1이슈를 개선하기 위해선 Fetch Join
을 사용하거나, @EntityGraph
를 사용하여 즉시 로딩으로 값을 가져올 수 있다.
4. Getter,Setter
- 내가 생각한 질문 의도 : Getter와 Setter를 반드시 사용해야하는가?
- 원래 답변 : Setter의 경우는 지양을 하는 편이다. Entity라는 ORM에서 중요한 요소가 외부의 Setter라는 요소로 인해 값이 변하는 것을 막아야하기에 반드시 지양하고 빌더 패턴을 이용하여 값을 초기화 하는 작업을 진행한다.
Getter의 경우에도 사용을 줄인다면 디미터의 법칙과 같은 예시를 들며, 객체지향적 완성도를 높이고 싶다면, 이를 지향하면 좋다고 했다.
4. 개선된 답변
- 메소드를 통한 변경감지와 같은 기술을 덧 붙여 설명했으면 좋았을 것이라고 생각한다.
이 후 5번과 6번은 명확한 답변이 주어진 질문은 아니지만 아쉬움이 생겨 개선된 답변을 적어보고자 한다.
5. 객체지향적 설계에서 무엇을 최우선적으로 고려하여야하는가?
SOLID 5원칙 중 SRP의 책임을 크게 생각하고 있다.
실제 경험 사례로 하나의 메소드에 핵심 로직을 몰아서 작성하였던 경험이 존재하였다.
그러다가, 해당 메서드에서 문제가 발생하고 이를 컴파일러 조차 파악하지 못하는 까다로운 디버깅 작업을 거쳐서야 사소하게도, 부가 로직에 존재하였던 type 변환 이슈로 인해 핵심로직 자체에 에러를 생기게 한 경험이 있었다.
이러한 경험을 통해 메소드의 분리를 통해 얻는 이점이 크다고 생각한다.
메소드의 명확성이 높아지고, 디버깅 단계에서도 에러를 쉽게 찾을 수 있으며, 하나의 작은 이슈가 MVP 로직을 망칠 수도 있다고 생각하여 SRP를 중요시하고 있다.
6. 서버개발자로서 서버 규모와 사용자가 많아지면 무엇을 최우선으로 고려해야하는가?
아무래도 사용자가 많아짐에 따라 늘어나는 트래픽의 분산이 가장 큰 이슈로 자리 잡지 않을까 싶다.
비용적인 측면과 서버장애를 가져다 줄 수 있는 측면에서 고려해보았을 때 갑작스러운 클라이언트의 증가는 예상치 못한 장애를 유발한다.
서버를 분산처리 하지 않는이상 하나의 인스턴스로 몰리는 트래픽을 감당하기란 힘들며, 이를 고려한 트래픽 분산처리를 설계 단계부터 고려해보아야 한다고 생각한다.
결론
기술 면접은 완전 처음이었기에 많이 떨리는 경험이었으나, 이를 발판 삼아 성장하게되는 방법을 깨달은 것같다.
오늘 오후에 결과가 드디어 나오게 된다. 나는 탄식할까 행복해할까
'대외활동' 카테고리의 다른 글
[SW 사관학교 정글] Week.0 회고 (2) | 2024.03.16 |
---|---|
DND 8기 지원후기 및 여러 동아리 및 대외활동 지원 후기 (0) | 2023.01.05 |
[우아한테크코스] 프리코스 4주차 리뷰 (0) | 2022.11.24 |
[우아한테크코스] 프리코스 3주차 리뷰 (0) | 2022.11.16 |
[우아한테크코스] 프리코스 2주차 리뷰 (1) | 2022.11.09 |