Scalable Social Games, Robert Zubek of Zynga (liveblog)

Social games interesting from an engineering point of view sinc ethey live at the intersection of games and web. We spend time thinking about making games fun, making players want to come back. We know those engineering challenges, but the web introduces its own set, especially around users arriving somewhat unpredictably, effects where huge populations come in suddenly. SNSes are a great example of this, with spreading network effects and unpredictable traffi fluctuations.

At Zynga we have 65m daily players, 225m monthly. And usage can vary drastically — Roller Coaster Kingdom gained 1m DAUs in one weekend going from 700k to 1.7m. Another example, Fishville grow from 0 to 6m DAUs in one week. Huge scalability challenges. And finally, Farmville grew 25m DAUs in five months. The cliff is not as steep but the order of magnitude difference adds its own challenge.

Talk outline: Introducing game developers to best practices for web development. Maybe you come from consoles or mobile or whatever, the web world introduces its own set of challenges and also a whole set of solutions that are already developed that we steal, or, uh, learn from. :) If you are alreayd an experiened web developer, you may know this stuff already.

2 server approaches and two client approaches. So you get three major types.

1. Web server stack + HTML, Mafia Wars, Vampires, et
2. Web server stack + Flash, Farmville, Fishwville, Cafe world
3. Web + MMO stack + Flash, yoVille, Zynga Poker, Roller Coaster Kingdom

Web stack based on LAMP, logic in PHP, HTTP Comms. Very well understood protocol, limitations well known.

Mixed stack has game logic in MMO server such as Java, web stack for everything else. When web stack limitations are preventing the game development. Use web for the SNS pieces.

Fishville:

DB servers
–> web stack
Cache and queue servers

yoVille:

DB    >    MMO
Cache    >    Web & CDN

Why web stack? HTTP is very scalable, very short lived requests, scales very well, and easy to load balance. Each request is atomic. Stateless, easy to add more servers. But limitations esp for games: server-initiated actions (NPCs running around, if you come to lose, the monster reacts…) are hard to do over HTTP, since it is request/response. There are some tricks, like the long poll, but fundamentally this makes it harder to scale. Load balancers will get unhappy with you, you can saturate a connection.

The other thing is storing state between requests. This is more particular to game dev than web. Say you areplaying Farmville and collecting apples. You do a bunch of actions which result in many different requests to the servers, but we want to make sure that only the first click gives you an apple, so you cannot click a dozen times on one tree. Whih means stored state and validation. If you had clients talking to many web servers, you cannot use the DB< the poor thing will fall over. If we can guaratee that the client only talks to one web server, you can store it there, and save to db later. But this is tricky to do. Ensuring that people are no allowed to break session affinity even in the presence of maliious clients and browsers… hard.

So instead, you can wrap th DB servers in a caching layer that is faster that does not hit the DB all the time, such as Network Attached Caching. This works much better.

MMO servers… minimally MMO. Persistent socket connection per lient, live game support such as chat and server side push. Keeps game state in memory. We know when a player logs in and load from DB then… session affinity by default. Very different from web! We can’t do the easy load balancing like on web.

Why do them? They are harder to scale out because of load balaning. But you get stuff like the server side push, live events, lots of game state.

Diagram:

DB servers, maybe less caching wrapping it — talks to both web server and MMO server, then those both talk to client.

On the client side, things are simpler.

Flash allows high prodution quality games, game logic on client, can keep open socket. You can talk any protocol you want.

HTML+AJAX  the game is “just” a web page, minimal system reqs, and limited graphics.

SNS integration. “Easy” but not relate dto scaling. Call the host network to get friends, etc. You do run into lateny and scaling problems, as you grow larger you need to build your infrastructure so it can support gradeful performane degradation in the face of network issues. Networks provide REST APIs and sometimes client libraries.

Architectures:

Data is shared across all three of these: database, cache, etc.

Part II: Scaling solutions

aka not blowing up as you grow.

Two approaches: scaling up or scaling out.

up means that as you hit processor or IO limits, you get a better box.
out means that you add more boxes

The difference is largely architectural. When scaling up, you do not need to change code or design. But to scale out you need an architecture that works that way. Zynga chooses scaling out, huge win for us. At some point you cannot get a box big enough fast enough. Must easier to add small boxes, but you need the app to have architectural support for it.

Rollercoaster Kingdom gained a lot of players quickly. We started with one database, 500k DAUs in a week. Bottlenecked. Short term scaled up but switched to scaling out next.

Databases, very exciting. The first to fall over. Several ways to scale them. Terms unique to mySQL here but concepts the same for other systems:

Everyone starts out with one database, which is great. But you need to keep track of two things -  the limit on queries per second, do benchmarking using standard tools like SuperSmack. You want to know your q/s ceiling, and beyon that how will it perform. There are optimizations you can use to move it. And two, you need to know the player’s query profile in terms of inserts, selets, updates, and average profile per second. It might trail your DAU number, which is nice because then you can project q/s and know when you will reach capacity.

If your app grows then you will need to scale out.

Approach one, replicating data to read only slaves. Works well for blogs and web properties but hnot games, because games have a higher modification profile so your master is still a bottleneck. But useful for redundancy.

Approach two, multiple master. Better because of split writes, but now you have consistency resolution problems, which can be dealt with but increases CPU load.

Approach three and best and push the logic for resolution up to the app layer, a standard sharding approach. The app knows which data goes to which DB.

Partition data two ways”:

vertical by table, whih is easy but does not scale with DAUs. MOve players to a different box from items.

horizontal by row. Harder to do but gives best results. Different rows on different DBs, need good mapping from row to DB. Stripe rows across different boxes. Primary key modulo # of DBs. Do it on an immutable property of the row.  A logical RAID 0. Nice side eeffect to increase capacity… to sale out a shard, you add read only slaves, sync them, then shut down, cut replication, and hook it back up. Instant double capacity.

