카테고리 보관물: Uncategorized

LangChain: Retrieval Augmented Generation 문서 기반 응답

Retrieval Augmented Generation (RAG) 방법은 LLM에게 질문과 관련 정보를 함께 줘서 해당 정보를 바탕으로 응답하게 하는 방법입니다. LLM의 환각 현상을 줄일 수 있는 방법이자, 최신 정보나 특정 분야의 지식을 전달해줄 수 있는 방법입니다. LangChain에서 RAG를 구현하는 과정은 아래 그림과 같습니다.

LangChain RAG 구현 과정

  • Source: 문서 파일을 준비합니다.
  • Load: document_loaders 모듈을 이용해 문서의 내용을 읽어들입니다.
  • Transform: 문서가 길면 text_splitter 모듈을 이용해 나눕니다.
  • Embed: embeddings 모듈의 임베딩 모델을 이용해 텍스트를 벡터로 변환합니다.
  • Store: vectorstores 모듈의 벡터 데이터베이스에 임베딩 벡터를 저장합니다. 벡터 데이터베이스에서는 유사도 기반 벡터 검색 기능도 제공합니다.
  • Retrieve: 질문과 가장 가까운 문서를 반환하는 인터페이스로, index나 vectorstore를 이용해 문서를 검색합니다.

LangChain에서 index는 문서를 저장하고 검색하기 위한 데이터 구조로, 벡터 데이터베이스는 index의 일종이라고 할 수 있습니다. Index는 벡터 데이터베이스보다 더 큰 개념으로, 저장과 유사도 기반 검색 뿐 아니라 문서 관리(중복 제거, 업데이트, 삭제) 기능도 포함합니다. 위 과정을 코드로 살펴보겠습니다.

Retrieval Augmented Generation 예제

이 예제는 DeepLearning.AI에서 가져온 예제입니다. 예제에서 사용하는 CSV 파일은 1000 종류의 옷에 관한 정보를 포함한 파일입니다.

Source, Load (Transform은 생략)

from langchain.document_loaders import CSVLoader

loader = CSVLoader(file_path="09_OutdoorClothingCatalog_1000.csv")
docs = loader.load()

docs는 1000개의 Document 객체를 포함한 리스트입니다. CSV 파일의 한 행이 하나의 문서가 되었습니다. Document 길이가 길지 않기 때문에 text_splitter는 사용하지 않았습니다.

Embed, Store

! pip install docarray
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import DocArrayInMemorySearch

embeddings = OpenAIEmbeddings()
db = DocArrayInMemorySearch.from_documents(
    docs,
    embeddings
)

다양한 vectorstores들 중 DocArrayInMemorySearch를 사용했습니다. 다른 벡터 데이터베이스를 사용하는 것도 가능합니다.

Store (Vector Search)

query = "한여름 산행에 좋은 여성 옷을 추천해줘. 추천 이유를 한국어로 간략하게 설명해줘.\nOutput format: 'name: reason'"

docs = db.similarity_search(query)

docs는 네 개의 Document를 포함한 리스트입니다. 포함된 문서는 질문과 의미가 가장 가까운 문서들입니다.

Retrieve

from langchain.chat_models import ChatOpenAI

llm = ChatOpenAI(temperature = 0.0)
qdocs = "".join([docs[i].page_content for i in range(len(docs))])
rag_prompt = f"{qdocs} Question: {query}"

response = llm.predict(rag_prompt)

## 출력
"name: Women's Camo Mountain Fleece Vest\nreason: 한여름 산행에 좋은 여성 옷으로 추천합니다. 이 베스트는 두꺼운 300무게의 셔파 플리스로 제작되어 견고하고 따뜻한 착용감을 제공합니다. 여름에도 산행 시에는 밤에 추워질 수 있으므로 이 베스트는 완벽한 보온층이 될 것입니다. 또한, 팔 구멍과 밑단에 탄력 있는 실이 있어 편안하게 착용할 수 있으며 바람을 막아줍니다."

앞에서 검색한 네 개의 Document 내용을 프롬프트에 넣어 LLM에 질문과 함께 전달했고, 옷을 하나 추천 받았습니다. 위의 Retrieve 과정은 RetrievalQA Chain을 이용해 구현할 수도 있습니다.

Retrieve: RetrievalQA Chain을 이용하는 방법

from langchain.chains import RetrievalQA

retriever = db.as_retriever()

qa_stuff = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=retriever,
    verbose=True
)
response = qa_stuff.run(query)

문서 내용이 길지 않기 때문에 옵션에서 chain_typestuff로 했습니다.네 개의 Document와 질문을 함께 전달하기 때문에 실행할 때마다 추천하는 옷이 달라질 수도 있습니다. 이러한 Retrieval Augmented Generation은 자주 사용하는 방법이기 때문에 index를 이용해 좀 더 간단하게 구현하는 방법도 있습니다.

Vectorstore Index를 이용하는 방법

RAG 과정 중 Source와 Load (loader 선언까지) 과정은 앞과 동일합니다. 이후 Embed, Store, Retrieve는 다음과 같이 구현할 수 있습니다.

from langchain.indexes import VectorstoreIndexCreator

index = VectorstoreIndexCreator(
    vectorstore_cls=DocArrayInMemorySearch,
    embedding=embeddings
).from_loaders([loader])

response = index.query(query)

앞의 코드에 비해 많이 짧아졌죠? 중간 과정에서 별도의 처리가 필요하다면 앞의 코드를 사용해야겠지만, 그렇지 않다면 index를 사용하는 것이 편리하겠습니다.

LangChain: Document Loaders로 문서 읽어들이기

파일로 된 문서를 가지고 LLM으로 작업하기 위해서는 먼저 문서의 내용을 읽어들여야겠죠. 파이썬에서 직접 문서의 내용을 텍스트로 읽어서 LLM에 전달하는 것도 가능합니다. 하지만 LangChain에서 제공하는 Document loader를 이용하면 편리하게 다양한 문서를 통일된 방식으로 읽어들일 수 있습니다.

LangChain에는 PDF, HTML, Text, Markdown, Json, CSV 파일 외에도 다양한 종류의 로컬 파일들과 클라우드 드라이브의 파일들을 읽을 수 있는 Document loader들이 있습니다. Document loader를 이용해 문서를 읽으면 Document 객체의 리스트를 반환합니다. 분할 여부에 따라 하나의 객체만 있는 리스트가 반환될 수도 있고, 페이지마다 하나씩 객체가 생성되어 여러 개의 원소를 가진 리스트가 반환될 수도 있습니다. 문서의 내용은 Document 객체의 page_content 속성에 들어가고, 원본 파일, 문서 제목, 페이지 번호 등의 정보는 metadata 속성에 저장됩니다. 예제를 살펴보겠습니다.

