ChatGPT?
요즘 OpenAI에서 공개한 ChatGPT가 화제입니다. 유튜브에서도 블로그에서도 관련 글이 많이 보이는데요. 흥미가 생겨서 저도 한 번 사용해봤는데, 결과는 놀라웠습니다.
ChatGPT는 OpenAI에서 공개한 인공지능 챗봇입니다. GPT 3.5를 기반으로 하여 자연스러운 질답이 가능하며, 여러가지 프로그래밍 언어로 코드를 작성해주거나, 기존 코드를 리팩토링해주기까지 합니다. 저도 처음에는 큰 기대 없이 체험을 해봤는데, 생각한것보다 더 자연스럽고 대단했습니다.
ChatGPT는 작성일 기준으로 무료로 이용해볼 수 있습니다. (클릭)
ChatGPT를 어디에 활용할 수 있을까?
처음에는 먼저 ChatGPT를 상대로 여러 사소한 질문들을 해봤습니다. 인생 상담이나 학습 조언, 자료 검색 등 여러 요청에도 모두 자연스럽고 꽤 쓸모있는 답변을 얻을 수 있었습니다. 이것만으로도 존재가치를 증명하기에는 충분했습니다. 그럼에도 불구하고, 더 나아가서 ChatGPT를 실생활이나 업무 등에 활용해 실질적인 결과물을 만들어 볼 수도 있지 않을까 하는 생각이 들었습니다.
실제로 유튜브에는 이미 “ChatGPT로 일렉트릭 기타 페달 플러그인 만들기” 영상처럼 ChatGPT을 이용해 결과물을 만들어내는 컨텐츠가 있습니다. 저는 개발자니까, ChatGPT에게 개발을 시켜보기로 했습니다.
ChatGPT에게 프론트엔드 개발을 맡기다
계획이 정확히 “ChatGPT에게 프론트엔드 개발을 맡겨보자!”는 아니였습니다. ‘이 녀석이 코딩은 얼마나 잘 할까? 내가 잘 못하는 부분을 한 번 시켜보자.’ 하고, “CSS 작성해줘!” “HTML 작성해줘!” “Javascript 작성해줘!” 해봤더니 알아서 너무 잘 하는게 아니겠어요? 그 결과를 보고 놀라서 헐레벌떡 들고왔습니다. 프론트엔드 개발이라고 칭하기엔 너무 간단한 것들이긴 했지만, 짧으면서도 적절하게 제목으로 표현할 단어가 떠오르지 않았네요.😅
처음에는 “CSS로 애플처럼 예쁜 UI는 어떻게 만들까?” 하는 질문으로 시작했습니다. 질문은 모두 영어로 작성했는데, 제 생존영어를 인공지능 주제에 잘도 이해하더군요! 아래는 제 첫 질문과 답변입니다. 제 질문은 부끄럽지만 영어 그대로, ChatGPT의 답변은 한글로 의역해 요약하겠습니다.
나: How can I make a beautiful CSS like Apple UI?
ChatGPT: 애플 UI같이 아름다운 CSS 인터페이스를 만들려면, 아래 단계를 거쳐봐.
1. 깔끔하고 일관된 레이아웃을 사용한다: 애플의 UI는 깔끔하고 일관된 레이아웃으로 유명하고…(생략)
2. 깔끔한 폰트를 사용한다: 애플은 깔끔하고 가독성이 좋은 폰트를 사용해…(생략)
3. 높은 퀄리티의 이미지를…(생략)
4. 한정된 색 팔레트를 사용…(생략)
ChatGPT의 답변은 좋은 UI를 위한 조언으로 충분했습니다. 그래서 저는 실제 코드 예를 요구해봤습니다.
ChatGPT에게 애플 스타일 버튼 CSS를 요구하다
나: Show me an example, Apple style button.
ChatGPT: 자 여기, CSS로 만든 애플-스타일 버튼이야.
.apple-button {
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
padding: 8px 16px;
font-size: 16px;
font-weight: bold;
color: #333;
background-color: #fff;
cursor: pointer;
transition: background-color 0.2s;
}
.apple-button:hover {
background-color: #f2f2f2;
}
.apple-button:active {
background-color: #e6e6e6;
}
오? 저는 곧바로 ChatGPT가 만들어준 CSS를 이용해 간단한 HTML 파일을 작성해봤습니다.
<html>
<head>
<style>
<!-- ChatGPT가 만든 CSS -->
</style>
</head>
<body>
<button class="apple-button">This is Apple-style Button!</button>
</body>
</html>
만들어진 결과는 이랬습니다.
평소에는 왼쪽과 같고, 클릭하면 오른쪽처럼 변하는 꽤나 그럴듯한 버튼이 생겼습니다.
그런데 폰트가 별로 맘에 들지 않아서, ChatGPT에게 어떤 폰트가 좋을지도 한 번 물어봤습니다.
나: What would be the best font for that button?
ChatGPT: 애플 스타일의 버튼이라면, 폰트의 가독성이 중요해. 애플은 UI에 San Francisco와 Helvetica Neue 처럼 깔끔하고 가독성있는 폰트를 주로 사용하지.
San Francisco는 애플이 MacOS와 iOS에 사용하려고 특별히 디자인한…(San Francisco 폰트에 대한 설명) Helvetica Neue는 유명한 san-serif 폰트로, 브랜딩과 그래픽 디자인에 널리 사용되는…(Helvetica Neue에 대한 설명)
버튼에 웹 폰트를 사용하려면 CSS에 font-family 속성을 추가하면 돼! Helvetica Neue가 사용 불가능할 경우를 대비해서, 아래처럼 예비 폰트를 여러개 지정할 수도 있어.
.apple-button {
font-family: 'Helvetica Neue', 'Arial', sans-serif;
}
저는 ChatGPT의 지시에 따라서 CSS에 위 속성을 추가해줬습니다. 하지만 Helvetica Neue 폰트를 사용할 수 없어서인지, 변화가 없었습니다. 그래서 곧바로 ChatGPT에 그 현상에 대해 질문했습니다. (그리고 일부러 주어로 It을 사용해봤습니다!)
나: It is not available. How can I use Helvetica Neue?
ChatGPT: 웹사이트를 보는 기기가 Helvetica Neue 폰트를 지원하지 않으면, 대신 웹 폰트를 사용할 수 있어. 웹 폰트는 웹페이지가 로드될 때 브라우저가 다운로드 할 수 있도록 웹서버에서 호스팅하는 폰트야. 이를 통해 사용자의 기기에서 지원하지 않는 커스텀 폰트를 사용할 수 있지!
Helvetica Neue 폰트의 웹 폰트를 사용하려면, HTML 문서의 head 태그 안에 아래처럼 link 엘레먼트를 넣으면 돼.
<link href="https://fonts.googleapis.com/css?family=Helvetica+Neue" rel="stylesheet">
ChatGPT는 정확하게 문제 해결 방법을 설명해줬습니다. 지시에 따라 link 엘레먼트를 추가하자 아래처럼 예쁜 폰트로 바뀌었습니다.
ChatGPT에게 애플 스타일 Form CSS를 요구하다
조금 더 복잡한 건 어떨까? 몇 개의 레이블과 입력칸, Submit 버튼으로 이뤄진 Form을 요청해봤습니다.
나: It’s cool. Let’s expand it to an Apple style form, with several labels, inputs and submit button.
ChatGPT: 좋아! 여기 몇 개의 레이블과 입력칸, Submit 버튼으로 이뤄진 애플 스타일 Form이야! 먼저 HTML!
<form>
<div class="form-group">
<label for="name">Name:</label>
<input type="text" class="form-control" id="name" placeholder="Enter your name">
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" class="form-control" id="email" placeholder="Enter your email">
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" class="form-control" id="password" placeholder="Enter your password">
</div>
<button type="submit" class="apple-button">Sign up</button>
</form>
ChatGPT: 그리고 여기 CSS!
.form-group {
margin-bottom: 16px;
}
label {
display: block;
font-size: 14px;
font-weight: bold;
color: #333;
}
input.form-control {
display: block;
width: 100%;
height: 36px;
padding: 6px 12px;
font-size: 14px;
line-height: 1.428571429;
color: #555;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
input.form-control:focus {
border-color: #66afe9;
outline: 0;
box-shadow: inset 0 1px 1px rgba(0,0,0,0.075), 0 0 8px rgba(102,175,233,0.6);
}
ChatGPT가 작성해준 HTML과 CSS를 사용해보니 아래같은 결과물이 나왔습니다. 이쯤 든 생각은, ‘이 녀석 나보다 낫구나.’
그런데 이 폼은 브라우저의 가로 너비를 가득 채우고 있어서 마음에 들지 않았습니다. 그래서 ChatGPT에게 추가 요구사항을 전달했습니다. “예쁘게 정렬된 컨테이너로 감싸줘. 반응형으로.”
나: I want it to be surrounded by a container, beautifully aligned and responsive.
ChatGPT: 폼을 예쁘게 정렬된 반응형 컨테이너로 감싸려면, CSS 그리드와 미디어 쿼리를 사용하면 돼. 어떻게 하는지 예를 보여줄게.
<div class="container">
<form>
<!-- form content goes here -->
<form>
</div>
.container {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-gap: 16px;
max-width: 960px;
margin: 0 auto;
padding: 16px;
}
form {
grid-column: span 12;
}
@media (max-width: 768px) {
.container {
grid-template-columns: repeat(6, 1fr);
}
}
ChatGPT: 이 CSS는 컨테이너를 12개의 동일한 너비의 컬럼으로 나누는 그리드 레이아웃을 사용해. Form은 12개 컬럼을 모두 차지하도록 되어있어. 컨테이너의 최대 너비는 960 픽셀이고 가운데 정렬했어.
마지막의 미디어 쿼리는 작은 화면에서 컨테이너의 레이아웃을 변경해. 더 조밀한 레이아웃을 위해서 6개 컬럼만 사용하도록 하지.
이 녀석은 새로 작성한 HTML 코드의 주석으로 이전에 보여줬던 코드가 어디에 들어가야할지도 적어줬고, 자신이 작성한 CSS 코드를 친절하게 설명까지 해줬습니다. 이쯤되면 제가 ChatGPT에게 명령을 하는게 아니라 과외를 받고 있다고 봐도 될 것 같습니다.
결과는 아래와 같았습니다. ChatGPT가 설명한 것처럼, 화면이 960 픽셀을 넘어가면 중앙에 정렬되었습니다.
재미가 붙은 저는 “그러면 Select 태그(드롭다운 메뉴)도 넣어보자.”라고 요청했습니다.
나: Let’s add some select tags
ChatGPT: 좋아! Form에 Select 태그를 넣으려면 이렇게 하면 돼.
<form>
<!-- form content goes here -->
<div class="form-group">
<label for="country">Country:</label>
<select class="form-control" id="country">
<option>United States</option>
<option>Canada</option>
<option>Mexico</option>
<option>Other</option>
</select>
</div>
</form>
ChatGPT: 이렇게 하면 국가를 선택할 수 있는 드롭다운 메뉴가 추가될거야. option 태그로 원하는 만큼 선택지를 추가할 수 있어. 그리고 아래는 CSS 코드야.
select.form-control {
display: block;
width: 100%;
height: 36px;
padding: 6px 12px;
font-size: 14px;
line-height: 1.428571429;
color: #555;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
}
select.form-control:focus {
border-color: #66afe9;
outline: 0;
box-shadow: inset 0 1px 1px rgba(0,0,0,0.075), 0 0 8px rgba(102,175,233,0.6);
}
결과는 아래처럼 잘 동작하는 드랍다운 메뉴가 생겼습니다.
길고 복잡한 요구사항도 알아들을까?
꽤 복잡한 요청은 어떨지 궁금해져서, 제 스스로 작문하기 어려울 정도의 요청을 해봤습니다.
“드롭다운 메뉴를 하나 더 만드는데, 다른 드롭다운 메뉴의 상태에 따라서 동적으로 선택지가 변경되었으면 좋겠어. 예를 들면, 추가된 드롭다운 메뉴는 국가를 선택하는 드롭다운 메뉴에서 선택한 국가에 따라 그 국가의 도시로 선택지가 바뀌는 거지.”
나: I want to add one more select tag to it, which is dynamically changing its options according to another select tag’s status. for example, added select tag changes its options with cities of the selected country by another select tag.
ChatGPT: 다른 드롭다운 메뉴 상태에 따라 변하는 동적 드롭다운 메뉴를 만들고 싶으면, 자바스크립트를 이용해서 첫 번째 드롭다운 메뉴의 변화를 감시하고(listen for changes) 그에 따라서 두 번째 드롭다운 메뉴의 선택지를 바꾸면 돼.
<form>
<!-- form content goes here -->
<div class="form-group">
<label for="country">Country:</label>
<select class="form-control" id="country">
<option>United States</option>
<option>Canada</option>
<option>Mexico</option>
<option>Other</option>
</select>
</div>
<div class="form-group">
<label for="city">City:</label>
<select class="form-control" id="city">
<!-- options will be added dynamically -->
</select>
</div>
</form>
const countrySelect = document.getElementById('country');
const citySelect = document.getElementById('city');
const cities = {
'United States': ['New York', 'Los Angeles', 'Chicago', 'Houston'],
'Canada': ['Toronto', 'Montreal', 'Vancouver', 'Ottawa'],
'Mexico': ['Mexico City', 'Guadalajara', 'Monterrey', 'Puebla'],
'Other': ['Other city 1', 'Other city 2', 'Other city 3']
};
countrySelect.addEventListener('change', (event) => {
const country = event.target.value;
const options = cities[country];
citySelect.innerHTML = '';
for (const option of options) {
const optionElement = document.createElement('option');
optionElement.value = option;
optionElement.textContent = option;
citySelect.appendChild(optionElement);
}
});
꽤 복잡한 요청이였는데도, ChatGPT는 알아서 Javascript를 이용하면 된다는 답을 내놓고 코드까지 작성해주었습니다. ChatGPT가 작성한 코드를 적용하니 아래와 같이 동적으로 선택지가 변경되는 드롭다운 메뉴가 생겼습니다.
그런데 페이지가 처음 로드되었을 때, 도시를 선택하는 드롭다운 메뉴가 비어있는 버그가 있어 이어서 질문해봤습니다.
나: There is a bug. select tag for city is empty when it’s first loaded even though default value of select tag for country is United states.
ChatGPT: 페이지가 처음 로드됐을때 비어있는 문제는, 페이지가 로드될 때 기본값을 추가해주면 돼.
const countrySelect = document.getElementById('country');
const citySelect = document.getElementById('city');
const cities = {
'United States': ['New York', 'Los Angeles', 'Chicago', 'Houston'],
'Canada': ['Toronto', 'Montreal', 'Vancouver', 'Ottawa'],
'Mexico': ['Mexico City', 'Guadalajara', 'Monterrey', 'Puebla'],
'Other': ['Other city 1', 'Other city 2', 'Other city 3']
};
const updateCityOptions = (country) => {
const options = cities[country];
citySelect.innerHTML = '';
for (const option of options) {
const optionElement = document.createElement('option');
optionElement.value = option;
optionElement.textContent = option;
citySelect.appendChild(optionElement);
}
}
countrySelect.addEventListener('change', (event) => {
const country = event.target.value;
updateCityOptions(country);
});
// Set the default value for the city select tag
updateCityOptions('United States');
버그는 정확히 해결됐습니다. 게다가 반복해서 사용되는 로직을 함수로 분리까지 해주었네요. 그런데 기본값이 ‘United States’로 하드코딩 되어있습니다. 코드 관리 관점에서 좋지 않으니까, 리팩토링을 요청해봅니다.
“그런데 나중에 국가를 선택하는 드롭다운 메뉴의 기본값이 변경되면? 미래에 코드를 변경하지 않아도 되도록 리팩토링하려면 어떻게 해?”
나: But what if the default value of select tag for country changes in the future? How can I refactor the code to prevent future change?
ChatGPT: 코드를 더 유연하고, 미래에 국가 드롭다운 메뉴의 기본값이 바뀌더라도 깨지지 않게 하려면 데이터 속성을 이용해 명시적으로 기본값을 지정해주면 돼.
<form>
<!-- form content goes here -->
<div class="form-group">
<label for="country">Country:</label>
<select class="form-control" id="country" data-default-value="United States">
<option>United States</option>
<option>Canada</option>
<option>Mexico</option>
<option>Other</option>
</select>
</div>
<div class="form-group">
<label for="city">City:</label>
<select class="form-control" id="city">
<!-- options will be added dynamically -->
</select>
</div>
</form>
// Set the default value for the city select tag
const DEFAULT_COUNTRY = countrySelect.getAttribute('data-default-value'); updateCityOptions(DEFAULT_COUNTRY);
요청대로 코드를 리팩토링 해줬습니다. data-default-value 속성을 통해 기본값을 명시적으로 선택하게 하고, Javascript 코드에서 해당 값을 불러와 설정해주도록 했네요. 하지만 이렇게 하면 data-default-value의 값을 Mexico로 바꾸더라도, 국가를 나타내는 드롭다운 메뉴의 기본값은 그대로 최상위 선택지인 United States로 나타납니다. 완벽하지는 않았군요!
ChatGPT에게 백엔드와 연동을 요구하다
마지막 요청으로, 국가에 따른 도시 리스트를 백엔드에서 동적으로 받아오려면 어떻게 해야하는지 질문해봤습니다. 지금은 클라이언트의 자바스크립트 코드에 하드코딩 되어있죠?
“도시 딕셔너리가 하드코딩 되어있네. 도시 리스트를 백엔드에서 받아온다면?”
나: the cities dictionary is hard-coded. What if we receive the list of cities from backend?
ChatGPT: 코드를 더 유연하고, 미래의 변경에도 깨지지 않게 하려면, 도시의 리스트를 Javascript 코드에 하드코딩 하는 대신 AJAX 요청으로 백엔드에서 받아오도록 할 수 있어. 아래는 ‘fetch’ 함수를 사용하는 예야.
const countrySelect = document.getElementById('country');
const citySelect = document.getElementById('city');
const updateCityOptions = (country) => {
fetch(/cities?country=${country})
.then((response) => response.json())
.then((cities) => {
citySelect.innerHTML = '';
for (const city of cities) {
const optionElement = document.createElement('option');
optionElement.value = city;
optionElement.textContent = city;
citySelect.appendChild(optionElement);
}
});
}
countrySelect.addEventListener('change', (event) => {
const country = event.target.value;
updateCityOptions(country);
});
// Set the default value for the city select tag
const DEFAULT_COUNTRY = countrySelect.getAttribute('data-default-value');
updateCityOptions(DEFAULT_COUNTRY);
이번에도 ChatGPT가 “AJAX 요청”이라는 새로운 개념을 소개하고, 예로 코드도 작성해주었습니다.
마치며
처음에는 ChatGPT가 마치 사람인 것처럼 그럴듯한 대답을 내놓는다는 것만으로도 놀라웠습니다. 그런데 더 사용해보니 코드도 작성해주고, 리팩토링도 해주고, 조언까지 해줍니다.😂
또 저는 영어가 모국어가 아닌지라 분명 간간이 어색한 표현과 틀린 문법이 있을텐데도 ChatGPT는 큰 문제없이 알아들었습니다.
더더욱 놀라운 것은 ChatGPT가 채팅처럼 진행되는 대화의 맥락(Context)을 이해한다는 점입니다. 예를 들면 처음에 애플 스타일의 버튼을 만들어달라고 한 뒤에, 다짜고짜 “That button”이라고 칭하면서 “그 버튼에는 어떤 폰트가 어울릴까?”라고만 물어도 ChatGPT는 “That button”이 방금 전에 자신이 작성한 버튼을 이야기한다는 것을 이해합니다. 그 뒤에 더 모호한 케이스로, “도시 리스트를 백엔드에서 받아온다면?” 하고 질문했는데, 이전 질문과 같은 맥락이라는 것을 이해하고 답변에 “코드를 더 유연하고, 미래에 변경에도 깨지지 않게 하려면…” 하고 직접적으로 언급해주기도 했습니다. 정말이지 놀랍군요!
저는 평소에 AI 분야에 큰 관심과 기대가 없었습니다. 그래서 “기술이 급속도로 발전하고있다.”, “인공지능이 일자리를 위협한다.”, “인공지능이 불러올 미래의 위협에 대비해야한다.”하는 이야기를 들으면 그냥 코웃음만 치고는 했었는데요. 이번에 ChatGPT를 직접 사용해보면서 “기술이 정말 많이 발전했구나. 빠르게 발전하고 있구나. 경이롭다!”하고 느꼈습니다.
ChatGPT에 사용된 GPT 3.5에 이어 GPT 4가 2023년 초에 출시될 가능성이 크다고 합니다. GPT 3가 출시된지가 2년을 넘었다고 하니 얼마나 더 발전했을지 기대가 되네요. 5년, 10년, 20년 후에는 도대체 어떤 미래가 펼쳐져 있을까요?
그리고 한 편으로는 검색엔진 개발자의 입장에서 ChatGPT와 같은 인공지능 챗봇이 곧 Google, NAVER 검색 같은 기존의 정보 검색 방식을 대체할 것 같다는 의견도 흥미롭습니다. 실제로 ChatGPT를 사용해보면서 ChatGPT의 답변이 잘 정리된 검색 결과같다고 느껴진 경우가 많았거든요.
제가 평소에 입버릇처럼 하는 말이 있는데, 오늘 주제와 잘 어울릴 것 같습니다.
“오래 살고 볼 일입니다.”
(언젠가 미래 기술로 정말 오~~래 살 수 있게 될지도 모릅니다)