More clever schemes exist. Interaction layers which check where to go… but the nice thing about this is how straightforward it is.  No automatic replications, no magic, robust and easy to maintain.

YoVille: partiioning both ways, lots of joins had to be broken. Data patterns had to be redesigned, with sharding you need the shard id per query. Data replication had trouble catching up with high violume usage. In sharded world  cannot do joins across shards easily, there are solutions but they are expensive. Instead, do multiple selects or denormalize your data. Say a catalog of items and inventory, and you watch to match them. If catalog is small enough, just keep it in memory.

Skip transactions and foreign key constraints. Easier to push this to the app layer. The more you keep in RAM the less you will need to do this.

Caching.

If we don’t have to talk to the DB, let’s skip it. Spend memory to buy speed. Most popular right now is memache, network attached ram cache. Not just for caching queries but storing shared game state as well, such as the apple picking example. Stores simple key value pairs. Put structured game data there, and mutexes for actions across servers. Caveat: it is an LRU (least recently used) cache, not a DB. There is no persistence! If you put too much data in it, it will start dropping old values, so you need to make sure you have written the data to DB>

bc it is so foundational, you can shard it just like the DB. Different keys on different servers, or shard it veritcally or horizontally.

Game servers.

Web server part is very well known. Load-balance. Preferred approach is to load balance with a proxy first. This is nice from a security standpoint… but it i a single point of failure, capacity limits since the proxy will have a max # of connections.

If you hit those limits you load balance the load balancers… and using DNS load balancing in front of it. It doesn’t matter if dns propagation takes a while.

The other thing that is useful is redirecting media traffic away from media servers… swfs are big, audio is big, do not serve from the same place as game comms. You will spend all yor capaity on media files. Push it through a CDN, and if you are on the cloud already you can store them there instead. CDN makes it fast, sine the assets are close to the users. Another possibility is to use lightweight web servers that only server media files. But essentially, you want big server bank to only talk game data, not serve files. Seevral orders of magnitude performance by doing this.

MMO servers, the unusual part of the setup! Scaling is easiest when servers do not need to talk to each other. DBs can shard, memcache an shard, web can load balance farms, and MMOs? well, our approach is to shard like other servers.

Remove ny knowledge they have about each other and push complexity up or down. Moving it up means load balancing it somehow. Minimize interserver comms, all participants in a live event should be on the same server. Scaling out means no direct sharing — sharing thru third parties is OK, a separate service for that event traffic.

Do not let players choose their connections. Poor man’s load balancing, is a server gets hot remove it from the LB pool, if enough servers get hot, add more instances and send new connections there. Not quite true load balancing which limits scalability.

In deployment, downtime = lost revenues. In web just copy over PHP files. Socket servers are harder. How to deploy with zero downtime? Ideally you set up shadow new servers and slowly transition players over. This can be difficult — versioning issues.

For this reason, this is all harder than web servers.

Capacity planning.

We believe in scaling out, but demand can change fast.how to provision enough servers?  Different logistics. Do you provision physical servers or go to the cloud? If you have your own machines, you have more choice and controll and higher fixed costs. With cloud lower costs, faster provisioning, canot control CPU, virtualized IO, etc. On cloud easier to scale out than up.

For a legion of servers you need a custom dashboard for health, Munin for server monitoring graphs, and Nagios for alerts. First level for drilldown is graphs for every server family separately so you can isolate it to a given layer in the system. Once you know memache usage spiked, then you can drill down to particular machines…

Nagios… SMS alerts for server load, CPU load exeeds 4, test account fails to connect after 3 retries.

Put alerts on business stats too! DAUs dropping belo daily average for example. Sometimes they react faster than server stats.

If you are deployed in cloud, network problems are more common. Dropping off net or restarting is common. Be defensive, Reduce single points of failure, program defensively. This includes on the game side.

Q&A:

q: why mySQL? Other DBs are better for scaling.
a: there are other DBs that have been around longer, have greater community, but we don’t use the features those large DBs do. Looking back at the sharding slides — we don’t do a lot of even things like transactions. Easier to move that complexity to the app layer. Once you are on that path, it is a good solution.

q: did you benchmark, that sort of thing, for the different DBs?
a: yes, of course.

q: and for data integrity, if you threw foreign key constraints, that sounds scary! Is it kind of a nightmare?
a: No, not too bad at all, actually. Esp if you do not hit the DB all the time, you ind you don’t get into those dangerous situations as often.

q: is the task when you add more tables… is it as complex?
a: not too bad, has worke well.

q: assuming browsers pick it up, are you guys looking into webGL?
a: many technologies interesting, 3d in browser, silverlight. I would be interested in using them personally… once they achieve high market penetration.

q: why flash?
a: everyone has it. Very pragmatic approach.

q: Do you back up dbs?
a: of course

q: and how?
a: onc eyou go with cloud and amazon, you have to use that approach…  we have a number of redundant backups solutions.

q: I guess many joins are across friends… they have to tlak to multiple shards. Do you try to put friends on same shard?
a: no, everyone has different friends.

q: on SNS integration, did you run into issues with PHO not supporting asynh, with delays from answers from the SNS, running out of threads?
a: you will encounter delay with SNS comms, just part of the overall insfrastruture, could be anytihng, not just PHP. You have to program around it, have to find good solutions for dealing with it when it happens bc it will.

q: So you don’t switch from PHP, delay the process?
a: we did encounter a number of places where we had to dig deep into PHP in order to make it work well on that scale.

q: did you patch PHP?
a: we, uh… yes.

q: what are you feeling on tools like the no SQL sort of thing
a: we look into those atively, one the tech matures, it will be a very good candidate fot this sort of thing. But not currently implemented.

