Study/Development interview

Interview Question (링크참조)

Tree_Park 2021. 6. 10. 14:33
728x90

이 글은 깃허브에 올라온 글을 바탕으로 제가 그대로 타이핑한 글입니다. 더 자세하고 정확한 정보를 보시려면
아래 링크를 참조해 주세요.
Link

Part 1. 전산 기초

개발 상식 Link

  • 좋은 코드란?
  • 객체 지향 프로그래밍이란?
  • RESTFul API?
  • TDD란? 어떠한 장점이 있는가?
  • 함수형 프로그래밍?
  • MVC 패턴이란?
  • Git, GitHub란?

좋은 코드란 무엇일까?

Clean Code? Efficient Code? Short Code?

  • 읽기 쉬운 코드?

    • 주석을 쓰면 되지 않을까?
    • 그렇지만, 기본적으로 메타데이터이고, 주석의 내용과 실제 동작이 일치하는지는 어떻게 알아?
  • 나한테만 읽기 쉬운 코드?

    • 내 코드가 한 번 작성되고, 이 다음에 수정될 일이 없다고 누가 그래?
  • 읽기 쉽기만 하면 되는거야?

    • 읽기 쉬운데 전혀 효율적이지 못하고, 버그를 유발하는 각종 암덩어리가 숨어 있으면?
  • 테스트가 용이한 코드?

    • 테스트가 용이한 코드가 좀 더 신뢰성 있지만
    • 그 신뢰성을 계속 믿다간 큰 코를 다칠거야.
    • 또, 테스트가 용이 하다는 것이 무슨 의미지?
  • 중복이 없는 코드?

    • 동일 로직에 대한 공통적인 처리가 있으면,
    • 한가지로 모으는 작업은 거의 필수적이지.
    • 수정할 일이 생겼을 때, 그 한 가지만 수정하면 되니까!
    • 하지만 그 중복을 추출하는 과정을 어떻게 거쳐야 될까?

좋지 않은 코드

  • 쓰이지 않는 코드
  1. 거리
    • 코드가 동작하는 곳과 정의된 곳 간의 물리적 거리가 멀면 파악하기 힘들지.
    • 보고 있는 코드가 일정 범위에서만 사용된다는 확신이 있으면 그 범위만 확인 후 사용하지 않는 코드라는 확신을 얻을 수 있어.
  2. 순수하지 않은 함수
    • 함수 외부의 어떤 값을 기반으로 동작하는 함수는 그 side effect를 제어하기 힘들지.
    • 함수의 입출력만 확인하여 함수 내부를 수정할 수 없다면 수정하기 까다로워.
  3. 응급 처치를 한 코드
    • 중복으로 빼뒀지만 사용하는 곳에서 다른 로직을 추가해줘야 할 때
    • 이 때 수정으로 인한 Side effect가 두려워 함수에 입력을 추가하던가, 옵션 값을 추가하여 내부에서 억지로 처리할 때 좋지 않은 코드가 된다.
  4. 기술 부채
    • 응급처치가 무조건 나쁘다는 말이 아니지. 당장 문제를 해결하는 데에 이만큼 빠른 대응이 없지만, 전체적인 구조 리팩터링을 할 수가 없어.
    • 응급처치 코드들은 부채가되고 상환의 의무를 져야 해.

좋지 않은 코드를 줄이기

추출이 아닌, 추상화
추출 Extraction
  • 밖으로 끌어내
추상화 Abstraction
  • 먼 개념을 이끌어내
의존성을 드러내기 위한 추상화
  • 다른 곳에서 재사용하기 위해 분리하고

  • 파일이 커져서 분리하고

  • 단순히 중복된 코드 덩어리(chunk)에 대해 추출하면 재사용하기 어렵지.

  • 오히려 함수 간 의존 관계를 파악하기 위해 비용이 들어가게 되는거야.

  • 함수를 분리할 때는 그 함수의 역할을 인지하고 하나의 역할만 정의해야 해.

  • 의존성을 드러내기 위함이 추출의 목적이 되야하는거지.

  • 한 파일에 여러 로직이 얽혀 있을 때 각 코드 조각 중 서로 관계에 있는 것들을 추출해야 해.

  • 추상화가 된 함수는 하나의 목적(역할)을 갖게 되고 의미 있는 추출(추상화)이 가능하게 되는거지.

