우테코에서는 각 레벨이 끝날 때마다, 그 레벨에서 배웠던 내용을 기록하여 제출한다. 그리고 이 내용을 바탕으로 20분동안 크루 4~6명과 함께 코치님 또는 캡틴과 자유롭게 얘기를 나누는 시간을 가진다. 모의 면접이라고 생각하면 된다. 담당코치님은 랜덤으로 배정된다.
나의 경우는 레벨3를 시작하자마자 바로 다음 날에 레벨로그 인터뷰를 진행됐다. 나의 레벨로그 인터뷰를 맡아줄 코치님은 코치님이 아닌, 캡틴 포비였다. 포비와 인터뷰라니... 한 편으론 설레면서 한 편으론 두렵고 긴장되는 마음으로 입장하였다.
내 레벨 로그는 여기서 확인할 수 있다.
https://clean-nutria-44b.notion.site/2-42fb806797cf4486bc141fc55e0b7461
레벨로그 인터뷰 Q&A
DB 관련 질문
Q.
레벨로그 작성해주신 내용 중에 @Transactional이 있는데, 이 어노테이션이 해주는 역할은 무엇인가요?
A.
@Transactional이 해주는 역할을 두 가지로 말씀드리자면,
첫째로는 동시성 제어를 해줄 수 있다는 점입니다. 두 개 이상의 트랜잭션이 동시에 접근이 될 경우 발생할 수 있는 문제들을 @Transactional 어노테이션을 붙이면 방지해줄 수 있습니다. 가령, A라는 트랜잭션이 어떠한 작업을 처리할 때, B라는 트랜잭션이 해당 작업에 접근한다면 의도치 않은 값을 조회하게 됩니다. 이렇게 동시에 작업하는 경우에 발생할 수 있는 문제들을 방지해줄 수 있습니다.
둘째로는 예외가 발생했을 때 rollback해줄 수 있다는 점입니다. 트랜잭션이 실행되던 도중, 예외가 발생했을 경우에 해당 트랜잭션 내의 진행된 db 쿼리문들은 다시 롤백되어야 합니다. 그렇지 않으면 도메인과 db의 상태에 간극이 발생해 의도치 않은 결과 및 에러를 마주할 수 있게 됩니다.
내가 열심히 공부했던 내용을 크루가 질문해주었다. 다행히 이 주제는 조금 자신이 있었기 때문에 바로 답변할 수 있었다.
그런데, 트랜잭션 관련 질문은 여기서 끝나지 않았다.
내 답변을 듣고, 포비가 놓치지 않고 바로 꼬리질문을 해주셨다.
Q.
@Transactional 속성에 대해 아는 대로 말씀해주실 수 있나요?
다행히 나는 예전에 @Transactional 의 isolation level 에 대해 흥미롭게 공부한 적이 있어서 이 부분을 위주로 답변을 이끌어갈 수 있었다. 블로그 글(https://kth990303.tistory.com/313)로도 작성했었기 때문에 잘 기억할 수 있었다.
A.
@Transactional에는 readOnly 값을 설정해주어 조회용 트랜잭션임을 명시해줄 수 있는 기능이 존재합니다.
뿐만 아니라 isolation level 속성, propagation 속성 등으로 트랜잭션의 격리 레벨과 전파 속성을 설정해줄 수 있는 것으로 알고 있습니다. 백엔드 개발을 하면서 동시에 트랜잭션이 들어올 경우에 발생할 수 있는 문제를 @Transactional 이 어떻게 처리해줄 수 있을지 궁금했었기 때문에 isolation level 쪽을 공부해보았습니다.
isolation level을 0단계부터 3단계까지 설정해줄 수 있었는데요. 트랜잭션이 동시에 접근할 때 발생할 수 있는 문제들로 Dirty Read (오손 읽기), Non-Repeatable Read, Phantom Read 문제가 있었습니다. 제가 좋아하기도 하면서, 주로 사용했던 레벨은 2단계였습니다. 2단계에서는 Dirty Read, Non-Repeatable Read를 막아줄 수 있었기 때문이에요. Phantom Read를 막지 못한다는 문제점이 있지만, 해당 문제까지 막는 3단계는 완전히 다른 트랜잭션과 고립되어 오히려 성능 상 이슈가 발생할 수 있어 실제로도 많이 사용되지 않는다고 하더라고요. Phantom Read는 특정 데이터를 변경, 삭제, 수정하는 작업이 아닌 INSERT할 때 생기는 문제이기도 하여 사용자가 충분히 예상할 수 있을 것이라 생각하기도 했습니다. 그리고 2단계로도 충분히 Non-Repeatable Read를 막아주어 해당 데이터를 조회하는 중에, 다른 트랜잭션의 접근을 막아주기 때문에 웬만한 문제는 막을 수 있다고 생각했습니다. 어쩌고저쩌고...
아는 것을 최대한 다 말하고 싶었기 때문에, 그리고 긴장한 탓에 말을 아주 그냥 속사포로 해버렸다.
실제로 내 답변을 들으면서 크루들과 캡틴 포비가 이 부분에서 긴장한 탓인지 말이 좀 빨랐다고 피드백을 해주셨다.
아무튼, 답변 내용이 너무 길어진다고 생각하셨는지, 포비가 잠깐 답변을 중단시키고 아래 질문을 해주셨다.
Q. 설명을 너무 열심히 해서 중간에 질문을 못했는데, 트랜잭션이 무엇인가요?
A.
저는 트랜잭션은 DB에서 데이터를 다루는 하나의 가장 작은 비즈니스 작업 단위라고 생각합니다. (실제로는 조금 더 추상적으로 답변한 듯)
예시를 들어보겠습니다. 체스말을 이동시키는 작업을 한다고 해보겠습니다. 체스말을 이동할 때에 체스말의 위치를 update해야 하고, 화이트팀의 차례인지 블랙팀의 차례인지 턴을 update 해주어야 합니다. 만약 둘 중 하나의 SQL문만 처리한다면, 그건 제대로 된 체스말의 이동이라 볼 수 없겠죠. 이러한 묶음 단위를 트랜잭션이라 생각했습니다.
트랜잭션에 대한 정의를 명확하게 말하기가 어려워서, 예시를 들어서 설명했다.
다행히 내가 트랜잭션을 공부하게 된 계기가 우테코 레벨1~레벨2 때의 체스 미션이었어서 해당 예시가 바로 생각나서 빠르게 추가설명을 덧붙일 수 있었다.
이어서 포비가 추가로 질문을 해주셨다.
Q. 앞에서 설명해주신 내용 중에 Dirty Read를 얘기해주셨는데, 이게 무엇인지 설명해주실 수 있나요?
A.
Dirty Read는 하나의 트랜잭션에서 작업하여 발생한 데이터를 다시 롤백시켰을 때, 다른 트랜잭션에서 롤백하기 전 데이터를 열람하여 예상치 못한 데이터를 읽은 경우입니다.
예시를 들어서 설명하겠습니다. a라는 트랜잭션에서 작업한 데이터가 있다고 하겠습니다. a에서 어떠한 데이터를 수정하였습니다. 그리고 b는 이 수정한 데이터를 읽었습니다. 그런데, 문제가 발생하여 a에서 해당 데이터를 롤백했습니다. b는 롤백 전 데이터를 열람했기 때문에 해당 데이터가 옳다고 생각하게 됩니다. 이러한 경우를 Dirty Read라고 합니다.
Dirty Read는 롤백, Non-Repeatable Read는 변경 및 삭제, Phantom Read는 INSERT 라고 기억에 남아있어서 다행히 빠르게 답변드릴 수 있었다.
여기까지 얘기하고 나니 @Transactional 관련 질문은 끝이 났다.
테스트 및 설계 관련 질문
다른 주제로 넘어가서 테스트와 스프링 아키텍처 layer 구조에 관해서도 질문을 해 주셨다.
Q.
E2E test와 인수 테스트를 작성해주셨는데, e2e test와 인수 테스트가 무엇이 다른지 모르겠네요. 한 번 설명해주실 수 있나요?
A.
백엔드 개발 한정으로는 e2e 테스트와 인수 테스트가 동일할 수 있다고 생각합니다. e2e 테스트는 말 그대로 End point에서 End point까지, 시작부터 끝까지 테스트를 진행하는 것이며, 백엔드에서는 Request <-> Response API 테스트라 생각합니다. 그리고 인수테스트는 비즈니스 기능이 의도한대로 돌아가는지 테스트하는 것이라 생각합니다. 즉, e2e test는 기술적으로, 인수테스트는 비즈니스 기능적 관점으로 접근한다고 생각했습니다. 백엔드에서는 이 두 가지가 동일할 수 있다고 생각한 이유는, 우리는 API를 만드는 입장이기 때문에 이 과정이 시작에서부터 끝까지 우리가 작업하는 내용이기도 하고, 우리의 비즈니스 기능도 맞다는 데에 있었습니다.
만약, 프론트 개발까지 합쳐서 테스트할 경우에는 e2e와 인수 테스트가 서로 달라질 수 있다고 생각합니다. 백엔드에서의 e2e는 위에서 말씀드린대로 api 테스트가 될 것이고, 프론트에서의 e2e는 또 다를 수 있다고 생각합니다. 하지만, 인수 테스트는 사용자 입장에서의 비즈니스 기능을 테스트하는 것이므로 백엔드와 프론트엔드에 한정되지 않은 전체 테스트가 진행돼야 합니다. 이러한 점에서 인수테스트가 e2e 테스트를 포함하고 있는, 좀 더 큰 범위라고 생각합니다.
이 부분은 솔직히 정답은 없다고 생각했기 때문에, 내가 생각하는 내용을 바탕으로 답변했다. 사실 나는 e2e와 인수 테스트를 엄밀하게 구분하는 편은 아니긴 하다. 관점의 차이라고 생각한다.
추가로, 단위 테스트와 통합 테스트에 대해 설명해달라는 질문도 있었는데, 이 부분은 생략하겠다.
아무튼 답변을 한 이후에, 포비가 추가로 질문을 해주셨다. (트랜잭션 쪽 질문도 빡셌는데 ㅠ)
Q.
DAO test를 단위 테스트라고 답변해주셨는데, 다른 회사에서는 통합 테스트로 보는 입장도 있어요. 데이터베이스에 의존하고, 해당 기술 (ex. JdbcTemplate)과 함께 그 클래스의 메서드를 테스트하기 때문이에요.
~~~
다시 한 번 질문드릴게요. 단위테스트의 범위 안에 DAO test가 포함된다고 생각하시나요?
A.
그 의견도 이해는 됩니다. 그래도 저는 DAO test는 단위테스트에 좀 더 가깝지 않나 생각이 듭니다.
단위테스트는 해당 클래스의 메서드 단위를 테스트하는 것입니다. DAO test에서 JdbcTemplate 의존은 당연히 db를 다루는 메서드이기 때문에 당연히 필요한 느낌에 가깝다고 생각합니다. 이 기술을 우리가 의도한대로 제대로 로직을 짰는지 테스트하는 것이 DAO test인데, 이는 domain layer 테스트의 메서드 테스트와 유사하다고 생각합니다. DAO test는 메서드 단위의 작은 단위 테스트를 진행하는 것이며, 여러 DAO, 또는 다양한 레이어 계층의 클래스가 통합된 테스트가 아니기 때문에 저는 단위 테스트라 생각합니다.
그리고 실제 객체 사용 vs 모의 객체(mock) 사용 부분도 질문이 있었는데, 나는 실제 객체를 사용해도 괜찮다는 쪽으로 답변했다.
당연히 상황에 따라 변경될 수 있으며, 관점에 따라 다른 의견이 있을 수 있다는 말도 붙여주었다.
MVC 설계 쪽 관련해서도 포비의 질문을 받았다.
Q.
View, Controller layer, Service layer, Domain/DAO layer 로 설계하신다고 답변해주셨어요. 이러한 MVC 구조를 지키는 이유가 있나요? 가령, DAO에서 반환하는 로직을 서비스 클래스에서 별도로 작업하지 않고 바로 반환하는 경우들도 꽤 있지 않나요? 그럼에도 불구하고 Service layer를 작성하는 이유가 있을까요?
이 부분도 정답은 없는 것 같아서 나의 생각을 답변드렸다.
A.
물론 그런 경우도 있지만, 그럼에도 불구하고 저는 Service layer는 있는 것이 좋다고 생각합니다.
DAO는 db 관련 로직에 집중하고, 도메인은 도메인 관련 로직에 집중시키며, 서비스에서는 그 도메인과 db 로직을 통합적으로 다루는 데에 집중해야 한다고 생각합니다. 실제로 dao 반환 로직을 서비스에서 별도로 작업하지 않는 경우가 있더라도, 나중에 요구사항이 추가된다면 해당 작업만으로 충분하지 않은 경우가 발생할 수 있을 듯합니다. 또한, 도메인과 db와의 간극이 발생할 수도 있겠죠. 이러한 이유 때문에 service layer가 존재하면 layer indent가 증가하여 다소 복잡성이 증가한다 하더라도, 생성해주는 편입니다.
Controller layer에서 작업해주면 되냐는 의견도 있는 것으로 아는데요. 저는 Controller에서는 요청과 응답 쪽에 집중하는 것이 맞다고 생각했습니다. 컨트롤러에서 요청을 받아서 서비스 쪽으로 넘겨주면, 서비스에서 해당 요청에 대한 결과를 비즈니스적으로 처리해준 후 반환해줍니다. 컨트롤러는 그 결과를 바탕으로 사용자에게 응답을 보내줍니다. 이렇게 작업하는 것이 저는 관심사 및 책임 분리도 잘 된 것이라 생각하며, 타 개발자가 봤을 때 가독성 또한 좋다고 생각합니다.
테스트 및 설계 관련 답변 쪽에서도 포비의 피드백을 받았는데, 나만의 색깔이 있다는 것이었다.
물론 이 색깔이 매우 짙지는 않고, 어느 정도 색깔이 있다는 의견이었다.
처음에 이 말을 들었을 때는 긍정적인 피드백이라고만 생각했었다.
하지만, 마냥 긍정적인 것만은 아니었다.
우테코에서는 어느 정도 색깔이 있는 사람을 좋아하고, 자기만의 설계 스타일과 함께 실력이 있는 사람을 선호한다고 한다. 그렇지만, 어떤 회사는 색깔이 너무 뚜렷하여 고집있는 사람은 선호하지 않아서 채용하지 않는 경우가 있다고 한다. 이는 커머스 기업에서도 어느 정도 있고, 실제로 우형의 일부 부서에서도 존재하는 케이스라 한다.
포비는 개인적으로 내가 이러한 색깔이 있는 것이 좋다고 말씀해주셨다.
이 피드백을 듣기 전에는 사실 나만의 색깔이 있는줄도 몰랐다. 생각해보면 우테코에서 개발을 하면서, 어느 정도 나만의 뚜렷한 가치관을 세워둔 것 같기도 하다. 어떻게 보면 장점이자, 단점이 될 수도 있을 듯하다.
그렇지만, 또 너무 한쪽에만 치중하지 않기 위해 사람들의 의견을 들어보고 일리있는 의견이면 유연하게 변경하려 노력하기도 한다. 그렇기 때문에 나는 지금 내 색깔의 농도가 딱 좋은 듯하다. 지금은 배우는 입장이므로 내 색깔을 유연하게, 그리고 보다 더 예쁘게 정립하는 데에 신경쓰려고 한다.
인터뷰 마무리 및 느낀 점
그 뒤로는 HTTP 질문이 있었는데, 멱등성 얘기를 하다가 20분이 지나서 인터뷰가 끝나게 됐다.
트랜잭션 쪽에서 신나게 떠드느라 20분이 생각보다 빠르게 지나간 듯하다.
다른 크루들 인터뷰를 들어보니, 스프링 bean 사이클, AWS VPC와 서브넷, Spring Request 어노테이션, HTTP와 HTTPS 등등... 내가 모르는 쪽으로 굉장히 많은 얘기들이 나왔었다. 특히 알파는 HTTP, HTTPS 보안 암호화 과정을 OSI 7 layers와 함께 심도있게 설명해주었는데, 이걸 보고 정말 대단하다고 느꼈다. 나였다면 어버버버... 하면서 죄송합니다 했을 듯ㅋㅋ
내가 원하는 쪽으로 질문이 나와서 운이 좋았다는 것을 느꼈다.
그리고 다음에 인터뷰를 할 때는, 내가 자신 있는 부분으로 질문을 유도하도록 해야겠다는 생각도 갖게 됐다.
그리고 무엇보다 많이 느낀 점은, 이론 공부의 중요성이다.
레벨2에서 미션들이 굉장히 빠르게 몰아치다보니, 코딩을 하면서 구현하는 데는 확실히 실력이 많이 늘게 됐다. 하지만, 그에 대한 베이스는 아직 탄탄히 갖추지 못했다는 생각이 들었다. 레벨3~4 과정을 진행하면서, 그리고 우테코 수료 이후에 꾸준히 책을 읽어야겠다는 생각이 들었다. 베루스처럼 독서광이 돼야겠다는 생각이 든 하루였다.
또, 포비의 피드백이 너무 좋았다. 나만의 색깔이 있다는 것과, 그에 대한 고찰. 이 부분은 앞으로 열심히 공부하면서 더 선명하고 예쁘게, 그렇지만 너무 고인 색은 나오지 않게 하도록 꾸준히 정진해야겠다.
'JAVA > 우아한테크코스 4기' 카테고리의 다른 글
[220708] 우아한테크코스 1차 데모데이 후기 (0) | 2022.07.22 |
---|---|
[우아한테크코스] 레벨3 프로젝트 시작_ 내 마음을 편지로, 내편 📮 (4) | 2022.07.05 |
[220614] 우아한테크코스 레벨2 후기 (0) | 2022.06.15 |
[220609] 장바구니 협업 미션 회고 (0) | 2022.06.14 |
[220525] Spring 경로 조회 미션을 하면서 배운 점 (5) | 2022.05.25 |