q: on sharding, you said use modulo to distrbute load. Once you have found a bottleneck, howdo you prepare the data to be moved from one shard to another.
a: You don’t move people between shards. You just copy a shard to two machine, and both have redundant, and then remove the redundant data.

q: on partitioning, partitioning to two tables. Say item trading that goes across two DBs, transactions may break? Changing ownership on two different dbs?
a: you need to do a guarantee across multiple DBs, putting the data in a memcache layer, locking it, then doing the write, or putting it in the app layre, implementing”transactions lite”

q: being on the cloud did you have to not use a service approach and have each PHP layer write direct to the DB instead of use a service layer? Say an MMO, achievments or presence services. Do you keep the servie layer as a web servie, or write direct to the DB? Your service call time can add time… even on the cloud.
a: Yes, you want this to be nicely modular… we end up not putting it on different machines. Same box as the game logic so there is no network traffic, so there is no separate layer between. So modular, but not in terms of network topology.

Posted by 솔라리스™
:

Fantasy Bet Eleven is a live sports prediction game where real statistics from star player of the EPL are reflected in the fantasy team that you create in real time!

( http://www.facebook.com/FantasyBET11?v=wall )

Posted by 솔라리스™
:

오랫만에 아고라에 글을 올리려니 좀 서먹서먹하군요.

제목이 조금 쌩뚱맞기도 하고 왠지 어색해보이시죠?

 

공감이 가실려는지 모르겠습니다만,

며칠전 진수희 보건복지부 장관님의 담배값 인상에 관한 한국일보와의 인터뷰 기사를 보고나서

한마디 하고 싶었던 것을 아고라에 올려봅니다.

 

담배값 인상에 관한 이야기가 끊임없이 흘러나왔었죠? 담배값 인상에 대한 근거는 국민건강을

위해서 흡연율을 줄여야한다는 것이었고요. 보건복지부의 발표에 따르자면... 담배값이 어느 정도

인상되어야 금연을 하겠느냐는 설문조사에서 8천원 수준이라는 응답이 제일 많았다나요?

보건복지부 장관님께선 이 내용을 근거로 향후 3년간인가? 암튼 담배값을 5천원까지 인상해서

흡연률을 낮추겠다고 그랬었습니다. 그리고 올해나 내년쯤에는 담배값을 한갑당 천원씩 인상하는

방안을 추진중이라고 하는군요.

 

진수희 보건복지부 장관의 말을 빌리자면 담배값 인상의 구체적인 내역은 이러합니다.

현재 담배값에는 건강증진부담금.지방세.지방교육세 등이 포함되어서 총 1549.77원이 세금으로

부과되고 있는데, 이가운데 복지부가 관장하는 국민건강증진법을 개정해서 건강증진부담금을

올리겠다는 것입니다. 특히 진수희 장관은 담배가 주변사람의 건강을 해치기 때문에 개선해야

 한다고 주장을 하고 있으며.... 

 

그러다가 지난 11월 초에는 김황식 총리나 윤증현 내무부장관이 "연내에 담배값 인상 계획은 없다"

라고 청문회를 통해서 발표를 했더군요. 아마도 연내에 인상을 시키기엔 정치적 부담감이 크겠다는

계산을 한것으로 보입니다. 어쨌거나, 연내든 내년이든 인상은 시간상의 문제라는 생각이 드는군요.

그런데 위의 기사 내용들을 살펴보다가 저는 몇가지 의문점이 생겼습니다.

 

그 첫번째 의문점은... 

국민건강을 해치는 원인이며, 주변인들의 건강까지 해치기 때문에, 라는 심각한 문제의식을

보건복지부가 가지고 있었다면, 대체 공기업인 K&T한국담배인삼공사의 존재는 무엇이라는 말이죠? 

그토록 심각하게 국민 건강을 해쳐가면서까지 담배인삼공사의 이윤과 그것을 통한 세금의 확보가

필요한가요? 국가가 주체가 되어서 국민건강권을 담보로 잡아가면서까지 이윤과 세금을

충당해야만 합니까?

 

마약이 해로우니 마약가격을 올려서 마약을 못하게 하자는게 맞습니까? 마약을 제조하는

업자들을 발본색원해서 뿌리를 뽑는게 맞겠습니까?

 

그 두번째 의문점은...

담배값에 부과되고 있다는 1549.77원의 세금말입니다. 건강증진부담금.지방세.지방교육세등을

포함해 1549.77원이라는데요, 저는 보건복지부가 그토록 심각하게 흡연으로 인한 국민건강의

파괴를 걱정했다면, 그 1549.77원의 아주 일부라도, 금연을 유도하기 위한 사회적 투자에

썼어야 했던것 아니었느냐고 생각합니다.

 

담배한갑에 2500원 기준잡고, 1546.77원이 세금이니... 이 세금을 제외하면, 흡연자들은 1000원짜리

상품을 1500원 가량의 엄청난 세금을 물어가면서 국가가 생산하는 담배라는 상품을 소비해주는것

아니겠습니까? 대체 흡연자들에게서 걷어간 그 엄청난 세금이 흡연률을 낮추기 위해서 쓰여진적이

있습니까? 하다 못해서 보건소에 무료금연클리닉 한번 설치해준적 있습니까?

아니, 흡연자들은 그렇다 칩시다. 주변에까지 심각한 피해를 주는 것이 그렇게 걱정되었으면, 거의

대부분의 지역을 금역 구역으로 정해서 벌금 걷어가는것에만 열중할것이 아니라, 하다못해 환시시설

까지는 필요 없이 그냥 조그마한 흡연부츠라도 지어준 일이 있습니까? 

 

아니요?

천만에요...

진짜 더 웃기고 골때리는것은, 올해 금연 켐페인 관련 예산이 삭감이 아니라, 아예 삭제되었다는

사실입니다. 웃기지 않습니까? 이래놓고서...국가가 주체가 되어서 국민건강을 심각하게 위협하는

그토록 위험한 상품을 만들어서 팔고, 그 이익은 국가가 다 가져가고, 흡연으로 인한 폐해가 심각하니

담배값을 왕창 올려서 그 폐해를 줄이자? 그냥 하도 가소롭고 어이없어서 웃고맙니다.

  

담배는 몸에 해로운것은 분명 맞습니다. 그리고 주변에까지 피해를 주는것도 사실입니다.

저도 흡연을 하지만, 버스정류장 같은 사람 많은데서 담배연기 뿜어대는 사람이 있으면... 나이의 고하를

막론하고 금연 구역임을 상기시켜줍니다. 하지만 조금만 더 깊이 생각해봅시다.

본드나 환각제를 흡입하는 청소년들이 매해 늘어나고 사회적으로 문제가 되고 있습니다.

본드나 환각제 가격을 올려서 이런 문제를 해결할 것입니까?

 

이래놓고서 항상 흡연자와 비흡연자들의 대립적인 갈등 상황으로 몰아갑니다.  

장기적으로 흡연률을 낮추고 금연을 유도해야 한다는 주장에는 반론의 여지가 없습니다.

그러나 금연을 유도하는 방식에 있어서, "대폭적인 가격인상"이 대안이라는 주장에는 반대하고 싶습니다.

그 이전에 국가가 주체가 되어서 국민건강을 해치는 산업을 벌이고 있다는 그 자체가 우스운 일이니까요.

 

그리고 한국이 타 국가들에 비해서 담배값이 턱없이 낮고... 때문에 흡연자들이 늘어난다.. 라는 주장을

하실려거든... 담배값이 높은 국가들의 담배값에서 차지하는 원자재 가격의 비율을 따져보셔야합니다.

미국의 경우 담배값에서 차지하는 원자재(잎담배)등등의 비율이 50%에 육박합니다.   

(국가가 국민들의 금연을 책임져 드리겠습니다)

이런 정책 내는 사람있으면 그사람에 올인할겁니다.

.

.

.

.

.

.

자 여기까지는 제 주장이고요

다음은 한국일보 월요 인터뷰에서의 진수희 보건복지부 장관님의 말씀을 들어보도록 하겠습니다.

 

"욕을 먹더라도 내년에 담뱃값 인상을 추진할 생각이에요. 가격은 8,000원 정도면 금연 효과가 있지

않을까 싶습니다." 7일로 취임 100일을 맞는 진수희 보건복지부 장관이 '담배와의 전쟁'을 선포했다.

담배는 술보다 휠씬 더 해로운 것이며, 특히 어른들의 흡연을 보고 배운 아이들이 성인이 되면 담배로

인한 질환에 걸릴 위험성이 높고, 건강보험 적자구조의 핵심 원인이 될 가능성이 높다는 판단에서다.

진 장관은 금연을 보건 분야의 최우선 가치로 여기는 듯했다.

_담뱃값은 어느 정도가 합당하다고 보는지요.

"여러 연구를 보면, 소비자들이 금방 적응할 수준으로 가격을 올리는 것은 효과가 없어요.

1,000~2,000원 인상은 물가 인상만 부추기는 수준입니다. 얼마전 질병관리본부가 시뮬레이션해 본 결과,

8,000원 인상 정도면 효과가 나타난다고 나왔습니다.

그 정도면 지금의 세 배 이상인데 2012년 담배규제기본협약 총회 이전에 흡연율 추이에 의미있는 변화가

있지 않을까 싶어요."(2009년 현재 우리나라 흡연율은 47.7%다. (OECD) 국가 평균 28.3%를 20%포인트

가까이 웃도는 수준이다)

 