Object Oriented Programming

  • 학교에서 배웠던 대로, 인터넷에서 봐왔던 대로,

    현실 세계의 사물을 객체(Object)로 보고, 그 객체로부터 개발하고자 하는 애플리케이션에 필요한 특징들을 뽑아와 프로그래밍하여 하는 것(Abstraction)이지.

  • OOP로 코드를 작성한다면

    • 작성한 코드에 대한 재사용성이 높아.
    • 자주 사용되는 로직을 라이브러리로 만들어두어 계속 사용할 수 있어.
    • 라이브러리를 각종 예외 상황에 맞게 만들어둔다면 개발자가 사소한 실수를 하더라도 그 에러를 컴파일 단계에서 잡아낼 수 있어.
    • 내부적으로 어떻게 동작하는지 몰라도 개발자는 라이브러리가 제공하는 기능들을 사용할 수 있어 생산성이 높아져
    • 객체 단위로 코드가 나눠져 작성되기 때문에 디버깅이 쉽고 유지보수에 용이해
    • 데이터 모델링을 할 때 객체와 매핑하는 것이 수월해 요구사항을 보다 명확하게 파악하여 프로그래밍 할 수 있어.
  • 하지만

    • 객체간의 정보 교환이 모두 메시지 교환을 통해 일어나게 되어, 실행 시스템에 많은 overhead가 발생하게 될 수 있어.
      • 킹치만, 하드웨어의 발전으로 보완되고 있지
  • 객체가 상태를 갖게 되고, 변수가 존재하여, 이 변수를 통해 객체가 예측할 수 없는 상태를 갖게 되는 거지.

    • 애플리케이션 내부에서 버그를 발생해
    • 이로 인해 함수형 패러다임이 주목받고 있지.

객체 지향적 설계 원칙

  1. SRP : Single Responsibility Principle, 단일 책임 원칙
    • 클래스는 단 하나의 책임을 가져야 하며, 클래스를 변경하는 이유는 단 하나의 이유이어야 한다.
  2. OCP : Open-Closed Principle, 개방-폐쇄 원칙
    • 확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다.
  3. LSP : Liskov Subsitution Principle, 리스코프 치환 원칙
    • 상위 타입의 객체를 하위 타입의 객체로 치환해도, 상위 타입을 사용하는 프로그램은 정상적으로 동작해야 한다.
  4. ISP : Interface Segregation Principle, 인터페이스 분리 원칙
    • 인터페이스는 그 인터페이스를 사용하는 클라이언트를 기준으로 분리해야 한다.
  5. DIP : Dependency Inversion Principle, 역전 의존 원칙
    • 고수준 모듈은 저수준 모듈의 구현에 의존해서는 안된다.

RESTFul API

REST란, REpresentational State Transfer의 약자야. 여기에 ~ful 이라는 형용사형 어미를 붙여 REST한 API라는 표현으로 사용되는 거지.

REST는 디자인 패턴인지, 아키텍처인지 확실치는 않지만, 어떻게 보면 하나의 아키텍처로 볼 수 있지.

API 설계의 중심에 자원이 있고, HTTP Method를 통해 자원을 처리하도록 설계하는 거야.

REST 6가지 원칙

  1. Uniform Interface
  2. Stateless
  3. Caching
  4. Client-Server
  5. Hierarchical System
  6. Code on Demand
