2022.11.25 TIL

SUADI·2022년 11월 26일
0

11월 26일은 대망의 중간 발표가 있는 날이다. 중간 발표는 지금까지 진행된 프로젝트에 대해 시니어 멘토 님께 코드 리뷰를 하고, 여러 질문들과 피드백을 받는 식으로 진행될 것이다.

저번 기수 때엔 멘토님께서 질문을 했을 때 대답을 잘 하지 못해서 이번 기수에는 예상 질문 목록을 미리 주시고 공부해올 수 있는 시간을 벌게 해주셨다. 질문 목록을 보니 아무런 준비가 되지 않은 상태에서 이런 질문을 갑자기 받았다면 나 역시 아무말도 못했을 것 같다. 미리 질문 목록을 받아 안도감이 들면서도 한편으로는 진짜 취업 면접 때 아무런 준비가 되지 않은 상태에서 이런 질문들을 받지 않도록 미리 준비해야겠다는 경각심도 들었다.

질문 목록
1. 스프링에서 트랜잭션을 구현하는 원리를 알고계신가요?
2. AOP 에 대해서 아는부분만 설명 부탁드립니다!
3. 웹 공격기법중에서 XSS 에 대해서 설명 부탁드립니다.
4. 웹 공격기법중 CSRF 공격기법에 대해 설명 부탁드립니다.
5. DI 는 무엇인지, 왜 쓰는지 설명 부탁드립니다.

질문목록을 받고 충격받았던 사실은 트랙잭션, AOP, DI는 항해 강의 자료를 통해서, 혹은 WIL 과제 때문에라도 공부를 해야만 했었는데 CSRF, XSS는 단어 자체가 생소하다고 느꼈는데 구글링에 내가 검색한 기록이 이미 있었다. 사람은 역시 망각의 동물이 맞는 것 같고 기록의 중요성을 또 한 번 실감하게 되었다.

TIL 시작.

[1] 트랜잭션

{1} 트랜잭션의 의미

먼저 Transaction의 단어 뜻부터 살펴보면 표면적으로는 '거래' 라는 의미이고, 데이터베이스에서는 '더 이상 쪼갤 수 없는 업무 처리의 최소 단위' 라는 의미이다.

예를 들어서 설명하면 '거래' 라는 의미와 '더 이상 쪼갤 수 없는 업무 처리의 최소 단위'가 일맥상통하는 의미라는 사실을 알게 된다.
A라는 사람과 B라는 사람이 거래를 한다고 하자. 각자의 통장 잔고에는 10,000원이 있다. A가 B에게 5,000원을 준다고 하면 거래는 이렇게 성사될 것이다.

  1. A가 통장에서 5,000원을 인출 한다. (A 통장 잔고 : 5,000원)
  2. A가 B의 통장에 5,000원을 송금한다.
  3. B의 통장 내역에 15,000원이 찍힌다.

이 일련의 과정들이 하나의 '거래'가 되는 것이다. 이 중 하나라도 처리가 되질 않는다면 '거래'가 성립되지 않는다. 이 일련의 과정이 '더 이상 쪼갤 수 없는 업무 처리의 최소 단위'가 되는 것이다.

만약 서버에서 '더 이상 쪼갤 수 없는 업무 처리의 최소 단위'를 잘 설계하지 않는다면 db에도 정상적으로 처리되지 않을 것이고, 클라이언트에게도 잘못된 데이터를 전달하게 될 가능성이 매우 크다. 위의 예시처럼 A가 B에게 5,000원을 송금했는데 B의 통장 내역에 5,000원이 추가되지 않았다면 매우 위험한 상황에 처하게 되는 것이다.

{3} 트랜잭션의 특징

위와 같은 위험한 상황이 발생하지 않기 위해 트랜잭션이라는 장치를 둔 것이고, 트랜잭션은 다음과 같은 특징을 가지고 있다.

  • 원자성 (Atomicity)
  • 일관성 (Consistency)
  • 독립성 (Isolation)
  • 영속성 (Durability)

(1) 원자성

트랜잭션의 연산은 데이터베이스에 모두 반영되든지 아니면 전혀 반영되지 않아야 한다. 즉, commit 혹은 rollback이 이루어져야 한다. 트랜잭션 내의 모든 명령은 반드시 완벽히 수행(commit)되어야 하며, 모두가 완벽히 수행되지 않고 어느하나라도 오류가 발생하면 트랜잭션 전부가 취소(rollback)되어야 한다.

(2) 일관성