_흡연자들은 담뱃값 인상 자체도 불만이지만 가격 인상으로 늘어나는 세금이 건강보험

 적자 보전  등 금연 이외 사업에 쓰이는 것을 문제삼고 있어요.

"옳은 지적이라고 봐요. 가격인상으로 늘어난 세원은 금연 관련 분야에 전액 쓰는 게 맞다고 봅니다.

실제로 흡연자들을 위해 사용하는 것이 장기적으로 건강보험 재정악화를 막는 한 방법이기 때문입니다.

하지만 늘어난 세금 전체를 금연 관련 사업에 모두 투입할 수 없는 만큼, 실제 인상시 사용처에 대해선

좀더 논의가 필요합니다."
.

.

.

.

진수희 보건복지부 장관님... 마지막 부분에 대해서  질문좀 드릴게요.

(실제로 흡연자들을 위해 사용하는 것이 장기적으로 건강보험 재정악화를 막는 한 방법이기 때문입니다.

하지만 늘어난 세금 전체를 금연 관련 사업에 모두 투입할 수 없는 만큼, 실제 인상시 사용처에 대해선 좀

더 논의가 필요합니다.)라고 말씀 하셨는데요...

 

뭔가 착각하고 있으신거 아니심?

앞으로 인상될 부분에 대한 불만 뿐만 아니라요... 이전에 흡연자들에게 걷어간 막대한 세금이 흡연자들을

위해서 쓰여졌었는가를 묻는거에요. 아니나 다를까... 앞으로 늘어날 세금 또한 금연관련 사업에 모두 투입

할수는 없다고요? 뭥미?  순전히 국민건강권을 걱정해서 담배값 인상하신다면서요? 

앞에서는 (가격인상으로 늘어난 세원은 금연 관련분야에 전액 사용하는게 맞아요) 라고 말하시고선...

바로 그 뒤에선, (늘어난 세금 전체를 금연 사업에 쓸수는 없는 만큼, 사용처에 대해서는 좀더 논의가

필요합니다)라굽쇼?