RESTful하게 API를 디자인 한다는 것은?
  1. 리소스와 행위를 명시적이고 직관적으로 분리해

    • 리소스는 URI로 표현되고, 명사로 표현돼
    • 행위는 HTTP Method로 표현하고 각각 GET(조회), POST(생성), PUT(기존 Entity 전체 수정), PATCH(기존 Entity 일부 수정), DELETE(삭제)로 분명한 목적으로 사용해
  2. Message 는 Header와 Body를 명확하게 분리해서 사용해

    • Entity에 대한 내용은 Body에 담아.
    • 애플리케이션 서버가 행동할 판단의 근거가 되는 컨트롤 정보인 API 버전 정보, 응답받고자 하는 MIME 타입 등은 Header에 담아.
    • Header와 Body는 http header와 http body로 나눌 수도 있고, http body에 들어가는 json 구조로 분리할 수도 있어.
  3. API 버전을 관리해

    • 환경은 항상 변하기 때문에 API의 Signature가 변경될수도 있음에 유의
    • 특정 API를 변경할 때는 반드시 하위호환성을 보장해
  4. 서버와 클라이언트가 같은 방식을 사용해서 요청하도록 해

    • 브라우저는 form-data 형식의 submit으로 보내고 서버에서는 json 형태로 보내는 것보다, 방식을 하나로 통일하는 것이 좋아.
    • URI가 플랫폼 중립적이어야 한다는것

어떠한 장점?

  1. Open API 제공이 쉬워
  2. 멀티플랫폼 지원 및 연동이 용이해
  3. 원하는 타입으로 데이터를 주고 받을 수 있어
  4. 기존 웹 인프라(HTTP)를 그대로 사용할 수 있어

어떠한 단점?

  1. 사용할 수 있는 메소드가 4가지 밖에 없어
  2. 분산환경에는 부적합해
  3. HTTP 통신 모델에 대해서만 지원해
Reference

TDD

TDD란?

Test-Driven Development는 매우 짧은 개발사이클의 반복에 의존하는 소프트웨어 개발 프로세스야.

  • 개발자는 요구되는 새로운 기능에 대한 자동화된 테스트케이스를 작성하고 해당 테스트를 통과하는 가장 간단한 코드를 작성해
  • 테스트 통과하는 코드를 작성하고, 상황에 맞게 리팩토링 과정을 거치는 거지.
  • 테스트가 코드 작성을 주도하는 개발방식이야

Add a test

  • 새로운 기능을 추가하기 전 테스트를 먼저 작성해
  • 테스트를 작성하기 위해 개발자는 해당 기능의 요구사항과 명세를 분명히 이해하고 있어야 해
    • 사용자 케이스와 사용자 스토리 등으로 이해할 수 있고, 이는 개발자가 코드를 작성하기 전보다 요구사항에 보다 집중할 수 있도록 도와줘

Run all tests and see if new one fails

  • 어떤 새로운 기능을 추가하면 잘 작동하던 기능이 제대로 작동하지 않는 경우가 발생할 수 있어.
  • 더 위험한 경우는 개발자가 이를 미처 인지하지 못하는 경우야
    • 이러한 경우를 방지하기 위해 테스트 코드를 작성하는 거지.
    • 새로운 기능을 추가할 때 테스트 코드를 작성함으로써, 새로운 기능이 제대로 작동함과 동시에 작동하는 기존의 기능들이 잘 작동하는지 테스트를 통해 확인할 수 있어.

Refactor code

  • '좋은 코드'를 작성하는 것은 정말 어려워.

    • 코드를 작성할 때 고려해야 할 요소가 정말 다양하기 때문이지.
    • 가독성, Naming Rule, 확장성, 비즈니스 로직, 예외처리 등등
  • 코드량이 방대해지면서 리팩토링은 거의 필수적으로 수행되어지게 되는거야.

  • 이 때 테스트 주도 개발을 통해 개발을 해왔다면, 테스트 코드가 그 중심을 잡아줄 수 있지.

    • 뚱뚱해진 함수를 여러 함수로 나누는 과정에서 해당 기능이 오작동을 일으킬 수 있지만, 간단히 테스트를 돌려봄으로써 이에 대한 안심을 하고 계속해서 리팩토링을 진행할 수 있어.
    • 결과적으로 리팩토링 속도도 빨라지고, 코드의 퀼리티도 그만큼 향상되게 되는거야.
    • 보다 객체지향적이고, 확장 가능이 용이한 코드, 재설계의 시간을 단축시킬 수 있는 코드, 디버깅 시간이 단축되는 코드가 TDD와 함께 탄생하는 것이지

의문점들

Q. 코드 생산성이 문제가 있지 않을까?
  • 테스트 코드만큼 코드량이 늘어나고, 비즈니스 로직, 각종 코드 디자인에도 시간이 많이 소요되는거지. 코드 퀼리티보다는 빠른 생산성이 요구되는 시점에서 TDD는 큰 걸림돌이야.