트랜잭션이 진행되는 동안에 데이터베이스가 변경 되더라도 업데이트된 데이터베이스로 트랜잭션이 진행되는것이 아니라, 처음에 트랜잭션을 진행 하기 위해 참조한 데이터베이스로 진행된다.

예를 들어, 댓글 테이블에 FK로 게시물 PK값이 걸려 있을 경우, 게시물이 삭제되어 게시물 PK값이 변경되면 댓글 테이블 내에 걸려있는 게시물 PK값 역시 변경되어 일관성을 맞춰줘야 한다는 의미이다.

(3) 독립성

트랜잭션이 실행하는 도중에 변경한 데이터는 이 트랜잭션이 완료될 때까지 다른 트랜잭션이 참조하지 못하게 하는 특성이다. 데이터베이스는 클라이언트들이 같은 데이터를 공유하는 것이 목적이므로 여러 트랜잭션이 동시에 수행되어야 한다. 이때 트랜잭션은 상호 간의 존재를 모르고 독립적으로 수행되어야 한다. 이를 유지하기 위해서는 여러 트랜잭션이 동시에 접근하는 데이터에 대한 제어가 필요하다. 여러 트랜잭션이 동시에 수행되더라도 각각의 트랜잭션은 다른 트랜잭션의 수행에 영향을 받지 않고 독립적으로 수행되어야 한다.

(4) 영속성

트랜잭션의 성공 결과 값은 심지어 시스템에 장애가 발생이 되더라도 변함없이 보관되어야 한다는 것으로 트랜잭션이 정상적으로 완료된 경우에는 db에 확실히 기록해야 하며, 부분 완료된 경우에는 작업을 취소하여야 한다.

[2] AOP

{1} AOP의 필요성

객체지향적인 프로그래밍을 위해 어플리케이션을 설계할 때 책임과 관심사에 따라 클래스를 분리한다. 클래스가 하나의 책임만을 가지도록 분리함으로써 각 모듈의 응집도는 높아지고 결합도는 낮아지게 된다.

그러나 객체지향 설계 방식을 따르더라도 한 가지 아쉬운 점이 존재한다. 여러 클래스에 로깅이나 보안 및 트랜잭션 등 공통된 기능들이 흩어져 존재한다는 점이다. 이렇게 어플리케이션 전반에 걸쳐 흩어져있는 공통되는 부가 기능들을 관심사라고 한다.

만약 트랜잭션이나 로깅 및 보안 등의 부가 기능의 정책이나 API를 변경해야 한다면 이를 사용하는 모든 코드를 수정해야만 할 것이다. 이는 단일 책임 원칙을 위배하게 되고, 결국 서비스 클래스의 응집도가 떨어지면 가독성이 나빠지며, 변경할 부분이 명확하게 드러나지 않게 되는 등 유지보수 측면에서 아쉬운 점이 많아진다.

이러한 관심사를 어플리케이션의 핵심 비즈니스 로직 코드로부터 분리하는 방법론을 AOP, 관점지향 프로그래밍이라고 한다.

{2} AOP

AOP란 OOP로 독립적으로 분리하기 어려운 부가 기능을 모듈화하는 방식이다. 위의 예시처럼 트랜잭션 관리와 같은 부분이 바로 부가 기능 모듈이며, 이를 Aspect라고 한다. 핵심 비즈니스 로직을 담고 있지는 않지만 어플리케이션에 부가됨으로써 의미를 갖는 특별한 모듈이다. AOP는 핵심 비즈니스 로직과 부가 기능 Aspect를 분리하는 등 OOP를 보완하는 역할을 한다.

{3} AOP 사용법

  • Spring AOP 의존성을 추가한다.
  • 부가 기능에 해당하는 코드를 모듈화하기 위해 클래스를 만든다.
  • @Aspect를 설정하여 이 클래스가 Aspect임을 명시하고 @Component를 설정하여 스프링 빈으로 등록 한다.
  • AOP가 실행되는 시점을 설정해준다.

[3] XSS 공격 기법

XSS는 Cross-Site Scripting의 약자로 악의적인 사용자가 공격하려는 사이트에 스크립트를 넣는 기법을 말한다. 공격에 성공하면 사이트에 접속한 사용자는 삽입된 코드를 실행하게 되며, 보통 의도치 않은 행동을 수행시키거나 쿠키나 세션 토큰 등의 민감한 정보를 탈취한다. XSS는 크게 Reflected / Stored / DOM 3가지의 타입으로 나누어 볼 수 있다.