HTML 문서 읽기

import requests

url = "https://www.gutenberg.org/cache/epub/2680/pg2680-images.html"

response = requests.get(url)

with open("Meditations_pg.html",'wb') as fh:
    fh.write(response.content)

연습을 위해 프로젝트 구텐베르크 사이트에서 페이지를 하나 다운받아 Meditations_pg.html 파일로 저장했습니다. 마르쿠스 아우렐리우스의 명상록입니다. 이 html 파일을 읽어보겠습니다. BSHTMLLoader를 이용할텐데, 이를 위해서는 BeautifulSoup4 패키지를 먼저 설치해야 합니다.

# 설치: pip install beautifulsoup4

from langchain.document_loaders import BSHTMLLoader

loader = BSHTMLLoader("Meditations_pg.html")
data = loader.load()

위의 data는 Document 객체가 하나 들어있는 리스트입니다. 메타데이터를 확인해보겠습니다.

data[0].metadata
## 출력
{'source': 'Meditations_pg.html',
 'title': 'The Project Gutenberg eBook of Meditations, by Marcus Aurelius'}

이번엔 내용을 일부만 확인해보겠습니다.

data[0].page_content[:1000]
## 출력
'\n\nThe Project Gutenberg eBook of Meditations, by Marcus Aurelius\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nThe Project Gutenberg eBook of Meditations\nThis ebook is for the use of anyone anywhere in the United States and\nmost other parts of the world at no cost and with almost no restrictions\nwhatsoever. You may copy it, give it away or re-use it under the terms\nof the Project Gutenberg License included with this ebook or online\nat www.gutenberg.org. If you are not located in the United States,\nyou will have to check the laws of the country where you are located\nbefore using this eBook.\nTitle: Meditations\n\nAuthor: Emperor of Rome Marcus Aurelius\n\nRelease date: June 1, 2001 [eBook #2680]\n                Most recently updated: March 9, 2021\nLanguage: English\n\n*** START OF THE PROJECT GUTENBERG EBOOK MEDITATIONS ***\n\n\n      MEDITATIONS\n    \n\n      By Marcus Aurelius\n    \n\n      MARCUS AURELIUS ANTONINUS THE ROMAN EMPEROR\n    \n\n \n\n\n\n      BOOKS\n    \n\n INTRODUCTION \n\n\n\n\n\nHIS FIRST BOOK\n\n\nTHE SECOND BOOK\n\n\nTHE THI'

전체 길이를 확인해보죠.

len(data[0].page_content)
## 출력
487994

공백 포함 48만자가 넘네요. 이 내용을 LLM에 전달하면 token 제한에 걸리겠죠? LLM에 전달할 때는 내용을 chunk로 분할해서 전달하게 됩니다.

PDF 문서 읽기

이번에는 위 웹 페이지를 pdf로 출력한 파일을 읽어보겠습니다. 이를 위해서는 pypdf 패키지를 미리 설치해야 합니다.

# 설치: pip install pypdf

from langchain.document_loaders import PyPDFLoader

loader = PyPDFLoader("Meditations.pdf")
pages = loader.load_and_split()
len(pages)
## 출력
151

load_and_split 명령으로 pdf 파일을 읽으면서 분할했습니다. 그랬더니 길이가 151인 리스트가 나왔습니다. 실제 pdf 파일의 페이지 수가 151입니다.

pages[0].metadata  ## {'source': 'Meditations.pdf', 'page': 0}
pages[150].metadata  ## {'source': 'Meditations.pdf', 'page': 150}

Metadata에 들어있는 항목이 html 파일의 경우와 달라졌죠? 문서에 따라 metadata의 내용이 달라진다는 것을 알 수 있습니다.

pages[0]
## 출력
Document(page_content='10/6/23, 10:40 PM The Project Gutenberg eBook of Meditations, by Marcus Aurelius\nhttps://www.gutenberg.org/cache/epub/2680/pg2680-images.html 1/151The Project Gutenberg eBook of Meditations\nThis ebook is for the use of anyone anywhere in the United\nStates and most other parts of the world at no cost and with\nalmost no restrictions whatsoever . You may copy it, give it\naway or re-use it under the terms of the Project Gutenber g\nLicense included with this ebook or online at\nwww .gutenber g.org. If you are not located in the United\nStates, you will have to check the laws of the country where\nyou are located before using this eBook.\nTitle: Meditations\nAuthor : Emperor of Rome Marcus Aurelius\nRelease date : June 1, 2001 [eBook #2680]\nMost recently updated: March 9, 2021\nLanguage : English\n*** ST ART OF THE PROJECT  GUTENBERG EBOOK\nMEDIT ATIONS ***\nMEDIT A TIONS\nBy Mar cus Aurelius\nMARCUS AURELIUS ANTONINUS\nTHE ROMAN EMPEROR\nBOOKS\nINTRODUCTION\nHIS FIRST  BOOK\nTHE SECOND BOOK\nTHE THIRD BOOK\nTHE FOUR TH BOOK\nTHE FIFTH BOOK\nTHE SIXTH BOOK\nTHE SEVENTH BOOK\nTHE EIGHTH BOOK\nTHE NINTH BOOK', metadata={'source': 'Meditations.pdf', 'page': 0})

리스트의 첫 번째 원소를 확인해보니 Document 객체가 들어있고, 페이지 내용은 page_content 속성에, 추가 정보는 metadata 속성에 들어가 있는 것을 확인할 수 있습니다.

이렇게 LangChain의 Document loader를 이용하면 다양한 유형의 파일들을 편리하게 읽어들일 수 있습니다.

대학생의 자유로부터의 도피

책 – 자유로부터의 도피

에리히 프롬은 ‘자유로부터의 도피’에서 중세에서 근대로 오면서 사람들이 자유를 얻었을 때 어떻게 반응해왔는지 알려줍니다. 중세 사회는 사람들이 사회 체제 안에서 자신의 역할에 묶여 있는 사회였습니다. 자유가 없는 대신 소속감, 안전, 속박이 있는 사회였죠. 근대 자본주의 사회에서 사람들은 속박에서 해방되어 자유를 얻게 되었지만, 대신 소속감을 잃고 고립되어 불안해하는 경우가 많았습니다. 이러한 불안감으로부터 도피하기 위해 사람들은 크게 세 가지 방법을 선택했습니다.

  1. 권위주의: 자기 이외의 어떤 사람이나 사물에 의지하는 방법입니다.
  2. 파괴성: 어떤 대상을 파괴하는 행동입니다.
  3. 자동 인형적 순응: 자아를 상실하고 타인의 기대에 따라 살아가는 방법입니다.