논리도 없고 근거도 없고 재미도 없고 감동도 없고... 지금 말장난 하심미까?

 

진수희 보건복지부 장관님... 국민건강권 개드립 그만 치시고요...

사실은 세금이 졸라 부족해서 올려야겠다고 솔직하게 말씀하세요.  

http://bbs3.agora.media.daum.net/gaia/do/story/read?bbsId=K161&articleId=211899
Posted by 솔라리스™
:



 

올해 7월. 저는 뉴욕에 있었습니다. 100일간의 미국 렌터카 여행이라는 이유로 말이죠.

제 사랑하는 그녀는 그래서 100일간 저와 생이별을 해야 했었습니다. 그렇기에 미안한 마음을 항상 가지고 있었습니다. 2년 가까이 만나온 그녀와 꼭 결혼을 하고 싶었고, 그래서 여행 도중에 프로포즈를 위한 준비를 준비하게 되었습니다. 처음에는 어떤 프러포즈를 할 까 할까 고민이 참 많았습니다. 촛불을 켜고 그 안에 '사랑해' 라고 적는 것에서부터, 레스토랑에서 식사를 하고 반지를 건네주는 특별한 이벤트들을 가장 많이 하더군요.

하지만, 제 그녀에게는 조금 더 기억될만한 저만 할 수 있는 특별한 프러포즈가 하고 싶었습니다.

제 사랑하는 사람은 사람들 앞에서 다같이 축하받는 것 보다는 단둘이 있는 시간을 즐기는 사람이기에, 명동 한복판에서 화려하게 하는 프로포즈보다는 조금 더 조용한 곳에서 할 수 있는 특별한 프로포즈를 준비했습니다. 그렇게, 인터넷에서 결혼한 친구를 위해 사람들에게 화이트보드에 메세지를 적는 영상을 본 것에서 아이디어를 얻어, 뉴욕에서 만난 사람들에게 "프로포즈를 위한 메세지"를 100개를 얻는 프로젝트를 준비했습니다.


프로포즈를 위한 계획을 준비하기 위해서 가장 먼저 찾아간 곳은 뉴욕에 있는 스테이플스였습니다. 오피스 물품들을 판매하는 곳이지요. 이곳에서는 프로포즈를 준비하는데 있어서 필요한 물건들을 구입할 수 있었습니다.


다양한 화이트보드(Dry-erase board)가 있었는데, 그 중에서..


딱 적당해 보이는 11x17인치의 화이트보드를 구입했습니다. 사람들이 한 손으로 들고 부담없이 쓸 수 있어야 하고, 사진으로 찍었을 때 사람들과의 비율이 잘 맞는 녀석이 필요했기 때문이었지요.


그리고 마지막으로 화이트보드에 사용할 펜과 지울 수 있는 지우개를 산 뒤에 준비물을 준비하는 과정을 마쳤습니다. 사실, 이렇게 화이트보드와 펜을 준비하는 과정까지는 사실 어렵지 않았습니다. 그냥 가서 구입하기만 하면 되는것이었죠. 화이트보드와 펜, 그리고 지우개를 구입한 비용은 $25(3만원) 정도였으니.. 나름대로 준비한 큰 프로포즈를 위한 준비물 치고는 참 싼 편이었지요.





원래 처음의 프로포즈 컨셉은 '뉴욕에서 만난 100인과 함께하는 프로포즈'였습니다. 하지만, 실제 한장의 사진에 한명만 들어가는 것이 아니라서, 100장의 사진과 함께하는 프로포즈로 약간 방향을 틀었습니다. 길에서 만난 연인들에게 묻기도 하고, 뉴욕의 경찰 NYPD, 도미노피자의 직원, 호텔 컨시어지 직원, 뉴욕에 관광온 관광객, 홍보를 하는 사람, 가판대 상인, 거리공연을 하는 사람들.. 정말 많은 사람들을 만났습니다.

사실, 처음에는 화이트보드를 들고 사람들에게 이런 질문을 한다는 것이 정말 쑥스럽고 어려운 일이었습니다. 사랑하는 사람을 위해서 하는 일이라지만, 처음보는 사람들을 대한다는 것이 그렇게 쉬운 일은 아니었기 때문이지요. 그래서 자신감이 조금 없었나 봅니다. 화이트보드를 들고서 다가가면 사람들이 처음부터 거절하기 십상이었습니다. 아, 이거.. 정말 어려운건가? 하는 생각이 들었죠.

하지만, 첫번째로 메세지를 써 준 커플 이후에 자신감이 붙었습니다. 그리고 나서 사람들에게 어떤식으로 말을 건네야 할지도 알게 되었고, 나중에는 10명 중 8~9명의 사람들이 혼쾌히 메세지를 써 주셨습니다. 정말 감사할 따름이지요. 메세지는 어느나라 언어이건, 어느 내용이건 상관없었습니다. 그녀를 위한 메세지면 모두 다 가능했어요.



덕분에 메세지에는 영어, 불어, 독어, 스페인어, 아이슬란드어 등 다양한 나라의 언어로 메세지가 적히기도 했습니다. 메세지를 적은 후에는 양해를 얻은 다음에 이렇게 사진을 한장씩 찍었습니다. 한장을 찍는데에도 5~10분 가까이 소요되는데다가, 한 곳에서 모든 사진을 찍는 것이 아니라 다양한 장소에서 찍으려고 하다보니 100장의 사진을 모두 찍는데는 일이라는 시간이 걸렸습니다.