{1} Reflected XSS

검색, 조회 기능과 같이 사용자로부터 입력 받은 데이터가 페이지에 반사되어 노출되는 경우, 공격코드가 포함된 URL을 타 사용자에게 전달하는 방식으로 공격을 수행한다.

{2} Stored XSS

게시글, 사용자 정보 등 한번 저장되면 장기적으로 XSS 공격코드가 웹 서비스에 남아 사용자에게 지속적으로 피해를 줄 수 있다. 보통 서비스 기능 상 장기적으로 데이터가 남는 프로필 저장, 게시글 작성, 댓글 작성등의 기능에서 나타나는 경우가 많다.

{3} DOM XSS

사용자 입력이 페이지에 직접 반영되는 형태가 아닌, JS 함수등으로 인해 DOM 내부에서 처리되는 중 스크립트가 실행 가능한 XSS를 의미한다.

[4] CSRF 공격 기법

{1} CSRF란?

Cross-Site Request Forgery(CSRF, 사용자간 요청 위조)는 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 특정 웹사이트에 요청하게 하는 공격을 말한다.

{2} CSRF 공격 과정

CSRF 공격을 받는 상황이 몇가지 전제되어 있어야 한다.
일단 사용자가 보안이 취약한 서버로부터 이미 인증을 받은 상태여야 하고, 쿠키 기반으로 서버 세션 정보를 획득할 수 있어야 합니다. 그리고 공격자는 서버를 공격하기 위한 요청 방법에 대해 미리 파악하고 있어야 한다. 예상치 못한 파라미터가 있으면 불가능하다.

이러한 전제 조건이 있는 상황에서 사용자가 보안에 취약한 서버에 로그인을 하게 되면, 사용자 브라우저에 저장되어 있는 세션 아이디를 이용하여 사용자가 악성 스크립트 페이지를 누르도록 유도한다. 사용자가 악성 스크립트가 작성된 페이지 접근하게 되면 쿠키에 저장된 sessionID는 브라우저에 의해 자동적으로 함께 서버로 요청된다. 서버는 쿠키에 담긴 sessionID를 통해 해당 요청이 인증된 사용자로부터 온 것으로 판단하고 처리하게 되면서 악성 코드가 사용자의 pc에서 실행이 된다.

[5] DI

DI는 Dependency Injection의 줄임말로 의존관계 주입이라는 의미이다. 우리말로 풀어도 무슨 의미인지 잘 모르겠으니 단어 하나 하나 다 알아보도록 하자.

{1} Dependency(의존 관계)

'A가 B를 의존한다' 라는 의미는 B에 따라 A에 영향을 미친다는 의미로 바꿔 말할 수도 있다. 예를 들어 요리사는 김치찌개 레시피를 보고 요리를 한다고 하면, 요리사는 김치찌개 레시피에 의존적이고, 레시피가 변하면 그에 맞춰 요리사도 요리를 달리하게 될 것이다.

이를 코드로 표현하면,


public class Chef {

	private final KimchiSoupRecipe kimchiSoupRecipe;
    
    public Chef() {
    	kimchiSoupRecipe = new KimchiSoupRecipe();
    }
}

김치찌개 레시피가 변화할 때마다 Chef 객체가 생성될 때, 변화된 레시피가 초기화되기 때문에 의존적이라고 할 수 있다.

이렇게 서로 종속적인 관계를 맺는 형태는 객체지향적이지 못한 코드라고 할 수 있다. 어느 한 코드를 수정해야할 경우에 이에 의존적인 다른 모든 코드를 수정해야만 하는 상황이 오기 때문이다.

이를 OOP의 5가지 원칙 중 하나인 의존관계 역전 원칙을 통해 상위 모듈이 하위 모듈에 의존하지 않고, 상위 모듈, 하위 모듈 모두 추상화된 모듈에 의존하게끔 코드를 작성해야만 한다.

이해하기 어려우므로 예를 들어서 설명하면, 김치찌개 레시피가 아닌 한식 레시피라는 추상화된 인터페이스를 생성한 후, 인터페이스 내에는 각종 한식 요리의 레시피 메서드를 선언만 해놓은후, 각종 레시피는 인터페이스를 구현해 놓고 따로 정의를 해놓고 가져다 쓰게 되면, 레시피가 달라지더라도 레시피 클래스만 변경하면 되므로 관계가 느슨해지고 결합도가 낮아진다.

참고 자료

0개의 댓글

관련 채용 정보