Q. 테스트 코드를 작성하기 쉬워?
  • TDD라는 개발 방식을 적용하기에 큰 걸림돌이지. 진입 장벽이 분명 존재해.

    • 어떤 부분을 테스트해야 할지
    • 어떻게 테스트해야 할지
    • 여러 테스트 프레임워크 중 어떤 것이 우리의 서비스와 맞는지 등
  • 여러 부분들에 대한 학습이 필요하고 익숙해지는데도 시간이 걸려.

  • 또, 한 명이 익숙해진다고 되는 일이 아니라, 개발은 팀 단위로 수행되는 거니까 팀원 전체에 대한 동의가 필요하고, 팀원 전체가 익숙해져야 하는거야.

Q. 모든 상황에 대해 테스트 코드를 작성할 수 있어야 해?
  • 세상에는 다양한 사용자가 존재하고, 생각지도 못한 예외 케이스가 존재할 수 있어.

  • 만약 테스트를 반드시 해봐야 하는 부분에 있어서 테스트 코드를 작성하는데 어려움이 발생한다면?

    • 주객이 전도하는 상황이 발생하는거야
  • 실제 코드가 더 중심이 되어야 하는데 테스트를 위해서 코드의 구조를 바꿔야 하는 고민이 생기거나 발생할 수 있는 상황에 대한 테스트 코드를 작성하기 위해 배보다 배꼽이 더 커지는 경우가 허다해.

  • 모든 코드에 대해서 테스트 코드를 작성할 수 없고, 작성할 필요도 없어. 그리고 테스트 코드를 작성한다고해서 버그가 발생하지 않는 것도 아니야.

함수형 프로그래밍

함수형 프로그래밍의 가장 큰 특징 두가지는 immutable data와 first class citizen으로서의 function이야.

immutable vs mutable

  • immutable이란 말 그대로 변경 불가능함을 의미해
  • immutable 객체는 객체가 가지고 있는 값을 변경할 수 없는 객체를 의미하여 값이 변경될 경우, 새로운 객체를 생성하고 변경된 값을 주입하여 반환해야 해.
  • 이와 달리 mutable 객체는 해당 객체의 값이 변경될 경우 값을 변경해.

first-citizen

함수형 프로그래밍 패러다임을 따르고 있는 언어에서의 함수는 일급 객체로 간주돼.

  • 변수다 데이터 구조 안에 함수를 담을 수 있어서 함수의 파라미터로 전달할 수 있고, 함수의 반환값으로 사용할 수 있어.
  • 할당에 사용된 이름과 관계없이 고유한 구별이 가능해.
  • 함수를 리터럴로 바로 정의할 수 있어.

Reactive Programming

반응형 프로그래밍은 선언형 프로그래밍이라고도 불리고, 명령형 프로그래밍의 반대말이야.

  • 또, 함수형 프로그래밍 패러다임을 활용하는 것을 말해.
  • 반응형 프로그래밍은 기본적으로 모든 것을 스트림(stream)으로 봐.
  • 스트림이란 값들의 집합으로 볼 수 있고, 제공되는 함수형 메소드를 통해 데이터를 immutable하게 관리할 수 있어.

Reference

MVC 패턴이란 무엇인가?

그림과 함께 설명하는 것이 더 좋다고 판단하여 포스팅으로 대체한다.

뒤로/위로

Git 과 GitHub 에 대해서

Git 이란 VCS(Version Control System)에 대해서 기본적인 이해를 요구하고 있다.

Git 을 사용하기 위한 각종 전략(strategy)들이 존재한다. 해당 전략들에 대한 이해를 기반으로 Git 을 사용해야 하기 때문에 면접에서 자주 물어본다. 주로 사용되는 strategy 중심으로 질문이 들어오며 유명한 세 가지를 비교한 글을 첨부한다.

많은 회사들이 GitHub 을 기반으로 협업을 하게 되는데, (BitBucket 이라는 훌륭한 도구도 존재합니다.) GitHub 에서 어떤 일을 할 수 있는지, 어떻게 GitHub Repository 에 기여를 하는지 정리한 글을 첨부한다.