뉴욕의 타임스퀘어, 센트럴파크, 메트로폴리탄박물관, 구겐하임미술관, 소호거리, 자유의여신상, 그랜드센트럴역 등 다양한 곳에서 수많은 사람들과 이야기를 했습니다. 그들이 글과 함께 남겨준 축하의 말들.. 그 한마디 한마디가 너무 고마웠고 감사했습니다. 지금 그 분들에게 돌려드릴 것은 없지만, 메세지를 쓰고, 사진을 사용할 수 있게 허락해주신 것에 대해 너무 큰 감사의 말씀을 드리고 싶습니다.

그리고.. 그렇게 찍은.. 100장의 사진들..

그 일부는 아래에서 보실 수 있습니다.




# 아이슬란드 친구들


# 한마디가 강렬했던 그녀


# 공원에서 만났던 커플


# 오히려 더 기뻐해줬던 그녀들


# 결혼은 아름다운 것이라며, 포즈를 취해주던 멋진 커플


# 지금이 가장 소중한 시간이라던, W의 직원


# 너무 잘 어울렸던 프랑스 커플


# 타임스퀘어로부터의 메세지


# 러시아에서 뉴욕에 놀러왔던 친구들


# 뉴욕 경찰의 메세지


# 가장 반응이 폭발적이었던 6인의 여성들


# 저, 귀여운 사람일까요? ^^


# 전, 사랑스러운 남자가 되고 싶어요.


# 이런 친구들도 혼쾌히 도와 줬습니다 ^^


# 레스토랑의 직원분도..


# 뉴욕의 스파이더맨도 프로포즈를 도와주셨습니다.


# 그랜드 하얏트 호텔의 컨시어지 분들


# 센트럴파크에서 공연하던 커플


# 특히나 아름다웠던 미소의 커플


# 자유의 여신상의 레인저


# 5분만 시간을 달라던 커플


# 아이들도 저의 프로포즈의 성공을 빌어 줬습니다.

.
.
.
.
.


그리고, 대망의 프로포즈의 시간.

11월 18일.

장소 물색이 필요했습니다.



조용히 단둘이 있을 수 있는 곳에서 갤러리처럼 방안에 전시를 할 수 있는 곳이 필요했는데 그런 곳을 찾기가 힘들었습니다. 카페에 사진 전시를 하려면 다른 사람들에게 방해가 되고, 펜션에서 하려고 했지만 방을 갤러리처럼 사용할 수 있는 공간을 가진 곳들이 거의 없더라구요. 그래서 정말 많은 곳을 찾아다니다가, 사진에서 정말 적합할 것 같은 공간을 발견했습니다.

W호텔의 스튜디오 스위트룸. 방의 크기도 크기였지만, 긴 하얀색의 벽이 사진만을 부각시켜줄 수 있을 것 같았습니다. 그리고 100장을 전시할만큼 넓은 공간이 있었던 것도 이곳을 선택한 가장 큰 이유였지요. 


그리고, 침대 앞에 있는 커다란 TV 역시 만들어 놓은 영상을 보여주면서, 고백 멘트를 하기에 최고의 환경이었습니다. 다만, 가장 큰 문제는 스위트룸이라는 것과 대여 비용이었습니다. 일반적으로 1박에 50만원이 넘어가는 방이었기에 그냥 빌리기가 쉽지 않았기 때문이었지요.


다행히도 스타우드 호텔 체인의 플래티넘 회원이었기 때문에, 일반룸으로 예약을 하고 나서, 호텔의 컨시어지에 연락해서 그날 프로포즈를 할 예정이니 업그레이드를 해 줄 수 있냐고 부탁을 했습니다. 플래티넘 회원이고, 특별한 날이라 하니 미리 업그레이드를 받을 수 있었습니다. 최상층인 14층의 스위트룸을 말이죠. 보통 업그레이드는 사전에 해 주지 않지만, 특별히 배려를 해 주셔서 너무 감사했습니다.


사진은 15x10 인치, 12x8인치 그리고 4x6인치로 다양하게 준비했습니다. 대형인화가 그렇게 비싼지 몰랐는데, 다양한 사이즈를 섞어서 인화를 하고 나니 인화비용이 꽤 들었습니다.그 중 90% 비용은 대형인화 비용. 하지만, 작은 사진만으로는 아무래도 바로 알아보기 힘들기 때문에 큰 사진들을 선택했습니다.

프로포즈 당일날은 저희의 2주년 기념일이었습니다. 그녀에게는 미리 낮에는 일이 있어서 어쩔 수 없이 못보고, 저녁이나 같이 좋은 곳에서 먹자고 말을 해 놓았습니다. 여자친구가 구리에 살고 있다가 남양주로 이사를 갔는데, W호텔은 가까운 장점 때문에 이전에도 기념일에 식사를 하러 갔던 곳이라 이곳에 약속을 잡아도 그리 어색하지 않았습니다.

그리고, 저는 일을 한다는 핑계를 대 놓고는 미리 호텔에 가서 체크인을 하고, 방을 꾸미는 사전 작업을 했습니다. 풍선이나 초는 없지만, 그녀를 위한 메세지가 가득한 사진들을 방안 가득히 전시하는 것이 제가 해야 할 일이었지요.


둥그런 모양의 빨간색 침대 위에는 사진으로 하트 모양을 만들고..





하얀색의 긴 벽에는 100장의 사진들을 하나하나 전시해 놓았습니다. 들어와서 불을 켜고 봤을 때이질적이지 않으면서, 한번 다시 보면 그 메세지를 읽게 되는 것이 계획이었는데 생각대로 잘 진행되었습니다. 조금은 단순한 배열이었을지 모르지만, 사진의 장수가 워낙 많았던지라 더 이상의 배열을 생각할 수 없더군요. 사실, 제 디자인 센스 부족이기도 하고 ㅠㅠ