세 가지 방법 모두 바람직한 방법은 아닙니다. 에리히 프롬이 제안한 대안은 소극적 자유로부터 적극적 자유로 나아가는 것입니다. 소극적 자유가 속박으로부터의 자유라면, 적극적 자유는 사랑과 일 속에서 자신의 능력을 발휘하며 바깥 세계와 자연스럽게 관계를 맺는 자유입니다.

대학생의 자유로부터의 도피

고등학생 때까지 별다른 자유 없이 공부만 하다가 대학에 들어온 학생들은 갑자기 대인관계, 수강신청, 동아리 등 다양한 선택의 자유를 얻게 됩니다. 하지만 자유에 따르는 책임, 취업, 진로, 인간관계의 어려움 등으로 인해 불안감이 생기죠. 에리히 프롬의 분류에 따른 대학생의 도피 방식은 다음과 같이 생각해볼 수 있습니다.

  1. 권위주의: 학교의 규칙, 교수나 멘토의 기대에 맞는 틀 안에서만 움직이는 방법입니다.
  2. 파괴성: 갈등이나 대인관계의 문제 등을 파괴적인 행동으로 해결하려고 시도합니다.
  3. 자동 인형적 순응: 사회의 기대에 맞추어 행동하고 자신의 개성 없이 트렌드나 패션을 맹목적으로 따릅니다.

바람직한 반응은 적극적 자유로 나아가는 것이죠.

  • 다른 사람의 기대에 따라 사는 것이 아니라 자신의 삶을 주도하겠다고 결심합시다.
  • 자신만의 고유한 가치를 긍정적으로 받아들여 자신만의 정체성을 찾아가시기 바랍니다.
  • 다양한 책을 읽으며 스스로 생각하는 힘을 키웁시다.
  • 삶의 의미를 찾아가며 존재하는 삶을 살아가시길 바랍니다.

이러한 과정에서 여러 어려움과 실패가 있겠지만 우리는 실패를 통해 배우고 성장할 수 있습니다.

대학생의 옵션 구매

옵션이란?

경제에서 옵션은 선택할 수 있는 권리를 말합니다.

예를 들어, 현재 브렌트유 가격이 리터당 1700원이라고 해봅시다. 한 달 후에 1리터를 1750원에 살 수 있는 권리를 50원에 팔고 있다고 해봅시다. 사겠습니까?

한 달 후 유가가 리터당 1800원이 넘어갈 것이라 예상한다면 이 권리를 사는 것이 좋습니다. 만약 2000원이 된다면 1750원을 내고 2000원짜리 브렌트유 1리터를 살 수 있으므로 250원 이득이네요. 옵션 구매에 50원을 투자했으니 총 이득은 250원에서 50원을 뺀 200원이 됩니다. 50원 투자해서 한 달만에 200원 순이익을 남겼다면 대단히 성공적인 투자죠?

반대로 유가가 1400원으로 떨어졌다고 해봅시다. 얼마나 손해를 볼까요? 옵션은 권리라고 했습니다. 손해볼 것 같으면 안 사면 됩니다. 따라서 유가가 아무리 떨어져도 최대 손실은 옵션 구매에 쓴 50원으로 제한됩니다.

이렇게 이득은 커질 수 있고, 손실은 제한되는 비대칭적 선택권이 바로 옵션입니다. 미래에 변동이 없다면 옵션은 필요 없습니다. 유가가 한 달 후에도 1700원이라면 옵션을 구매할 이유가 없죠. 변동성이 크고 불확실할수록 옵션은 빛을 발합니다.

대학생의 옵션

옵션을 대학 생활에 적용해봅시다. 4년 동안 열심히 공부해서 우수한 성적으로 졸업하고 원하는 기업에 취직할 것이 확실하다면 옵션이 필요 없습니다. 부모님께 물려받을 재산이 많다면 역시 옵션이 필요 없습니다. 졸업 후가 불확실하다면 나만의 옵션을 준비하는 것이 어떻까요?

대학생은 돈이 별로 없으니 옵션은 시간과 노력으로 구매해야 합니다. 예를 들면 인스타그램 보는 시간을 줄이고, A0 받을 만큼 공부하는 대신 B+ 받을 만큼만 공부해서 남는 시간과 노력으로 미래에 도움이 될 수도 있을만한 다른 것을 공부하거나 만드는 것입니다. 이 때 많이들 하는 스펙 쌓기가 아니라 남들과 차별화할 수 있는 일을 해야 좋은 옵션이 됩니다.

어학 연수? 단순히 어학 연수 다녀왔다는 것은 좋은 옵션이 아닙니다. 원어민처럼 말하고 듣는다면 물론 좋은 옵션이 될 수 있지만 시간, 노력 뿐 아니라 돈도 많이 들 수 있습니다. 생성AI 공부? 빠르게 실력을 쌓는다면 향후 몇 년간 좋은 옵션이 될 수 있을 것으로 보입니다. 컨텐츠 크리에이터? 2년 이상 한 가지 분야에서 전문성을 쌓아가는 과정을 보여준다면 훌륭한 옵션이 될 수 있습니다. 창업? 대학생 때 창업을 한다면 우선 위험 부담 없는 창업으로 경험을 쌓기를 권장합니다. 역시 좋은 옵션이 될 수 있습니다.

옵션은 권리라고 했습니다. 자신이 준비한 옵션이 졸업 후 취업이나 창업에 도움이 된다면 사용하면 되고, 도움이 되지 않는다면 안 쓰면 됩니다. 손해보는 것은 물론 옵션을 준비하는데 들어간 시간과 노력(나중에 보면 손해가 아닐 수도 있습니다)이지만 잘 될 경우 옵션으로 인해 여러분의 진로와 인생이 달라질 수 있습니다.

Tip: 리눅스 환경(Centos 7)에서 SSH Terminal + Docker + Jupyter Notebook을 이용한 Tensorflow GPU 버전 사용

리눅스 환경(Centos 7 기준)에서 Nvidia Docker를 이용하여 Tensorflow GPU 버전을 사용하는 방법에 대해 알아보겠습니다.

먼저 리눅스 환경에서 Docker를 설치합니다.
Docker 설치 방법은 아래 링크를 참고해주세요.
https://github.com/NVIDIA/nvidia-docker
https://docs.docker.com/install/linux/docker-ce/centos/

Docker 설치 후 일반 계정에서 Docker를 사용할 수 있도록 권한을 부여해줍니다.
root 계정으로 로그인 한 다음, shell에서 usermod -aG docker <id> 를 입력해줍니다.
입력 후 다시 로그인합니다.

