작가 한 사람, 혹은 작품 한 개에 대한 설명을 담은 책보다는 전반적인 흐름을 설명하는 책을 찾다 <현대미술은 처음인데요>를 발견했다.
A~Z까지의 챕터로 구성되어 있고 각 챕터가 길지는 않아 빠르게 진도를 뺄 수 있었다.
참여형 전시에 대해서는 꽤 부정적인 의견을 가진 사람이었다.
특히 사진용 전시를 참여형 전시로 포장한 전시장을 방문할 때에는 표값과 시간이 아까워졌다.
그러나 이 책을 읽으며 참여형 전시, 퍼포먼스 전시가 현대미술의 흐름 속에 자연스레 생겨난 점을 알게 되었다. 또한 내가 편협한 시각으로 이 예술들을 바라보고 있었음도 깨달았다.
참여형 전시의 경우 사진용 전시가 전부가 아니라 자신이 표현하고자 하는 내용을 관객들의 참여를 통해 완성하는 예술임을 배웠다.
그 대표적인 예시 작품으로는 쿠사마 야요이의 <소멸의 방>, 펠릭스 곤잘레스의무제(내 사랑로스)이 있다.
퍼포먼스 전시 역시 인터넷상에서는 이를 조롱하거나 비하하는 사람들이 많았지만, 그들은 자신의 몸을 매개로 주제를 나타내는 사람들이라는 인식으로 변경되었다.
다른 현대 미술에 대해서도 마찬가지지만, 참여형 전시와 퍼포먼스 전시에 대해 편협한 시각을 줄여보려 한다.
책에서는 아래와 같이 말한다.
지금 만난 작품이 어떤 작품인지 알아내기란 그리 간단한 일이 아니다. 왜냐하면, 현대미술의 종류는 너무 많고 모두 새로운 것이며 대부분의 경우 좋은 작품과 나쁜 작품을 구분할 만큼 충분한 시간을 거치지 못했기 때문이다. 자신이 본 작품에 대해 누구도 확신할 수 없고, 상당히 많은 작품이 쓰레기가 될지도 모른다는 사실은 우리를 아주 흥분시키기도 하지만 무섭게 만들기도 한다. 그러니 너무 빨리 결론 내리는 실수는 하지 말자!
이처럼 내가 받아들이기 어려운 전시라고 하찮게 여기거나 무시하는 것이 아닌, 왜 이런 매체를 선택했고 어떤 점을 이야기하려 하는지 더욱 열린 마음으로 받아들여야겠다.
책을 읽으며 <미술관에 스파이가 있다>에서 읽은 내용들이 꽤 연상되어 즐겁게 읽었다.
몇 가지만 예로 들자면,
어떤 작가의 작품을 사들였다가 고점일 때 금세 판매하는 것을 Flipping이라고 하는데, 이런 과정이 여러 번 반복되면 작가에게 치명적이라는 것
화이트 큐브가 요즘 전시장의 주된 테마라는 점
아트페어에 참여하기 위해 많은 돈과 인력과 시간이 든다는 점
갤러리 중 네임드 갤러리(ex. 가고시안) 혹은 미술관의 영향력이 크다는 점
책의 발행 연도를 확인하니 2017년이었다. 2026년 현재의 화두는 AI인데 아마 책이 조금 더 늦게 나왔더라면 AI와 관련된 내용도 있지 않았을까 짐작해 본다.
현대미술에 대한 배경지식이 없더라도 부담스럽지 않게 흐름을 알게 되는 책이라 현대미술에 관심이 있는 사람이라면 추천한다.
BIT는 Built-In Test의 약자로, 장비의 상태를 보고하기 위한 자가진단 기능이다. 단순한 상태값이라기보다는, 장비가 스스로 자신의 상태를 점검하고 그 결과를 외부에 알려주는 메커니즘이라 볼 수 있다.
각 항목은 장비마다, 운용 로직마다 다르게 구성할 수 있으며 상태 관리를 위해 필요한 항목을 BIT에 넣어 관리한다. 일반적으로 어떤 항목이 구성되어 있는지는 ICD(Interface Control Document, 인터페이스 통제문서) 혹은 별도로 정의한 문서에서 확인할 수 있다.
BIT는 크게 3가지로 구성되어 있다.
PBIT(Power-Up BIT): 처음 보드가 부팅될 때 수행되는 BIT
IBIT(Initiated IT): 요청이 있을 때 수행되는 초기 진단 시험
CBIT(Continuoous BIT): 장비의 상태를 지속적으로 확인하는 연속 진단 BIT
각 BIT는 구성 항목이 같을 수도, 다를 수도 있다. 상태를 확인하는 시점에 따라 필요한 정보가 달라질 수 있기 때문에, BIT 항목을 목적에 맞게 다르게 구성하는 것이 일반적이다.
BIT 데이터 가져오기
PBIT은 부팅 시점에 한 번만 실행된다. 검사가 완료되면 결과를 레지스터에 반영하며, 이후 값은 변경되지 않는다.
부팅이 완료된 후 해당 레지스터를 읽으면 결과를 확인할 수 있다.
CBIT도 PBIT과 마찬가지로 장비가 검사를 완료한 뒤 결과를 레지스터에 반영한다. 다만 운용 중에 지속적으로 갱신되기 때문에, 읽는 시점에 따라 결괏값이 달라질 수 있다.
IBIT은 요청-응답 흐름이 필요하다. 장비에 IBIT 실행 명령을 보내면 장비는 이를 수신하고 IBIT을 수행한다. 완료되면 완료 Flag 신호를 보내며, 이 Flag를 확인한 후에 결과 데이터를 읽어야 한다. Flag 확인 없이 결과를 읽으면 적절하지 않은 값을 가져올 수 있으므로 주의가 필요하다.
아래 예제코드는 드라이버가 제공하는 레지스터 주소를 구조체 포인터로 매핑하여 데이터를 복사해 가져오는 방식으로 작성되었다. PBIT은 CBIT과 구조가 동일하고 부팅 후 1회만 읽으면 되므로 생략한다.
아침마다 우리가 하는 루틴은 꽤 정해져 있다. 특히 회사를 다닌다면 매일 아침 여는 폴더, 사이트는 어느 정도 일정하다. 이때, 매번 클릭해서 세팅하는 것이 아닌 배치파일을 이용한 자동화가 가능하다.
@echo off
:: 현재 시각의 시(hour)만 추출
for /f "tokens=1 delims=:" %%h in ("%time%") do set HOUR=%%h
:: 오전(9시 이전)이면 업무 시작 모드, 이후면 복귀 모드
if %HOUR% LSS 9 (
echo start working...
start "" "https://slack.com"
start "" "https://notion.so"
start "" "C:\works\myproject"
) else (
echo Welcome back. Opening the working directory.
start "" "C:\works\myproject"
)
실행 시각에 따라 출근 모드와 복귀 모드 설정
URL과 폴더는 각자 상황에 맞게 변경 가능
2. git 연동 - 태그 기반 히스토리 작상
깃 태그를 이용한 히스토리 관리를 배치파일을 이용해 자동화 가능하다.
@echo off
setlocal enabledelayedexpansion
chcp 65001 > nul
set OUTPUT_DIR=releaseNote
set OUTPUT_FILE=%OUTPUT_DIR%\release_note.md
set TEMP_FILE=%OUTPUT_DIR%\_temp.md
if not exist %OUTPUT_DIR% mkdir %OUTPUT_DIR%
:: 태그 존재 확인
for /f "tokens=*" %%t in ('git tag') do set HAS_TAG=1
if not defined HAS_TAG (
echo [INFO] No tags found.
goto :EOF
)
:: 최신 태그 감지
for /f "tokens=*" %%t in ('git describe --tags --abbrev=0') do set LATEST_TAG=%%t
echo [INFO] Latest tag: %LATEST_TAG%
:: 모드 판별
set MODE=view
if not exist %OUTPUT_FILE% set MODE=generate
if "%MODE%"=="view" findstr /c:"%LATEST_TAG%" %OUTPUT_FILE% > nul 2>&1 || set MODE=generate
echo [INFO] Mode: %MODE%
echo.
:: 태그 목록 출력 (공통)
echo ================================
echo TAG LIST
echo ================================
for /f "tokens=*" %%t in ('git tag --sort=-v:refname') do (
for /f "tokens=*" %%h in ('git rev-list -n 1 %%t') do (
set HASH=%%h
echo [%%t] !HASH:~0,7!
)
)
echo ================================
echo.
if "%MODE%"=="view" (
echo [INFO] Release note is up to date.
goto :EOF
)
:: 릴리즈 노트 생성
echo [INFO] Generating release note...
(
echo # Release Note
echo.
echo ## History
echo.
echo ^| Version ^| Date ^| Type ^| Key Change ^| Author ^| Commit ^|
echo ^|---^|---^|---^|---^|---^|---^|
) > %TEMP_FILE%
for /f "tokens=*" %%t in ('git tag --sort=-v:refname') do (
set TAG=%%t
set TAG_DATE= & set TAG_KEY= & set TAG_AUTHOR= & set TAG_TYPE= & set TAG_HASH=
for /f "tokens=*" %%h in ('git rev-list -n 1 %%t') do (
set FULL=%%h
set TAG_HASH=!FULL:~0,7!
)
for /f "tokens=1* delims=:" %%a in ('git tag -l -n99 %%t') do (
if /i "%%a"=="Date" set TAG_DATE=%%b
if /i "%%a"=="Key Change" set TAG_KEY=%%b
if /i "%%a"=="Author" set TAG_AUTHOR=%%b
if /i "%%a"=="Type" set TAG_TYPE=%%b
)
echo ^|[!TAG!]^(#!TAG!^)^|!TAG_DATE!^|!TAG_TYPE!^|!TAG_KEY!^|!TAG_AUTHOR!^|!TAG_HASH!^|
) >> %TEMP_FILE%
for /f "tokens=*" %%t in ('git tag --sort=-v:refname') do (
(
echo.
echo ---
echo.
echo ## %%t
echo.
) >> %TEMP_FILE%
git tag -l -n99 %%t >> %TEMP_FILE%
)
move /y %TEMP_FILE% %OUTPUT_FILE% > nul
echo [INFO] Done: %OUTPUT_FILE%
pause
전시회를 종종 다니기는 했었으나 예술계가 어떻게 흐르고 있는지, 어떤 맥락을 가지고 있는지에 대해서는 큰 관심이 없었다.
그러나 예술계의 밑낯을 보여준다는 책의 홍보 문구에 나도 모르게 끌려 이 책을 읽게 되었다.
전시회, 아트 페어를 다니면서도 현대 예술에 대해서는 꽤 회의적인 시각을 가지고 있었다.
현대 예술이 지닌 맥락과 의미를 잘 이해하지 못했기에 미술관에 가서도 주로 중세 회화만을 감상하곤 했다.
책을 통해 예술 생태계의 단면을 조금이나마 보게 되었다. 젊은 신인 작가부터 예술계에서 미술관이 가지는 위치까지 조금이나마 맛봤다. 뉴욕의 젊은 예술가들은 생각보다 고단하게 삶을 이어가고 있었고, 예술계가 누구에게나 열려있지만 모두에게 닫혀있음을 알게 되었다.
작가의 예술계 진입기를 함께 하면서 어떤 게 예술인지 같이 고민했고 미술관에 작품이 들어가는 것만이 좋은 작품의 증표인지에 대해 생각해 보았다.
이러한 과정에서 고전 회화만이 진정한 '예술'이라 생각해 왔던 스스로를 반성했다. 내가 고전 작품에 끌렸던 이유는 단지 책에서 여러 번 마주한 '익숙함' 때문이었을지도 모른다. 또한 흔히 사람은 추상보다 형상이 명확한 구상회화를 선호하는데, 중세 미술이 현대 미술보다 구상적인 측면이 강하다 보니 현대 미술에서 눈을 돌렸던 것일지도 모른다.
하지만 현실을 살짝 비틀어 새로운 세계를 보여주는 것은 시대를 관통하는 예술의 한 줄기라 생각한다.
과거와 현대 미술이 결국 한 줄기로 이어져 있다는 사실을 깨닫자, 이제는 현대 작가들이 각자의 시각으로 세상을 어떻게 해석하고 표현하는지 궁금해졌다.
이제 다시 전시를 다니면서 다양한 예술을 접해보려 한다. 안목을 기르기 위한 목적도 있지만 다양한 예술을 하는 사람들을 응원하고 넓은 예술을 계속 만들어주기를 바라는 측면에서 전시를 다녀보려 한다.
아래는 간단한 느낀 점들이다.
돈 많은 컬렉터들만 작품을 사는 것이 아니다.
작품은 다양한 가격대로 형성되어 있고, 작품을 사는 것을 너무 부담스럽게 생각하지 않아도 괜찮다.
작품을 산다는 것이 누군가에게는 응원으로, 작가의 삶을 이어가게 해주는 원동력이 된다는 것을 알게 되었다.
나도 '내가 집에 두고 싶은 작품'을 만나면 구매해보고 싶다.
미술관에 있는 작품들은 누군가에 의해 필터링된 작품들이다.
미술관에 있다고 해서 '인증된' 작품이 아닐 수도 있다.
큐레이팅도 사람이 하는 것이라 누군가의 취향과 입김이 들어가 있을 수 있다.
아직 안목이 없는 사람으로서 미술관 선정 작품 위주로 즐기되 미술관이 제공한 시선만이 '좋은' 예술이라고 받아들이지는 않아야겠다.
예술을 접하는 방식에는 여러 가지가 있다.
예술의 맥락(어떤 큐레이터가 이 작가 게시글에 좋아요를 눌렀는지, 어떤 대학을 나왔고, 어떤 컬렉터가 해당 예술을 좋아하는지 등...)을 기반으로 작품을 이해하는 방식이 있다.
예술 그 자체를 즐기는 방식이 있다. 책에서는 한 작품을 최소 5분을 보면서 어떤 점들이 나의 눈에 들어오는지 5가지를 꼽으면서 즐기면 한 작품을 보더라도 다양하게 즐길 수 있다고 한다.
개인적으로는 후자의 방식이 더 마음에 든다. 천천히 작품을 즐기는 시간을 가지며 미술관을 다녀보려 한다.
배치 파일이란 CMD에 하나씩 입력하던 명령어들을 메모장에 쭉 적어두고, 한 번에 실행시키는 파일이다.
확장자는 .bat이고, 더블클릭 하거나 터미널에서 해당 파일을 실행시킴으로써 동작한다.
배치 파일을 사용하는 가장 큰 이유는 업무 자동화 때문이다.
매번 반복되는 시스템 설정이나 파일 관리 작업을 일일이 수동으로 처리하다 보면 실수가 발생하기 쉽지만, 배치 파일을 이용하면 정해진 명령어를 실행해 오류를 방지한다.
이 글에서는 자주 사용할 수 있는 기본 문법을 알아보자.
변수 활용과 사용자 입력받기
가장 먼저 익혀야 할 것은 set 명령어를 통해 데이터를 저장하고 불러오는 방법이다.
@echo off
set /p USER_NAME=what is your name? :
set GREETING=hello, %USER_NAME%!
echo ---------------------------------
echo %GREETING%
echo today's date is %date%, current time is %time%.
echo ---------------------------------
pause
@echo off (화면 정리) : 실행되는 명령어 과정을 숨기고 결과만 보여줌 (default로 사용하면 좋음)
pause (창 닫기 방지): 작업이 끝난 뒤 창이 바로 꺼지지 않게 일시 정지 ("계속하려면 아무 키나 누르십시오"라는 문구 띄움)
| (파이프)와 find
파이프는 앞 명령어의 결과물(출력)을 뒤 명령어의 재료(입력)로 바로 넘긴다. 주로 특정 단어를 검색할 때 많이 쓴다.
@echo off
echo find all files including 'config'.
dir | find "config"
:: 네트워크 연결 상태 중 'ESTABLISHED'된 연결만 확인
echo.
echo current network list:
netstat -an | find "ESTABLISHED"
pause
& (순차 실행)와 && (성공 시 실행)
명령어 여러 개를 한 줄에 쓸 때 사용한다.
@echo off
:: 폴더를 만들고(mkdir), 성공하면(&&) 그 안으로 이동(cd)해서 파일을 생성
mkdir test_folder && cd test_folder && echo 성공! > result.txt
echo current folder location: %cd%
pause
응용
@echo off
set REPORT_NAME=Weekly_Report
set /p USER_ID=Enter User ID:
:: (기존 양식 내용 + 사용자 정보)를 합쳐서 하나의 파일로 저장
(
echo ==============================
echo report title: %REPORT_NAME%
echo author: %USER_ID%
echo date: %date%
echo ==============================
echo.
echo [directory information]
dir /b
) > Final_Report.txt
echo Final_Report.txt created.
pause
>는 기존 내용을 지우고 새로 쓰며, >>는 기존 내용 끝에 덧붙인다.
()를 사용하면 한 번에 여러 내용 작성 가능하다.
dir /b는 현재 디렉토리를 알파벳 순으로 정렬해서 보여주고, /r을 사용하면 역순으로 보여준다.
현대 CPU는 성능을 극대화하기 위해 명령어 실행 순서를 임의로 바꾸는 비순차적 실행(Out-of-Order Execution)을 수행한다. 특히 읽기(Load)와 쓰기(Store) 연산이 서로 독립적이라고 판단되면, 하드웨어는 효율을 위해 그 순서를 마음대로 재정렬한다. 단일 코어에서는 문제가 없으나, 공유 메모리를 사용하는 멀티 코어 환경이나 하드웨어 레지스터를 제어할 때는 데이터가 꼬이는 치명적인 결과를 초래한다.
vxWorks는 이러한 메모리 순서 문제를 해결하기 위해 아키텍처별 전용 어셈블리를 추상화한 메모리 배리어 매크로를 제공한다.
Read Memory Barrier: VX_MEM_BARRIER_R()
이 매크로는 배리어 이전의 읽기(Load) 연산들이 배리어 이후의 읽기 연산들보다 반드시 먼저 완료되도록 보장한다. 다만, 쓰기(Store) 연산의 순서에는 관여하지 않는다. 주로 공유 변수나 플래그를 먼저 확인한 후, 그 상태에 의존적인 다른 데이터를 읽어야 할 때 사용한다.
/* 다른 프로세서나 하드웨어가 데이터를 먼저 쓰고 flag를 1로 바꿈 */
void processData(void) {
int currentStatus;
int sensorValue;
// 1. 상태 플래그 확인
currentStatus = shared_status_flag;
if (currentStatus == READY) {
/* 하드웨어가 효율을 위해 플래그 확인(1)과 데이터 읽기(3) 순서를 바꿀 수 있음
이를 방지하기 위해 Read Barrier 사용 */
VX_MEM_BARRIER_R();
// 3. 최신 데이터 읽기
sensorValue = shared_data_value;
printf("Sensor: %d\n", sensorValue);
}
}
Write Memory Barrier: VX_MEM_BARRIER_W()
이 매크로는 배리어 이전의 쓰기(Store) 연산들이 배리어 이후의 쓰기 연산들보다 먼저 메모리에 반영(가시화)되도록 보장한다. 주로 데이터 값을 메모리에 완전히 쓴 후, 상태 신호를 보내야 하는 하드웨어 제어 시나리오에 필수적이다.
void updateControlRegister(uint32_t data) {
*(volatile uint32_t *)REG_DATA = data; // 1. 설정값 입력
VX_MEM_BARRIER_W(); // 2. 쓰기 순서 고정
*(volatile uint32_t *)REG_CTRL = 0x1; // 3. 시작 신호 전송
}
Full Memory Barrier: VX_MEM_BARRIER_RW()
이 매크로는 읽기와 쓰기 모두에 대해 장벽을 세운다. 배리어 이전의 모든 메모리 접근이 배리어 이후의 모든 메모리 접근보다 먼저 완료됨을 엄격히 보장한다. 주로 읽기와 쓰기가 뒤섞인 복합적인 연산에서 데이터 순서가 절대적으로 중요할 때 사용한다. 가장 안전하지만 성능 비용이 가장 크다.
/* 양방향 통신이나 메시지 큐 인터페이스 구현 시 */
void exchangeMessage(uint32_t outMsg) {
// 1. 메시지 송신 (Store)
*(volatile uint32_t *)TX_BUF = outMsg;
/* 모든 읽기/쓰기가 완료될 때까지 대기.
메시지를 다 쓰기 전에 응답을 읽으려 하거나,
순서가 섞이는 것을 원천 차단함 */
VX_MEM_BARRIER_RW();
// 3. 상대방의 응답 수신 (Load)
uint32_t response = *(volatile uint32_t *)RX_BUF;
}
개발 중인 시스템의 요구사항에 맞춰 적절한 배리어를 선택하여 개발한다면 더욱 안정적인 시스템 개발이 가능하다.
와치독(Watchdog)이란 시스템의 오동작을 감지하고 자동으로 복구하기 위한 타이머 기반의 감시 메커니즘이다. 정상적인 동작 중에는 소프트웨어가 주기적으로 와치독 타이머를 갱신(refresh)하여 시스템이 정상 동작 중임을 알린다. 만약 소프트웨어가 오류, 무한 루프, 데드락 등으로 인해 타이머를 갱신하지 못하면, 와치독은 시스템을 리셋하거나 미리 등록된 복구 루틴을 실행한다.
임베디드 시스템, RTOS 환경, 하드웨어 장치 등 신뢰성이 중요한 시스템에서 광범위하게 사용된다.
소프트웨어 와치독 vs 하드웨어 와치독
와치독은 어디서 구현되느냐에 따라 소프트웨어 와치독과 하드웨어 와치독으로 나뉜다. 두 가지 모두 "일정 주기마다 뭔가를 한다"는 타이머 역할은 동일하다.
하드웨어 와치독
소프트웨어 와치독
구현 위치
MCU/FPGA 내부 전용 하드웨어 회로
OS 또는 소프트웨어 레이어
OS hang 시 동작 여부
동작함
같이 죽음
신뢰성
높음
상대적으로 낮음
예시
FPGA WDT 레지스터, MCU 내장 WDT
VxWorks `wdCreate/wdStart`
이 글에서는 각각의 대표적인 활용 예시로 아래 두 가지를 다룬다.
소프트웨어 와치독 (VxWorks API) → 주기적 태스크 실행에 활용
하드웨어 와치독 (FPGA 레지스터) → 시스템 생존 감시에 활용
소프트웨어 와치독 - vxWorks API를 활용한 주기적 태스크 제어
VxWorks에서 제공하는 소프트웨어 와치독 API를 사용하면, taskDelay보다 더 정교하게 일정 주기마다 태스크를 제어할 수 있다.
#define WATCHDOG_PERIOD (30)
typedef struct {
SEM_ID syncSem;
WDOG_ID periodicWd;
} WdParam;
/* 와치독 핸들러: 인터럽트 레벨에서 호출됨 */
static void watchdogHandler(WdParam *arg) {
/* 다음 주기를 위해 와치독을 재시작 (핸들러는 일회성이므로 반드시 재등록 필요) */
wdStart(arg->periodicWd, WATCHDOG_PERIOD, (FUNCPTR)watchdogHandler, (long)arg);
semGive(arg->syncSem);
}
/* 주기적으로 실행될 태스크 */
void taskManager(SEM_ID syncSem) {
while (1) {
semTake(syncSem, WAIT_FOREVER);
/* 이 아래에 주기마다 실행할 작업을 작성 */
}
}
void initTask(void) {
SEM_ID syncSem;
WDOG_ID periodicWd;
WdParam wdParam;
TASK_ID taskId;
/* 1. 바이너리 세마포어 및 와치독 생성 */
syncSem = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
periodicWd = wdCreate();
wdParam.syncSem = syncSem;
wdParam.periodicWd = periodicWd;
/* 2. 태스크 생성 후 활성화
* taskSpawn : 생성과 동시에 실행
* taskCreate : 생성만 수행 → taskActivate로 별도 실행 필요
*/
taskId = taskCreate("testTask", 100, VX_USR_TASK_OPTIONS_BASE,
0x400000, (FUNCPTR)taskManager,
(long)syncSem, 0, 0, 0, 0, 0, 0, 0, 0, 0);
taskActivate(taskId);
/* 3. 와치독 시작 */
wdStart(wdParam.periodicWd, sysClkRateGet() * WATCHDOG_PERIOD,
(FUNCPTR)watchdogHandler, (long)&wdParam);
while (1) {
taskDelay(sysClkRateGet());
}
}