그리고, 벽 이외에도 호텔 곳곳에서 사진들을 발견할 수 있도록 배치를 해 놓았습니다. 욕조 위라거나, 침대 뒤 스피커, 책상위 책꽃이 등등 많은 장소에 사진들을 배분해 놓았습니다. 한 곳에서만 모든 사진이 모여 있으면 아무래도 심심한 감이 있기 때문이었지요. 호텔의 자체 인테리어에는 손을 댈 수 없었기 때문에 사진은 모두 기울여서 벽에 걸쳐놓는 방법을 이용했습니다.


그리고, 마지막으로 커다란 TV에 연결해서 동영상을 출력할 준비를 함으로써 이날의 프로포즈 준비를 마쳤습니다. 원래는 TV에 USB만 꽃으면 될 줄 알았는데, USB가 없는 모델이라 작은 MID를 이용해서 S-video로 출력할 수 있었던 것이 다행이었습니다.


그리고, 저는 약속시간에 로비로 내려가서 레스토랑에서 그녀와 태연하게 식사를 했습니다. 그냥 별다른 준비가 없는 평범한 2주념 기념일인 것 처럼요. 그리고, 그녀를 제가 모든 프로포즈를 준비해 놓은 호텔 방으로 데리고 갔습니다. 왜 방으로 올라가려고 하는지에 대해서 의문이 생길 수 있기에 작은 이벤트를 준비했다는 이야기만 살짝 언급을 했었습니다.

그리고, 방으로 올라가서 불을 켜고.. 주위의 사진들이 보이니 어리둥절한 눈치였습니다. '원래 있었던 인테리어 인줄 알았어요.' 라는 말이 나올 정도로 어쩌면 제가 준비한 것이 잘 어울렸나 봅니다. 그리고, 저는 그녀의 손을 잡고 침대에 앉아 TV를 켜고 준비해놓았던 영상을 보여줬습니다. 영상을 잘 만들지 못해 이틀간 낑낑댄 것이긴 하지만, 그래도 만들고 나니 뿌듯한 영상이었어요.






그리고 말했습니다.

"이 장미 꽃들이 모두 시들때까지, 사랑할게요.
 저와 결혼해 주시겠어요?"

21송이의 장미 중 한송이는 조화였습니다. 앞으로 시들일이 없는.. 제게 있어서는 "영원히 사랑할게요."란 의미였습니다.

.
.
.
.

어쩌면, 프로포즈 반지도 없는 시시한 프로포즈였을지도 모릅니다.
하지만, 제가 준비할 수 있었던 최고의 마음이었고,
저를 도와준 뉴욕의 수많은 사람들의 마음이었습니다.

그리고,

그녀는 "네"라고 말해주었습니다.



Posted by 솔라리스™
:

올바른 영어 표기법

ㄱ 가 ga

각 gak

간 gan

갈 gal

감 gam

갑 gap

갓 gat

강 gang

개 gae

객 gaek

거 geo

건 geon

걸 geol

검 geom

겁 geop

게 ge

겨 gyeo

격 gyeok

견 gyeon

결 gyeol

겸 gyeom

겹 gyeop

경 gyeong

계 gye

고 go

곡 gok

곤 gon

골 gol

곳 got

공 gong

곶 got

과 gwa

곽 gwak

관 gwan

괄 gwal

광 gwang

괘 gwae

괴 goe

굉 goeng

교 gyo

구 gu

국 guk

군 gun

굴 gul

굿 gut

궁 gung

권 gwon

궐 gwol

귀 gwi

규 gyu

균 gyun

귤 gyul

그 geu

극 geuk

근 geun

글 geul

금 geum

급 geup

긍 geung

기 gi

긴 gin

길 gil

김 gim

까 kka

깨 kkae

꼬 kko

꼭 kkok

꽃 kkot

꾀 kkoe

꾸 kku

꿈 kkum

끝 kkeut

끼 kki

 

 

ㄴ 나 na

낙 nak

 

 

 

난 nan

날 nal

남 nam

납 nap

낭 nang

내 nae

냉 naeng

너 neo

널 neol

네 ne

녀 nyeo

녁 nyeok

년 nyeon

념 nyeom

녕 nyeong

노 no

녹 nok

논 non

놀 nol

농 nong

뇌 noe

누 nu

눈 nun

눌 nul

느 neu

늑 neuk

늠 neum

능 neung

늬 nui

니 ni

닉 nik

닌 nin

닐 nil

님 nim

 

ㄷ 다 da

 

 

 

 

단 dan

달 dal

담 dam

답 dap

당 dang

대 dae

댁 daek

더 deo

덕 deok

도 do

독 dok

돈 don

돌 dol

동 dong

돼 dwae

되 doe

된 doen

두 du

둑 duk

둔 dun

뒤 dwi

드 deu

득 deuk

들 deul

등 deung

디 di

따 tta

땅 ttang

때 ttae

또 tto

뚜 ttu

뚝 ttuk

뜨 tteu

띠 tti

 

ㄹ 라 ra

 

 

 

 

락 rak

란 ran

람 ram

랑 rang

래 rae

랭 raeng

량 ryang

렁 reong

레 re

려 ryeo

력 ryeok

련 ryeon

렬 ryeol

렴 ryeom

렵 ryeop

령 ryeong

례 rye

로 ro

록 rok

론 ron

롱 rong

뢰 roe

료 ryo

룡 ryong

루 ru

류 ryu

륙 ryuk

륜 ryun

률 ryul

륭 ryung

르 reu

륵 reuk

른 reun

름 reum

릉 reung

리 ri

린 rin

림 rim

립 rip

 

ㅁ 마 ma

 

 

 

 

막 mak

만 man

말 mal

망 mang

매 mae

맥 maek

맨 maen

맹 maeng

머 meo

먹 meok

메 me

며 myeo

멱 myeok

면 myeon

멸 myeol

명 myeong