Nvidia Docker를 사용하면 CUDA, CUDNN 등 CUDA 프로그래밍에 필요한 파일들을 설치하지 않아도 됩니다. Graphic Driver만 설치되어 있으면 사용이 가능합니다.
shell에서 nvidia-smi 명령어를 사용하여 Graphic Driver가 설치되어있는지 확인합니다.
만약 드라이버가 설치되어 있지 않다면 설치합니다.
https://www.nvidia.com/Download/index.aspx

드라이버가 설치되었으면, Nvidia tensorflow gpu 버전 docker 이미지를 다운받습니다.
docker pull 명령어를 통해 docker image를 다운받는데, 이 때 다양한 태그를 통해 여러 버전의 이미지를 받을 수 있습니다.
(참고 : https://www.tensorflow.org/install/docker )
이번에는 Tensorflow GPU, Python3, Jupyter notebook 환경을 사용할 것이기 때문에, 아래와 같이 shell에 명령어를 입력합니다.
docker pull tensorflow/tensorflow:latest-gpu-py3-jupyter

다운로드가 완료됐으면 docker images 명령어를 통해 이미지를 확인해줍니다.

그 다음 docker container를 만듭니다. container를 만드는 명령어는 다음과 같습니다.

docker run –runtime=nvidia –name=<name> -v </home/ID/directory:/directory -it –entrypoint=bash -p 8888:8888 -p 6006:6006 tensorflow/tensorflow:latest-gpu-py3-jupyter

위의 명령어를 실행하기 전에 위에서 사용된 docker 명령어에 대해 알아봅시다.
1) –name=<name> 도커 컨테이너의 이름을 지정해주는 명령어입니다. 컨테이너를 다시 시작할 때, 복잡한 컨테이너 ID를 사용하기 번거로우므로, 별명을 지정해줘서 사용하기 편하게 해줍니다. <name> 부분에 본인이 원하는 이름을 적어주면 됩니다.

2) -v 호스트의 디렉토리를 도커 컨테이너에 마운트 하는 명령어입니다. 호스트에 있는 파일을 작업하기 편하도록 마운트 해줍니다. 마운트하기 원하는 디렉토리의 주소(pwd 명령어로 확인)를 </home/ID/directory:/directory> 형식으로 입력합니다.

3) -it 명령어로 shell에 입출력이 가능해집니다.

4) –entrypoint=bash 컨테이너 시작시에 수행할 명령어입니다. 위의 예시의 경우 Jupyter notebook이 자동으로 실행되지 않게 하기 위해 입력한 것입니다.

5) -p 8888:8888 -p 6006:6006 Jupyter notebook (8888)과 tensorboard (6006)를 사용하기 위해 포트 설정을 해주는 옵션입니다.

사용 예시) 만약, test라는 계정의 works 디렉토리를 컨테이너에 works 디렉토리로 만들고 컨테이너 이름을 hello로 만들고 싶다면, 다음과 같이 입력하면 됩니다. (v, it, p 앞에는 – 1개, runtime, name, entrypoint 앞에는 – 2개)
docker run –runtime=nvidia –name=hello -v /home/test/works:/works -it –entrypoint=bash -p 8888:8888 -p 6006:6006 tensorflow/tensorflow:latest-gpu-py3-jupyter

성공적으로 컨테이너가 만들어 졌다면 아래와 같은 화면이 출력됩니다.

호스트의 디렉토리가 마운트 된 것도 확인할 수 있습니다.

이어서 사용환경 setting에 대해 알아보겠습니다.
nvidia docker 이미지는 ubuntu os가 설치되어 있습니다. 하지만 기본적인 프로그램 설치가 되어있지 않기 때문에 필요한 프로그램을 설치해줍니다.
저는 우선 vim 편집기를 설치했습니다
shell에 apt-get install vim 입력하고 설치합니다.

그 다음 jupyter notebook을 실행합니다.
그러면 아래와 같은 에러 메시지가 출력됩니다.

해당 에러를 해결하기 위해, jupyter notebook configuration 파일을 생성해줍니다.
shell에 jupyter notebook –generate-config 명령어를 입력합니다. (generate 앞에 – 2개, config 앞에 – 1개)

그 다음 vim 편집기를 이용해 config 파일을 수정해줍니다.
shell에 vi /root/.jupyter/jupyter_notebook_config.py 를 입력해줍니다.

vim 편집기 에서 / 를 사용하여 notebook_dir, NotebookApp.ip, NotebookApp.port, allow_root, 를 각각 검색합니다.
notebook_dir는 노트북 시작시 홈 디렉토리를 설정하는 파라미터입니다. 마운트 한 디렉토리로 바꾸는것이 사용에 편리할 것입니다.
ip 는 ‘0.0.0.0’ 으로 수정합니다.
port 는 8888로 수정합니다.
allow_root는 True로 바꿔줍니다.

(수정할 때 앞의 주석처리 #을 지워주는것을 잊지 마세요!)

위와 같이 수정했다면 :wq 를 입력하여 수정한 파일을 저장합니다. 그 다음 다시 jupyter notebook을 실행합니다.

이렇게 된 상태에서 터미널을 하나 더 실행하여 host 계정으로 접속합니다. host에서 웹 브라우저를 실행합니다. 저는 firefox를 사용하겠습니다.

웹브라우저 주소창에 127.0.0.1:8888 을 입력합니다.

아래와 같은 창이 뜨면, 도커 컨테이너에서 token 값을 복사하여 입력합니다.
그리고 필요에 따라 password를 설정해서 사용할 수 있습니다.

토큰을 입력하면 다음과 같이 실행됨을 알 수 있습니다.

수고하셨습니다. 연구에 도움이 되길 바랍니다.

책: 국가란 무엇인가(유시민 작가)

“국가란 무엇인가”라는 다소 식상하고 지루할 수 있는 주제를 유시민 작가만의 독특한 화법으로 이해하기 쉽게 설명해줍니다. 앞 장에서는 ‘국가란 무엇인가’ , ‘누가 다스려야 하는가’ 라는 주제로 동서고금 철학자들의 생각을 시대순으로 언급하면서 국가관의 발전상을 보여주었고, 제 5장 ‘애국심은 고귀한 감정인가’ 라는 의문사 형태로 질문하면서 애국심이란 국가라는 특수한 집단에 의해 생겨난 상호 배타적인 감정이라고 말합니다. 그런 다음, 제 6장 ‘혁명이냐 개량이냐’에서는 혁명은 개량의 길이 봉쇄되었을 때 즉, 점진적 공학이 더 이상 소용이 없을 때 일어난다고 하였으며 제 7장 ‘진보정치란 무엇인가’에서부터 작가가 원하는 정의로운 국가의 모습이 어떠한 형태인지 나타나게 됩니다. 마지막 장에는 우리나라 정치와 국가 방향에 대한 솔직한 생각을 피력하면서 마무리합니다.

작가가 꿈꾸는 훌륭한 국가는 고대 그리스 목적론적 국가론처럼 사람들 사이에 정의를 실현하는 국가라고 합니다. 국민 한 사람 한 사람을 수단이 아니라 목적으로 대하고(칸트의 도덕법), 국민을 인간으로 존중하고 책임지고 보호해주는 그런 국가(진보자유주의, 복지국가)를 말합니다. 그는 촛불집회를 보면서 “이게 나라냐” , “이것이 국가란 말인가?”라는 구호를 듣게 되었고 2011년에 출판한 이 책이 개정신판으로 다시 세상에 나오게 되었습니다.

저는 아직까지 모두가 훌륭하다고 할 수 있는 그런 국가를 경험해보지 못 한 것 같습니다. 그러나 불행 중 다행인 점은 우리나라는 악을 최소화할 수 있는 제도가 있는 민주주의 사회에 살고 있으며 모든 시민들이 국정에 관심을 가지고 훌륭한 국가를 만들려고 노력한다면 마냥 불가능한 이야기는 아닐 것이라고 생각합니다.

‘국가’라는 정의는 다양하고 여러가지 국가론이 있지만 현재 우리나라의 경우 훌륭한 국가를 만든다고 하면 남녀노소 누구든지 책임윤리를 가지고 정치인의 말과 행동에 관심을 가져야 한다고 생각합니다. 민주주의 정치제도의 핵심은 국민의 참여와 소통인데 만약 이 부분이 결여된다면 국민을 속이고 사리사욕만 챙기는 악인이 민주적 절차를 통해 당선되는 경우가 발생할 수 있으며, 또는 국가와 국민을 위해 일하는 선인을 온갖 권모술수로 방해할 수도 있습니다. 정치에 염증을 느껴 떠난 사람들, 하루 먹고 살기 바쁜 사람들, 정치에 관심이 없는 사람들이 점점 사회에 많아질수록 민주주의는 고대 그리스 때처럼 중우정치에 빠질 확률이 높아질 것입니다. 따라서 본인의 행동에 책임윤리를 가지고 자신이 국가의 주인이라는 인식을 가진다면 예를 들어 적어도 투표는 선택이 아닌 권리이자 의무로 임할 것이라고 생각합니다.

유시민 작가는 우리나라 민주주의를 후불제 민주주의라고 표현하였습니다. 충분히 일리가 있는 표현이라고 생각합니다. 4·19 혁명 때 거리에 쓰러졌던 청년과 학생들, 유신시대에 목숨을 잃거나 고문을 당했던 대학생과 종교 지식인들, 5·18광주민중항쟁 희생자들, 6월민주항쟁 때 최루탄과 경찰과 맞섰던 시민들, 광우병 촛불시위와 박근혜 대통령 탄핵 요구 촛불시위 등 민주공화국을 세울 때 미리 치르지 않았던 비용을 후불하였다는 이야기입니다. 안타깝게도 저는 개인적으로 노무현 참여정부 이후 진보정치의 무능력 및 책임회피과 시민들의 정치 무관심이 민주주의 국가시스템의 근본이 위협받는 상황까지 가게 만들었고 결국 촛불시위가 일어난 것이 아닌가?라고 생각합니다.

앞서 언급한 것처럼 민주주의 제도 하에서 훌륭한 국가로 나아가기 위해서는 모든 시민들이 국정에 관심을 가지고 적극적으로 참여해야 하는 것이 중요하다고 생각합니다. 그 결과, 정치인이 국민을 두려워하고 국민의 요구를 파악하면서 의지를 대표할 수 있도록 노력할 것입니다. 마지막으로 이 책에서 언급한 아리스토텔레스의 인용구로 끝맺도록 하겠습니다. “훌륭한 국가는 우연과 행운이 아니라 지혜와 윤리적 결단의 산물이다. 국가가 훌륭해지려면 국정에 참여하는 시민이 훌륭해야 한다. 따라서 시민 각자가 어떻게 해야 스스로가 훌륭해질 수 있는지 고민해야 한다.”

책: 여행의 이유(김영하 산문)

소설가 김영하의 여행, 그리고 여행을 바라보는 아홉 가지 이야기.

1장 추방과 멀미

첫 번째 이야기는 2005년 당시, 작가가 집필을 위해 중국으로 떠났지만 입국을 거부당하고 추방당했던 일화로 시작합니다. 매우 불운한 일로 생각할 수 있지만 이러한 흔치 않은 경험이 결국 좋은 이야기 소재가 되었다고 말하면서 ‘여행의 의미가 무엇인가?”라는 본질적인 질문으로 이어집니다. 그는 여행이란 “여행을 떠난 주인공이 여러 시련을 겪다가 원래 성취하고자 했던 것과 다른 어떤 것을 얻고 오는 것”이라고 말합니다. 여러가지 이야기로 예시를 보여주는데, 여행을 떠난 많은 이들이 여행을 마쳤을 때 본인이 원하던 외면적 목적 달성 여부와 관계없이 평소에 인식하지 못 했던 내면적 목표를 달성하는 경우가 많다고 합니다. 그러나 한편, 여행의 어원이 travail(고역)에서 유래된 점을 보면 20세기 이전의 사람들은 여행이란 고향에서 머물지 못 하고 타지를 떠돌아 다니는 고통스럽고 힘든 시련이라고 여겼을 것이라 생각합니다. 즉, 현재 우리는 지루한 일상을 떠나 새로운 것을 얻고 싶은 마음과 안정적이고 통제된 삶에서 위험한 변수를 피하고 싶은 마음이 서로 상존하고 있을지도 모릅니다.

2장 상처를 몽땅 흡수한 물건들로부터 달아나기

작가는 서두에 “나는 호텔이 좋다.”라고 말하면서 운을 뗍니다. 결론부터 말하자면 호텔에 머무는 동안에는 일상과 가족, 인간관계로부터 받는 상처와 피로로부터 벗어날 수 있기 때문입니다. 실제로 삶이 부과하는 문제가 크면 클수록 작가는 여행을 더욱 갈망하였다고 합니다. 필자도 일상에서 주어지는 문제에 도피하고 싶을 때 소설이나 영화 속 이야기를 상상하곤 하는데 아마도 비슷한 감정이지 않을까 싶습니다.

3장 오직 현재

사람들은 대개 과거를 후회하고 다가올 미래에 대해 불안감을 느끼며 살아갑니다. 여행은 그런 우리를 과거와 미래로부터 끌어내 현재에 집중하게 만든다고 합니다. 그 경험들 중 의미있는 것들을 생각으로 바꿔 저장하고 이로부터 영감을 얻습니다. 그래서 작가는 언제나 그 순간에 있었던 여행지보다는 집에 누워있을 때 영감을 얻는다고 합니다.

4장 여행하는 인간, 호모 비아토르

철학자 가브리엘 마르셀은 인류를 호모 비아토르(여행하는 인간)으로 정의하기도 했는데 인간은 끝없이 이동해왔고 그런 본능이 우리 몸에 새겨져 있다고 합니다. 1995년 전에는 전 세계적으로 여행 인구가 5억 2천만 명이었으나 인터넷 시대가 도래하면서 2016년에는 12억 4천만 명으로 두 배가 넘게 증가하였습니다. 여행은 피곤하고 위험하면서 비용도 많이 들지만 인류의 본능이 여행을 포기하지 않고 기술이 발전하면 할수록 더 많이 이동하는 것을 통계가 보여주고 있습니다. 어쩌면 인류가 여행이 선택이 아닌 필수라고 생각하는 날이 올지도 모르는 일입니다.

5장 알아두면 쓸데없는 신비한 여행

다섯 번째 이야기는 “알아두면 쓸데없는 신비한 잡학사전”에 출연한 김영하 작가가 독특한 화법으로 방송 경험을 풀어내는데 특히 프로그램 편집에 대해 바라보는 관점이 놀라웠습니다. 출연자들이 뿔뿔히 흩어져 각자의 여행을 다니고 저녁 식사 때 모여 본인들이 겪은 여행 이야기를 들려주는 방식인데, 편집하는 제작진들도 모든 여행을 리뷰할 수 없어 최종 영상을 통해 간접적으로 경험하게 된다고 합니다. 작가도 최종 편집본을 통해 간접적으로 다른 여행들을 체험하게 되는데 심지어 본인이 직접 다녀온 여행지조차 편집하는 사람의 느낌과 색깔에 영향을 받아 좀 더 깊이 있고 색다른 여행을 경험한다고 합니다. 즉, 최종 영상은 타인이 보여주고 싶은 여행의 정수만 골라서 체험할 수 있으면서 본인은 여행 과정에 수반되는 고통과 비용을 지불하지 않아도 됩니다. 이를 “방구석 여행자”라고 표현했는데 모두가 어느정도는 방구석 여행자이며 일인칭 시점으로 수행한 이 ‘진짜’ 여행은 다른 사람들의 경험과 생각이 함께 숙성되면서 우리의 여행이 좀 더 명료해진다고 합니다.

6장 그림자를 판 사나이

아델베르트 폰 샤미소의 “그림자를 판 사나이” 소설을 보면 주인공은 자신의 그림자를 신비한 인물(악마)한테 파는 대가로 무엇이든 꺼낼 수 있는 ‘행운의 자루’를 얻게 됩니다. 그림자라는 평소에는 신경도 쓰지 않는 것을 파는 대신 엄청난 부를 얻었지만 주인공은 곧 그림자가 인간에게 매우 중요하다는 사실을 알게 됩니다. 그림자가 없는 인간은 사회에 환대받지 못 하였고 결국 혼자가 되었지만, 우연히 어디든지 갈 수 있는 마법의 장화를 얻게 되면서 여행자로 살아가게 됩니다. 즉, 현실에서 여행자는 그림자가 없는 존재이기 때문에 타지에서 어떤 의무와 책임도 또한 어떤 소속감도 가지지 않습니다.

7장 아폴로 8호에서 보내온 사진

일곱 번째 이야기는 여섯 번째 이야기의 반전을 담아냈는데, 여행을 통해 얻는 또다른 기쁨은 타지에서 경험하는 환대라고 합니다. 지구라는 작은 행성에 같이 탑승하고 있는 승객으로서 모두가 동료이고 소중한 존재라는 관점에서 보면 곤란한 여행자를 도와주는 것은 선순환을 유발합니다. 인류는 오랜 세월동안 서로를 적대하고 살육해왔지만 한편으로 낯선 이들을 손님으로 맞이하고 절실한 것들을 제공하면서 떠나보내기도 하였습니다. 거의 모든 문명에, 특히 유목민들에게는 손님을 잘 대접하라는 계율이 남아있다고 합니다.

8장 노바디의 여행

실뱅 테송은 “여행의 기쁨”에서 괴테를 인용하는데 ‘여행은 여행자가 외부 세계에 감행하는 습격이며 , 여행자는 언젠가 노획물을 잔뜩 짊어지고 집으로 돌아가는 약탈자다’라고 언급합니다. 반면에 식사와 잠자리를 제공하면 고마워하며 소식이나 정보 및 선물 등을 주고 떠나는 이들도 있으므로 외부인은 위험하면서도 동시에 매력적이라고 표현합니다. 성숙한 여행자라면 자신을 타지의 상황에 따라 “섬바디(특별한 사람)” 혹은 “노바디(현지인 코스프레)” 중 하나를 선택해서 현명하게 대처하게 되는데 이는 인생을 지혜롭게 살아가는 방법이기도 합니다.

9장 여행으로 돌아가다

일상과 여행의 관계는 마치 현실과 소설의 관계와 같다고 합니다. 현실은 어지럽고 복잡하고 무질서합니다. 그러나 소설은 현실과 비슷한 일이 일어나지만 질서가 있고 통제가 가능합니다. 여행은 우리를 집중시키고 한 도시의 정수만을 맛보길 원하며 여행에서 보고 듣는 모든 것들이 유기적으로 연결되어 있다는 느낌을 받습니다. 여행은 시작과 끝이 분명하다는 점에서 소설과 닮았으며 설렘과 흥분 속에서 낯선 세계를 탐험하고 안전하게 출발점에 돌아옵니다. 작가는 자신의 정체성을 여행자로 규정할 수 밖에 없는 최종적인 이유가 여기서 두드러지는데 지루한 일상을 벗어나 세상을 다시 느끼고 정신이 한껏 고양된 상태로 돌아오면서 다시 일상을 여행할 수 있는 힘을 얻는다고 합니다.

한 마디로 말하라 – Mini Goss

우리는 전달하고자 하는 메시지를 언어를 이용한 문장을 통해 의사소통을 합니다. 우리는 이러한 메시지를 하루에도 수백, 수천 개씩 처리해야 하고, 서로의 메시지를 제대로 이해하지 못하면 오해, 논쟁, 결렬 등이 발생할 수 있습니다. 따라서 우리는 전달하고자 하는 메시지를 정확하게 파악하고 간결한 문장으로 전달하는 것이 중요합니다. 저자는 이 간결한 문장을 ‘결정적 한 마디’라고 말하고 있습니다. 결정적 한 마디는 맥락과 무관하거나 지나치게 복잡한 정보를 제거하여 우리와 청중이 중요한 메시지에 집중할 수 있도록 만들어 줍니다. 이러한 결정적 한 마디는 면접, 발표, 연설, 협상 등 공적인 자리뿐만 아니라, 일상적인 대화나 유머, 심지어 술자리 건배사 같은 사적인 자리에서도 효과적인 기술입니다. 이 책에서 설명하는 힘 있고 인상적인 결정적 한 마디를 만들기 위한 방법과 우리에게 도움이 될 수 있는 활용법을 설명하겠습니다.

힘 있고 인상적인 결정적 한 마디를 만들기 위해서는 우리가 전달하고자 하는 메시지를 사람(1~5), 행동(6~8), 드라마(9~11)으로 나누고, 다음과 같은 항목에 대한 정보를 체크합니다.

  1. 주제와 관계있는 사람은 누구인가?
  2. 메시지를 듣는 사람은 누구인가?
  3. 그들에게서 알고자 하는 것은 무엇인가?
  4. 그들은 당신에 대해 무엇을 알고 있는가?
  5. 그것을 묘사하는 방직은 어떠한가”?
  6. 전달하고자 하는 정확한 내용이 무엇인가?
  7. 당신에게 가장 중요한 행동은 무엇인가?
  8. 청중에게 가장 중요한 행동은 무엇인가?
  9. 메시지에서 가장 흥미로운 극적 요소는 무엇인가?
  10. 그 요소로 어떤 대화를 시작할 수 있는가?
  11. 서로의 목표를 함께 달성할 수 있도록 청중을 사로잡을 수 있는가?

체크했다면, 각 항목에서 가장 중요하다고 생각하는 단어들을 표시합니다. 이 단어들이 결정적 한 마디에 들어가야 할 핵심 단어들입니다. 그리고 자신의 목표와 청중의 목표 중 중복되는 것에 기반을 두고 핵심 단어들을 활용하여 결정적 한 마디를 구성합니다. 결정적 한 마디를 구성했다면, 구상한 문장을 직접 읽어봅니다. 만약 자신이 읽었을 때 어색하게 들린다면, 대화체로 바꿔주는 것이 좋습니다. 또한 가능한 청중들이 마음속으로 메시지를 그릴 수 있도록 구체적이고 시각적인 표현을 사용하고, 쉽게 이해하고 기억할 수 있도록 쉽고 매력적인 단어들을 사용하는 것이 효과적입니다.

이러한 과정을 통해서 결정적 한 마디하는 활용해서, 우리가 전달하고자 하는 생각을 효과적으로 전달하는 방법도 존재합니다.

<빙산분석법>
빙산 분석법은 청중들이 듣기 원하는 메시지를 찾아서 전달하는 것으로, 우리가 청중에게 전달하고자 하는 전체 내용을 바다에 떠 있는 빙산에 비유한 방법입니다. 우리는 빙산 전체를 알고 있지만, 청중은 수면위로 드러난 빙산의 꼭대기만 볼 수 있습니다. 따라서 우리는 빙산의 꼭대기를 결정적 한 마디를 활용하여 채우고, 수면 아래는 뒷받침하는 내용들을 중요도에 따라서 채워야 합니다.
빙산 분석법은 언론 기자들이 효과적으로 독자의 관심을 끌고, 정보를 신속하게 파악할 수 있도록 기사나 보도를 편집할 때 사용하는 방법입니다. 언론 기자들은 독자들에게 전달할 중요 내용을 빙산 꼭대기에 배치하고, 뒷받침하는 내용들을 중요도에 따라 배치합니다. 그리고 주어진 기사나 보도의 길이에 맞추기 위해, 중요도가 낮은 내용부터 잘라냅니다.

<5분 미팅법>
5분 미팅법은 짧은 시간 내에 결정적 한 마디에 집중 할 수 있도록 도와주는 훈련법으로, 상대가 5분 동안 자신의 생각을 설명하라고 요구했다고 가정하는 방법입니다. 우리는 상대가 집중할 수 있도록 상대가 원하는 내용을 세심하게 고려하고 열정적으로 이야기할 수 있도록, 상대의 의견을 반영할 수 있도록 결정적 한 마디를 수정해야 합니다. 결정적 한 마디를 수정하면서, 결정적 한 마디를 뒷받침 하는 2~3가지의 정보와 현실성을 부여할 수 있는 흥미로운 통계수치나 사례를 함께 준비하는 것이 좋습니다. 또한 우리는 항상 상대의 생각이 우리와 같지 않을 수 있다는 것을 명심하고, 그들이 제시하는 핵심적인 반론을 신중하게 경청하는 자세를 유지해야 합니다.

우리는 때때로 면접이나 발표, 논문의 초록 등 짧은 시간 동안 상대방의 관심을 집중 시켜 중요한 메시지를 전달해야 하는 상황을 마주하게 됩니다. 이러한 상황에서 우리는 결정적 한 마디를 활용하여 청중들에게 효과적으로 우리의 생각을 전달할 수 있다고 생각합니다.

영화: 미스트(The Mist, 2007)

당신이 알던 세상은 안개 속으로 사라진다.

소설이 원작인 SF 영화 ‘미스트’는 다소 식상?하고 근본 없는 SF 소재를 사용했지만 초점은 위기 상황에 직면했을 때, 고립된 사회에서 나타나는 인간의 다양한 모습들을 보여주는 철학적인 내용을 담았습니다.

어느 날 강력한 비바람이 몰아친 다음 날, 사람들은 이러한 재난을 대비하고 극복하기 위해 마트에서 생필품을 구입하고 있었습니다. 기이한 안개는 점차 마을을 향해 몰려오고 있었고 심지어 군인과 소방관, 경찰관들이 출동하는 사태가 발생하게 됩니다. 안개 속에서 도망친 한 노인이 피를 흘리면서 “안개 속에 무언가가 있다!” 라고 소리치면서 마트 안에 들어오게 되고 마트 밖은 앞이 아무것도 보이지 않는 안개 속에 갇히게 됩니다.

‘미스트’의 이야기는 안개 속에 갇힌 마트 안의 사람들이 문제를 어떻게 접근하고 해결하려는 부분에서 시작됩니다. 먼저 안개 속의 ‘괴물’의 존재를 믿지 않는 사람들(주: 변호사 브렌트 노턴)은 이성적으로 생각하라면서 마트 밖에 나갑니다. 그 후 돌아오거나 살아남았다는 장면은 나오지 않습니다. 군인들이 구출해주길 기다리는 남은 사람들은 주인공 데이빗의 말을 따라 마트 유리벽에 장벽을 쌓게 됩니다. 하지만 시간이 흐르면서 고립된 사람들은 점점 불안해지고 데이빗의 아이를 돌보시던 할머니 한 분이 수면제를 먹고 죽음을 택하는 경우도 발생합니다. 이러한 절망적인 상황에서 카모디 부인은 성경의 말씀을 악용하면서 선동을 일으켜 추종자들을 끌어들입니다. 주인공 일행은 카모디 부인 일행과 마찰을 일으키게 되고 결국 주인공 일행은 마트에서 빠져 나가기로 결정합니다. 마트에서 탈출한 후 차를 타고 안개에서 벗어나려고 시도했지만 차 연료가 다 떨어지자 데이빗은 최후의 선택을 합니다. 차 안에 남아 있는 인원들은 전부 데이빗 손에 죽게 되고 본인은 총알이 부족해 혼자 살아남아 차에서 내립니다. 그 순간 데이빗은 사람들을 구출한 군인들을 만나게 되고 마지막 장면 1분을 위해 이 영화가 존재한다는 말이 있을 정도로 현실?적이고 씁쓸한 결말로 막을 내립니다.

재난 또는 한 치 앞도 알 수 없는 상황을 상징하는 ‘안개’, 모든 종류의 인간을 반영한 하나의 고립된 사회를 상징하는 ‘마트’, 안개 속에 존재하는 위험요소인 ‘괴물’. 이 영화의 SF 요소는 단지 고립된 사회를 형성하기 위한 하나의 장치라고 생각되고 본질은 이러한 위기상황에 나타날 수 있는 인간의 선한 면과 악한 면 그리고 이성적인 면과 감성적인 면 등을 관람객의 입장, 즉 최대한 객관적인 입장에서 바라보라는 의미가 아닐까?라는 생각을 하였습니다.

화살촉 프로젝트나 마트에 고립된 군인 병사 한 명이 마녀사냥 당하는 장면 등 언급하지 않은 내용들이 많습니다. 이런 부분들은 영화를 보신 후 직접 판단해보시는 것을 권유합니다. 저는 영화 ‘미스트’에서 작가나 감독이 말하고 싶은 내용은 진짜 위기는 외부에 있지 않고 내부에 있다는 것과 어느 순간에도 ‘희망’을 잃지 말라는 것이 아닐까?라고 생각합니다. 비록 요즘 시대에 비해 조금 허술할 수 있는 SF 요소라는 점이 있지만 스토리텔링만큼은 전혀 식상하지 않고 현실적인 폭로를 담아낸 명작이라고 생각합니다.

책 : 아가씨와 밤 – 기욤 뮈소

“사랑하는 사람을 위한 행동”으로 만들어낸 완전범죄 이야기

기욤 뮈소의 새 소설 ‘아가씨와 밤’은 생택쥐페리 고등학교의 개교 50주년 행사에 25년 전 ‘빙카 사건’에 연관된 졸업생들이 참석하게 되면서 이야기가 시작됩니다. ‘빙카 사건’은 25년 전 학교의 모든 남학생들의 사랑을 독차지하던 여학생 ‘빙카 로크웰’이 학교의 철학 선생님 ‘알렉시 클레망’과 함께 사랑의 도피를 떠나 실종된 사건을 말합니다. 이 사건은 학교 내의 연극 동아리에서 연극 소재로 활용해 공연을 할 정도로 학교의 전설적인 이야기로 내려오고 있지만, 사건의 전말은 단순한 사랑의 도피가 아닌 살인과 사체유기로 물든 치정사건 이였습니다.

빙카 사건이 있던 25년 전 그 날, 주인공을 비롯한 주요 인물들은 각자 ‘사랑하는 사람을 위한 행동’ 이라는 의도를 가지고 행동을 합니다. 하지만 그 행동들의 결과, 빙카와 ‘알렉시 클레망’이 사망하게 됩니다. 그리고 살인 사건을 은폐하기 위해서 둘의 시체를 유기하고 사랑의 도피를 떠났다는 소문까지 만들어 냅니다. 이야기가 진행되면서 그 날 살해당한 ‘알렉시 클레망’이 완전히 무고한 사람이라는 사실을 알게 되지만, 이 소설의 마지막까지 주요 인물들은 사건이 밝혀서 자신들에게 올 피해와 빙카 사건의 복수를 하고 있는 사람을 찾으려고 할 뿐이였습니다. 심지어 주인공 유명 소설가인 토마는 모든 사건이 완전 범죄로 마무리 되자, ‘소설가의 특권’이라는 합리화와 함께 이 사건을 자신의 새 작품의 소재로 사용하는 등 뻔뻔한 모습을 보여주기까지 합니다.

이렇게 무고한 사람을 죽이고, 시신까지 유기한 범인들이 전혀 죄책감이나 후회를 느끼지 않는 모습을 보고, 저는 오랫동안 빙카 사건을 조사해왔던 기자 스테판이 마지막에 진실을 밝히면서 권선징악을 행하는 장면을 기대했습니다. 하지만 스테판은 토마의 부모님의 ‘사랑하는 사람을 위한 행동’이 빙카 사건을 얼마나 철저하게 완전범죄로 만들었는지를 깨닫게 되고 빙카 사건의 진실을 알리는 것을 포기하게 됩니다. 이렇게 완벽하게 무고했던 피해자 ‘알렉시 클레망’을 살해하고 시체를 유기한 범인의 처벌은 물론, 유족들에게 생사조차 알릴 수 없게 끝난 것이 매우 아쉬웠습니다. 그리고 살인을 저지른 자식을 지키기 위해 범죄를 은폐하고 빙카 사건의 복수자로부터 자식을 지키기 위해 싸우는 모습을 보고,
“그들의 행동을 올바른 모성애와 부성애의 모습으로 생각할 수 있을까?”
“만약 내가 그들의 입장에 있었다면, 지금처럼 그들의 행동을 비판할 수 있는 선택을 할 수 있을까?”
라는 두가지 생각이 함께 들었습니다.

개인적으로 아쉬운 점도 있었지만 다양한 인물의 관점에서 생각을 해 볼 수 있었고, 과거 기욤 뮈소의 작품들처럼 뻔한 러브스토리가 아닌 새로운 방식으로 써 내려간 소설이라는 생각이 드는 작품이었습니다.