모 mo

목 mok

몰 mol

못 mot

몽 mong

뫼 moe

묘 myo

무 mu

묵 muk

문 mun

물 mul

므 meu

미 mi

민 min

밀 mil

 

 

 

 

ㅂ 바 ba

박 bak

반 ban

발 bal

 

밥 bap

방 bang

배 bae

백 baek

뱀 baem

버 beo

번 beon

벌 beol

범 beom

법 beop

벼 byeo

벽 byeok

변 byeon

별 byeol

병 byeong

보 bo

복 bok

본 bon

봉 bong

부 bu

북 buk

분 bun

불 bul

붕 bung

비 bi

빈 bin

빌 bil

빔 bim

빙 bing

빠 ppa

빼 ppae

뻐 ppeo

뽀 ppo

뿌 ppu

쁘 ppeu

삐 ppi

 

 

 

 

ㅅ 사 sa

삭 sak

산 san

살 sal

 

삼 sam

삽 sap

상 sang

샅 sat

새 sae

색 saek

생 saeng

서 seo

석 seok

선 seon

설 seol

섬 seom

섭 seop

성 seong

세 se

셔 syeo

소 so

속 sok

손 son

솔 sol

솟 sot

송 song

쇄 swae

쇠 soe

수 su

숙 suk

순 sun

술 sul

숨 sum

숭 sung

쉬 swi

스 seu

슬 seul

슴 seum

습 seup

승 seung

시 si

식 sik

신 sin

실 sil

심 sim

십 sip

싱 sing

싸 ssa

쌍 ssang

쌔 ssae

쏘 sso

쑥 ssuk

씨 ssi

 

ㅇ 아 a

 

 

 

 

악 ak

안 an

알 al

암 am

압 ap

앙 ang

앞 ap

애 ae

액 aek

앵 aeng

야 ya

약 yak

얀 yan

양 yang

어 eo

억 eok

언 eon

얼 eol

엄 eom

업 eop

에 e

여 yeo

역 yeok

연 yeon

열 yeol

염 yeom

엽 yeop

영 yeong

예 ye

오 o

옥 ok

온 on

올 ol

옴 om

옹 ong

와 wa

완 wan

왈 wal

왕 wang

왜 wae

외 oe

왼 oen

요 yo

욕 yok

용 yong

우 u

욱 uk

운 un

울 ul

움 um

웅 ung

워 wo

원 won

월 wol

위 wi

유 yu

육 yuk

윤 yun

율 yul

융 yung

윷 yut

으 eu

은 eun

을 eul

음 eum

읍 eup

응 eung

의 ui

이 i

익 ik

인 in

일 il

임 im

입 ip

잉 ing

ㅈ 자 ja

작 jak

잔 jan

잠 jam

잡 jap

장 jang

재 jae

쟁 jaeng

저 jeo

적 jeok

전 jeon

절 jeol

점 jeom

접 jeop

정 jeong

제 je

조 jo

족 jok

존 jon

졸 jol

종 jong

좌 jwa

죄 joe

주 ju

죽 juk

준 jun

줄 jul

중 jung

쥐 jwi

즈 jeu

즉 jeuk

즐 jeul

즘 jeum

즙 jeup

증 jeung

지 ji

직 jik

진 jin

질 jil

짐 jim

집 jip

징 jing

짜 jja

째 jjae

쪼 jjo

찌 jji

 

 

 

 

ㅊ 차 cha

착 chak

찬 chan

찰 chal

 

참 cham

창 chang

채 chae

책 chaek

처 cheo

척 cheok

천 cheon

철 cheol

첨 cheom

첩 cheop

청 cheong

체 che

초 cho

촉 chok

촌 chon

총 chong

최 choe

추 chu

축 chuk

춘 chun

출 chul

춤 chum

충 chung

측 cheuk

층 cheung

치 chi

칙 chik

친 chin

칠 chil

침 chim

칩 chip

칭 ching

 

 

 

칩 chip

칭 ching

 

 

 

ㅋ 코 ko

쾌 kwae

크 keu

큰 keun

키 ki

ㅌ 타 ta

탁 tak

탄 tan

 

 

탈 tal

탐 tam

탑 tap

탕 tang

태 tae

택 taek

탱 taeng

터 teo

테 te

토 to

톤 ton

톨 tol

통 tong

퇴 toe

투 tu

퉁 tung

튀 twi

트 teu

특 teuk

틈 teum

티 ti

 

 

 

 

ㅍ 파 pa

판 pan

팔 pal

패 pae

 

팽 paeng

퍼 peo

페 pe

펴 pyeo

편 pyeon

폄 pyeom

평 pyeong

폐 pye

포 po

폭 pok

표 pyo

푸 pu

품 pum

풍 pung

프 peu

피 pi

픽 pik

필 pil

핍 pip

 

ㅎ 하 ha

 

 

 

 

학 hak

한 han

할 hal

함 ham

합 hap

항 hang

해 hae

핵 haek

행 haeng

향 hyang

허 heo

헌 heon

험 heom

헤 he

혀 hyeo

혁 hyeok

현 hyeon

혈 hyeol

혐 hyeom

협 hyeop

형 hyeong

혜 hye

호 ho

혹 hok

혼 hon

홀 hol

홉 hop

홍 hong

화 hwa

확 hwak

환 hwan

활 hwal

황 hwang

홰 hwae

횃 hwaet

회 hoe

획 hoek

횡 hoeng

효 hyo

후 hu

훈 hun

훤 hwon

훼 hwe

휘 hwi

휴 hyu

휼 hyul

흉 hyung

흐 heu

흑 heuk

흔 heun

흘 heul

흠 heum

흡 heup

흥 heung

희 hui

흰 huin

히 hi

힘 him

 

 




Posted by 솔라리스™
: